mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
net/netlink: Add RTM neigh notify support
Signed-off-by: meijian <meijian@xiaomi.com>
This commit is contained in:
parent
34aeeb024c
commit
8eaefd2424
4 changed files with 333 additions and 132 deletions
|
|
@ -61,6 +61,7 @@
|
|||
#include <nuttx/net/ip.h>
|
||||
|
||||
#include "netdev/netdev.h"
|
||||
#include "netlink/netlink.h"
|
||||
#include "arp/arp.h"
|
||||
|
||||
#ifdef CONFIG_NET_ARP
|
||||
|
|
@ -208,6 +209,37 @@ static FAR struct arp_entry_s *arp_lookup(in_addr_t ipaddr,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arp_get_arpreq
|
||||
*
|
||||
* Description:
|
||||
* Translate (struct arp_entry_s) to (struct arpreq) for netlink notify.
|
||||
*
|
||||
* Input Parameters:
|
||||
* output - Location to return the ARP table copy
|
||||
* input - The arp entry in table
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NETLINK_ROUTE
|
||||
static void arp_get_arpreq(FAR struct arpreq *output,
|
||||
FAR struct arp_entry_s *input)
|
||||
{
|
||||
FAR struct sockaddr_in *outaddr;
|
||||
|
||||
DEBUGASSERT(output != NULL && input != NULL);
|
||||
|
||||
outaddr = (FAR struct sockaddr_in *)&output->arp_pa;
|
||||
outaddr->sin_family = AF_INET;
|
||||
outaddr->sin_port = 0;
|
||||
outaddr->sin_addr.s_addr = input->at_ipaddr;
|
||||
memcpy(output->arp_ha.sa_data, input->at_ethaddr.ether_addr_octet,
|
||||
sizeof(struct ether_addr));
|
||||
strlcpy((FAR char *)output->arp_dev, input->at_dev->d_ifname,
|
||||
sizeof(output->arp_dev));
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -237,6 +269,11 @@ int arp_update(FAR struct net_driver_s *dev, in_addr_t ipaddr,
|
|||
FAR const uint8_t *ethaddr)
|
||||
{
|
||||
FAR struct arp_entry_s *tabptr = &g_arptable[0];
|
||||
#ifdef CONFIG_NETLINK_ROUTE
|
||||
struct arpreq arp_notify;
|
||||
bool found = false;
|
||||
bool new_entry;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
/* Walk through the ARP mapping table and try to find an entry to
|
||||
|
|
@ -257,6 +294,9 @@ int arp_update(FAR struct net_driver_s *dev, in_addr_t ipaddr,
|
|||
/* An old entry found, break. */
|
||||
|
||||
tabptr = &g_arptable[i];
|
||||
#ifdef CONFIG_NETLINK_ROUTE
|
||||
found = true;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
|
@ -267,6 +307,21 @@ int arp_update(FAR struct net_driver_s *dev, in_addr_t ipaddr,
|
|||
}
|
||||
}
|
||||
|
||||
/* When overwite old entry, notify old entry RTM_DELNEIGH */
|
||||
|
||||
#ifdef CONFIG_NETLINK_ROUTE
|
||||
if (!found && tabptr->at_ipaddr != 0)
|
||||
{
|
||||
arp_get_arpreq(&arp_notify, tabptr);
|
||||
netlink_neigh_notify(&arp_notify, RTM_DELNEIGH, AF_INET);
|
||||
}
|
||||
|
||||
/* Need to notify when entry is not found or changes in table */
|
||||
|
||||
new_entry = !found || memcmp(tabptr->at_ethaddr.ether_addr_octet,
|
||||
ethaddr, ETHER_ADDR_LEN) != 0;
|
||||
#endif
|
||||
|
||||
/* Now, tabptr is the ARP table entry which we will fill with the new
|
||||
* information.
|
||||
*/
|
||||
|
|
@ -275,6 +330,17 @@ int arp_update(FAR struct net_driver_s *dev, in_addr_t ipaddr,
|
|||
memcpy(tabptr->at_ethaddr.ether_addr_octet, ethaddr, ETHER_ADDR_LEN);
|
||||
tabptr->at_dev = dev;
|
||||
tabptr->at_time = clock_systime_ticks();
|
||||
|
||||
/* Notify the new entry */
|
||||
|
||||
#ifdef CONFIG_NETLINK_ROUTE
|
||||
if (new_entry)
|
||||
{
|
||||
arp_get_arpreq(&arp_notify, tabptr);
|
||||
netlink_neigh_notify(&arp_notify, RTM_NEWNEIGH, AF_INET);
|
||||
}
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
@ -392,12 +458,21 @@ int arp_find(in_addr_t ipaddr, FAR uint8_t *ethaddr,
|
|||
int arp_delete(in_addr_t ipaddr, FAR struct net_driver_s *dev)
|
||||
{
|
||||
FAR struct arp_entry_s *tabptr;
|
||||
|
||||
#ifdef CONFIG_NETLINK_ROUTE
|
||||
struct arpreq arp_notify;
|
||||
#endif
|
||||
/* Check if the IPv4 address is in the ARP table. */
|
||||
|
||||
tabptr = arp_lookup(ipaddr, dev);
|
||||
if (tabptr != NULL)
|
||||
{
|
||||
/* Notify to netlink */
|
||||
|
||||
#ifdef CONFIG_NETLINK_ROUTE
|
||||
arp_get_arpreq(&arp_notify, tabptr);
|
||||
netlink_neigh_notify(&arp_notify, RTM_DELNEIGH, AF_INET);
|
||||
#endif
|
||||
|
||||
/* Yes.. Set the IP address to zero to "delete" it */
|
||||
|
||||
tabptr->at_ipaddr = 0;
|
||||
|
|
@ -459,7 +534,6 @@ unsigned int arp_snapshot(FAR struct arpreq *snapshot,
|
|||
unsigned int nentries)
|
||||
{
|
||||
FAR struct arp_entry_s *tabptr;
|
||||
FAR struct sockaddr_in *outaddr;
|
||||
clock_t now;
|
||||
unsigned int ncopied;
|
||||
int i;
|
||||
|
|
@ -474,16 +548,7 @@ unsigned int arp_snapshot(FAR struct arpreq *snapshot,
|
|||
if (tabptr->at_ipaddr != 0 &&
|
||||
now - tabptr->at_time <= ARP_MAXAGE_TICK)
|
||||
{
|
||||
outaddr = (FAR struct sockaddr_in *)&snapshot[ncopied].arp_pa;
|
||||
outaddr->sin_family = AF_INET;
|
||||
outaddr->sin_port = 0;
|
||||
outaddr->sin_addr.s_addr = tabptr->at_ipaddr;
|
||||
memcpy(snapshot[ncopied].arp_ha.sa_data,
|
||||
tabptr->at_ethaddr.ether_addr_octet,
|
||||
sizeof(struct ether_addr));
|
||||
strlcpy((FAR char *)snapshot[ncopied].arp_dev,
|
||||
tabptr->at_dev->d_ifname,
|
||||
sizeof(snapshot[ncopied].arp_dev));
|
||||
arp_get_arpreq(&snapshot[ncopied], tabptr);
|
||||
ncopied++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include <nuttx/net/neighbor.h>
|
||||
|
||||
#include "netdev/netdev.h"
|
||||
#include "netlink/netlink.h"
|
||||
#include "neighbor/neighbor.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -65,6 +66,8 @@ void neighbor_add(FAR struct net_driver_s *dev, FAR net_ipv6addr_t ipaddr,
|
|||
uint8_t lltype;
|
||||
clock_t oldest_time;
|
||||
int oldest_ndx;
|
||||
bool found = false;
|
||||
bool new_entry;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(dev != NULL && addr != NULL);
|
||||
|
|
@ -85,6 +88,7 @@ void neighbor_add(FAR struct net_driver_s *dev, FAR net_ipv6addr_t ipaddr,
|
|||
net_ipv6addr_cmp(g_neighbors[i].ne_ipaddr, ipaddr))
|
||||
{
|
||||
oldest_ndx = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -95,6 +99,19 @@ void neighbor_add(FAR struct net_driver_s *dev, FAR net_ipv6addr_t ipaddr,
|
|||
}
|
||||
}
|
||||
|
||||
/* When overwite old entry, need to notify RTM_DELNEIGH */
|
||||
|
||||
if (!found && g_neighbors[oldest_ndx].ne_time != 0)
|
||||
{
|
||||
netlink_neigh_notify(&g_neighbors[oldest_ndx], RTM_DELNEIGH,
|
||||
AF_INET6);
|
||||
}
|
||||
|
||||
/* Need to notify when entry is not found or changes in table */
|
||||
|
||||
new_entry = !found || memcmp(&g_neighbors[oldest_ndx].ne_addr.u, addr,
|
||||
g_neighbors[oldest_ndx].ne_addr.na_llsize) != 0;
|
||||
|
||||
/* Use the oldest or first free entry (either pointed to by the
|
||||
* "oldest_ndx" variable).
|
||||
*/
|
||||
|
|
@ -109,6 +126,14 @@ void neighbor_add(FAR struct net_driver_s *dev, FAR net_ipv6addr_t ipaddr,
|
|||
memcpy(&g_neighbors[oldest_ndx].ne_addr.u, addr,
|
||||
g_neighbors[oldest_ndx].ne_addr.na_llsize);
|
||||
|
||||
/* Notify the new entry */
|
||||
|
||||
if (new_entry)
|
||||
{
|
||||
netlink_neigh_notify(&g_neighbors[oldest_ndx], RTM_NEWNEIGH,
|
||||
AF_INET6);
|
||||
}
|
||||
|
||||
/* Dump the contents of the new entry */
|
||||
|
||||
neighbor_dumpentry("Added entry", &g_neighbors[oldest_ndx]);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
# define netlink_device_notify(dev)
|
||||
# define netlink_device_notify_ipaddr(dev, type, domain, addr, preflen)
|
||||
# define netlink_route_notify(route, type, domain)
|
||||
# define netlink_neigh_notify(neigh, type, domain)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_NETLINK
|
||||
|
|
@ -532,6 +533,25 @@ void netlink_device_notify_ipaddr(FAR struct net_driver_s *dev,
|
|||
void netlink_route_notify(FAR const void *route, int type, int domain);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_neigh_notify()
|
||||
*
|
||||
* Description:
|
||||
* Perform the neigh broadcast for the NETLINK_ROUTE protocol.
|
||||
*
|
||||
* Input Parameters:
|
||||
* neigh - The ARP entry or neighbour entry
|
||||
* type - The type of the message, RTM_*NEIGH
|
||||
* domain - The domain of the message
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NETLINK_DISABLE_GETNEIGH)
|
||||
# define netlink_neigh_notify(neigh, type, domain)
|
||||
#else
|
||||
void netlink_neigh_notify(FAR const void *neigh, int type, int domain);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nla_next
|
||||
*
|
||||
|
|
|
|||
|
|
@ -489,7 +489,7 @@ static int netlink_get_devlist(NETLINK_HANDLE handle,
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_get_arptable()
|
||||
* Name: netlink_fill_arptable()
|
||||
*
|
||||
* Description:
|
||||
* Return the entire ARP table.
|
||||
|
|
@ -497,162 +497,229 @@ static int netlink_get_devlist(NETLINK_HANDLE handle,
|
|||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NET_ARP) && !defined(CONFIG_NETLINK_DISABLE_GETNEIGH)
|
||||
static int netlink_get_arptable(NETLINK_HANDLE handle,
|
||||
FAR const struct nlroute_sendto_request_s *req)
|
||||
static size_t netlink_fill_arptable(
|
||||
FAR struct getneigh_recvfrom_rsplist_s **entry)
|
||||
{
|
||||
FAR struct getneigh_recvfrom_rsplist_s *entry;
|
||||
unsigned int ncopied;
|
||||
size_t allocsize;
|
||||
size_t tabsize;
|
||||
size_t rspsize;
|
||||
|
||||
/* Lock the network so that the ARP table will be stable, then copy
|
||||
* the ARP table into the allocated memory.
|
||||
*/
|
||||
|
||||
net_lock();
|
||||
ncopied = arp_snapshot((FAR struct arpreq *)(*entry)->payload.data,
|
||||
CONFIG_NET_ARPTAB_SIZE);
|
||||
net_unlock();
|
||||
|
||||
/* Now we have the real number of valid entries in the ARP table and
|
||||
* we can trim the allocation.
|
||||
*/
|
||||
|
||||
if (ncopied > 0)
|
||||
{
|
||||
FAR struct getneigh_recvfrom_rsplist_s *newentry;
|
||||
|
||||
tabsize = ncopied * sizeof(struct arpreq);
|
||||
rspsize = SIZEOF_NLROUTE_RECVFROM_RESPONSE_S(tabsize);
|
||||
allocsize = SIZEOF_NLROUTE_RECVFROM_RSPLIST_S(tabsize);
|
||||
|
||||
newentry = kmm_realloc(*entry, allocsize);
|
||||
|
||||
if (newentry != NULL)
|
||||
{
|
||||
*entry = newentry;
|
||||
}
|
||||
|
||||
(*entry)->payload.hdr.nlmsg_len = rspsize;
|
||||
(*entry)->payload.attr.rta_len = RTA_LENGTH(tabsize);
|
||||
}
|
||||
|
||||
return ncopied;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_fill_nbtable()
|
||||
*
|
||||
* Description:
|
||||
* Return the entire IPv6 neighbor table.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NET_IPv6) && !defined(CONFIG_NETLINK_DISABLE_GETNEIGH)
|
||||
static size_t netlink_fill_nbtable(
|
||||
FAR struct getneigh_recvfrom_rsplist_s **entry)
|
||||
{
|
||||
unsigned int ncopied;
|
||||
size_t allocsize;
|
||||
size_t tabsize;
|
||||
size_t rspsize;
|
||||
|
||||
/* Lock the network so that the Neighbor table will be stable, then
|
||||
* copy the Neighbor table into the allocated memory.
|
||||
*/
|
||||
|
||||
net_lock();
|
||||
ncopied = neighbor_snapshot(
|
||||
(FAR struct neighbor_entry_s *)(*entry)->payload.data,
|
||||
CONFIG_NET_IPv6_NCONF_ENTRIES);
|
||||
net_unlock();
|
||||
|
||||
/* Now we have the real number of valid entries in the Neighbor table
|
||||
* and we can trim the allocation.
|
||||
*/
|
||||
|
||||
if (ncopied > 0)
|
||||
{
|
||||
FAR struct getneigh_recvfrom_rsplist_s *newentry;
|
||||
|
||||
tabsize = ncopied * sizeof(struct neighbor_entry_s);
|
||||
rspsize = SIZEOF_NLROUTE_RECVFROM_RESPONSE_S(tabsize);
|
||||
allocsize = SIZEOF_NLROUTE_RECVFROM_RSPLIST_S(tabsize);
|
||||
|
||||
newentry = kmm_realloc(*entry, allocsize);
|
||||
|
||||
if (newentry != NULL)
|
||||
{
|
||||
*entry = newentry;
|
||||
}
|
||||
|
||||
(*entry)->payload.hdr.nlmsg_len = rspsize;
|
||||
(*entry)->payload.attr.rta_len = RTA_LENGTH(tabsize);
|
||||
}
|
||||
|
||||
return ncopied;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_fill_nbtable()
|
||||
*
|
||||
* Description:
|
||||
* Return the entire IPv6 neighbor table.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_NETLINK_DISABLE_GETNEIGH)
|
||||
static FAR struct netlink_response_s *
|
||||
netlink_get_neighbor(FAR const void *neigh, int domain, int type,
|
||||
FAR const struct nlroute_sendto_request_s *req)
|
||||
{
|
||||
FAR struct getneigh_recvfrom_rsplist_s *alloc;
|
||||
FAR struct getneigh_recvfrom_response_s *resp;
|
||||
size_t allocsize;
|
||||
size_t tabsize;
|
||||
size_t tabnum;
|
||||
size_t rspsize;
|
||||
|
||||
/* Preallocate memory to hold the maximum sized ARP table
|
||||
* REVISIT: This is probably excessively large and could cause false
|
||||
* memory out conditions. A better approach would be to actually count
|
||||
* the number of valid entries in the ARP table.
|
||||
*/
|
||||
|
||||
tabsize = CONFIG_NET_ARPTAB_SIZE * sizeof(struct arpreq);
|
||||
#if defined(CONFIG_NET_ARP)
|
||||
if (domain == AF_INET)
|
||||
{
|
||||
tabnum = req ? CONFIG_NET_ARPTAB_SIZE : 1;
|
||||
tabsize = tabnum * sizeof(struct arpreq);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPv6)
|
||||
if (domain == AF_INET6)
|
||||
{
|
||||
tabnum = req ? CONFIG_NET_IPv6_NCONF_ENTRIES : 1;
|
||||
tabsize = tabnum * sizeof(struct neighbor_entry_s);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rspsize = SIZEOF_NLROUTE_RECVFROM_RESPONSE_S(tabsize);
|
||||
allocsize = SIZEOF_NLROUTE_RECVFROM_RSPLIST_S(tabsize);
|
||||
|
||||
entry = kmm_zalloc(allocsize);
|
||||
if (entry == NULL)
|
||||
/* Allocate the response buffer */
|
||||
|
||||
alloc = kmm_zalloc(allocsize);
|
||||
if (alloc == NULL)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate response buffer.\n");
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Populate the entry */
|
||||
/* Initialize the response buffer */
|
||||
|
||||
memcpy(&entry->payload.hdr, &req->hdr, sizeof(struct nlmsghdr));
|
||||
entry->payload.hdr.nlmsg_len = rspsize;
|
||||
entry->payload.msg.ndm_family = req->gen.rtgen_family;
|
||||
entry->payload.attr.rta_len = RTA_LENGTH(tabsize);
|
||||
resp = &alloc->payload;
|
||||
resp->hdr.nlmsg_len = rspsize;
|
||||
resp->hdr.nlmsg_type = type;
|
||||
resp->hdr.nlmsg_flags = req ? req->hdr.nlmsg_flags : 0;
|
||||
resp->hdr.nlmsg_seq = req ? req->hdr.nlmsg_seq : 0;
|
||||
resp->hdr.nlmsg_pid = req ? req->hdr.nlmsg_pid : 0;
|
||||
|
||||
/* Lock the network so that the ARP table will be stable, then copy
|
||||
* the ARP table into the allocated memory.
|
||||
*/
|
||||
resp->msg.ndm_family = domain;
|
||||
resp->attr.rta_len = RTA_LENGTH(tabsize);
|
||||
|
||||
net_lock();
|
||||
ncopied = arp_snapshot((FAR struct arpreq *)entry->payload.data,
|
||||
CONFIG_NET_ARPTAB_SIZE);
|
||||
net_unlock();
|
||||
/* Copy neigh or arp entries into resp data */
|
||||
|
||||
/* Now we have the real number of valid entries in the ARP table and
|
||||
* we can trim the allocation.
|
||||
*/
|
||||
|
||||
if (ncopied < CONFIG_NET_ARPTAB_SIZE)
|
||||
if (req == NULL)
|
||||
{
|
||||
FAR struct getneigh_recvfrom_rsplist_s *newentry;
|
||||
|
||||
tabsize = ncopied * sizeof(struct arpreq);
|
||||
rspsize = SIZEOF_NLROUTE_RECVFROM_RESPONSE_S(tabsize);
|
||||
allocsize = SIZEOF_NLROUTE_RECVFROM_RSPLIST_S(tabsize);
|
||||
|
||||
newentry = (FAR struct getneigh_recvfrom_rsplist_s *)
|
||||
kmm_realloc(entry, allocsize);
|
||||
|
||||
if (newentry != NULL)
|
||||
if (neigh == NULL)
|
||||
{
|
||||
entry = newentry;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry->payload.hdr.nlmsg_len = rspsize;
|
||||
entry->payload.attr.rta_len = RTA_LENGTH(tabsize);
|
||||
/* Only one entry need to notify */
|
||||
|
||||
memcpy(resp->data, neigh, tabsize);
|
||||
}
|
||||
#if defined(CONFIG_NET_ARP)
|
||||
else if (domain == AF_INET)
|
||||
{
|
||||
tabnum = netlink_fill_arptable(&alloc);
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPv6)
|
||||
else if (domain == AF_INET6)
|
||||
{
|
||||
tabnum = netlink_fill_nbtable(&alloc);
|
||||
}
|
||||
|
||||
/* Finally, add the data to the list of pending responses */
|
||||
|
||||
netlink_add_response(handle, (FAR struct netlink_response_s *)entry);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_get_nbtable()
|
||||
*
|
||||
* Description:
|
||||
* Return the entire IPv6 neighbor table.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* If no entry in table, just free alloc */
|
||||
|
||||
#if defined(CONFIG_NET_IPv6) && !defined(CONFIG_NETLINK_DISABLE_GETNEIGH)
|
||||
static int netlink_get_nbtable(NETLINK_HANDLE handle,
|
||||
if (tabnum <= 0)
|
||||
{
|
||||
kmm_free(alloc);
|
||||
nwarn("WARNING: Failed to get entry in %s table.\n",
|
||||
domain == AF_INET ? "ARP" : "neighbor");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (FAR struct netlink_response_s *)alloc;
|
||||
}
|
||||
|
||||
static int netlink_get_neighborlist(NETLINK_HANDLE handle, int domain,
|
||||
FAR const struct nlroute_sendto_request_s *req)
|
||||
{
|
||||
FAR struct getneigh_recvfrom_rsplist_s *entry;
|
||||
unsigned int ncopied;
|
||||
size_t allocsize;
|
||||
size_t tabsize;
|
||||
size_t rspsize;
|
||||
FAR struct netlink_response_s *resp;
|
||||
|
||||
/* Preallocate memory to hold the maximum sized Neighbor table
|
||||
* REVISIT: This is probably excessively large and could cause false
|
||||
* memory out conditions. A better approach would be to actually count
|
||||
* the number of valid entries in the Neighbor table.
|
||||
*/
|
||||
|
||||
tabsize = CONFIG_NET_IPv6_NCONF_ENTRIES *
|
||||
sizeof(struct neighbor_entry_s);
|
||||
rspsize = SIZEOF_NLROUTE_RECVFROM_RESPONSE_S(tabsize);
|
||||
allocsize = SIZEOF_NLROUTE_RECVFROM_RSPLIST_S(tabsize);
|
||||
|
||||
entry = kmm_zalloc(allocsize);
|
||||
if (entry == NULL)
|
||||
resp = netlink_get_neighbor(NULL, domain, RTM_GETNEIGH, req);
|
||||
if (resp == NULL)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate response buffer.\n");
|
||||
return -ENOMEM;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Populate the entry */
|
||||
netlink_add_response(handle, resp);
|
||||
|
||||
memcpy(&entry->payload.hdr, &req->hdr, sizeof(struct nlmsghdr));
|
||||
entry->payload.hdr.nlmsg_len = rspsize;
|
||||
entry->payload.msg.ndm_family = req->gen.rtgen_family;
|
||||
entry->payload.attr.rta_len = RTA_LENGTH(tabsize);
|
||||
|
||||
/* Lock the network so that the Neighbor table will be stable, then
|
||||
* copy the Neighbor table into the allocated memory.
|
||||
*/
|
||||
|
||||
net_lock();
|
||||
ncopied = neighbor_snapshot(
|
||||
(FAR struct neighbor_entry_s *)entry->payload.data,
|
||||
CONFIG_NET_IPv6_NCONF_ENTRIES);
|
||||
net_unlock();
|
||||
|
||||
/* Now we have the real number of valid entries in the Neighbor table
|
||||
* and we can trim the allocation.
|
||||
*/
|
||||
|
||||
if (ncopied < CONFIG_NET_IPv6_NCONF_ENTRIES)
|
||||
{
|
||||
FAR struct getneigh_recvfrom_rsplist_s *newentry;
|
||||
|
||||
tabsize = ncopied * sizeof(struct neighbor_entry_s);
|
||||
rspsize = SIZEOF_NLROUTE_RECVFROM_RESPONSE_S(tabsize);
|
||||
allocsize = SIZEOF_NLROUTE_RECVFROM_RSPLIST_S(tabsize);
|
||||
|
||||
newentry = (FAR struct getneigh_recvfrom_rsplist_s *)
|
||||
kmm_realloc(entry, allocsize);
|
||||
|
||||
if (newentry != NULL)
|
||||
{
|
||||
entry = newentry;
|
||||
}
|
||||
|
||||
entry->payload.hdr.nlmsg_len = rspsize;
|
||||
entry->payload.attr.rta_len = RTA_LENGTH(tabsize);
|
||||
}
|
||||
|
||||
/* Finally, add the response to the list of pending responses */
|
||||
|
||||
netlink_add_response(handle, (FAR struct netlink_response_s *)entry);
|
||||
return OK;
|
||||
return netlink_add_terminator(handle, &req->hdr, 0);
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_NETLINK_DISABLE_GETNEIGH */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_ipv4_route
|
||||
|
|
@ -1234,7 +1301,7 @@ ssize_t netlink_route_sendto(NETLINK_HANDLE handle,
|
|||
|
||||
if (req->gen.rtgen_family == AF_INET)
|
||||
{
|
||||
ret = netlink_get_arptable(handle, req);
|
||||
ret = netlink_get_neighborlist(handle, AF_INET, req);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
@ -1244,7 +1311,7 @@ ssize_t netlink_route_sendto(NETLINK_HANDLE handle,
|
|||
|
||||
if (req->gen.rtgen_family == AF_INET6)
|
||||
{
|
||||
ret = netlink_get_nbtable(handle, req);
|
||||
ret = netlink_get_neighborlist(handle, AF_INET6, req);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
@ -1491,4 +1558,28 @@ void netlink_route_notify(FAR const void *route, int type, int domain)
|
|||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_neigh_notify()
|
||||
*
|
||||
* Description:
|
||||
* Perform the neigh broadcast for the NETLINK_ROUTE protocol.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NETLINK_DISABLE_GETNEIGH
|
||||
void netlink_neigh_notify(FAR const void *neigh, int type, int domain)
|
||||
{
|
||||
FAR struct netlink_response_s *resp;
|
||||
|
||||
resp = netlink_get_neighbor(neigh, domain, type, NULL);
|
||||
if (resp == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
netlink_add_broadcast(RTNLGRP_NEIGH, resp);
|
||||
netlink_add_terminator(NULL, NULL, RTNLGRP_NEIGH);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NETLINK_ROUTE */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue