Skip to content

Commit

Permalink
netlink: add netlink route notify support
Browse files Browse the repository at this point in the history
  • Loading branch information
anchao authored and gregory-nutt committed Apr 16, 2020
1 parent 6f1c86d commit 10acadb
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 38 deletions.
18 changes: 18 additions & 0 deletions net/netlink/netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@
#include "devif/devif.h"
#include "socket/socket.h"

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#ifndef CONFIG_NETLINK_ROUTE
#define netlink_device_notify(dev)
#endif

#ifdef CONFIG_NET_NETLINK

/****************************************************************************
Expand Down Expand Up @@ -277,6 +285,16 @@ ssize_t netlink_route_sendto(NETLINK_HANDLE handle,
size_t len, int flags,
FAR const struct sockaddr_nl *to,
socklen_t tolen);

/****************************************************************************
* Name: netlink_device_notify()
*
* Description:
* Perform the route broadcast for the NETLINK_ROUTE protocol.
*
****************************************************************************/

void netlink_device_notify(FAR struct net_driver_s *dev);
#endif

#undef EXTERN
Expand Down
131 changes: 93 additions & 38 deletions net/netlink/netlink_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,32 +184,21 @@ struct nlroute_info_s
****************************************************************************/

/****************************************************************************
* Name: netlink_device_callback
* Name: netlink_get_device
*
* Description:
* Handle one device.
* Generate one device response.
*
****************************************************************************/

#ifndef CONFIG_NETLINK_DISABLE_GETLINK
static int netlink_device_callback(FAR struct net_driver_s *dev,
FAR void *arg)
static FAR struct netlink_response_s *
netlink_get_device(FAR struct net_driver_s *dev,
FAR const struct nlroute_sendto_request_s *req)
{
FAR struct getlink_recvfrom_rsplist_s *alloc;
FAR struct getlink_recvfrom_response_s *resp;
FAR struct nlroute_info_s *info = arg;

DEBUGASSERT(dev != NULL && arg != NULL);
DEBUGASSERT(info->handle != NULL && info->req != NULL);

/* Check if the link is in the UP state */

if ((dev->d_flags & IFF_UP) == 0)
{
/* No.. skip this device */

return 0;
}
int up = IFF_IS_UP(dev->d_flags);

/* Allocate the response buffer */

Expand All @@ -218,20 +207,20 @@ static int netlink_device_callback(FAR struct net_driver_s *dev,
if (alloc == NULL)
{
nerr("ERROR: Failed to allocate response buffer.\n");
return -ENOMEM;
return NULL;
}

/* Initialize the response buffer */

resp = &alloc->payload;

resp->hdr.nlmsg_len = sizeof(struct getlink_recvfrom_response_s);
resp->hdr.nlmsg_type = RTM_NEWLINK;
resp->hdr.nlmsg_flags = info->req->hdr.nlmsg_flags;
resp->hdr.nlmsg_seq = info->req->hdr.nlmsg_seq;
resp->hdr.nlmsg_pid = info->req->hdr.nlmsg_pid;
resp->hdr.nlmsg_type = up ? RTM_NEWLINK : RTM_DELLINK;
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;

resp->iface.ifi_family = info->req->gen.rtgen_family;
resp->iface.ifi_family = req ? req->gen.rtgen_family : AF_PACKET;
resp->iface.ifi_type = dev->d_lltype;
#ifdef CONFIG_NETDEV_IFINDEX
resp->iface.ifi_index = dev->d_ifindex;
Expand All @@ -244,23 +233,22 @@ static int netlink_device_callback(FAR struct net_driver_s *dev,

strncpy((FAR char *)resp->data, dev->d_ifname, IFNAMSIZ);

/* Finally, add the data to the list of pending responses */
/* Finally, return the response */

netlink_add_response(info->handle, (FAR struct netlink_response_s *)alloc);
return OK;
return (FAR struct netlink_response_s *)alloc;
}
#endif

/****************************************************************************
* Name: netlink_response_terminator
* Name: netlink_get_terminator
*
* Description:
* Dump a list of all network devices of the specified type.
* Generate one NLMSG_DONE response.
*
****************************************************************************/

static int netlink_response_terminator(NETLINK_HANDLE handle,
FAR const struct nlroute_sendto_request_s *req)
static FAR struct netlink_response_s *
netlink_get_terminator(FAR const struct nlroute_sendto_request_s *req)
{
FAR struct netlink_response_s *resp;
FAR struct nlmsghdr *hdr;
Expand All @@ -271,19 +259,41 @@ static int netlink_response_terminator(NETLINK_HANDLE handle,
if (resp == NULL)
{
nerr("ERROR: Failed to allocate response terminator.\n");
return -ENOMEM;
return NULL;
}

/* Initialize and send the list terminator */

hdr = &resp->msg;
hdr->nlmsg_len = sizeof(struct nlmsghdr);
hdr->nlmsg_type = NLMSG_DONE;
hdr->nlmsg_flags = req->hdr.nlmsg_flags;
hdr->nlmsg_seq = req->hdr.nlmsg_seq;
hdr->nlmsg_pid = req->hdr.nlmsg_pid;
hdr->nlmsg_flags = req ? req->hdr.nlmsg_flags : 0;
hdr->nlmsg_seq = req ? req->hdr.nlmsg_seq : 0;
hdr->nlmsg_pid = req ? req->hdr.nlmsg_pid : 0;

/* Finally, add the response to the list of pending responses */
/* Finally, return the response */

return resp;
}

/****************************************************************************
* Name: netlink_add_terminator
*
* Description:
* Add one NLMSG_DONE response to handle.
*
****************************************************************************/

static int netlink_add_terminator(NETLINK_HANDLE handle,
FAR const struct nlroute_sendto_request_s *req)
{
FAR struct netlink_response_s * resp;

resp = netlink_get_terminator(req);
if (resp == NULL)
{
return -ENOMEM;
}

netlink_add_response(handle, resp);
return OK;
Expand All @@ -298,6 +308,22 @@ static int netlink_response_terminator(NETLINK_HANDLE handle,
****************************************************************************/

#ifndef CONFIG_NETLINK_DISABLE_GETLINK
static int netlink_device_callback(FAR struct net_driver_s *dev,
FAR void *arg)
{
FAR struct nlroute_info_s *info = arg;
FAR struct netlink_response_s * resp;

resp = netlink_get_device(dev, info->req);
if (resp == NULL)
{
return -ENOMEM;
}

netlink_add_response(info->handle, resp);
return OK;
}

static int netlink_get_devlist(NETLINK_HANDLE handle,
FAR const struct nlroute_sendto_request_s *req)
{
Expand All @@ -317,7 +343,7 @@ static int netlink_get_devlist(NETLINK_HANDLE handle,
return ret;
}

return netlink_response_terminator(handle, req);
return netlink_add_terminator(handle, req);
}
#endif

Expand Down Expand Up @@ -576,7 +602,7 @@ static int netlink_get_ipv4route(NETLINK_HANDLE handle,

/* Terminate the routing table */

return netlink_response_terminator(handle, req);
return netlink_add_terminator(handle, req);
}
#endif

Expand Down Expand Up @@ -669,7 +695,7 @@ static int netlink_get_ip6vroute(NETLINK_HANDLE handle,

/* Terminate the routing table */

return netlink_response_terminator(handle, req);
return netlink_add_terminator(handle, req);
}
#endif

Expand Down Expand Up @@ -784,4 +810,33 @@ ssize_t netlink_route_sendto(NETLINK_HANDLE handle,
return ret;
}

/****************************************************************************
* Name: netlink_device_notify()
*
* Description:
* Perform the route broadcast for the NETLINK_ROUTE protocol.
*
****************************************************************************/

#ifndef CONFIG_NETLINK_DISABLE_GETLINK
void netlink_device_notify(FAR struct net_driver_s *dev)
{
FAR struct netlink_response_s *resp;

DEBUGASSERT(dev != NULL);

resp = netlink_get_device(dev, NULL);
if (resp != NULL)
{
netlink_add_broadcast(RTNLGRP_LINK, resp);

resp = netlink_get_terminator(NULL);
if (resp != NULL)
{
netlink_add_broadcast(RTNLGRP_LINK, resp);
}
}
}
#endif

#endif /* CONFIG_NETLINK_ROUTE */

0 comments on commit 10acadb

Please sign in to comment.