aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/mip6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/mip6.c')
-rw-r--r--net/ipv6/mip6.c62
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
124static struct mip6_report_rate_limiter mip6_report_rl = { 127static 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
128static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb) 131static 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;