Version:  2.6.34 2.6.35 2.6.36 2.6.37 2.6.38 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14

Linux/net/ipv6/exthdrs_core.c

  1 /*
  2  * IPv6 library code, needed by static components when full IPv6 support is
  3  * not configured or static.
  4  */
  5 #include <net/ipv6.h>
  6 
  7 /*
  8  * find out if nexthdr is a well-known extension header or a protocol
  9  */
 10 
 11 int ipv6_ext_hdr(u8 nexthdr)
 12 {
 13         /*
 14          * find out if nexthdr is an extension header or a protocol
 15          */
 16         return ( (nexthdr == NEXTHDR_HOP)       ||
 17                  (nexthdr == NEXTHDR_ROUTING)   ||
 18                  (nexthdr == NEXTHDR_FRAGMENT)  ||
 19                  (nexthdr == NEXTHDR_AUTH)      ||
 20                  (nexthdr == NEXTHDR_NONE)      ||
 21                  (nexthdr == NEXTHDR_DEST) );
 22 }
 23 
 24 /*
 25  * Skip any extension headers. This is used by the ICMP module.
 26  *
 27  * Note that strictly speaking this conflicts with RFC 2460 4.0:
 28  * ...The contents and semantics of each extension header determine whether
 29  * or not to proceed to the next header.  Therefore, extension headers must
 30  * be processed strictly in the order they appear in the packet; a
 31  * receiver must not, for example, scan through a packet looking for a
 32  * particular kind of extension header and process that header prior to
 33  * processing all preceding ones.
 34  *
 35  * We do exactly this. This is a protocol bug. We can't decide after a
 36  * seeing an unknown discard-with-error flavour TLV option if it's a
 37  * ICMP error message or not (errors should never be send in reply to
 38  * ICMP error messages).
 39  *
 40  * But I see no other way to do this. This might need to be reexamined
 41  * when Linux implements ESP (and maybe AUTH) headers.
 42  * --AK
 43  *
 44  * This function parses (probably truncated) exthdr set "hdr".
 45  * "nexthdrp" initially points to some place,
 46  * where type of the first header can be found.
 47  *
 48  * It skips all well-known exthdrs, and returns pointer to the start
 49  * of unparsable area i.e. the first header with unknown type.
 50  * If it is not NULL *nexthdr is updated by type/protocol of this header.
 51  *
 52  * NOTES: - if packet terminated with NEXTHDR_NONE it returns NULL.
 53  *        - it may return pointer pointing beyond end of packet,
 54  *          if the last recognized header is truncated in the middle.
 55  *        - if packet is truncated, so that all parsed headers are skipped,
 56  *          it returns NULL.
 57  *        - First fragment header is skipped, not-first ones
 58  *          are considered as unparsable.
 59  *        - ESP is unparsable for now and considered like
 60  *          normal payload protocol.
 61  *        - Note also special handling of AUTH header. Thanks to IPsec wizards.
 62  *
 63  * --ANK (980726)
 64  */
 65 
 66 int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp)
 67 {
 68         u8 nexthdr = *nexthdrp;
 69 
 70         while (ipv6_ext_hdr(nexthdr)) {
 71                 struct ipv6_opt_hdr _hdr, *hp;
 72                 int hdrlen;
 73 
 74                 if (nexthdr == NEXTHDR_NONE)
 75                         return -1;
 76                 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
 77                 if (hp == NULL)
 78                         return -1;
 79                 if (nexthdr == NEXTHDR_FRAGMENT) {
 80                         __be16 _frag_off, *fp;
 81                         fp = skb_header_pointer(skb,
 82                                                 start+offsetof(struct frag_hdr,
 83                                                                frag_off),
 84                                                 sizeof(_frag_off),
 85                                                 &_frag_off);
 86                         if (fp == NULL)
 87                                 return -1;
 88 
 89                         if (ntohs(*fp) & ~0x7)
 90                                 break;
 91                         hdrlen = 8;
 92                 } else if (nexthdr == NEXTHDR_AUTH)
 93                         hdrlen = (hp->hdrlen+2)<<2;
 94                 else
 95                         hdrlen = ipv6_optlen(hp);
 96 
 97                 nexthdr = hp->nexthdr;
 98                 start += hdrlen;
 99         }
100 
101         *nexthdrp = nexthdr;
102         return start;
103 }
104 
105 EXPORT_SYMBOL(ipv6_ext_hdr);
106 EXPORT_SYMBOL(ipv6_skip_exthdr);
107 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us