net/arp: Make the function arp_find() thread-safe. It now returns a copy of the ARP table entry, rather than a potentially unstable reference to the ARP table entry.
This commit is contained in:
parent
e8270defc9
commit
9774d35010
10 changed files with 142 additions and 54 deletions
|
@ -54,6 +54,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <semaphore.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
@ -369,21 +370,38 @@ void arp_notify(in_addr_t ipaddr);
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arp_find
|
||||
* Name: arp_lookup
|
||||
*
|
||||
* Description:
|
||||
* Find the ARP entry corresponding to this IP address.
|
||||
* Find the ARP entry corresponding to this IP address in the ARP table.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipaddr - Refers to an IP address in network order
|
||||
*
|
||||
* Assumptions
|
||||
* The network is locked; Returned value will become unstable when the
|
||||
* network is unlocked or if any other network APIs are called.
|
||||
* Assumptions:
|
||||
* The network is locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct arp_entry *arp_find(in_addr_t ipaddr);
|
||||
FAR struct arp_entry *arp_lookup(in_addr_t ipaddr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arp_find
|
||||
*
|
||||
* Description:
|
||||
* Find the ARP entry corresponding to this IP address which may or may
|
||||
* not be in the ARP table (it may, instead, be a local network device).
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipaddr - Refers to an IP address in network order
|
||||
* entry - location to return a copy of the ARP table entry.
|
||||
*
|
||||
* Assumptions
|
||||
* The network is locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arp_find(in_addr_t ipaddr, FAR struct arp_entry *entry);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arp_delete
|
||||
|
@ -400,14 +418,7 @@ FAR struct arp_entry *arp_find(in_addr_t ipaddr);
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define arp_delete(ipaddr) \
|
||||
{ \
|
||||
struct arp_entry *tabptr = arp_find(ipaddr); \
|
||||
if (tabptr) \
|
||||
{ \
|
||||
tabptr->at_ipaddr = 0; \
|
||||
} \
|
||||
}
|
||||
void arp_delete(in_addr_t ipaddr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arp_update
|
||||
|
@ -487,7 +498,7 @@ void arp_dump(FAR struct arp_hdr_s *arp);
|
|||
# define arp_wait_cancel(n) (0)
|
||||
# define arp_wait(n,t) (0)
|
||||
# define arp_notify(i)
|
||||
# define arp_find(i) (NULL)
|
||||
# define arp_find(i,e) (-ENOSYS)
|
||||
# define arp_delete(i)
|
||||
# define arp_update(i,m);
|
||||
# define arp_hdr_update(i,m);
|
||||
|
|
|
@ -136,11 +136,12 @@ static const uint8_t g_multicast_ethaddr[3] =
|
|||
|
||||
void arp_out(FAR struct net_driver_s *dev)
|
||||
{
|
||||
FAR const struct arp_entry *tabptr = NULL;
|
||||
FAR struct eth_hdr_s *peth = ETHBUF;
|
||||
FAR struct arp_iphdr_s *pip = IPBUF;
|
||||
in_addr_t ipaddr;
|
||||
in_addr_t destipaddr;
|
||||
struct arp_entry entry;
|
||||
FAR struct eth_hdr_s *peth = ETHBUF;
|
||||
FAR struct arp_iphdr_s *pip = IPBUF;
|
||||
in_addr_t ipaddr;
|
||||
in_addr_t destipaddr;
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_PKT) || defined(CONFIG_NET_ARP_SEND)
|
||||
/* Skip sending ARP requests when the frame to be transmitted was
|
||||
|
@ -249,8 +250,8 @@ void arp_out(FAR struct net_driver_s *dev)
|
|||
|
||||
/* Check if we already have this destination address in the ARP table */
|
||||
|
||||
tabptr = arp_find(ipaddr);
|
||||
if (tabptr == NULL)
|
||||
ret = arp_find(ipaddr, &entry);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ninfo("ARP request for IP %08lx\n", (unsigned long)ipaddr);
|
||||
|
||||
|
@ -265,7 +266,7 @@ void arp_out(FAR struct net_driver_s *dev)
|
|||
|
||||
/* Build an Ethernet header. */
|
||||
|
||||
memcpy(peth->dest, tabptr->at_ethaddr.ether_addr_octet, ETHER_ADDR_LEN);
|
||||
memcpy(peth->dest, entry.at_ethaddr.ether_addr_octet, ETHER_ADDR_LEN);
|
||||
|
||||
/* Finish populating the Ethernet header */
|
||||
|
||||
|
|
|
@ -304,7 +304,8 @@ int arp_send(in_addr_t ipaddr)
|
|||
|
||||
/* Remember the routing device name */
|
||||
|
||||
strncpy((FAR char *)state.snd_ifname, (FAR const char *)dev->d_ifname, IFNAMSIZ);
|
||||
strncpy((FAR char *)state.snd_ifname, (FAR const char *)dev->d_ifname,
|
||||
IFNAMSIZ);
|
||||
|
||||
/* Now loop, testing if the address mapping is in the ARP table and re-
|
||||
* sending the ARP request if it is not.
|
||||
|
@ -314,6 +315,8 @@ int arp_send(in_addr_t ipaddr)
|
|||
|
||||
while (state.snd_retries < CONFIG_ARP_SEND_MAXTRIES)
|
||||
{
|
||||
struct arp_entry entry;
|
||||
|
||||
/* Check if the address mapping is present in the ARP table. This
|
||||
* is only really meaningful on the first time through the loop.
|
||||
*
|
||||
|
@ -321,7 +324,7 @@ int arp_send(in_addr_t ipaddr)
|
|||
* issue.
|
||||
*/
|
||||
|
||||
if (arp_find(ipaddr))
|
||||
if (arp_find(ipaddr, &entry) >= 0)
|
||||
{
|
||||
/* We have it! Break out with success */
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
@ -284,10 +285,10 @@ void arp_hdr_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr)
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arp_find
|
||||
* Name: arp_lookup
|
||||
*
|
||||
* Description:
|
||||
* Find the ARP entry corresponding to this IP address.
|
||||
* Find the ARP entry corresponding to this IP address in the ARP table.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipaddr - Refers to an IP address in network order
|
||||
|
@ -297,10 +298,9 @@ void arp_hdr_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct arp_entry *arp_find(in_addr_t ipaddr)
|
||||
FAR struct arp_entry *arp_lookup(in_addr_t ipaddr)
|
||||
{
|
||||
FAR struct arp_entry *tabptr;
|
||||
struct arp_entry entry;
|
||||
int i;
|
||||
|
||||
/* Check if the IPv4 address is already in the ARP table. */
|
||||
|
@ -314,21 +314,86 @@ FAR struct arp_entry *arp_find(in_addr_t ipaddr)
|
|||
}
|
||||
}
|
||||
|
||||
/* No.. check if the IPv4 address is the address assigned to a local
|
||||
* Ethernet network device. If so, return a "fake" arp table entry
|
||||
* mapping that IP address to the Ethernet MAC address of the device.
|
||||
*/
|
||||
|
||||
entry.at_ipaddr = ipaddr;
|
||||
if (netdev_foreach(arp_match, &entry) != 0)
|
||||
{
|
||||
return &entry;
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arp_find
|
||||
*
|
||||
* Description:
|
||||
* Find the ARP entry corresponding to this IP address which may or may
|
||||
* not be in the ARP table (it may, instead, be a local network device).
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipaddr - Refers to an IP address in network order
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arp_find(in_addr_t ipaddr, FAR struct arp_entry *entry)
|
||||
{
|
||||
FAR struct arp_entry *tabptr;
|
||||
|
||||
DEBUGASSERT(entry);
|
||||
|
||||
/* Check if the IPv4 address is already in the ARP table. */
|
||||
|
||||
tabptr = arp_lookup(ipaddr);
|
||||
if (tabptr != NULL)
|
||||
{
|
||||
memcpy(entry, tabptr, sizeof(struct arp_entry));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* No.. check if the IPv4 address is the address assigned to a local
|
||||
* Ethernet network device. If so, return a "fake" arp table entry
|
||||
* mapping that IP address to the Ethernet MAC address of the device.
|
||||
*/
|
||||
|
||||
entry->at_ipaddr = ipaddr;
|
||||
if (netdev_foreach(arp_match, entry) != 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arp_delete
|
||||
*
|
||||
* Description:
|
||||
* Remove an IP association from the ARP table
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipaddr - Refers to an IP address in network order
|
||||
*
|
||||
* Assumptions
|
||||
* Interrupts are disabled to assure exclusive access to the ARP table
|
||||
* (and because arp_find() is called).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void arp_delete(in_addr_t ipaddr)
|
||||
{
|
||||
FAR struct arp_entry *tabptr;
|
||||
|
||||
/* Check if the IPv4 address is in the ARP table. */
|
||||
|
||||
tabptr = arp_lookup(ipaddr);
|
||||
if (tabptr != NULL)
|
||||
{
|
||||
/* Yes.. set the IP address to zero to "delete" it */
|
||||
|
||||
tabptr->at_ipaddr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_ARP */
|
||||
#endif /* CONFIG_NET */
|
||||
|
|
|
@ -159,7 +159,11 @@ static inline bool ipfwd_addrchk(FAR struct forward_s *fwd)
|
|||
{
|
||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||
FAR struct ipv4_hdr_s *ipv4 = (FAR struct ipv4_hdr_s *)fwd->f_iob->io_data;
|
||||
return (arp_find(*(in_addr_t *)ipv4->destipaddr) != NULL);
|
||||
struct arp_entry entry;
|
||||
int ret;
|
||||
|
||||
ret = arp_find(*(in_addr_t *)ipv4->destipaddr, &entry);
|
||||
return (ret >= 0);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
|
|
@ -1259,7 +1259,7 @@ static int netdev_arp_ioctl(FAR struct socket *psock, int cmd,
|
|||
|
||||
/* Find the existing ARP table entry for this protocol address. */
|
||||
|
||||
FAR struct arp_entry *entry = arp_find(addr->sin_addr.s_addr);
|
||||
FAR struct arp_entry *entry = arp_lookup(addr->sin_addr.s_addr);
|
||||
if (entry != NULL)
|
||||
{
|
||||
/* The ARP table is fixed size; an entry is deleted
|
||||
|
@ -1287,24 +1287,21 @@ static int netdev_arp_ioctl(FAR struct socket *psock, int cmd,
|
|||
{
|
||||
FAR struct sockaddr_in *addr =
|
||||
(FAR struct sockaddr_in *)&req->arp_pa;
|
||||
struct arp_entry entry;
|
||||
|
||||
/* Find the existing ARP table entry for this protocol address. */
|
||||
|
||||
FAR struct arp_entry *entry = arp_find(addr->sin_addr.s_addr);
|
||||
if (entry != NULL)
|
||||
ret = arp_find(addr->sin_addr.s_addr, &entry);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Return the mapped hardware address. */
|
||||
|
||||
req->arp_ha.sa_family = ARPHRD_ETHER;
|
||||
memcpy(req->arp_ha.sa_data,
|
||||
entry->at_ethaddr.ether_addr_octet,
|
||||
entry.at_ethaddr.ether_addr_octet,
|
||||
ETHER_ADDR_LEN);
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ENOENT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -309,7 +309,9 @@ static inline bool psock_send_addrchck(FAR struct tcp_conn_s *conn)
|
|||
#endif
|
||||
|
||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||
if (arp_find(conn->u.ipv4.raddr) != NULL)
|
||||
struct arp_entry entry;
|
||||
|
||||
if (arp_find(conn->u.ipv4.raddr, &entry) >= 0)
|
||||
{
|
||||
/* Return true if the address was found in the ARP table */
|
||||
|
||||
|
|
|
@ -257,9 +257,10 @@ static inline bool psock_send_addrchck(FAR struct tcp_conn_s *conn)
|
|||
#ifdef CONFIG_NET_ROUTE
|
||||
in_addr_t router;
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||
if (arp_find(conn->u.ipv4.raddr) != NULL)
|
||||
struct arp_entry entry;
|
||||
|
||||
if (arp_find(conn->u.ipv4.raddr, &entry) >= 0)
|
||||
{
|
||||
/* Return true if the address was found in the ARP table */
|
||||
|
||||
|
|
|
@ -296,7 +296,9 @@ static inline bool sendfile_addrcheck(FAR struct tcp_conn_s *conn)
|
|||
#endif
|
||||
{
|
||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||
return (arp_find(conn->u.ipv4.raddr) != NULL);
|
||||
struct arp_entry entry;
|
||||
|
||||
return (arp_find(conn->u.ipv4.raddr, &entry) >= 0);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
|
|
@ -281,7 +281,9 @@ static inline bool sendto_addrcheck(FAR struct udp_conn_s *conn,
|
|||
#endif
|
||||
{
|
||||
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
|
||||
return (arp_find(conn->u.ipv4.raddr) != NULL);
|
||||
struct arp_entry entry;
|
||||
|
||||
return (arp_find(conn->u.ipv4.raddr, entry) >= 0);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue