Blame view

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