|
@@ -1440,6 +1440,9 @@ static void __exit ip6_tables_fini(void)
|
|
|
* If target header is found, its offset is set in *offset and return protocol
|
|
|
* number. Otherwise, return -1.
|
|
|
*
|
|
|
+ * If the first fragment doesn't contain the final protocol header or
|
|
|
+ * NEXTHDR_NONE it is considered invalid.
|
|
|
+ *
|
|
|
* Note that non-1st fragment is special case that "the protocol number
|
|
|
* of last header" is "next header" field in Fragment header. In this case,
|
|
|
* *offset is meaningless and fragment offset is stored in *fragoff if fragoff
|
|
@@ -1463,12 +1466,12 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
|
|
|
if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
|
|
|
if (target < 0)
|
|
|
break;
|
|
|
- return -1;
|
|
|
+ return -ENOENT;
|
|
|
}
|
|
|
|
|
|
hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
|
|
|
if (hp == NULL)
|
|
|
- return -1;
|
|
|
+ return -EBADMSG;
|
|
|
if (nexthdr == NEXTHDR_FRAGMENT) {
|
|
|
unsigned short _frag_off, *fp;
|
|
|
fp = skb_header_pointer(skb,
|
|
@@ -1477,7 +1480,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
|
|
|
sizeof(_frag_off),
|
|
|
&_frag_off);
|
|
|
if (fp == NULL)
|
|
|
- return -1;
|
|
|
+ return -EBADMSG;
|
|
|
|
|
|
_frag_off = ntohs(*fp) & ~0x7;
|
|
|
if (_frag_off) {
|
|
@@ -1488,7 +1491,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
|
|
|
*fragoff = _frag_off;
|
|
|
return hp->nexthdr;
|
|
|
}
|
|
|
- return -1;
|
|
|
+ return -ENOENT;
|
|
|
}
|
|
|
hdrlen = 8;
|
|
|
} else if (nexthdr == NEXTHDR_AUTH)
|