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