~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ipv6/xfrm6_input.c

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * xfrm6_input.c: based on net/ipv4/xfrm4_input.c
  3  *
  4  * Authors:
  5  *      Mitsuru KANDA @USAGI
  6  *      Kazunori MIYAZAWA @USAGI
  7  *      Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  8  *      YOSHIFUJI Hideaki @USAGI
  9  *              IPv6 support
 10  */
 11 
 12 #include <net/inet_ecn.h>
 13 #include <net/ip.h>
 14 #include <net/ipv6.h>
 15 #include <net/xfrm.h>
 16 
 17 static inline void ipip6_ecn_decapsulate(struct ipv6hdr *iph,
 18                                          struct sk_buff *skb)
 19 {
 20         if (INET_ECN_is_ce(ip6_get_dsfield(iph)) &&
 21             INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
 22                 IP6_ECN_set_ce(skb->nh.ipv6h);
 23 }
 24 
 25 int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
 26 {
 27         struct sk_buff *skb = *pskb;
 28         int err;
 29         u32 spi, seq;
 30         struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
 31         struct xfrm_state *x;
 32         int xfrm_nr = 0;
 33         int decaps = 0;
 34         int nexthdr = 0;
 35         u8 *prevhdr = NULL;
 36 
 37         ip6_find_1stfragopt(skb, &prevhdr);
 38         nexthdr = *prevhdr;
 39         *nhoffp = prevhdr - skb->nh.raw;
 40 
 41         if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
 42                 goto drop;
 43         
 44         do {
 45                 struct ipv6hdr *iph = skb->nh.ipv6h;
 46 
 47                 if (xfrm_nr == XFRM_MAX_DEPTH)
 48                         goto drop;
 49 
 50                 x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, nexthdr, AF_INET6);
 51                 if (x == NULL)
 52                         goto drop;
 53                 spin_lock(&x->lock);
 54                 if (unlikely(x->km.state != XFRM_STATE_VALID))
 55                         goto drop_unlock;
 56 
 57                 if (x->props.replay_window && xfrm_replay_check(x, seq))
 58                         goto drop_unlock;
 59 
 60                 if (xfrm_state_check_expire(x))
 61                         goto drop_unlock;
 62 
 63                 nexthdr = x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb);
 64                 if (nexthdr <= 0)
 65                         goto drop_unlock;
 66 
 67                 if (x->props.replay_window)
 68                         xfrm_replay_advance(x, seq);
 69 
 70                 x->curlft.bytes += skb->len;
 71                 x->curlft.packets++;
 72 
 73                 spin_unlock(&x->lock);
 74 
 75                 xfrm_vec[xfrm_nr++].xvec = x;
 76 
 77                 if (x->props.mode) { /* XXX */
 78                         if (nexthdr != IPPROTO_IPV6)
 79                                 goto drop;
 80                         skb->nh.raw = skb->data;
 81                         if (!(x->props.flags & XFRM_STATE_NOECN))
 82                                 ipip6_ecn_decapsulate(iph, skb);
 83                         iph = skb->nh.ipv6h;
 84                         decaps = 1;
 85                         break;
 86                 }
 87 
 88                 if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) < 0)
 89                         goto drop;
 90         } while (!err);
 91 
 92         /* Allocate new secpath or COW existing one. */
 93         if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
 94                 struct sec_path *sp;
 95                 sp = secpath_dup(skb->sp);
 96                 if (!sp)
 97                         goto drop;
 98                 if (skb->sp)
 99                         secpath_put(skb->sp);
100                 skb->sp = sp;
101         }
102 
103         if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
104                 goto drop;
105 
106         memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
107         skb->sp->len += xfrm_nr;
108         skb->ip_summed = CHECKSUM_NONE;
109 
110         if (decaps) {
111                 if (!(skb->dev->flags&IFF_LOOPBACK)) {
112                         dst_release(skb->dst);
113                         skb->dst = NULL;
114                 }
115                 netif_rx(skb);
116                 return -1;
117         } else {
118                 return 1;
119         }
120 
121 drop_unlock:
122         spin_unlock(&x->lock);
123         xfrm_state_put(x);
124 drop:
125         while (--xfrm_nr >= 0)
126                 xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
127         kfree_skb(skb);
128         return -1;
129 }
130 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp