Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/ipv6/exthdrs_core.c
15109 views
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
108