These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / ipv6 / icmp.c
index 2c2b5d5..0a37ddc 100644 (file)
@@ -68,6 +68,7 @@
 #include <net/xfrm.h>
 #include <net/inet_common.h>
 #include <net/dsfield.h>
+#include <net/l3mdev.h>
 
 #include <asm/uaccess.h>
 
@@ -207,7 +208,7 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
                        struct inet_peer *peer;
 
                        peer = inet_getpeer_v6(net->ipv6.peers,
-                                              &rt->rt6i_dst.addr, 1);
+                                              &fl6->daddr, 1);
                        res = inet_peer_xrlim_allow(peer, tmo);
                        if (peer)
                                inet_putpeer(peer);
@@ -329,7 +330,7 @@ static struct dst_entry *icmpv6_route_lookup(struct net *net,
        struct flowi6 fl2;
        int err;
 
-       err = ip6_dst_lookup(sk, &dst, fl6);
+       err = ip6_dst_lookup(net, sk, &dst, fl6);
        if (err)
                return ERR_PTR(err);
 
@@ -337,7 +338,7 @@ static struct dst_entry *icmpv6_route_lookup(struct net *net,
         * We won't send icmp if the destination is known
         * anycast.
         */
-       if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) {
+       if (ipv6_anycast_destination(dst, &fl6->daddr)) {
                net_dbg_ratelimited("icmp6_send: acast source\n");
                dst_release(dst);
                return ERR_PTR(-EINVAL);
@@ -361,7 +362,7 @@ static struct dst_entry *icmpv6_route_lookup(struct net *net,
        if (err)
                goto relookup_failed;
 
-       err = ip6_dst_lookup(sk, &dst2, &fl2);
+       err = ip6_dst_lookup(net, sk, &dst2, &fl2);
        if (err)
                goto relookup_failed;
 
@@ -452,7 +453,8 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
         *      and anycast addresses will be checked later.
         */
        if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
-               net_dbg_ratelimited("icmp6_send: addr_any/mcast source\n");
+               net_dbg_ratelimited("icmp6_send: addr_any/mcast source [%pI6c > %pI6c]\n",
+                                   &hdr->saddr, &hdr->daddr);
                return;
        }
 
@@ -460,7 +462,8 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
         *      Never answer to a ICMP packet.
         */
        if (is_ineligible(skb)) {
-               net_dbg_ratelimited("icmp6_send: no reply to icmp error\n");
+               net_dbg_ratelimited("icmp6_send: no reply to icmp error [%pI6c > %pI6c]\n",
+                                   &hdr->saddr, &hdr->daddr);
                return;
        }
 
@@ -496,6 +499,9 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
        else if (!fl6.flowi6_oif)
                fl6.flowi6_oif = np->ucast_oif;
 
+       if (!fl6.flowi6_oif)
+               fl6.flowi6_oif = l3mdev_master_ifindex(skb->dev);
+
        dst = icmpv6_route_lookup(net, skb, sk, &fl6);
        if (IS_ERR(dst))
                goto out;
@@ -509,7 +515,8 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
        len = skb->len - msg.offset;
        len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr));
        if (len < 0) {
-               net_dbg_ratelimited("icmp: len problem\n");
+               net_dbg_ratelimited("icmp: len problem [%pI6c > %pI6c]\n",
+                                   &hdr->saddr, &hdr->daddr);
                goto out_dst_release;
        }
 
@@ -564,7 +571,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 
        if (!ipv6_unicast_destination(skb) &&
            !(net->ipv6.sysctl.anycast_src_echo_reply &&
-             ipv6_anycast_destination(skb)))
+             ipv6_anycast_destination(skb_dst(skb), saddr)))
                saddr = NULL;
 
        memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
@@ -575,7 +582,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        fl6.daddr = ipv6_hdr(skb)->saddr;
        if (saddr)
                fl6.saddr = *saddr;
-       fl6.flowi6_oif = skb->dev->ifindex;
+       fl6.flowi6_oif = l3mdev_fib_oif(skb->dev);
        fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
        fl6.flowi6_mark = mark;
        security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
@@ -591,7 +598,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        else if (!fl6.flowi6_oif)
                fl6.flowi6_oif = np->ucast_oif;
 
-       err = ip6_dst_lookup(sk, &dst, &fl6);
+       err = ip6_dst_lookup(net, sk, &dst, &fl6);
        if (err)
                goto out;
        dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), sk, 0);
@@ -781,7 +788,8 @@ static int icmpv6_rcv(struct sk_buff *skb)
                if (type & ICMPV6_INFOMSG_MASK)
                        break;
 
-               net_dbg_ratelimited("icmpv6: msg of unknown type\n");
+               net_dbg_ratelimited("icmpv6: msg of unknown type [%pI6c > %pI6c]\n",
+                                   saddr, daddr);
 
                /*
                 * error of unknown type.
@@ -826,11 +834,6 @@ void icmpv6_flow_init(struct sock *sk, struct flowi6 *fl6,
        security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
 }
 
-/*
- * Special lock-class for __icmpv6_sk:
- */
-static struct lock_class_key icmpv6_socket_sk_dst_lock_key;
-
 static int __net_init icmpv6_sk_init(struct net *net)
 {
        struct sock *sk;
@@ -852,15 +855,6 @@ static int __net_init icmpv6_sk_init(struct net *net)
 
                net->ipv6.icmp_sk[i] = sk;
 
-               /*
-                * Split off their lock-class, because sk->sk_dst_lock
-                * gets used from softirqs, which is safe for
-                * __icmpv6_sk (because those never get directly used
-                * via userspace syscalls), but unsafe for normal sockets.
-                */
-               lockdep_set_class(&sk->sk_dst_lock,
-                                 &icmpv6_socket_sk_dst_lock_key);
-
                /* Enough space for 2 64K ICMP packets, including
                 * sk_buff struct overhead.
                 */