Merge tag 'net-next-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev...
[linux-2.6-microblaze.git] / net / ipv4 / icmp.c
index bdaaee5..07f67ce 100644 (file)
@@ -457,6 +457,23 @@ out_bh_enable:
        local_bh_enable();
 }
 
+/*
+ * The device used for looking up which routing table to use for sending an ICMP
+ * error is preferably the source whenever it is set, which should ensure the
+ * icmp error can be sent to the source host, else lookup using the routing
+ * table of the destination device, else use the main routing table (index 0).
+ */
+static struct net_device *icmp_get_route_lookup_dev(struct sk_buff *skb)
+{
+       struct net_device *route_lookup_dev = NULL;
+
+       if (skb->dev)
+               route_lookup_dev = skb->dev;
+       else if (skb_dst(skb))
+               route_lookup_dev = skb_dst(skb)->dev;
+       return route_lookup_dev;
+}
+
 static struct rtable *icmp_route_lookup(struct net *net,
                                        struct flowi4 *fl4,
                                        struct sk_buff *skb_in,
@@ -465,6 +482,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
                                        int type, int code,
                                        struct icmp_bxm *param)
 {
+       struct net_device *route_lookup_dev;
        struct rtable *rt, *rt2;
        struct flowi4 fl4_dec;
        int err;
@@ -479,7 +497,8 @@ static struct rtable *icmp_route_lookup(struct net *net,
        fl4->flowi4_proto = IPPROTO_ICMP;
        fl4->fl4_icmp_type = type;
        fl4->fl4_icmp_code = code;
-       fl4->flowi4_oif = l3mdev_master_ifindex(skb_dst(skb_in)->dev);
+       route_lookup_dev = icmp_get_route_lookup_dev(skb_in);
+       fl4->flowi4_oif = l3mdev_master_ifindex(route_lookup_dev);
 
        security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4));
        rt = ip_route_output_key_hash(net, fl4, skb_in);
@@ -503,7 +522,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
        if (err)
                goto relookup_failed;
 
-       if (inet_addr_type_dev_table(net, skb_dst(skb_in)->dev,
+       if (inet_addr_type_dev_table(net, route_lookup_dev,
                                     fl4_dec.saddr) == RTN_LOCAL) {
                rt2 = __ip_route_output_key(net, &fl4_dec);
                if (IS_ERR(rt2))
@@ -690,9 +709,9 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
                rcu_read_unlock();
        }
 
-       tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) |
+       tos = icmp_pointers[type].error ? (RT_TOS(iph->tos) |
                                           IPTOS_PREC_INTERNETCONTROL) :
-                                         iph->tos;
+                                          iph->tos;
        mark = IP4_REPLY_MARK(net, skb_in->mark);
 
        if (__ip_options_echo(net, &icmp_param.replyopts.opt.opt, skb_in, opt))
@@ -784,7 +803,7 @@ EXPORT_SYMBOL(icmp_ndo_send);
 
 static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
 {
-       const struct iphdr *iph = (const struct iphdr *) skb->data;
+       const struct iphdr *iph = (const struct iphdr *)skb->data;
        const struct net_protocol *ipprot;
        int protocol = iph->protocol;