1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
diff --exclude-from=/home/dang/.diffrc -up -ruN linux-2.6.18-usermode-r1.orig/net/ipv6/netfilter/ip6_tables.c linux-2.6.18-usermode-r1/net/ipv6/netfilter/ip6_tables.c
--- linux-2.6.18-usermode-r1.orig/net/ipv6/netfilter/ip6_tables.c 2007-01-02 21:03:01.000000000 -0500
+++ linux-2.6.18-usermode-r1/net/ipv6/netfilter/ip6_tables.c 2007-01-02 23:02:56.000000000 -0500
@@ -1445,6 +1445,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
@@ -1468,12 +1471,12 @@ int ipv6_find_hdr(const struct sk_buff *
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,
@@ -1482,7 +1485,7 @@ int ipv6_find_hdr(const struct sk_buff *
sizeof(_frag_off),
&_frag_off);
if (fp == NULL)
- return -1;
+ return -EBADMSG;
_frag_off = ntohs(*fp) & ~0x7;
if (_frag_off) {
@@ -1493,7 +1496,7 @@ int ipv6_find_hdr(const struct sk_buff *
*fragoff = _frag_off;
return hp->nexthdr;
}
- return -1;
+ return -ENOENT;
}
hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH)
diff --exclude-from=/home/dang/.diffrc -up -ruN linux-2.6.18-usermode-r1.orig/net/ipv6/netfilter/ip6t_ah.c linux-2.6.18-usermode-r1/net/ipv6/netfilter/ip6t_ah.c
--- linux-2.6.18-usermode-r1.orig/net/ipv6/netfilter/ip6t_ah.c 2006-09-19 23:42:06.000000000 -0400
+++ linux-2.6.18-usermode-r1/net/ipv6/netfilter/ip6t_ah.c 2007-01-02 23:03:50.000000000 -0500
@@ -54,9 +54,14 @@ match(const struct sk_buff *skb,
const struct ip6t_ah *ahinfo = matchinfo;
unsigned int ptr;
unsigned int hdrlen = 0;
-
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL) < 0)
- return 0;
+ int err;
+
+ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL);
+ if (err < 0) {
+ if (err != -ENOENT)
+ *hotdrop = 1;
+ return 0;
+ }
ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
if (ah == NULL) {
diff --exclude-from=/home/dang/.diffrc -up -ruN linux-2.6.18-usermode-r1.orig/net/ipv6/netfilter/ip6t_frag.c linux-2.6.18-usermode-r1/net/ipv6/netfilter/ip6t_frag.c
--- linux-2.6.18-usermode-r1.orig/net/ipv6/netfilter/ip6t_frag.c 2006-09-19 23:42:06.000000000 -0400
+++ linux-2.6.18-usermode-r1/net/ipv6/netfilter/ip6t_frag.c 2007-01-02 23:04:29.000000000 -0500
@@ -52,9 +52,14 @@ match(const struct sk_buff *skb,
struct frag_hdr _frag, *fh;
const struct ip6t_frag *fraginfo = matchinfo;
unsigned int ptr;
-
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL) < 0)
- return 0;
+ int err;
+
+ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL);
+ if (err < 0) {
+ if (err != -ENOENT)
+ *hotdrop = 1;
+ return 0;
+ }
fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
if (fh == NULL) {
diff --exclude-from=/home/dang/.diffrc -up -ruN linux-2.6.18-usermode-r1.orig/net/ipv6/netfilter/ip6t_rt.c linux-2.6.18-usermode-r1/net/ipv6/netfilter/ip6t_rt.c
--- linux-2.6.18-usermode-r1.orig/net/ipv6/netfilter/ip6t_rt.c 2006-09-19 23:42:06.000000000 -0400
+++ linux-2.6.18-usermode-r1/net/ipv6/netfilter/ip6t_rt.c 2007-01-02 23:04:53.000000000 -0500
@@ -58,9 +58,14 @@ match(const struct sk_buff *skb,
unsigned int hdrlen = 0;
unsigned int ret = 0;
struct in6_addr *ap, _addr;
-
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL) < 0)
- return 0;
+ int err;
+
+ err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL);
+ if (err < 0) {
+ if (err != -ENOENT)
+ *hotdrop = 1;
+ return 0;
+ }
rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
if (rh == NULL) {
|