Commit f8696133 authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Jakub Kicinski

arp: Factorise ip_route_output() call in arp_req_set() and arp_req_delete().

When ioctl(SIOCDARP/SIOCSARP) is issued for non-proxy entry (no ATF_COM)
without arpreq.arp_dev[] set, arp_req_set() and arp_req_delete() looks up
dev based on IPv4 address by ip_route_output().

Let's factorise the same code as arp_req_dev().
Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Link: https://lore.kernel.org/r/20240430015813.71143-4-kuniyu@amazon.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 05923674
...@@ -1003,6 +1003,27 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -1003,6 +1003,27 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
* User level interface (ioctl) * User level interface (ioctl)
*/ */
static struct net_device *arp_req_dev(struct net *net, struct arpreq *r)
{
struct net_device *dev;
struct rtable *rt;
__be32 ip;
ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
rt = ip_route_output(net, ip, 0, 0, 0, RT_SCOPE_LINK);
if (IS_ERR(rt))
return ERR_CAST(rt);
dev = rt->dst.dev;
ip_rt_put(rt);
if (!dev)
return ERR_PTR(-EINVAL);
return dev;
}
/* /*
* Set (create) an ARP cache entry. * Set (create) an ARP cache entry.
*/ */
...@@ -1045,25 +1066,17 @@ static int arp_req_set_public(struct net *net, struct arpreq *r, ...@@ -1045,25 +1066,17 @@ static int arp_req_set_public(struct net *net, struct arpreq *r,
static int arp_req_set(struct net *net, struct arpreq *r, static int arp_req_set(struct net *net, struct arpreq *r,
struct net_device *dev) struct net_device *dev)
{ {
__be32 ip;
struct neighbour *neigh; struct neighbour *neigh;
__be32 ip;
int err; int err;
if (r->arp_flags & ATF_PUBL) if (r->arp_flags & ATF_PUBL)
return arp_req_set_public(net, r, dev); return arp_req_set_public(net, r, dev);
ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
if (!dev) { if (!dev) {
struct rtable *rt = ip_route_output(net, ip, 0, 0, 0, dev = arp_req_dev(net, r);
RT_SCOPE_LINK); if (IS_ERR(dev))
return PTR_ERR(dev);
if (IS_ERR(rt))
return PTR_ERR(rt);
dev = rt->dst.dev;
ip_rt_put(rt);
if (!dev)
return -EINVAL;
} }
switch (dev->type) { switch (dev->type) {
#if IS_ENABLED(CONFIG_FDDI) #if IS_ENABLED(CONFIG_FDDI)
...@@ -1086,6 +1099,8 @@ static int arp_req_set(struct net *net, struct arpreq *r, ...@@ -1086,6 +1099,8 @@ static int arp_req_set(struct net *net, struct arpreq *r,
break; break;
} }
ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev); neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev);
err = PTR_ERR(neigh); err = PTR_ERR(neigh);
if (!IS_ERR(neigh)) { if (!IS_ERR(neigh)) {
...@@ -1191,14 +1206,9 @@ static int arp_req_delete(struct net *net, struct arpreq *r, ...@@ -1191,14 +1206,9 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
if (!dev) { if (!dev) {
struct rtable *rt = ip_route_output(net, ip, 0, 0, 0, dev = arp_req_dev(net, r);
RT_SCOPE_LINK); if (IS_ERR(dev))
if (IS_ERR(rt)) return PTR_ERR(dev);
return PTR_ERR(rt);
dev = rt->dst.dev;
ip_rt_put(rt);
if (!dev)
return -EINVAL;
} }
return arp_invalidate(dev, ip, true); return arp_invalidate(dev, ip, true);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment