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.c41
1 files changed, 13 insertions, 28 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 7b326529e6a2..f6c84a6eb238 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -400,6 +400,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
400 int len; 400 int len;
401 int hlimit; 401 int hlimit;
402 int err = 0; 402 int err = 0;
403 u32 mark = IP6_REPLY_MARK(net, skb->mark);
403 404
404 if ((u8 *)hdr < skb->head || 405 if ((u8 *)hdr < skb->head ||
405 (skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb)) 406 (skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb))
@@ -466,6 +467,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
466 fl6.daddr = hdr->saddr; 467 fl6.daddr = hdr->saddr;
467 if (saddr) 468 if (saddr)
468 fl6.saddr = *saddr; 469 fl6.saddr = *saddr;
470 fl6.flowi6_mark = mark;
469 fl6.flowi6_oif = iif; 471 fl6.flowi6_oif = iif;
470 fl6.fl6_icmp_type = type; 472 fl6.fl6_icmp_type = type;
471 fl6.fl6_icmp_code = code; 473 fl6.fl6_icmp_code = code;
@@ -474,6 +476,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
474 sk = icmpv6_xmit_lock(net); 476 sk = icmpv6_xmit_lock(net);
475 if (sk == NULL) 477 if (sk == NULL)
476 return; 478 return;
479 sk->sk_mark = mark;
477 np = inet6_sk(sk); 480 np = inet6_sk(sk);
478 481
479 if (!icmpv6_xrlim_allow(sk, type, &fl6)) 482 if (!icmpv6_xrlim_allow(sk, type, &fl6))
@@ -493,12 +496,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
493 if (IS_ERR(dst)) 496 if (IS_ERR(dst))
494 goto out; 497 goto out;
495 498
496 if (ipv6_addr_is_multicast(&fl6.daddr)) 499 hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
497 hlimit = np->mcast_hops;
498 else
499 hlimit = np->hop_limit;
500 if (hlimit < 0)
501 hlimit = ip6_dst_hoplimit(dst);
502 500
503 msg.skb = skb; 501 msg.skb = skb;
504 msg.offset = skb_network_offset(skb); 502 msg.offset = skb_network_offset(skb);
@@ -556,6 +554,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
556 int err = 0; 554 int err = 0;
557 int hlimit; 555 int hlimit;
558 u8 tclass; 556 u8 tclass;
557 u32 mark = IP6_REPLY_MARK(net, skb->mark);
559 558
560 saddr = &ipv6_hdr(skb)->daddr; 559 saddr = &ipv6_hdr(skb)->daddr;
561 560
@@ -574,11 +573,13 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
574 fl6.saddr = *saddr; 573 fl6.saddr = *saddr;
575 fl6.flowi6_oif = skb->dev->ifindex; 574 fl6.flowi6_oif = skb->dev->ifindex;
576 fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY; 575 fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
576 fl6.flowi6_mark = mark;
577 security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); 577 security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
578 578
579 sk = icmpv6_xmit_lock(net); 579 sk = icmpv6_xmit_lock(net);
580 if (sk == NULL) 580 if (sk == NULL)
581 return; 581 return;
582 sk->sk_mark = mark;
582 np = inet6_sk(sk); 583 np = inet6_sk(sk);
583 584
584 if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) 585 if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
@@ -593,12 +594,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
593 if (IS_ERR(dst)) 594 if (IS_ERR(dst))
594 goto out; 595 goto out;
595 596
596 if (ipv6_addr_is_multicast(&fl6.daddr)) 597 hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
597 hlimit = np->mcast_hops;
598 else
599 hlimit = np->hop_limit;
600 if (hlimit < 0)
601 hlimit = ip6_dst_hoplimit(dst);
602 598
603 idev = __in6_dev_get(skb->dev); 599 idev = __in6_dev_get(skb->dev);
604 600
@@ -702,22 +698,11 @@ static int icmpv6_rcv(struct sk_buff *skb)
702 saddr = &ipv6_hdr(skb)->saddr; 698 saddr = &ipv6_hdr(skb)->saddr;
703 daddr = &ipv6_hdr(skb)->daddr; 699 daddr = &ipv6_hdr(skb)->daddr;
704 700
705 /* Perform checksum. */ 701 if (skb_checksum_validate(skb, IPPROTO_ICMPV6, ip6_compute_pseudo)) {
706 switch (skb->ip_summed) { 702 LIMIT_NETDEBUG(KERN_DEBUG
707 case CHECKSUM_COMPLETE: 703 "ICMPv6 checksum failed [%pI6c > %pI6c]\n",
708 if (!csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, 704 saddr, daddr);
709 skb->csum)) 705 goto csum_error;
710 break;
711 /* fall through */
712 case CHECKSUM_NONE:
713 skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len,
714 IPPROTO_ICMPV6, 0));
715 if (__skb_checksum_complete(skb)) {
716 LIMIT_NETDEBUG(KERN_DEBUG
717 "ICMPv6 checksum failed [%pI6c > %pI6c]\n",
718 saddr, daddr);
719 goto csum_error;
720 }
721 } 706 }
722 707
723 if (!pskb_pull(skb, sizeof(*hdr))) 708 if (!pskb_pull(skb, sizeof(*hdr)))