diff options
Diffstat (limited to 'net/ipv6/mip6.c')
-rw-r--r-- | net/ipv6/mip6.c | 62 |
1 files changed, 35 insertions, 27 deletions
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 0afcabdd8ed6..13b7160fb892 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -90,23 +90,26 @@ int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) | |||
90 | { | 90 | { |
91 | struct ip6_mh *mh; | 91 | struct ip6_mh *mh; |
92 | 92 | ||
93 | if (!pskb_may_pull(skb, (skb->h.raw - skb->data) + 8) || | 93 | if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) || |
94 | !pskb_may_pull(skb, (skb->h.raw - skb->data) + ((skb->h.raw[1] + 1) << 3))) | 94 | !pskb_may_pull(skb, (skb_transport_offset(skb) + |
95 | ((skb_transport_header(skb)[1] + 1) << 3)))) | ||
95 | return -1; | 96 | return -1; |
96 | 97 | ||
97 | mh = (struct ip6_mh *)skb->h.raw; | 98 | mh = (struct ip6_mh *)skb_transport_header(skb); |
98 | 99 | ||
99 | if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { | 100 | if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { |
100 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", | 101 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", |
101 | mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); | 102 | mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); |
102 | mip6_param_prob(skb, 0, (&mh->ip6mh_hdrlen) - skb->nh.raw); | 103 | mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) - |
104 | skb_network_header(skb))); | ||
103 | return -1; | 105 | return -1; |
104 | } | 106 | } |
105 | 107 | ||
106 | if (mh->ip6mh_proto != IPPROTO_NONE) { | 108 | if (mh->ip6mh_proto != IPPROTO_NONE) { |
107 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", | 109 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", |
108 | mh->ip6mh_proto); | 110 | mh->ip6mh_proto); |
109 | mip6_param_prob(skb, 0, (&mh->ip6mh_proto) - skb->nh.raw); | 111 | mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) - |
112 | skb_network_header(skb))); | ||
110 | return -1; | 113 | return -1; |
111 | } | 114 | } |
112 | 115 | ||
@@ -122,12 +125,12 @@ struct mip6_report_rate_limiter { | |||
122 | }; | 125 | }; |
123 | 126 | ||
124 | static struct mip6_report_rate_limiter mip6_report_rl = { | 127 | static struct mip6_report_rate_limiter mip6_report_rl = { |
125 | .lock = SPIN_LOCK_UNLOCKED | 128 | .lock = __SPIN_LOCK_UNLOCKED(mip6_report_rl.lock) |
126 | }; | 129 | }; |
127 | 130 | ||
128 | static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb) | 131 | static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb) |
129 | { | 132 | { |
130 | struct ipv6hdr *iph = skb->nh.ipv6h; | 133 | struct ipv6hdr *iph = ipv6_hdr(skb); |
131 | struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data; | 134 | struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data; |
132 | 135 | ||
133 | if (!ipv6_addr_equal(&iph->saddr, (struct in6_addr *)x->coaddr) && | 136 | if (!ipv6_addr_equal(&iph->saddr, (struct in6_addr *)x->coaddr) && |
@@ -152,10 +155,10 @@ static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb) | |||
152 | iph = (struct ipv6hdr *)skb->data; | 155 | iph = (struct ipv6hdr *)skb->data; |
153 | iph->payload_len = htons(skb->len - sizeof(*iph)); | 156 | iph->payload_len = htons(skb->len - sizeof(*iph)); |
154 | 157 | ||
155 | nexthdr = *skb->nh.raw; | 158 | nexthdr = *skb_network_header(skb); |
156 | *skb->nh.raw = IPPROTO_DSTOPTS; | 159 | *skb_network_header(skb) = IPPROTO_DSTOPTS; |
157 | 160 | ||
158 | dstopt = (struct ipv6_destopt_hdr *)skb->h.raw; | 161 | dstopt = (struct ipv6_destopt_hdr *)skb_transport_header(skb); |
159 | dstopt->nexthdr = nexthdr; | 162 | dstopt->nexthdr = nexthdr; |
160 | 163 | ||
161 | hao = mip6_padn((char *)(dstopt + 1), | 164 | hao = mip6_padn((char *)(dstopt + 1), |
@@ -215,21 +218,22 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct | |||
215 | if (likely(opt->dsthao)) { | 218 | if (likely(opt->dsthao)) { |
216 | offset = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); | 219 | offset = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); |
217 | if (likely(offset >= 0)) | 220 | if (likely(offset >= 0)) |
218 | hao = (struct ipv6_destopt_hao *)(skb->nh.raw + offset); | 221 | hao = (struct ipv6_destopt_hao *) |
222 | (skb_network_header(skb) + offset); | ||
219 | } | 223 | } |
220 | 224 | ||
221 | skb_get_timestamp(skb, &stamp); | 225 | skb_get_timestamp(skb, &stamp); |
222 | 226 | ||
223 | if (!mip6_report_rl_allow(&stamp, &skb->nh.ipv6h->daddr, | 227 | if (!mip6_report_rl_allow(&stamp, &ipv6_hdr(skb)->daddr, |
224 | hao ? &hao->addr : &skb->nh.ipv6h->saddr, | 228 | hao ? &hao->addr : &ipv6_hdr(skb)->saddr, |
225 | opt->iif)) | 229 | opt->iif)) |
226 | goto out; | 230 | goto out; |
227 | 231 | ||
228 | memset(&sel, 0, sizeof(sel)); | 232 | memset(&sel, 0, sizeof(sel)); |
229 | memcpy(&sel.daddr, (xfrm_address_t *)&skb->nh.ipv6h->daddr, | 233 | memcpy(&sel.daddr, (xfrm_address_t *)&ipv6_hdr(skb)->daddr, |
230 | sizeof(sel.daddr)); | 234 | sizeof(sel.daddr)); |
231 | sel.prefixlen_d = 128; | 235 | sel.prefixlen_d = 128; |
232 | memcpy(&sel.saddr, (xfrm_address_t *)&skb->nh.ipv6h->saddr, | 236 | memcpy(&sel.saddr, (xfrm_address_t *)&ipv6_hdr(skb)->saddr, |
233 | sizeof(sel.saddr)); | 237 | sizeof(sel.saddr)); |
234 | sel.prefixlen_s = 128; | 238 | sel.prefixlen_s = 128; |
235 | sel.family = AF_INET6; | 239 | sel.family = AF_INET6; |
@@ -253,11 +257,13 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
253 | u8 **nexthdr) | 257 | u8 **nexthdr) |
254 | { | 258 | { |
255 | u16 offset = sizeof(struct ipv6hdr); | 259 | u16 offset = sizeof(struct ipv6hdr); |
256 | struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1); | 260 | struct ipv6_opt_hdr *exthdr = |
257 | unsigned int packet_len = skb->tail - skb->nh.raw; | 261 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); |
262 | const unsigned char *nh = skb_network_header(skb); | ||
263 | unsigned int packet_len = skb->tail - skb->network_header; | ||
258 | int found_rhdr = 0; | 264 | int found_rhdr = 0; |
259 | 265 | ||
260 | *nexthdr = &skb->nh.ipv6h->nexthdr; | 266 | *nexthdr = &ipv6_hdr(skb)->nexthdr; |
261 | 267 | ||
262 | while (offset + 1 <= packet_len) { | 268 | while (offset + 1 <= packet_len) { |
263 | 269 | ||
@@ -288,7 +294,7 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
288 | 294 | ||
289 | offset += ipv6_optlen(exthdr); | 295 | offset += ipv6_optlen(exthdr); |
290 | *nexthdr = &exthdr->nexthdr; | 296 | *nexthdr = &exthdr->nexthdr; |
291 | exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 297 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); |
292 | } | 298 | } |
293 | 299 | ||
294 | return offset; | 300 | return offset; |
@@ -361,10 +367,10 @@ static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb) | |||
361 | iph = (struct ipv6hdr *)skb->data; | 367 | iph = (struct ipv6hdr *)skb->data; |
362 | iph->payload_len = htons(skb->len - sizeof(*iph)); | 368 | iph->payload_len = htons(skb->len - sizeof(*iph)); |
363 | 369 | ||
364 | nexthdr = *skb->nh.raw; | 370 | nexthdr = *skb_network_header(skb); |
365 | *skb->nh.raw = IPPROTO_ROUTING; | 371 | *skb_network_header(skb) = IPPROTO_ROUTING; |
366 | 372 | ||
367 | rt2 = (struct rt2_hdr *)skb->h.raw; | 373 | rt2 = (struct rt2_hdr *)skb_transport_header(skb); |
368 | rt2->rt_hdr.nexthdr = nexthdr; | 374 | rt2->rt_hdr.nexthdr = nexthdr; |
369 | rt2->rt_hdr.hdrlen = (x->props.header_len >> 3) - 1; | 375 | rt2->rt_hdr.hdrlen = (x->props.header_len >> 3) - 1; |
370 | rt2->rt_hdr.type = IPV6_SRCRT_TYPE_2; | 376 | rt2->rt_hdr.type = IPV6_SRCRT_TYPE_2; |
@@ -383,11 +389,13 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
383 | u8 **nexthdr) | 389 | u8 **nexthdr) |
384 | { | 390 | { |
385 | u16 offset = sizeof(struct ipv6hdr); | 391 | u16 offset = sizeof(struct ipv6hdr); |
386 | struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1); | 392 | struct ipv6_opt_hdr *exthdr = |
387 | unsigned int packet_len = skb->tail - skb->nh.raw; | 393 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); |
394 | const unsigned char *nh = skb_network_header(skb); | ||
395 | unsigned int packet_len = skb->tail - skb->network_header; | ||
388 | int found_rhdr = 0; | 396 | int found_rhdr = 0; |
389 | 397 | ||
390 | *nexthdr = &skb->nh.ipv6h->nexthdr; | 398 | *nexthdr = &ipv6_hdr(skb)->nexthdr; |
391 | 399 | ||
392 | while (offset + 1 <= packet_len) { | 400 | while (offset + 1 <= packet_len) { |
393 | 401 | ||
@@ -397,7 +405,7 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
397 | case NEXTHDR_ROUTING: | 405 | case NEXTHDR_ROUTING: |
398 | if (offset + 3 <= packet_len) { | 406 | if (offset + 3 <= packet_len) { |
399 | struct ipv6_rt_hdr *rt; | 407 | struct ipv6_rt_hdr *rt; |
400 | rt = (struct ipv6_rt_hdr *)(skb->nh.raw + offset); | 408 | rt = (struct ipv6_rt_hdr *)(nh + offset); |
401 | if (rt->type != 0) | 409 | if (rt->type != 0) |
402 | return offset; | 410 | return offset; |
403 | } | 411 | } |
@@ -417,7 +425,7 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
417 | 425 | ||
418 | offset += ipv6_optlen(exthdr); | 426 | offset += ipv6_optlen(exthdr); |
419 | *nexthdr = &exthdr->nexthdr; | 427 | *nexthdr = &exthdr->nexthdr; |
420 | exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 428 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); |
421 | } | 429 | } |
422 | 430 | ||
423 | return offset; | 431 | return offset; |