Blame view
net/ipv6/exthdrs_core.c
3.42 KB
1da177e4c 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 net: Add export.h... |
5 |
#include <linux/export.h> |
1da177e4c Linux-2.6.12-rc2 |
6 |
#include <net/ipv6.h> |
1ab1457c4 [NET] IPV6: Fix w... |
7 |
/* |
1da177e4c 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 [NET] IPV6: Fix w... |
13 |
/* |
1da177e4c Linux-2.6.12-rc2 |
14 15 |
* find out if nexthdr is an extension header or a protocol */ |
a02cec215 net: return opera... |
16 |
return (nexthdr == NEXTHDR_HOP) || |
1da177e4c Linux-2.6.12-rc2 |
17 18 19 20 |
(nexthdr == NEXTHDR_ROUTING) || (nexthdr == NEXTHDR_FRAGMENT) || (nexthdr == NEXTHDR_AUTH) || (nexthdr == NEXTHDR_NONE) || |
a02cec215 net: return opera... |
21 |
(nexthdr == NEXTHDR_DEST); |
1da177e4c 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 [NET] IPV6: Fix w... |
28 |
* ...The contents and semantics of each extension header determine whether |
1da177e4c 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 [NET] IPV6: Fix w... |
34 |
* |
1da177e4c Linux-2.6.12-rc2 |
35 |
* We do exactly this. This is a protocol bug. We can't decide after a |
1ab1457c4 [NET] IPV6: Fix w... |
36 |
* seeing an unknown discard-with-error flavour TLV option if it's a |
1da177e4c Linux-2.6.12-rc2 |
37 38 |
* ICMP error message or not (errors should never be send in reply to * ICMP error messages). |
1ab1457c4 [NET] IPV6: Fix w... |
39 |
* |
1da177e4c 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 [SELINUX]: Fix ip... |
44 45 |
* This function parses (probably truncated) exthdr set "hdr". * "nexthdrp" initially points to some place, |
1da177e4c 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 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 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 ipv6: Add fragmen... |
68 69 |
int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, __be16 *frag_offp) |
1da177e4c Linux-2.6.12-rc2 |
70 71 |
{ u8 nexthdr = *nexthdrp; |
75f2811c6 ipv6: Add fragmen... |
72 |
*frag_offp = 0; |
1da177e4c Linux-2.6.12-rc2 |
73 74 75 |
while (ipv6_ext_hdr(nexthdr)) { struct ipv6_opt_hdr _hdr, *hp; int hdrlen; |
1da177e4c 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 [SELINUX]: Fix ip... |
80 |
return -1; |
1da177e4c Linux-2.6.12-rc2 |
81 |
if (nexthdr == NEXTHDR_FRAGMENT) { |
e69a4adc6 [IPV6]: Misc endi... |
82 |
__be16 _frag_off, *fp; |
1da177e4c 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 ipv6: Add fragmen... |
90 91 |
*frag_offp = *fp; if (ntohs(*frag_offp) & ~0x7) |
1da177e4c Linux-2.6.12-rc2 |
92 93 94 |
break; hdrlen = 8; } else if (nexthdr == NEXTHDR_AUTH) |
1ab1457c4 [NET] IPV6: Fix w... |
95 |
hdrlen = (hp->hdrlen+2)<<2; |
1da177e4c Linux-2.6.12-rc2 |
96 |
else |
1ab1457c4 [NET] IPV6: Fix w... |
97 |
hdrlen = ipv6_optlen(hp); |
1da177e4c Linux-2.6.12-rc2 |
98 99 |
nexthdr = hp->nexthdr; |
1da177e4c 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); |