aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/icmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/icmp.c')
-rw-r--r--net/ipv6/icmp.c226
1 files changed, 121 insertions, 105 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 03e62f94ff8..83cb4f9add8 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -157,32 +157,32 @@ static int is_ineligible(struct sk_buff *skb)
157/* 157/*
158 * Check the ICMP output rate limit 158 * Check the ICMP output rate limit
159 */ 159 */
160static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type, 160static inline bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
161 struct flowi *fl) 161 struct flowi6 *fl6)
162{ 162{
163 struct dst_entry *dst; 163 struct dst_entry *dst;
164 struct net *net = sock_net(sk); 164 struct net *net = sock_net(sk);
165 int res = 0; 165 bool res = false;
166 166
167 /* Informational messages are not limited. */ 167 /* Informational messages are not limited. */
168 if (type & ICMPV6_INFOMSG_MASK) 168 if (type & ICMPV6_INFOMSG_MASK)
169 return 1; 169 return true;
170 170
171 /* Do not limit pmtu discovery, it would break it. */ 171 /* Do not limit pmtu discovery, it would break it. */
172 if (type == ICMPV6_PKT_TOOBIG) 172 if (type == ICMPV6_PKT_TOOBIG)
173 return 1; 173 return true;
174 174
175 /* 175 /*
176 * Look up the output route. 176 * Look up the output route.
177 * XXX: perhaps the expire for routing entries cloned by 177 * XXX: perhaps the expire for routing entries cloned by
178 * this lookup should be more aggressive (not longer than timeout). 178 * this lookup should be more aggressive (not longer than timeout).
179 */ 179 */
180 dst = ip6_route_output(net, sk, fl); 180 dst = ip6_route_output(net, sk, fl6);
181 if (dst->error) { 181 if (dst->error) {
182 IP6_INC_STATS(net, ip6_dst_idev(dst), 182 IP6_INC_STATS(net, ip6_dst_idev(dst),
183 IPSTATS_MIB_OUTNOROUTES); 183 IPSTATS_MIB_OUTNOROUTES);
184 } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { 184 } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
185 res = 1; 185 res = true;
186 } else { 186 } else {
187 struct rt6_info *rt = (struct rt6_info *)dst; 187 struct rt6_info *rt = (struct rt6_info *)dst;
188 int tmo = net->ipv6.sysctl.icmpv6_time; 188 int tmo = net->ipv6.sysctl.icmpv6_time;
@@ -191,7 +191,9 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type,
191 if (rt->rt6i_dst.plen < 128) 191 if (rt->rt6i_dst.plen < 128)
192 tmo >>= ((128 - rt->rt6i_dst.plen)>>5); 192 tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
193 193
194 res = xrlim_allow(dst, tmo); 194 if (!rt->rt6i_peer)
195 rt6_bind_peer(rt, 1);
196 res = inet_peer_xrlim_allow(rt->rt6i_peer, tmo);
195 } 197 }
196 dst_release(dst); 198 dst_release(dst);
197 return res; 199 return res;
@@ -215,7 +217,7 @@ static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
215 return (*op & 0xC0) == 0x80; 217 return (*op & 0xC0) == 0x80;
216} 218}
217 219
218static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len) 220static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len)
219{ 221{
220 struct sk_buff *skb; 222 struct sk_buff *skb;
221 struct icmp6hdr *icmp6h; 223 struct icmp6hdr *icmp6h;
@@ -231,9 +233,9 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct
231 if (skb_queue_len(&sk->sk_write_queue) == 1) { 233 if (skb_queue_len(&sk->sk_write_queue) == 1) {
232 skb->csum = csum_partial(icmp6h, 234 skb->csum = csum_partial(icmp6h,
233 sizeof(struct icmp6hdr), skb->csum); 235 sizeof(struct icmp6hdr), skb->csum);
234 icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src, 236 icmp6h->icmp6_cksum = csum_ipv6_magic(&fl6->saddr,
235 &fl->fl6_dst, 237 &fl6->daddr,
236 len, fl->proto, 238 len, fl6->flowi6_proto,
237 skb->csum); 239 skb->csum);
238 } else { 240 } else {
239 __wsum tmp_csum = 0; 241 __wsum tmp_csum = 0;
@@ -244,9 +246,9 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct
244 246
245 tmp_csum = csum_partial(icmp6h, 247 tmp_csum = csum_partial(icmp6h,
246 sizeof(struct icmp6hdr), tmp_csum); 248 sizeof(struct icmp6hdr), tmp_csum);
247 icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src, 249 icmp6h->icmp6_cksum = csum_ipv6_magic(&fl6->saddr,
248 &fl->fl6_dst, 250 &fl6->daddr,
249 len, fl->proto, 251 len, fl6->flowi6_proto,
250 tmp_csum); 252 tmp_csum);
251 } 253 }
252 ip6_push_pending_frames(sk); 254 ip6_push_pending_frames(sk);
@@ -298,6 +300,68 @@ static void mip6_addr_swap(struct sk_buff *skb)
298static inline void mip6_addr_swap(struct sk_buff *skb) {} 300static inline void mip6_addr_swap(struct sk_buff *skb) {}
299#endif 301#endif
300 302
303static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
304 struct sock *sk, struct flowi6 *fl6)
305{
306 struct dst_entry *dst, *dst2;
307 struct flowi6 fl2;
308 int err;
309
310 err = ip6_dst_lookup(sk, &dst, fl6);
311 if (err)
312 return ERR_PTR(err);
313
314 /*
315 * We won't send icmp if the destination is known
316 * anycast.
317 */
318 if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) {
319 LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n");
320 dst_release(dst);
321 return ERR_PTR(-EINVAL);
322 }
323
324 /* No need to clone since we're just using its address. */
325 dst2 = dst;
326
327 dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), sk, 0);
328 if (!IS_ERR(dst)) {
329 if (dst != dst2)
330 return dst;
331 } else {
332 if (PTR_ERR(dst) == -EPERM)
333 dst = NULL;
334 else
335 return dst;
336 }
337
338 err = xfrm_decode_session_reverse(skb, flowi6_to_flowi(&fl2), AF_INET6);
339 if (err)
340 goto relookup_failed;
341
342 err = ip6_dst_lookup(sk, &dst2, &fl2);
343 if (err)
344 goto relookup_failed;
345
346 dst2 = xfrm_lookup(net, dst2, flowi6_to_flowi(&fl2), sk, XFRM_LOOKUP_ICMP);
347 if (!IS_ERR(dst2)) {
348 dst_release(dst);
349 dst = dst2;
350 } else {
351 err = PTR_ERR(dst2);
352 if (err == -EPERM) {
353 dst_release(dst);
354 return dst2;
355 } else
356 goto relookup_failed;
357 }
358
359relookup_failed:
360 if (dst)
361 return dst;
362 return ERR_PTR(err);
363}
364
301/* 365/*
302 * Send an ICMP message in response to a packet in error 366 * Send an ICMP message in response to a packet in error
303 */ 367 */
@@ -310,10 +374,8 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
310 struct ipv6_pinfo *np; 374 struct ipv6_pinfo *np;
311 struct in6_addr *saddr = NULL; 375 struct in6_addr *saddr = NULL;
312 struct dst_entry *dst; 376 struct dst_entry *dst;
313 struct dst_entry *dst2;
314 struct icmp6hdr tmp_hdr; 377 struct icmp6hdr tmp_hdr;
315 struct flowi fl; 378 struct flowi6 fl6;
316 struct flowi fl2;
317 struct icmpv6_msg msg; 379 struct icmpv6_msg msg;
318 int iif = 0; 380 int iif = 0;
319 int addr_type = 0; 381 int addr_type = 0;
@@ -380,22 +442,22 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
380 442
381 mip6_addr_swap(skb); 443 mip6_addr_swap(skb);
382 444
383 memset(&fl, 0, sizeof(fl)); 445 memset(&fl6, 0, sizeof(fl6));
384 fl.proto = IPPROTO_ICMPV6; 446 fl6.flowi6_proto = IPPROTO_ICMPV6;
385 ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr); 447 ipv6_addr_copy(&fl6.daddr, &hdr->saddr);
386 if (saddr) 448 if (saddr)
387 ipv6_addr_copy(&fl.fl6_src, saddr); 449 ipv6_addr_copy(&fl6.saddr, saddr);
388 fl.oif = iif; 450 fl6.flowi6_oif = iif;
389 fl.fl_icmp_type = type; 451 fl6.fl6_icmp_type = type;
390 fl.fl_icmp_code = code; 452 fl6.fl6_icmp_code = code;
391 security_skb_classify_flow(skb, &fl); 453 security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
392 454
393 sk = icmpv6_xmit_lock(net); 455 sk = icmpv6_xmit_lock(net);
394 if (sk == NULL) 456 if (sk == NULL)
395 return; 457 return;
396 np = inet6_sk(sk); 458 np = inet6_sk(sk);
397 459
398 if (!icmpv6_xrlim_allow(sk, type, &fl)) 460 if (!icmpv6_xrlim_allow(sk, type, &fl6))
399 goto out; 461 goto out;
400 462
401 tmp_hdr.icmp6_type = type; 463 tmp_hdr.icmp6_type = type;
@@ -403,61 +465,14 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
403 tmp_hdr.icmp6_cksum = 0; 465 tmp_hdr.icmp6_cksum = 0;
404 tmp_hdr.icmp6_pointer = htonl(info); 466 tmp_hdr.icmp6_pointer = htonl(info);
405 467
406 if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) 468 if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
407 fl.oif = np->mcast_oif; 469 fl6.flowi6_oif = np->mcast_oif;
408 470
409 err = ip6_dst_lookup(sk, &dst, &fl); 471 dst = icmpv6_route_lookup(net, skb, sk, &fl6);
410 if (err) 472 if (IS_ERR(dst))
411 goto out; 473 goto out;
412 474
413 /* 475 if (ipv6_addr_is_multicast(&fl6.daddr))
414 * We won't send icmp if the destination is known
415 * anycast.
416 */
417 if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) {
418 LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n");
419 goto out_dst_release;
420 }
421
422 /* No need to clone since we're just using its address. */
423 dst2 = dst;
424
425 err = xfrm_lookup(net, &dst, &fl, sk, 0);
426 switch (err) {
427 case 0:
428 if (dst != dst2)
429 goto route_done;
430 break;
431 case -EPERM:
432 dst = NULL;
433 break;
434 default:
435 goto out;
436 }
437
438 if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6))
439 goto relookup_failed;
440
441 if (ip6_dst_lookup(sk, &dst2, &fl2))
442 goto relookup_failed;
443
444 err = xfrm_lookup(net, &dst2, &fl2, sk, XFRM_LOOKUP_ICMP);
445 switch (err) {
446 case 0:
447 dst_release(dst);
448 dst = dst2;
449 break;
450 case -EPERM:
451 goto out_dst_release;
452 default:
453relookup_failed:
454 if (!dst)
455 goto out;
456 break;
457 }
458
459route_done:
460 if (ipv6_addr_is_multicast(&fl.fl6_dst))
461 hlimit = np->mcast_hops; 476 hlimit = np->mcast_hops;
462 else 477 else
463 hlimit = np->hop_limit; 478 hlimit = np->hop_limit;
@@ -480,14 +495,14 @@ route_done:
480 err = ip6_append_data(sk, icmpv6_getfrag, &msg, 495 err = ip6_append_data(sk, icmpv6_getfrag, &msg,
481 len + sizeof(struct icmp6hdr), 496 len + sizeof(struct icmp6hdr),
482 sizeof(struct icmp6hdr), hlimit, 497 sizeof(struct icmp6hdr), hlimit,
483 np->tclass, NULL, &fl, (struct rt6_info*)dst, 498 np->tclass, NULL, &fl6, (struct rt6_info*)dst,
484 MSG_DONTWAIT, np->dontfrag); 499 MSG_DONTWAIT, np->dontfrag);
485 if (err) { 500 if (err) {
486 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); 501 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
487 ip6_flush_pending_frames(sk); 502 ip6_flush_pending_frames(sk);
488 goto out_put; 503 goto out_put;
489 } 504 }
490 err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr)); 505 err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, len + sizeof(struct icmp6hdr));
491 506
492out_put: 507out_put:
493 if (likely(idev != NULL)) 508 if (likely(idev != NULL))
@@ -509,7 +524,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
509 struct in6_addr *saddr = NULL; 524 struct in6_addr *saddr = NULL;
510 struct icmp6hdr *icmph = icmp6_hdr(skb); 525 struct icmp6hdr *icmph = icmp6_hdr(skb);
511 struct icmp6hdr tmp_hdr; 526 struct icmp6hdr tmp_hdr;
512 struct flowi fl; 527 struct flowi6 fl6;
513 struct icmpv6_msg msg; 528 struct icmpv6_msg msg;
514 struct dst_entry *dst; 529 struct dst_entry *dst;
515 int err = 0; 530 int err = 0;
@@ -523,30 +538,31 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
523 memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr)); 538 memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
524 tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY; 539 tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY;
525 540
526 memset(&fl, 0, sizeof(fl)); 541 memset(&fl6, 0, sizeof(fl6));
527 fl.proto = IPPROTO_ICMPV6; 542 fl6.flowi6_proto = IPPROTO_ICMPV6;
528 ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); 543 ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->saddr);
529 if (saddr) 544 if (saddr)
530 ipv6_addr_copy(&fl.fl6_src, saddr); 545 ipv6_addr_copy(&fl6.saddr, saddr);
531 fl.oif = skb->dev->ifindex; 546 fl6.flowi6_oif = skb->dev->ifindex;
532 fl.fl_icmp_type = ICMPV6_ECHO_REPLY; 547 fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
533 security_skb_classify_flow(skb, &fl); 548 security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
534 549
535 sk = icmpv6_xmit_lock(net); 550 sk = icmpv6_xmit_lock(net);
536 if (sk == NULL) 551 if (sk == NULL)
537 return; 552 return;
538 np = inet6_sk(sk); 553 np = inet6_sk(sk);
539 554
540 if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) 555 if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
541 fl.oif = np->mcast_oif; 556 fl6.flowi6_oif = np->mcast_oif;
542 557
543 err = ip6_dst_lookup(sk, &dst, &fl); 558 err = ip6_dst_lookup(sk, &dst, &fl6);
544 if (err) 559 if (err)
545 goto out; 560 goto out;
546 if ((err = xfrm_lookup(net, &dst, &fl, sk, 0)) < 0) 561 dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), sk, 0);
562 if (IS_ERR(dst))
547 goto out; 563 goto out;
548 564
549 if (ipv6_addr_is_multicast(&fl.fl6_dst)) 565 if (ipv6_addr_is_multicast(&fl6.daddr))
550 hlimit = np->mcast_hops; 566 hlimit = np->mcast_hops;
551 else 567 else
552 hlimit = np->hop_limit; 568 hlimit = np->hop_limit;
@@ -560,7 +576,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
560 msg.type = ICMPV6_ECHO_REPLY; 576 msg.type = ICMPV6_ECHO_REPLY;
561 577
562 err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), 578 err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
563 sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl, 579 sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl6,
564 (struct rt6_info*)dst, MSG_DONTWAIT, 580 (struct rt6_info*)dst, MSG_DONTWAIT,
565 np->dontfrag); 581 np->dontfrag);
566 582
@@ -569,7 +585,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
569 ip6_flush_pending_frames(sk); 585 ip6_flush_pending_frames(sk);
570 goto out_put; 586 goto out_put;
571 } 587 }
572 err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr)); 588 err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, skb->len + sizeof(struct icmp6hdr));
573 589
574out_put: 590out_put:
575 if (likely(idev != NULL)) 591 if (likely(idev != NULL))
@@ -768,20 +784,20 @@ drop_no_count:
768 return 0; 784 return 0;
769} 785}
770 786
771void icmpv6_flow_init(struct sock *sk, struct flowi *fl, 787void icmpv6_flow_init(struct sock *sk, struct flowi6 *fl6,
772 u8 type, 788 u8 type,
773 const struct in6_addr *saddr, 789 const struct in6_addr *saddr,
774 const struct in6_addr *daddr, 790 const struct in6_addr *daddr,
775 int oif) 791 int oif)
776{ 792{
777 memset(fl, 0, sizeof(*fl)); 793 memset(fl6, 0, sizeof(*fl6));
778 ipv6_addr_copy(&fl->fl6_src, saddr); 794 ipv6_addr_copy(&fl6->saddr, saddr);
779 ipv6_addr_copy(&fl->fl6_dst, daddr); 795 ipv6_addr_copy(&fl6->daddr, daddr);
780 fl->proto = IPPROTO_ICMPV6; 796 fl6->flowi6_proto = IPPROTO_ICMPV6;
781 fl->fl_icmp_type = type; 797 fl6->fl6_icmp_type = type;
782 fl->fl_icmp_code = 0; 798 fl6->fl6_icmp_code = 0;
783 fl->oif = oif; 799 fl6->flowi6_oif = oif;
784 security_sk_classify_flow(sk, fl); 800 security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
785} 801}
786 802
787/* 803/*