From 0af9a197ac32ab55b6e7d53e6a81addb2a9b8d49 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 8 Feb 2016 11:17:22 -0600 Subject: [PATCH] ARP: Add IOCTL commands to manage the ARP table --- ChangeLog | 4 +- TODO | 2 +- include/nuttx/net/arp.h | 34 +++++++++- include/nuttx/net/ioctl.h | 129 ++++++++++++++++++----------------- net/arp/arp.h | 35 ++++++++-- net/arp/arp_arpin.c | 4 +- net/arp/arp_ipin.c | 2 +- net/arp/arp_table.c | 40 +++++++++-- net/netdev/netdev_ioctl.c | 137 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 312 insertions(+), 75 deletions(-) diff --git a/ChangeLog b/ChangeLog index f9b22e44a4..44e9c3cc68 100755 --- a/ChangeLog +++ b/ChangeLog @@ -11466,4 +11466,6 @@ g_readytorun() with the wrapper this_task() which hides the implementation and will permit such things as more scalable representations of task queues and SMP (2016-02-06). - + * include/nuttx/net/arp.h, include/nuttx/net/ioctl.h, net/netdev/netdev_ioctl.c, + and ARP-related files: Add support for IOCTL commands to manage the + ARP table (2016-02-08). diff --git a/TODO b/TODO index 7710e0bc1c..bd3bc69191 100644 --- a/TODO +++ b/TODO @@ -1740,7 +1740,7 @@ o Network Utilities (apps/netutils/) Priority: Low Title: DHCPD ACCESSES KERNEL PRIVATE INTERFACE - Description: arp_update() is referenced outside of nuttx/net. It is used in + Description: arp_hdr_update() is referenced outside of nuttx/net. It is used in in the netutils/ DHCPD logic to set entries in the ARP table. That is violation of the separation of kernel and OS functionality. As a consequence, dhcpd will not work with the diff --git a/include/nuttx/net/arp.h b/include/nuttx/net/arp.h index 502d89b0e6..dab5e27876 100644 --- a/include/nuttx/net/arp.h +++ b/include/nuttx/net/arp.h @@ -2,7 +2,7 @@ * include/nuttx/net/arp.h * Macros and definitions for the ARP module. * - * Copyright (C) 2007, 2009-2012, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009-2012, 2015-2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Derived from uIP with has a similar BSD-styple license: @@ -48,6 +48,7 @@ #include #include +#include #include #include @@ -60,6 +61,15 @@ * Pre-processor Definitions ****************************************************************************/ +/* ARP protocol HARDWARE identifiers. Provided as the sa_family member of a + * struct sockaddr. + * + * When sa_family is ARPHRD_ETHER, the 6 byte Ethernet address is provided + * in the first 6-bytes of the sockaddr sa_data array. + */ + +#define ARPHRD_ETHER 1 /* Only Ethernet is supported */ + /**************************************************************************** * Public Types ****************************************************************************/ @@ -70,9 +80,29 @@ struct arp_entry { in_addr_t at_ipaddr; /* IP address */ struct ether_addr at_ethaddr; /* Hardware address */ - uint8_t at_time; + uint8_t at_time; /* Time of last usage */ }; +/* Used with the SIOCSARP, SIOCDARP, and SIOCGARP IOCTL commands to set, + * delete, or get an ARP table entry. + * + * SIOCSARP - Both values are inputs a define the new ARP table entry + * SIOCDARP - Only the protcol address is required as an input. The ARP + * table entry with that matching address will be deleted, + * regardless of the hardware address. + * SIOCGARP - The protocol address is an input an identifies the table + * entry to locate; The hardware address is an output and + * on a successful lookup, provides the matching hardware + * address. + */ + +struct arpreq +{ + struct sockaddr arp_pa; /* Protocol address */ + struct sockaddr arp_ha; /* Hardware address */ +}; + + /**************************************************************************** * Public Data ****************************************************************************/ diff --git a/include/nuttx/net/ioctl.h b/include/nuttx/net/ioctl.h index 4a13ed523f..a20d5e231b 100644 --- a/include/nuttx/net/ioctl.h +++ b/include/nuttx/net/ioctl.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/nuttx/net/ioctl.h * - * Copyright (C) 2007-2008, 2010-2013, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2008, 2010-2013, 2015-2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -94,97 +94,106 @@ #define SIOCGIPMSFILTER _SIOC(0x001a) /* Retrieve source filter addresses */ #define SIOCSIPMSFILTER _SIOC(0x001b) /* Set source filter content */ +/* ARP Table. Argument is a reference to sruct arpreq as defined + * include/nuttx/net/arp.h + */ + +#define SIOCSARP _SIOC(0x001c) /* Set an ARP mapping */ +#define SIOCDARP _SIOC(0x001d) /* Delete an ARP mapping */ +#define SIOCGARP _SIOC(0x001e) /* Get an ARP mapping */ + /* Routing table. Argument is a reference to struct rtentry as defined in * include/net/route.h */ -#define SIOCADDRT _SIOC(0x001c) /* Add an entry to the routing table */ -#define SIOCDELRT _SIOC(0x001d) /* Delete an entry from the routing table */ +#define SIOCADDRT _SIOC(0x001f) /* Add an entry to the routing table */ +#define SIOCDELRT _SIOC(0x0020) /* Delete an entry from the routing table */ /* Wireless ioctl commands **************************************************/ +/* Not currently used */ -#define SIOCSIWCOMMIT _SIOC(0x001e) /* Commit pending changes to driver */ -#define SIOCGIWNAME _SIOC(0x001f) /* Get name of wireless protocol */ +#define SIOCSIWCOMMIT _SIOC(0x0021) /* Commit pending changes to driver */ +#define SIOCGIWNAME _SIOC(0x0022) /* Get name of wireless protocol */ -#define SIOCSIWNWID _SIOC(0x0020) /* Set network ID (pre-802.11) */ -#define SIOCGIWNWID _SIOC(0x0021) /* Get network ID (the cell) */ -#define SIOCSIWFREQ _SIOC(0x0022) /* Set channel/frequency (Hz) */ -#define SIOCGIWFREQ _SIOC(0x0023) /* Get channel/frequency (Hz) */ -#define SIOCSIWMODE _SIOC(0x0024) /* Set operation mode */ -#define SIOCGIWMODE _SIOC(0x0025) /* Get operation mode */ -#define SIOCSIWSENS _SIOC(0x0026) /* Set sensitivity (dBm) */ -#define SIOCGIWSENS _SIOC(0x0027) /* Get sensitivity (dBm) */ +#define SIOCSIWNWID _SIOC(0x0023) /* Set network ID (pre-802.11) */ +#define SIOCGIWNWID _SIOC(0x0024) /* Get network ID (the cell) */ +#define SIOCSIWFREQ _SIOC(0x0025) /* Set channel/frequency (Hz) */ +#define SIOCGIWFREQ _SIOC(0x0026) /* Get channel/frequency (Hz) */ +#define SIOCSIWMODE _SIOC(0x0027) /* Set operation mode */ +#define SIOCGIWMODE _SIOC(0x0028) /* Get operation mode */ +#define SIOCSIWSENS _SIOC(0x0029) /* Set sensitivity (dBm) */ +#define SIOCGIWSENS _SIOC(0x002a) /* Get sensitivity (dBm) */ -#define SIOCGIWRANGE _SIOC(0x0028) /* Get range of parameters */ -#define SIOCGIWPRIV _SIOC(0x0029) /* Get private ioctl interface info */ -#define SIOCGIWSTATS _SIOC(0x002a) /* Get wireless stats */ +#define SIOCGIWRANGE _SIOC(0x002b) /* Get range of parameters */ +#define SIOCGIWPRIV _SIOC(0x002c) /* Get private ioctl interface info */ +#define SIOCGIWSTATS _SIOC(0x002d) /* Get wireless stats */ -#define SIOCSIWSPY _SIOC(0x002b) /* Set spy addresses */ -#define SIOCGIWSPY _SIOC(0x002c) /* Get spy info (quality of link) */ -#define SIOCSIWTHRSPY _SIOC(0x002d) /* Set spy threshold (spy event) */ -#define SIOCGIWTHRSPY _SIOC(0x002e) /* Get spy threshold */ +#define SIOCSIWSPY _SIOC(0x002e) /* Set spy addresses */ +#define SIOCGIWSPY _SIOC(0x002f) /* Get spy info (quality of link) */ +#define SIOCSIWTHRSPY _SIOC(0x0030) /* Set spy threshold (spy event) */ +#define SIOCGIWTHRSPY _SIOC(0x0031) /* Get spy threshold */ -#define SIOCSIWAP _SIOC(0x002f) /* Set access point MAC addresses */ -#define SIOCGIWAP _SIOC(0x0030) /* Get access point MAC addresses */ -#define SIOCGIWAPLIST _SIOC(0x0031) /* Deprecated in favor of scanning */ -#define SIOCSIWSCAN _SIOC(0x0032) /* Trigger scanning (list cells) */ -#define SIOCGIWSCAN _SIOC(0x0033) /* Get scanning results */ +#define SIOCSIWAP _SIOC(0x0032) /* Set access point MAC addresses */ +#define SIOCGIWAP _SIOC(0x0033) /* Get access point MAC addresses */ +#define SIOCGIWAPLIST _SIOC(0x0034) /* Deprecated in favor of scanning */ +#define SIOCSIWSCAN _SIOC(0x0035) /* Trigger scanning (list cells) */ +#define SIOCGIWSCAN _SIOC(0x0036) /* Get scanning results */ -#define SIOCSIWESSID _SIOC(0x0034) /* Set ESSID (network name) */ -#define SIOCGIWESSID _SIOC(0x0035) /* Get ESSID */ -#define SIOCSIWNICKN _SIOC(0x0036) /* Set node name/nickname */ -#define SIOCGIWNICKN _SIOC(0x0037) /* Get node name/nickname */ +#define SIOCSIWESSID _SIOC(0x0037) /* Set ESSID (network name) */ +#define SIOCGIWESSID _SIOC(0x0038) /* Get ESSID */ +#define SIOCSIWNICKN _SIOC(0x0039) /* Set node name/nickname */ +#define SIOCGIWNICKN _SIOC(0x003a) /* Get node name/nickname */ -#define SIOCSIWRATE _SIOC(0x0038) /* Set default bit rate (bps) */ -#define SIOCGIWRATE _SIOC(0x0039) /* Get default bit rate (bps) */ -#define SIOCSIWRTS _SIOC(0x003a) /* Set RTS/CTS threshold (bytes) */ -#define SIOCGIWRTS _SIOC(0x003b) /* Get RTS/CTS threshold (bytes) */ -#define SIOCSIWFRAG _SIOC(0x003c) /* Set fragmentation thr (bytes) */ -#define SIOCGIWFRAG _SIOC(0x003d) /* Get fragmentation thr (bytes) */ -#define SIOCSIWTXPOW _SIOC(0x003e) /* Set transmit power (dBm) */ -#define SIOCGIWTXPOW _SIOC(0x003f) /* Get transmit power (dBm) */ -#define SIOCSIWRETRY _SIOC(0x0040) /* Set retry limits and lifetime */ -#define SIOCGIWRETRY _SIOC(0x0041) /* Get retry limits and lifetime */ +#define SIOCSIWRATE _SIOC(0x003b) /* Set default bit rate (bps) */ +#define SIOCGIWRATE _SIOC(0x003c) /* Get default bit rate (bps) */ +#define SIOCSIWRTS _SIOC(0x003d) /* Set RTS/CTS threshold (bytes) */ +#define SIOCGIWRTS _SIOC(0x003e) /* Get RTS/CTS threshold (bytes) */ +#define SIOCSIWFRAG _SIOC(0x003f) /* Set fragmentation thr (bytes) */ +#define SIOCGIWFRAG _SIOC(0x0040) /* Get fragmentation thr (bytes) */ +#define SIOCSIWTXPOW _SIOC(0x0041) /* Set transmit power (dBm) */ +#define SIOCGIWTXPOW _SIOC(0x0042) /* Get transmit power (dBm) */ +#define SIOCSIWRETRY _SIOC(0x0043) /* Set retry limits and lifetime */ +#define SIOCGIWRETRY _SIOC(0x0044) /* Get retry limits and lifetime */ -#define SIOCSIWPOWER _SIOC(0x0042) /* Set Power Management settings */ -#define SIOCGIWPOWER _SIOC(0x0043) /* Get Power Management settings */ +#define SIOCSIWPOWER _SIOC(0x0045) /* Set Power Management settings */ +#define SIOCGIWPOWER _SIOC(0x0046) /* Get Power Management settings */ -#define SIOCSIWGENIE _SIOC(0x0044) /* Set generic IE */ -#define SIOCGIWGENIE _SIOC(0x0045) /* Get generic IE */ +#define SIOCSIWGENIE _SIOC(0x0047) /* Set generic IE */ +#define SIOCGIWGENIE _SIOC(0x0048) /* Get generic IE */ -#define SIOCSIWMLME _SIOC(0x0046) /* Request MLME operation */ +#define SIOCSIWMLME _SIOC(0x0049) /* Request MLME operation */ -#define SIOCSIWAUTH _SIOC(0x0047) /* Set authentication mode params */ -#define SIOCGIWAUTH _SIOC(0x0048) /* Get authentication mode params */ +#define SIOCSIWAUTH _SIOC(0x004a) /* Set authentication mode params */ +#define SIOCGIWAUTH _SIOC(0x004b) /* Get authentication mode params */ -#define SIOCSIWENCODEEXT _SIOC(0x0049) /* Set encoding token & mode */ -#define SIOCGIWENCODEEXT _SIOC(0x004a) /* Get encoding token & mode */ +#define SIOCSIWENCODEEXT _SIOC(0x004c) /* Set encoding token & mode */ +#define SIOCGIWENCODEEXT _SIOC(0x004d) /* Get encoding token & mode */ -#define SIOCSIWPMKSA _SIOC(0x004b) /* PMKSA cache operation */ +#define SIOCSIWPMKSA _SIOC(0x004e) /* PMKSA cache operation */ /* MDIO/MCD *****************************************************************/ -#define SIOCMIINOTIFY _SIOC(0x004b) /* Receive notificaion via signal on - * PHY state change */ -#define SIOCGMIIPHY _SIOC(0x004c) /* Get address of MII PHY in use */ -#define SIOCGMIIREG _SIOC(0x004d) /* Get a MII register via MDIO */ -#define SIOCSMIIREG _SIOC(0x004e) /* Set a MII register via MDIO */ +#define SIOCMIINOTIFY _SIOC(0x004f) /* Receive notificaion via signal on + * PHY state change */ +#define SIOCGMIIPHY _SIOC(0x0050) /* Get address of MII PHY in use */ +#define SIOCGMIIREG _SIOC(0x0051) /* Get a MII register via MDIO */ +#define SIOCSMIIREG _SIOC(0x0052) /* Set a MII register via MDIO */ /* Unix domain sockets ******************************************************/ -#define SIOCINQ _SIOC(0x004f) /* Returns the amount of queued unread - * data in the receive */ +#define SIOCINQ _SIOC(0x0053) /* Returns the amount of queued unread + * data in the receive */ /* Telnet driver ************************************************************/ -#define SIOCTELNET _SIOC(0x0050) /* Create a Telnet sessions. - * See include/nuttx/net/telnet.h */ +#define SIOCTELNET _SIOC(0x0054) /* Create a Telnet sessions. + * See include/nuttx/net/telnet.h */ /**************************************************************************** - * Type Definitions + * Pulbic Type Definitions ****************************************************************************/ -/* See include/net/if.h */ +/* See include/net/if.h, include/net/route.h, and include/net/arp.h */ /**************************************************************************** * Public Function Prototypes diff --git a/net/arp/arp.h b/net/arp/arp.h index 65846b0015..b32490b411 100644 --- a/net/arp/arp.h +++ b/net/arp/arp.h @@ -1,7 +1,7 @@ /**************************************************************************** * net/arp/arp.h * - * Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -420,15 +420,41 @@ FAR struct arp_entry *arp_find(in_addr_t ipaddr); * address of an existing association. * * Input parameters: - * pipaddr - Refers to an IP address uint16_t[2] in network order + * ipaddr - The IP address as an inaddr_t * ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN] * + * Returned Value: + * Zero (OK) if the ARP table entry was successfully modified. A negated + * errno value is returned on any error. + * * Assumptions - * Interrupts are disabled to assure exclusive access to the ARP table. + * The network is locked to assure exclusive access to the ARP table * ****************************************************************************/ -void arp_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr); +int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr); + +/**************************************************************************** + * Name: arp_hdr_update + * + * Description: + * Add the IP/HW address mapping to the ARP table -OR- change the IP + * address of an existing association. + * + * Input parameters: + * pipaddr - Refers to an IP address uint16_t[2] in network order + * ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN] + * + * Returned Value: + * Zero (OK) if the ARP table entry was successfully modified. A negated + * errno value is returned on any error. + * + * Assumptions + * The network is locked to assure exclusive access to the ARP table + * + ****************************************************************************/ + +void arp_hdr_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr); /**************************************************************************** * Name: arp_dump @@ -467,6 +493,7 @@ void arp_dump(FAR struct arp_hdr_s *arp); # define arp_find(i) (NULL) # define arp_delete(i) # define arp_update(i,m); +# define arp_hdr_update(i,m); # define arp_dump(arp) #endif /* CONFIG_NET_ARP */ diff --git a/net/arp/arp_arpin.c b/net/arp/arp_arpin.c index feb2dc0a06..883d2f2a42 100644 --- a/net/arp/arp_arpin.c +++ b/net/arp/arp_arpin.c @@ -132,7 +132,7 @@ void arp_arpin(FAR struct net_driver_s *dev) * with this host in the future. */ - arp_update(arp->ah_sipaddr, arp->ah_shwaddr); + arp_hdr_update(arp->ah_sipaddr, arp->ah_shwaddr); arp->ah_opcode = HTONS(ARP_REPLY); memcpy(arp->ah_dhwaddr, arp->ah_shwaddr, ETHER_ADDR_LEN); @@ -161,7 +161,7 @@ void arp_arpin(FAR struct net_driver_s *dev) { /* Yes... Insert the address mapping in the ARP table */ - arp_update(arp->ah_sipaddr, arp->ah_shwaddr); + arp_hdr_update(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 558af73f3a..febcaf82dc 100644 --- a/net/arp/arp_ipin.c +++ b/net/arp/arp_ipin.c @@ -101,7 +101,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_update(IPBUF->eh_srcipaddr, ETHBUF->src); + arp_hdr_update(IPBUF->eh_srcipaddr, ETHBUF->src); } } diff --git a/net/arp/arp_table.c b/net/arp/arp_table.c index a9e201c733..9113cf8e25 100644 --- a/net/arp/arp_table.c +++ b/net/arp/arp_table.c @@ -142,18 +142,21 @@ void arp_timer(void) * address of an existing association. * * Input parameters: - * pipaddr - Refers to an IP address uint16_t[2] + * ipaddr - The IP address as an inaddr_t * ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN] * + * Returned Value: + * Zero (OK) if the ARP table entry was successfully modified. A negated + * errno value is returned on any error. + * * Assumptions - * Interrupts are disabled + * The network is locked to assure exclusive access to the ARP table * ****************************************************************************/ -void arp_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr) +int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr) { struct arp_entry *tabptr = NULL; - in_addr_t ipaddr = net_ip4addr_conv32(pipaddr); int i; /* Walk through the ARP mapping table and try to find an entry to @@ -229,6 +232,35 @@ void arp_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr) tabptr->at_time = g_arptime; } +/**************************************************************************** + * Name: arp_hdr_update + * + * Description: + * Add the IP/HW address mapping to the ARP table -OR- change the IP + * address of an existing association. + * + * Input parameters: + * pipaddr - Refers to an IP address uint16_t[2] in network order + * ethaddr - Refers to a HW address uint8_t[IFHWADDRLEN] + * + * Returned Value: + * Zero (OK) if the ARP table entry was successfully modified. A negated + * errno value is returned on any error. + * + * Assumptions + * The network is locked to assure exclusive access to the ARP table + * + ****************************************************************************/ + +void arp_hdr_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr) +{ + in_addr_t ipaddr = net_ip4addr_conv32(pipaddr); + + /* Update the ARP table */ + + (void)arp_update(ipaddr, ethaddr); +} + /**************************************************************************** * Name: arp_find * diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index 24578e9f85..077cfa7b13 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -57,12 +57,14 @@ #include #include +#include #ifdef CONFIG_NET_IGMP # include "sys/sockio.h" # include "nuttx/net/igmp.h" #endif +#include "arp/arp.h" #include "socket/socket.h" #include "netdev/netdev.h" #include "devif/devif.h" @@ -808,6 +810,129 @@ static int netdev_imsfioctl(FAR struct socket *psock, int cmd, } #endif +/**************************************************************************** + * Name: netdev_arpioctl + * + * Description: + * Perform ARP table specific operations. + * + * Parameters: + * psock Socket structure + * dev Ethernet driver device structure + * cmd The ioctl command + * req The argument of the ioctl cmd + * + * Return: + * >=0 on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ARP +static int netdev_arpioctl(FAR struct socket *psock, int cmd, + FAR struct arpreq *req) +{ + int ret; + + /* Execute the command */ + + switch (cmd) + { + case SIOCSARP: /* Set an ARP mapping */ + { + if (req != NULL && + 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); + } + else + { + ret = -EINVAL; + } + } + break; + + case SIOCDARP: /* Delete an ARP mapping */ + { + if (req != NULL && req->arp_pa.sa_family == AF_INET) + { + FAR struct sockaddr_in *addr = + (FAR struct sockaddr_in *)&req->arp_pa; + + /* 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) + { + /* The ARP table is fixed size; an entry is deleted + * by nullifying its protocol address. + */ + + entry->at_ipaddr = 0; + ret = OK; + } + else + { + ret = -ENOENT; + } + } + else + { + ret = -EINVAL; + } + } + break; + + case SIOCGARP: /* Get an ARP mapping */ + { + if (req != NULL && req->arp_pa.sa_family == AF_INET) + { + FAR struct sockaddr_in *addr = + (FAR struct sockaddr_in *)&req->arp_pa; + + /* 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) + { + /* Return the mapped hardware address. */ + + req->arp_ha.sa_family = ARPHRD_ETHER; + memcpy(req->arp_ha.sa_data, + entry->at_ethaddr.ether_addr_octet, + ETHER_ADDR_LEN); + ret = OK; + } + else + { + ret = -ENOENT; + } + } + else + { + ret = -EINVAL; + } + } + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} +#endif + /**************************************************************************** * Name: netdev_rtioctl * @@ -972,6 +1097,18 @@ int netdev_ioctl(int sockfd, int cmd, unsigned long arg) ret = netdev_imsfioctl(psock, cmd, (FAR struct ip_msfilter *)((uintptr_t)arg)); } #endif + + /* Check for ARP table IOCTL commands */ + +#ifdef CONFIG_NET_ARP + if (ret == -ENOTTY) + { + ret = netdev_arpioctl(psock, cmd, (FAR struct arpreq *)((uintptr_t)arg)); + } +#endif + + /* Check for Routing table IOCTL commands */ + #ifdef CONFIG_NET_ROUTE if (ret == -ENOTTY) {