1 /* 2 * xfrm4_input.c 3 * 4 * Changes: 5 * YOSHIFUJI Hideaki @USAGI 6 * Split up af-specific portion 7 * Derek Atkins <derek@ihtfp.com> 8 * Add Encapsulation support 9 * 10 */ 11 12 #include <linux/module.h> 13 #include <linux/string.h> 14 #include <linux/netfilter.h> 15 #include <linux/netfilter_ipv4.h> 16 #include <net/ip.h> 17 #include <net/xfrm.h> 18 19 int xfrm4_rcv(struct sk_buff *skb) 20 { 21 return xfrm4_rcv_encap(skb, 0); 22 } 23 24 EXPORT_SYMBOL(xfrm4_rcv); 25 26 static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) 27 { 28 switch (nexthdr) { 29 case IPPROTO_IPIP: 30 *spi = skb->nh.iph->saddr; 31 *seq = 0; 32 return 0; 33 } 34 35 return xfrm_parse_spi(skb, nexthdr, spi, seq); 36 } 37 38 #ifdef CONFIG_NETFILTER 39 static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) 40 { 41 struct iphdr *iph = skb->nh.iph; 42 43 if (skb->dst == NULL) { 44 if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, 45 skb->dev)) 46 goto drop; 47 } 48 return dst_input(skb); 49 drop: 50 kfree_skb(skb); 51 return NET_RX_DROP; 52 } 53 #endif 54 55 int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) 56 { 57 int err; 58 u32 spi, seq; 59 struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; 60 struct xfrm_state *x; 61 int xfrm_nr = 0; 62 int decaps = 0; 63 64 if ((err = xfrm4_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0) 65 goto drop; 66 67 do { 68 struct iphdr *iph = skb->nh.iph; 69 70 if (xfrm_nr == XFRM_MAX_DEPTH) 71 goto drop; 72 73 x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, iph->protocol, AF_INET); 74 if (x == NULL) 75 goto drop; 76 77 spin_lock(&x->lock); 78 if (unlikely(x->km.state != XFRM_STATE_VALID)) 79 goto drop_unlock; 80 81 if ((x->encap ? x->encap->encap_type : 0) != encap_type) 82 goto drop_unlock; 83 84 if (x->props.replay_window && xfrm_replay_check(x, seq)) 85 goto drop_unlock; 86 87 if (xfrm_state_check_expire(x)) 88 goto drop_unlock; 89 90 if (x->type->input(x, skb)) 91 goto drop_unlock; 92 93 /* only the first xfrm gets the encap type */ 94 encap_type = 0; 95 96 if (x->props.replay_window) 97 xfrm_replay_advance(x, seq); 98 99 x->curlft.bytes += skb->len; 100 x->curlft.packets++; 101 102 spin_unlock(&x->lock); 103 104 xfrm_vec[xfrm_nr++] = x; 105 106 if (x->mode->input(x, skb)) 107 goto drop; 108 109 if (x->props.mode) { 110 decaps = 1; 111 break; 112 } 113 114 if ((err = xfrm_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) < 0) 115 goto drop; 116 } while (!err); 117 118 /* Allocate new secpath or COW existing one. */ 119 120 if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { 121 struct sec_path *sp; 122 sp = secpath_dup(skb->sp); 123 if (!sp) 124 goto drop; 125 if (skb->sp) 126 secpath_put(skb->sp); 127 skb->sp = sp; 128 } 129 if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH) 130 goto drop; 131 132 memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec, 133 xfrm_nr * sizeof(xfrm_vec[0])); 134 skb->sp->len += xfrm_nr; 135 136 nf_reset(skb); 137 138 if (decaps) { 139 if (!(skb->dev->flags&IFF_LOOPBACK)) { 140 dst_release(skb->dst); 141 skb->dst = NULL; 142 } 143 netif_rx(skb); 144 return 0; 145 } else { 146 #ifdef CONFIG_NETFILTER 147 __skb_push(skb, skb->data - skb->nh.raw); 148 skb->nh.iph->tot_len = htons(skb->len); 149 ip_send_check(skb->nh.iph); 150 151 NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, 152 xfrm4_rcv_encap_finish); 153 return 0; 154 #else 155 return -skb->nh.iph->protocol; 156 #endif 157 } 158 159 drop_unlock: 160 spin_unlock(&x->lock); 161 xfrm_state_put(x); 162 drop: 163 while (--xfrm_nr >= 0) 164 xfrm_state_put(xfrm_vec[xfrm_nr]); 165 166 kfree_skb(skb); 167 return 0; 168 } 169