ipv4: Set scope explicitly in ip_route_output().
authorGuillaume Nault <gnault@redhat.com>
Fri, 5 Apr 2024 20:05:00 +0000 (22:05 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 8 Apr 2024 12:20:51 +0000 (13:20 +0100)
Add a "scope" parameter to ip_route_output() so that callers don't have
to override the tos parameter with the RTO_ONLINK flag if they want a
local scope.

This will allow converting flowi4_tos to dscp_t in the future, thus
allowing static analysers to flag invalid interactions between
"tos" (the DSCP bits) and ECN.

Only three users ask for local scope (bonding, arp and atm). The others
continue to use RT_SCOPE_UNIVERSE. While there, add a comment to warn
users about the limitations of ip_route_output().

Signed-off-by: Guillaume Nault <gnault@redhat.com>
Acked-by: Leon Romanovsky <leonro@nvidia.com> # infiniband
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/infiniband/hw/irdma/cm.c
drivers/infiniband/hw/qedr/qedr_iw_cm.c
drivers/net/bonding/bond_main.c
drivers/net/ethernet/broadcom/cnic.c
include/net/route.h
net/atm/clip.c
net/bridge/br_netfilter_hooks.c
net/ipv4/arp.c
net/ipv4/igmp.c
net/mpls/af_mpls.c

index 1ee7a4e0d8d82e7aa61d596784a2e516c0f483af..36bb7e5ce63829c06634a33a840f9a31ff91fab8 100644 (file)
@@ -1985,7 +1985,8 @@ static int irdma_addr_resolve_neigh(struct irdma_device *iwdev, u32 src_ip,
        __be32 dst_ipaddr = htonl(dst_ip);
        __be32 src_ipaddr = htonl(src_ip);
 
-       rt = ip_route_output(&init_net, dst_ipaddr, src_ipaddr, 0, 0);
+       rt = ip_route_output(&init_net, dst_ipaddr, src_ipaddr, 0, 0,
+                            RT_SCOPE_UNIVERSE);
        if (IS_ERR(rt)) {
                ibdev_dbg(&iwdev->ibdev, "CM: ip_route_output fail\n");
                return -EINVAL;
index a51fc68549844de87c199d23f89c113c7fae1409..259303b9907c133412a584c40e232bcf3e5de4b3 100644 (file)
@@ -447,7 +447,8 @@ qedr_addr4_resolve(struct qedr_dev *dev,
        struct rtable *rt = NULL;
        int rc = 0;
 
-       rt = ip_route_output(&init_net, dst_ip, src_ip, 0, 0);
+       rt = ip_route_output(&init_net, dst_ip, src_ip, 0, 0,
+                            RT_SCOPE_UNIVERSE);
        if (IS_ERR(rt)) {
                DP_ERR(dev, "ip_route_output returned error\n");
                return -EINVAL;
index 2c5ed0a7cb18c6724fa80836943381816449c909..c9f0415f780ab0a9ecb26424795695eff951421a 100644 (file)
@@ -3014,8 +3014,8 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
                tags = NULL;
 
                /* Find out through which dev should the packet go */
-               rt = ip_route_output(dev_net(bond->dev), targets[i], 0,
-                                    RTO_ONLINK, 0);
+               rt = ip_route_output(dev_net(bond->dev), targets[i], 0, 0, 0,
+                                    RT_SCOPE_LINK);
                if (IS_ERR(rt)) {
                        /* there's no route to target - try to send arp
                         * probe to generate any traffic (arp_validate=0)
index 3d63177e7e52b6d44fd1fd49fbdd3af388eb73d0..c2b4188a1ef1c5a81bd22925eee1947946d9e0f1 100644 (file)
@@ -3682,7 +3682,8 @@ static int cnic_get_v4_route(struct sockaddr_in *dst_addr,
 #if defined(CONFIG_INET)
        struct rtable *rt;
 
-       rt = ip_route_output(&init_net, dst_addr->sin_addr.s_addr, 0, 0, 0);
+       rt = ip_route_output(&init_net, dst_addr->sin_addr.s_addr, 0, 0, 0,
+                            RT_SCOPE_UNIVERSE);
        if (!IS_ERR(rt)) {
                *dst = &rt->dst;
                return 0;
index d4a0147942f1a7dff68ee90c2f5fc913f7ceb512..315a8acee6c6b94a635b26dd673c488d28f87bc6 100644 (file)
@@ -141,15 +141,22 @@ static inline struct rtable *ip_route_output_key(struct net *net, struct flowi4
        return ip_route_output_flow(net, flp, NULL);
 }
 
+/* Simplistic IPv4 route lookup function.
+ * This is only suitable for some particular use cases: since the flowi4
+ * structure is only partially set, it may bypass some fib-rules.
+ */
 static inline struct rtable *ip_route_output(struct net *net, __be32 daddr,
-                                            __be32 saddr, u8 tos, int oif)
+                                            __be32 saddr, u8 tos, int oif,
+                                            __u8 scope)
 {
        struct flowi4 fl4 = {
                .flowi4_oif = oif,
                .flowi4_tos = tos,
+               .flowi4_scope = scope,
                .daddr = daddr,
                .saddr = saddr,
        };
+
        return ip_route_output_key(net, &fl4);
 }
 
index 294cb9efe3d3820046cd123caf7037eeb0dbe9c4..362e8d25a79ec9b90ab30d4ae1832f11bd4bb0ac 100644 (file)
@@ -463,7 +463,7 @@ static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
                unlink_clip_vcc(clip_vcc);
                return 0;
        }
-       rt = ip_route_output(&init_net, ip, 0, 1, 0);
+       rt = ip_route_output(&init_net, ip, 0, 0, 0, RT_SCOPE_LINK);
        if (IS_ERR(rt))
                return PTR_ERR(rt);
        neigh = __neigh_lookup(&arp_tbl, &ip, rt->dst.dev, 1);
index 35e10c5a766d550e0c5cb85cf5a0c4835b52a89d..4242447be322bc0f25aafa67f5830ff5528f9afb 100644 (file)
@@ -399,7 +399,8 @@ static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_
                                goto free_skb;
 
                        rt = ip_route_output(net, iph->daddr, 0,
-                                            RT_TOS(iph->tos), 0);
+                                            RT_TOS(iph->tos), 0,
+                                            RT_SCOPE_UNIVERSE);
                        if (!IS_ERR(rt)) {
                                /* - Bridged-and-DNAT'ed traffic doesn't
                                 *   require ip_forwarding. */
index 0d0d725b46ad0c56b19b6356f6d3e6be8bdcae83..ab82ca1044963a5bf412961d423c256e70649334 100644 (file)
@@ -456,7 +456,8 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
        /*unsigned long now; */
        struct net *net = dev_net(dev);
 
-       rt = ip_route_output(net, sip, tip, 0, l3mdev_master_ifindex_rcu(dev));
+       rt = ip_route_output(net, sip, tip, 0, l3mdev_master_ifindex_rcu(dev),
+                            RT_SCOPE_UNIVERSE);
        if (IS_ERR(rt))
                return 1;
        if (rt->dst.dev != dev) {
@@ -1056,7 +1057,8 @@ static int arp_req_set(struct net *net, struct arpreq *r,
        if (r->arp_flags & ATF_PERM)
                r->arp_flags |= ATF_COM;
        if (!dev) {
-               struct rtable *rt = ip_route_output(net, ip, 0, RTO_ONLINK, 0);
+               struct rtable *rt = ip_route_output(net, ip, 0, 0, 0,
+                                                   RT_SCOPE_LINK);
 
                if (IS_ERR(rt))
                        return PTR_ERR(rt);
@@ -1188,7 +1190,8 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
 
        ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
        if (!dev) {
-               struct rtable *rt = ip_route_output(net, ip, 0, RTO_ONLINK, 0);
+               struct rtable *rt = ip_route_output(net, ip, 0, 0, 0,
+                                                   RT_SCOPE_LINK);
                if (IS_ERR(rt))
                        return PTR_ERR(rt);
                dev = rt->dst.dev;
index 717e97a389a8aee75f51a5a5d859cb94a5d868eb..9bf09de6a2e77c32f5eed565db8fd6c14bc7ea86 100644 (file)
@@ -1842,7 +1842,8 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
        if (!dev) {
                struct rtable *rt = ip_route_output(net,
                                                    imr->imr_multiaddr.s_addr,
-                                                   0, 0, 0);
+                                                   0, 0, 0,
+                                                   RT_SCOPE_UNIVERSE);
                if (!IS_ERR(rt)) {
                        dev = rt->dst.dev;
                        ip_rt_put(rt);
index 6dab883a08dda46ff6ddc1e6e407e6f48a10c8aa..1303acb9cdd23f48f22c35e019115895d14df8b4 100644 (file)
@@ -594,7 +594,7 @@ static struct net_device *inet_fib_lookup_dev(struct net *net,
        struct in_addr daddr;
 
        memcpy(&daddr, addr, sizeof(struct in_addr));
-       rt = ip_route_output(net, daddr.s_addr, 0, 0, 0);
+       rt = ip_route_output(net, daddr.s_addr, 0, 0, 0, RT_SCOPE_UNIVERSE);
        if (IS_ERR(rt))
                return ERR_CAST(rt);