From 22df5534437fd6f2f95e75c032d2bbfe976c3adf Mon Sep 17 00:00:00 2001 From: songlinzhang Date: Thu, 18 Nov 2021 13:29:25 +0800 Subject: [PATCH] net/arp: clean the arp table when netdev carrier off Fix the arp address changed if netdev renew, since the arp table should be cleared when the netdev carrier off Signed-off-by: songlinzhang --- include/nuttx/net/arp.h | 7 ++++--- net/arp/arp.h | 29 +++++++++++++++++++++++---- net/arp/arp_arpin.c | 4 ++-- net/arp/arp_ipin.c | 2 +- net/arp/arp_table.c | 38 ++++++++++++++++++++++++++++++++--- net/netdev/netdev_carrier.c | 2 ++ net/netdev/netdev_ioctl.c | 40 ++++++++++++++++++++++++++++++++----- 7 files changed, 104 insertions(+), 18 deletions(-) diff --git a/include/nuttx/net/arp.h b/include/nuttx/net/arp.h index 920a636935..df58a27268 100644 --- a/include/nuttx/net/arp.h +++ b/include/nuttx/net/arp.h @@ -82,9 +82,10 @@ struct arp_entry_s { - in_addr_t at_ipaddr; /* IP address */ - struct ether_addr at_ethaddr; /* Hardware address */ - clock_t at_time; /* Time of last usage */ + in_addr_t at_ipaddr; /* IP address */ + struct ether_addr at_ethaddr; /* Hardware address */ + clock_t at_time; /* Time of last usage */ + FAR struct net_driver_s *at_dev; /* The device driver structure */ }; /**************************************************************************** diff --git a/net/arp/arp.h b/net/arp/arp.h index e0aec9f3ef..a30c900561 100644 --- a/net/arp/arp.h +++ b/net/arp/arp.h @@ -358,6 +358,22 @@ int arp_find(in_addr_t ipaddr, FAR struct ether_addr *ethaddr); void arp_delete(in_addr_t ipaddr); +/**************************************************************************** + * Name: arp_cleanup + * + * Description: + * Clear the ARP table on the network device + * + * Input Parameters: + * dev - The device driver structure + * + * Assumptions + * The network is locked to assure exclusive access to the ARP table. + * + ****************************************************************************/ + +void arp_cleanup(FAR struct net_driver_s *dev); + /**************************************************************************** * Name: arp_update * @@ -366,6 +382,7 @@ void arp_delete(in_addr_t ipaddr); * address of an existing association. * * Input Parameters: + * dev - The device driver structure * ipaddr - The IP address as an inaddr_t * ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN] * @@ -378,7 +395,8 @@ void arp_delete(in_addr_t ipaddr); * ****************************************************************************/ -int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr); +int arp_update(FAR struct net_driver_s *dev, in_addr_t ipaddr, + FAR uint8_t *ethaddr); /**************************************************************************** * Name: arp_hdr_update @@ -388,6 +406,7 @@ int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr); * address of an existing association. * * Input Parameters: + * dev - The device driver structure * pipaddr - Refers to an IP address uint16_t[2] in network order * ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN] * @@ -400,7 +419,8 @@ int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr); * ****************************************************************************/ -void arp_hdr_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr); +void arp_hdr_update(FAR struct net_driver_s *dev, FAR uint16_t *pipaddr, + FAR uint8_t *ethaddr); /**************************************************************************** * Name: arp_snapshot @@ -462,8 +482,9 @@ void arp_dump(FAR struct arp_hdr_s *arp); # define arp_notify(i) # define arp_find(i,e) (-ENOSYS) # define arp_delete(i) -# define arp_update(i,m); -# define arp_hdr_update(i,m); +# define arp_cleanup(d) +# define arp_update(d,i,m); +# define arp_hdr_update(d,i,m); # define arp_snapshot(s,n) (0) # define arp_dump(arp) diff --git a/net/arp/arp_arpin.c b/net/arp/arp_arpin.c index 008413730e..12f87602da 100644 --- a/net/arp/arp_arpin.c +++ b/net/arp/arp_arpin.c @@ -121,7 +121,7 @@ void arp_arpin(FAR struct net_driver_s *dev) * with this host in the future. */ - arp_hdr_update(arp->ah_sipaddr, arp->ah_shwaddr); + arp_hdr_update(dev, arp->ah_sipaddr, arp->ah_shwaddr); arp->ah_opcode = HTONS(ARP_REPLY); memcpy(arp->ah_dhwaddr, arp->ah_shwaddr, ETHER_ADDR_LEN); @@ -152,7 +152,7 @@ void arp_arpin(FAR struct net_driver_s *dev) { /* Yes... Insert the address mapping in the ARP table */ - arp_hdr_update(arp->ah_sipaddr, arp->ah_shwaddr); + arp_hdr_update(dev, arp->ah_sipaddr, arp->ah_shwaddr); /* Then notify any logic waiting for the ARP result */ diff --git a/net/arp/arp_ipin.c b/net/arp/arp_ipin.c index 3f562f9644..f3be022442 100644 --- a/net/arp/arp_ipin.c +++ b/net/arp/arp_ipin.c @@ -90,7 +90,7 @@ void arp_ipin(FAR struct net_driver_s *dev) srcipaddr = net_ip4addr_conv32(IPBUF->eh_srcipaddr); if (net_ipv4addr_maskcmp(srcipaddr, dev->d_ipaddr, dev->d_netmask)) { - arp_hdr_update(IPBUF->eh_srcipaddr, ETHBUF->src); + arp_hdr_update(dev, IPBUF->eh_srcipaddr, ETHBUF->src); } } diff --git a/net/arp/arp_table.c b/net/arp/arp_table.c index 06437c77de..b26534e304 100644 --- a/net/arp/arp_table.c +++ b/net/arp/arp_table.c @@ -181,6 +181,7 @@ arp_return_old_entry(FAR struct arp_entry_s *e1, FAR struct arp_entry_s *e2) * address of an existing association. * * Input Parameters: + * dev - The device driver structure * ipaddr - The IP address as an inaddr_t * ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN] * @@ -193,7 +194,8 @@ arp_return_old_entry(FAR struct arp_entry_s *e1, FAR struct arp_entry_s *e2) * ****************************************************************************/ -int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr) +int arp_update(FAR struct net_driver_s *dev, in_addr_t ipaddr, + FAR uint8_t *ethaddr) { FAR struct arp_entry_s *tabptr = &g_arptable[0]; int i; @@ -231,6 +233,7 @@ int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr) tabptr->at_ipaddr = ipaddr; memcpy(tabptr->at_ethaddr.ether_addr_octet, ethaddr, ETHER_ADDR_LEN); + tabptr->at_dev = dev; tabptr->at_time = clock_systime_ticks(); return OK; } @@ -243,6 +246,7 @@ int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr) * address of an existing association. * * Input Parameters: + * dev - The device driver structure * pipaddr - Refers to an IP address uint16_t[2] in network order * ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN] * @@ -255,13 +259,14 @@ int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr) * ****************************************************************************/ -void arp_hdr_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr) +void arp_hdr_update(FAR struct net_driver_s *dev, FAR uint16_t *pipaddr, + FAR uint8_t *ethaddr) { in_addr_t ipaddr = net_ip4addr_conv32(pipaddr); /* Update the ARP table */ - arp_update(ipaddr, ethaddr); + arp_update(dev, ipaddr, ethaddr); } /**************************************************************************** @@ -393,6 +398,33 @@ void arp_delete(in_addr_t ipaddr) } } +/**************************************************************************** + * Name: arp_cleanup + * + * Description: + * Clear the ARP table on the network device + * + * Input Parameters: + * dev - The device driver structure + * + * Assumptions + * The network is locked to assure exclusive access to the ARP table. + * + ****************************************************************************/ + +void arp_cleanup(FAR struct net_driver_s *dev) +{ + int i; + + for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) + { + if (dev == g_arptable[i].at_dev) + { + memset(&g_arptable[i], 0, sizeof(g_arptable[i])); + } + } +} + /**************************************************************************** * Name: arp_snapshot * diff --git a/net/netdev/netdev_carrier.c b/net/netdev/netdev_carrier.c index a6bfb86a88..fe087649d6 100644 --- a/net/netdev/netdev_carrier.c +++ b/net/netdev/netdev_carrier.c @@ -37,6 +37,7 @@ #include "netdev/netdev.h" #include "netlink/netlink.h" +#include "arp/arp.h" /**************************************************************************** * Public Functions @@ -94,6 +95,7 @@ int netdev_carrier_off(FAR struct net_driver_s *dev) /* Notify clients that the network has been taken down */ devif_dev_event(dev, NULL, NETDEV_DOWN); + arp_cleanup(dev); return OK; } diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index 1189b55e5a..764b1e5fe8 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -1222,6 +1222,40 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, int cmd, } #endif +/**************************************************************************** + * Name: netdev_arp_callback + * + * Description: + * This is a callback that checks if the Ethernet network device has the + * indicated name + * + * Input Parameters: + * dev Ethernet driver device structure + * req The argument of the ioctl cmd + * + * Returned Value: + * 1 on success + * 0 on error + ****************************************************************************/ + +#ifdef CONFIG_NET_ARP +static int netdev_arp_callback(FAR struct net_driver_s *dev, FAR void *arg) +{ + FAR struct arpreq *req = arg; + FAR struct sockaddr_in *addr = (FAR struct sockaddr_in *)&req->arp_pa; + + if (strncmp(dev->d_ifname, (FAR const char *)req->arp_dev, + sizeof(dev->d_ifname))) + { + return 0; + } + + arp_update(dev, addr->sin_addr.s_addr, + (FAR uint8_t *)req->arp_ha.sa_data); + return 1; +} +#endif + /**************************************************************************** * Name: netdev_arp_ioctl * @@ -1256,15 +1290,11 @@ static int netdev_arp_ioctl(FAR struct socket *psock, int cmd, req->arp_pa.sa_family == AF_INET && req->arp_ha.sa_family == ARPHRD_ETHER) { - FAR struct sockaddr_in *addr = - (FAR struct sockaddr_in *)&req->arp_pa; - /* Update any existing ARP table entry for this protocol * address -OR- add a new ARP table entry if there is not. */ - ret = arp_update(addr->sin_addr.s_addr, - (FAR uint8_t *)req->arp_ha.sa_data); + ret = netdev_foreach(netdev_arp_callback, req) ? OK : -EINVAL; } else {