ARP: Add IOCTL commands to manage the ARP table

This commit is contained in:
Gregory Nutt 2016-02-08 11:17:22 -06:00
parent 74db48202e
commit 0af9a197ac
9 changed files with 312 additions and 75 deletions

View File

@ -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).

2
TODO
View File

@ -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

View File

@ -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 <gnutt@nuttx.org>
*
* Derived from uIP with has a similar BSD-styple license:
@ -48,6 +48,7 @@
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <sys/socket.h>
#include <stdint.h>
#include <netinet/in.h>
@ -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
****************************************************************************/

View File

@ -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 <gnutt@nuttx.org>
*
* 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

View File

@ -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 <gnutt@nuttx.org>
*
* 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 */

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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
*

View File

@ -57,12 +57,14 @@
#include <netinet/in.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/arp.h>
#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)
{