diff options
Diffstat (limited to 'net/ipv6/icmp.c')
-rw-r--r-- | net/ipv6/icmp.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index fa8f1bb0aa52..23e540365a14 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -287,7 +287,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
287 | int iif = 0; | 287 | int iif = 0; |
288 | int addr_type = 0; | 288 | int addr_type = 0; |
289 | int len; | 289 | int len; |
290 | int hlimit; | 290 | int hlimit, tclass; |
291 | int err = 0; | 291 | int err = 0; |
292 | 292 | ||
293 | if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail) | 293 | if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail) |
@@ -374,7 +374,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
374 | if (err) | 374 | if (err) |
375 | goto out; | 375 | goto out; |
376 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) | 376 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) |
377 | goto out_dst_release; | 377 | goto out; |
378 | 378 | ||
379 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 379 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
380 | hlimit = np->mcast_hops; | 380 | hlimit = np->mcast_hops; |
@@ -385,6 +385,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
385 | if (hlimit < 0) | 385 | if (hlimit < 0) |
386 | hlimit = ipv6_get_hoplimit(dst->dev); | 386 | hlimit = ipv6_get_hoplimit(dst->dev); |
387 | 387 | ||
388 | tclass = np->cork.tclass; | ||
389 | if (tclass < 0) | ||
390 | tclass = 0; | ||
391 | |||
388 | msg.skb = skb; | 392 | msg.skb = skb; |
389 | msg.offset = skb->nh.raw - skb->data; | 393 | msg.offset = skb->nh.raw - skb->data; |
390 | 394 | ||
@@ -400,7 +404,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
400 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, | 404 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, |
401 | len + sizeof(struct icmp6hdr), | 405 | len + sizeof(struct icmp6hdr), |
402 | sizeof(struct icmp6hdr), | 406 | sizeof(struct icmp6hdr), |
403 | hlimit, NULL, &fl, (struct rt6_info*)dst, | 407 | hlimit, tclass, NULL, &fl, (struct rt6_info*)dst, |
404 | MSG_DONTWAIT); | 408 | MSG_DONTWAIT); |
405 | if (err) { | 409 | if (err) { |
406 | ip6_flush_pending_frames(sk); | 410 | ip6_flush_pending_frames(sk); |
@@ -434,6 +438,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
434 | struct dst_entry *dst; | 438 | struct dst_entry *dst; |
435 | int err = 0; | 439 | int err = 0; |
436 | int hlimit; | 440 | int hlimit; |
441 | int tclass; | ||
437 | 442 | ||
438 | saddr = &skb->nh.ipv6h->daddr; | 443 | saddr = &skb->nh.ipv6h->daddr; |
439 | 444 | ||
@@ -464,7 +469,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
464 | if (err) | 469 | if (err) |
465 | goto out; | 470 | goto out; |
466 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) | 471 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) |
467 | goto out_dst_release; | 472 | goto out; |
468 | 473 | ||
469 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 474 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
470 | hlimit = np->mcast_hops; | 475 | hlimit = np->mcast_hops; |
@@ -475,13 +480,17 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
475 | if (hlimit < 0) | 480 | if (hlimit < 0) |
476 | hlimit = ipv6_get_hoplimit(dst->dev); | 481 | hlimit = ipv6_get_hoplimit(dst->dev); |
477 | 482 | ||
483 | tclass = np->cork.tclass; | ||
484 | if (tclass < 0) | ||
485 | tclass = 0; | ||
486 | |||
478 | idev = in6_dev_get(skb->dev); | 487 | idev = in6_dev_get(skb->dev); |
479 | 488 | ||
480 | msg.skb = skb; | 489 | msg.skb = skb; |
481 | msg.offset = 0; | 490 | msg.offset = 0; |
482 | 491 | ||
483 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), | 492 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), |
484 | sizeof(struct icmp6hdr), hlimit, NULL, &fl, | 493 | sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl, |
485 | (struct rt6_info*)dst, MSG_DONTWAIT); | 494 | (struct rt6_info*)dst, MSG_DONTWAIT); |
486 | 495 | ||
487 | if (err) { | 496 | if (err) { |
@@ -496,7 +505,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
496 | out_put: | 505 | out_put: |
497 | if (likely(idev != NULL)) | 506 | if (likely(idev != NULL)) |
498 | in6_dev_put(idev); | 507 | in6_dev_put(idev); |
499 | out_dst_release: | ||
500 | dst_release(dst); | 508 | dst_release(dst); |
501 | out: | 509 | out: |
502 | icmpv6_xmit_unlock(); | 510 | icmpv6_xmit_unlock(); |
@@ -692,10 +700,7 @@ int __init icmpv6_init(struct net_proto_family *ops) | |||
692 | struct sock *sk; | 700 | struct sock *sk; |
693 | int err, i, j; | 701 | int err, i, j; |
694 | 702 | ||
695 | for (i = 0; i < NR_CPUS; i++) { | 703 | for_each_cpu(i) { |
696 | if (!cpu_possible(i)) | ||
697 | continue; | ||
698 | |||
699 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, | 704 | err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, |
700 | &per_cpu(__icmpv6_socket, i)); | 705 | &per_cpu(__icmpv6_socket, i)); |
701 | if (err < 0) { | 706 | if (err < 0) { |
@@ -741,9 +746,7 @@ void icmpv6_cleanup(void) | |||
741 | { | 746 | { |
742 | int i; | 747 | int i; |
743 | 748 | ||
744 | for (i = 0; i < NR_CPUS; i++) { | 749 | for_each_cpu(i) { |
745 | if (!cpu_possible(i)) | ||
746 | continue; | ||
747 | sock_release(per_cpu(__icmpv6_socket, i)); | 750 | sock_release(per_cpu(__icmpv6_socket, i)); |
748 | } | 751 | } |
749 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); | 752 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); |