aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_multicast.c3
-rw-r--r--net/bridge/netfilter/ebt_ip6.c3
-rw-r--r--net/bridge/netfilter/ebt_log.c3
-rw-r--r--net/ipv6/exthdrs_core.c11
-rw-r--r--net/ipv6/icmp.c7
-rw-r--r--net/ipv6/ip6_input.c3
-rw-r--r--net/ipv6/ip6_output.c3
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c3
-rw-r--r--net/netfilter/ipset/ip_set_getport.c4
-rw-r--r--net/netfilter/xt_AUDIT.c3
-rw-r--r--net/netfilter/xt_TCPMSS.c3
-rw-r--r--net/netfilter/xt_TCPOPTSTRIP.c3
-rw-r--r--net/netfilter/xt_hashlimit.c3
-rw-r--r--net/netfilter/xt_socket.c4
14 files changed, 40 insertions, 16 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 7743e0d109ea..375417e633c9 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1458,6 +1458,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1458 const struct ipv6hdr *ip6h; 1458 const struct ipv6hdr *ip6h;
1459 u8 icmp6_type; 1459 u8 icmp6_type;
1460 u8 nexthdr; 1460 u8 nexthdr;
1461 __be16 frag_off;
1461 unsigned len; 1462 unsigned len;
1462 int offset; 1463 int offset;
1463 int err; 1464 int err;
@@ -1483,7 +1484,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1483 return -EINVAL; 1484 return -EINVAL;
1484 1485
1485 nexthdr = ip6h->nexthdr; 1486 nexthdr = ip6h->nexthdr;
1486 offset = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nexthdr); 1487 offset = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nexthdr, &frag_off);
1487 1488
1488 if (offset < 0 || nexthdr != IPPROTO_ICMPV6) 1489 if (offset < 0 || nexthdr != IPPROTO_ICMPV6)
1489 return 0; 1490 return 0;
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c
index 2ed0056a39a8..99c85668f551 100644
--- a/net/bridge/netfilter/ebt_ip6.c
+++ b/net/bridge/netfilter/ebt_ip6.c
@@ -55,9 +55,10 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par)
55 return false; 55 return false;
56 if (info->bitmask & EBT_IP6_PROTO) { 56 if (info->bitmask & EBT_IP6_PROTO) {
57 uint8_t nexthdr = ih6->nexthdr; 57 uint8_t nexthdr = ih6->nexthdr;
58 __be16 frag_off;
58 int offset_ph; 59 int offset_ph;
59 60
60 offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr); 61 offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr, &frag_off);
61 if (offset_ph == -1) 62 if (offset_ph == -1)
62 return false; 63 return false;
63 if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) 64 if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO))
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 6e5a8bb9b940..88d7d1d1cb1b 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -113,6 +113,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
113 const struct ipv6hdr *ih; 113 const struct ipv6hdr *ih;
114 struct ipv6hdr _iph; 114 struct ipv6hdr _iph;
115 uint8_t nexthdr; 115 uint8_t nexthdr;
116 __be16 frag_off;
116 int offset_ph; 117 int offset_ph;
117 118
118 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); 119 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
@@ -123,7 +124,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
123 printk(" IPv6 SRC=%pI6 IPv6 DST=%pI6, IPv6 priority=0x%01X, Next Header=%d", 124 printk(" IPv6 SRC=%pI6 IPv6 DST=%pI6, IPv6 priority=0x%01X, Next Header=%d",
124 &ih->saddr, &ih->daddr, ih->priority, ih->nexthdr); 125 &ih->saddr, &ih->daddr, ih->priority, ih->nexthdr);
125 nexthdr = ih->nexthdr; 126 nexthdr = ih->nexthdr;
126 offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr); 127 offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr, &frag_off);
127 if (offset_ph == -1) 128 if (offset_ph == -1)
128 goto out; 129 goto out;
129 print_ports(skb, nexthdr, offset_ph); 130 print_ports(skb, nexthdr, offset_ph);
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index 37f548b7f6dc..72957f4a7c6c 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -57,6 +57,9 @@ int ipv6_ext_hdr(u8 nexthdr)
57 * it returns NULL. 57 * it returns NULL.
58 * - First fragment header is skipped, not-first ones 58 * - First fragment header is skipped, not-first ones
59 * are considered as unparsable. 59 * are considered as unparsable.
60 * - Reports the offset field of the final fragment header so it is
61 * possible to tell whether this is a first fragment, later fragment,
62 * or not fragmented.
60 * - ESP is unparsable for now and considered like 63 * - ESP is unparsable for now and considered like
61 * normal payload protocol. 64 * normal payload protocol.
62 * - Note also special handling of AUTH header. Thanks to IPsec wizards. 65 * - Note also special handling of AUTH header. Thanks to IPsec wizards.
@@ -64,10 +67,13 @@ int ipv6_ext_hdr(u8 nexthdr)
64 * --ANK (980726) 67 * --ANK (980726)
65 */ 68 */
66 69
67int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp) 70int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
71 __be16 *frag_offp)
68{ 72{
69 u8 nexthdr = *nexthdrp; 73 u8 nexthdr = *nexthdrp;
70 74
75 *frag_offp = 0;
76
71 while (ipv6_ext_hdr(nexthdr)) { 77 while (ipv6_ext_hdr(nexthdr)) {
72 struct ipv6_opt_hdr _hdr, *hp; 78 struct ipv6_opt_hdr _hdr, *hp;
73 int hdrlen; 79 int hdrlen;
@@ -87,7 +93,8 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp)
87 if (fp == NULL) 93 if (fp == NULL)
88 return -1; 94 return -1;
89 95
90 if (ntohs(*fp) & ~0x7) 96 *frag_offp = *fp;
97 if (ntohs(*frag_offp) & ~0x7)
91 break; 98 break;
92 hdrlen = 8; 99 hdrlen = 8;
93 } else if (nexthdr == NEXTHDR_AUTH) 100 } else if (nexthdr == NEXTHDR_AUTH)
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 9e2bdccf9143..01d46bff63c3 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -135,11 +135,12 @@ static int is_ineligible(struct sk_buff *skb)
135 int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; 135 int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data;
136 int len = skb->len - ptr; 136 int len = skb->len - ptr;
137 __u8 nexthdr = ipv6_hdr(skb)->nexthdr; 137 __u8 nexthdr = ipv6_hdr(skb)->nexthdr;
138 __be16 frag_off;
138 139
139 if (len < 0) 140 if (len < 0)
140 return 1; 141 return 1;
141 142
142 ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr); 143 ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, &frag_off);
143 if (ptr < 0) 144 if (ptr < 0)
144 return 0; 145 return 0;
145 if (nexthdr == IPPROTO_ICMPV6) { 146 if (nexthdr == IPPROTO_ICMPV6) {
@@ -596,6 +597,7 @@ static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
596 int inner_offset; 597 int inner_offset;
597 int hash; 598 int hash;
598 u8 nexthdr; 599 u8 nexthdr;
600 __be16 frag_off;
599 601
600 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 602 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
601 return; 603 return;
@@ -603,7 +605,8 @@ static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
603 nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; 605 nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
604 if (ipv6_ext_hdr(nexthdr)) { 606 if (ipv6_ext_hdr(nexthdr)) {
605 /* now skip over extension headers */ 607 /* now skip over extension headers */
606 inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); 608 inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
609 &nexthdr, &frag_off);
607 if (inner_offset<0) 610 if (inner_offset<0)
608 return; 611 return;
609 } else { 612 } else {
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index a46c64eb0a66..1ca5d45a12e8 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -280,6 +280,7 @@ int ip6_mc_input(struct sk_buff *skb)
280 u8 *ptr = skb_network_header(skb) + opt->ra; 280 u8 *ptr = skb_network_header(skb) + opt->ra;
281 struct icmp6hdr *icmp6; 281 struct icmp6hdr *icmp6;
282 u8 nexthdr = hdr->nexthdr; 282 u8 nexthdr = hdr->nexthdr;
283 __be16 frag_off;
283 int offset; 284 int offset;
284 285
285 /* Check if the value of Router Alert 286 /* Check if the value of Router Alert
@@ -293,7 +294,7 @@ int ip6_mc_input(struct sk_buff *skb)
293 goto out; 294 goto out;
294 } 295 }
295 offset = ipv6_skip_exthdr(skb, sizeof(*hdr), 296 offset = ipv6_skip_exthdr(skb, sizeof(*hdr),
296 &nexthdr); 297 &nexthdr, &frag_off);
297 if (offset < 0) 298 if (offset < 0)
298 goto out; 299 goto out;
299 300
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index a24e15557843..3221bc675654 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -329,10 +329,11 @@ static int ip6_forward_proxy_check(struct sk_buff *skb)
329{ 329{
330 struct ipv6hdr *hdr = ipv6_hdr(skb); 330 struct ipv6hdr *hdr = ipv6_hdr(skb);
331 u8 nexthdr = hdr->nexthdr; 331 u8 nexthdr = hdr->nexthdr;
332 __be16 frag_off;
332 int offset; 333 int offset;
333 334
334 if (ipv6_ext_hdr(nexthdr)) { 335 if (ipv6_ext_hdr(nexthdr)) {
335 offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr); 336 offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr, &frag_off);
336 if (offset < 0) 337 if (offset < 0)
337 return 0; 338 return 0;
338 } else 339 } else
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index b5a2aa58a03a..aad2fa41cf46 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -49,6 +49,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
49 const __u8 tclass = DEFAULT_TOS_VALUE; 49 const __u8 tclass = DEFAULT_TOS_VALUE;
50 struct dst_entry *dst = NULL; 50 struct dst_entry *dst = NULL;
51 u8 proto; 51 u8 proto;
52 __be16 frag_off;
52 struct flowi6 fl6; 53 struct flowi6 fl6;
53 54
54 if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || 55 if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
@@ -58,7 +59,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
58 } 59 }
59 60
60 proto = oip6h->nexthdr; 61 proto = oip6h->nexthdr;
61 tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); 62 tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off);
62 63
63 if ((tcphoff < 0) || (tcphoff > oldskb->len)) { 64 if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
64 pr_debug("Cannot get TCP header.\n"); 65 pr_debug("Cannot get TCP header.\n");
diff --git a/net/netfilter/ipset/ip_set_getport.c b/net/netfilter/ipset/ip_set_getport.c
index 052579fe389a..b71a6e7ab0a5 100644
--- a/net/netfilter/ipset/ip_set_getport.c
+++ b/net/netfilter/ipset/ip_set_getport.c
@@ -116,9 +116,11 @@ ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
116{ 116{
117 int protoff; 117 int protoff;
118 u8 nexthdr; 118 u8 nexthdr;
119 __be16 frag_off;
119 120
120 nexthdr = ipv6_hdr(skb)->nexthdr; 121 nexthdr = ipv6_hdr(skb)->nexthdr;
121 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); 122 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
123 &frag_off);
122 if (protoff < 0) 124 if (protoff < 0)
123 return false; 125 return false;
124 126
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index 4bca15a0c385..ba92824086f3 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -98,6 +98,7 @@ static void audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
98 struct ipv6hdr _ip6h; 98 struct ipv6hdr _ip6h;
99 const struct ipv6hdr *ih; 99 const struct ipv6hdr *ih;
100 u8 nexthdr; 100 u8 nexthdr;
101 __be16 frag_off;
101 int offset; 102 int offset;
102 103
103 ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h); 104 ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h);
@@ -108,7 +109,7 @@ static void audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
108 109
109 nexthdr = ih->nexthdr; 110 nexthdr = ih->nexthdr;
110 offset = ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h), 111 offset = ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h),
111 &nexthdr); 112 &nexthdr, &frag_off);
112 113
113 audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu", 114 audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu",
114 &ih->saddr, &ih->daddr, nexthdr); 115 &ih->saddr, &ih->daddr, nexthdr);
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 3ecade3966d5..ba722621ed25 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -204,11 +204,12 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par)
204{ 204{
205 struct ipv6hdr *ipv6h = ipv6_hdr(skb); 205 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
206 u8 nexthdr; 206 u8 nexthdr;
207 __be16 frag_off;
207 int tcphoff; 208 int tcphoff;
208 int ret; 209 int ret;
209 210
210 nexthdr = ipv6h->nexthdr; 211 nexthdr = ipv6h->nexthdr;
211 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); 212 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off);
212 if (tcphoff < 0) 213 if (tcphoff < 0)
213 return NF_DROP; 214 return NF_DROP;
214 ret = tcpmss_mangle_packet(skb, par->targinfo, 215 ret = tcpmss_mangle_packet(skb, par->targinfo,
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c
index 9dc9ecfdd546..3a295cc734bd 100644
--- a/net/netfilter/xt_TCPOPTSTRIP.c
+++ b/net/netfilter/xt_TCPOPTSTRIP.c
@@ -87,9 +87,10 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par)
87 struct ipv6hdr *ipv6h = ipv6_hdr(skb); 87 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
88 int tcphoff; 88 int tcphoff;
89 u_int8_t nexthdr; 89 u_int8_t nexthdr;
90 __be16 frag_off;
90 91
91 nexthdr = ipv6h->nexthdr; 92 nexthdr = ipv6h->nexthdr;
92 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); 93 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off);
93 if (tcphoff < 0) 94 if (tcphoff < 0)
94 return NF_DROP; 95 return NF_DROP;
95 96
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index dfd52bad1523..068698f64791 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -445,6 +445,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
445{ 445{
446 __be16 _ports[2], *ports; 446 __be16 _ports[2], *ports;
447 u8 nexthdr; 447 u8 nexthdr;
448 __be16 frag_off;
448 int poff; 449 int poff;
449 450
450 memset(dst, 0, sizeof(*dst)); 451 memset(dst, 0, sizeof(*dst));
@@ -480,7 +481,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
480 (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT))) 481 (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT)))
481 return 0; 482 return 0;
482 nexthdr = ipv6_hdr(skb)->nexthdr; 483 nexthdr = ipv6_hdr(skb)->nexthdr;
483 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); 484 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, &frag_off);
484 if ((int)protoff < 0) 485 if ((int)protoff < 0)
485 return -1; 486 return -1;
486 break; 487 break;
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index fe39f7e913df..c302e30dc50c 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -214,6 +214,7 @@ extract_icmp6_fields(const struct sk_buff *skb,
214 struct icmp6hdr *icmph, _icmph; 214 struct icmp6hdr *icmph, _icmph;
215 __be16 *ports, _ports[2]; 215 __be16 *ports, _ports[2];
216 u8 inside_nexthdr; 216 u8 inside_nexthdr;
217 __be16 inside_fragoff;
217 int inside_hdrlen; 218 int inside_hdrlen;
218 219
219 icmph = skb_header_pointer(skb, outside_hdrlen, 220 icmph = skb_header_pointer(skb, outside_hdrlen,
@@ -229,7 +230,8 @@ extract_icmp6_fields(const struct sk_buff *skb,
229 return 1; 230 return 1;
230 inside_nexthdr = inside_iph->nexthdr; 231 inside_nexthdr = inside_iph->nexthdr;
231 232
232 inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), &inside_nexthdr); 233 inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph),
234 &inside_nexthdr, &inside_fragoff);
233 if (inside_hdrlen < 0) 235 if (inside_hdrlen < 0)
234 return 1; /* hjm: Packet has no/incomplete transport layer headers. */ 236 return 1; /* hjm: Packet has no/incomplete transport layer headers. */
235 237