From 449290c8da5a83564cdc673d776d3d3f03f28065 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 11 Nov 2019 13:40:57 -0600 Subject: [PATCH] apps/examples/netlink_route: Add test/example of NETLINK_ROUTE 'get' opeations. apps/netutils/netlib: Fixes to NETLINK_ROUTE helpers found by testing with apps/examples/netlink_route. --- examples/netlink_route/.gitignore | 12 + examples/netlink_route/Kconfig | 30 ++ examples/netlink_route/Make.defs | 39 +++ examples/netlink_route/Makefile | 49 +++ examples/netlink_route/netlink_route_main.c | 346 ++++++++++++++++++++ include/netutils/netlib.h | 3 +- netutils/netlib/netlib_getarptab.c | 2 +- netutils/netlib/netlib_getdevs.c | 24 +- netutils/netlib/netlib_getnbtab.c | 2 +- netutils/netlib/netlib_getroute.c | 50 ++- 10 files changed, 529 insertions(+), 28 deletions(-) create mode 100644 examples/netlink_route/.gitignore create mode 100644 examples/netlink_route/Kconfig create mode 100644 examples/netlink_route/Make.defs create mode 100644 examples/netlink_route/Makefile create mode 100644 examples/netlink_route/netlink_route_main.c diff --git a/examples/netlink_route/.gitignore b/examples/netlink_route/.gitignore new file mode 100644 index 000000000..caa9bdef2 --- /dev/null +++ b/examples/netlink_route/.gitignore @@ -0,0 +1,12 @@ +/hello +/Make.dep +/.depend +/.built +/*.asm +/*.obj +/*.rel +/*.lst +/*.sym +/*.adb +/*.lib +/*.src diff --git a/examples/netlink_route/Kconfig b/examples/netlink_route/Kconfig new file mode 100644 index 000000000..3632576d5 --- /dev/null +++ b/examples/netlink_route/Kconfig @@ -0,0 +1,30 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config EXAMPLES_NETLINK_ROUTE + tristate "Netlink NETLINK_ROUTE test" + default n + depends on NETLINK_ROUTE + ---help--- + Enable the Netlink NETLINK_ROUTE test + +if EXAMPLES_NETLINK_ROUTE + +config EXAMPLES_NETLINK_ROUTE_PROGNAME + string "Program name" + default "netlink_route" + ---help--- + This is the name of the program that will be used when the NSH ELF + program is installed. + +config EXAMPLES_NETLINK_ROUTE_PRIORITY + int "Task priority" + default 100 + +config EXAMPLES_NETLINK_ROUTE_STACKSIZE + int "Stack size" + default 2048 + +endif diff --git a/examples/netlink_route/Make.defs b/examples/netlink_route/Make.defs new file mode 100644 index 000000000..21850f9b9 --- /dev/null +++ b/examples/netlink_route/Make.defs @@ -0,0 +1,39 @@ +############################################################################ +# apps/examples/netlink_route/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2015 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifneq ($(CONFIG_EXAMPLES_NETLINK_ROUTE),) +CONFIGURED_APPS += $(APPDIR)/examples/netlink_route +endif diff --git a/examples/netlink_route/Makefile b/examples/netlink_route/Makefile new file mode 100644 index 000000000..5a68c9632 --- /dev/null +++ b/examples/netlink_route/Makefile @@ -0,0 +1,49 @@ +############################################################################ +# apps/examples/netlink_route/Makefile +# +# Copyright (C) 2008, 2010-2013 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +# Netlink NETLINK_ROUTE built-in application info + +PROGNAME = $(CONFIG_EXAMPLES_NETLINK_ROUTE_PROGNAME) +PRIORITY = $(CONFIG_EXAMPLES_NETLINK_ROUTE_PRIORITY) +STACKSIZE = $(CONFIG_EXAMPLES_NETLINK_ROUTE_STACKSIZE) +MODULE = $(CONFIG_EXAMPLES_NETLINK_ROUTE) + +# Netlink NETLINK_ROUTE Example + +MAINSRC = netlink_route_main.c + +include $(APPDIR)/Application.mk diff --git a/examples/netlink_route/netlink_route_main.c b/examples/netlink_route/netlink_route_main.c new file mode 100644 index 000000000..2da814c36 --- /dev/null +++ b/examples/netlink_route/netlink_route_main.c @@ -0,0 +1,346 @@ +/**************************************************************************** + * examples/netlink_route/netlink_route_main.c + * + * Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "netutils/netlib.h" + +#ifdef CONFIG_NETLINK_ROUTE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX_DEVICES 16 +#define MAX_ROUTES 64 + +#ifdef CONFIG_NET_IPv6 +# define ROUTE_BUFSIZE INET6_ADDRSTRLEN +#else +# define ROUTE_BUFSIZE INET_ADDRSTRLEN +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void dump_devices(sa_family_t family) +{ + struct netlib_device_s devlist[MAX_DEVICES]; + ssize_t nentries; + int i; + + printf("\nDevice List"); + + /* Read the device list */ + + nentries = netlib_get_devices(devlist, MAX_DEVICES, family); + if (nentries < 0) + { + fprintf(stderr, "\nERROR: netlib_get_devices failed: %d\n", + (int)nentries); + return; + } + + printf(" (Entries: %ld)\n", (long)nentries); + + /* Dump the device list */ + + for (i = 0; i < nentries; i++) + { + FAR struct netlib_device_s *dev = &devlist[i]; + +#ifdef CONFIG_NETDEV_IFINDEX + printf(" Index: %2d ," dev->ifindex); +#else + printf(" "); +#endif + printf("Name: \"%s\"\n", dev->ifname); + } +} + +#ifdef CONFIG_NET_IPv6 +static void dump_neighbor(void) +{ + FAR struct neighbor_entry_s *nbtab; + FAR char buffer[INET6_ADDRSTRLEN]; + size_t allocsize; + ssize_t nentries; + int i; + int j; + + printf("\nIPv6 Neighbor Table"); + + /* Allocate a buffer to hold the neighbor table */ + + allocsize = CONFIG_NET_IPv6_NCONF_ENTRIES * + sizeof(struct neighbor_entry_s); + nbtab = (FAR struct neighbor_entry_s *)malloc(allocsize); + if (nbtab == NULL) + { + fprintf(stderr, "\nERROR: Failed to allocate neighbor table\n"); + return; + } + + /* Get the neighbor table */ + + nentries = netlib_get_nbtable(nbtab, CONFIG_NET_IPv6_NCONF_ENTRIES); + if (nentries < 0) + { + fprintf(stderr, "\nERROR: netlib_get_nbtable failed: %d\n", + (int)nentries); + return; + } + + printf(" (Entries: %ld)\n", (long)nentries); + + /* Show each neighbor */ + + for (i = 0; i < nentries; i++) + { + FAR struct neighbor_entry_s *nb = &nbtab[i]; + + (void)inet_ntop(AF_INET6, &nb->ne_ipaddr, buffer, INET6_ADDRSTRLEN); + printf(" Dest: %s MAC Type: %2u Size: %3u Addr: ", + buffer, nb->ne_addr.na_lltype, nb->ne_addr.na_llsize); + + for (j = 0; j < nb->ne_addr.na_llsize; j++) + { + if ((j + 1) >= nb->ne_addr.na_llsize) + { + printf("%02x", nb->ne_addr.u.na_addr); + } + else + { + printf("%02x.", nb->ne_addr.u.na_addr); + } + } + + for (; j < 7; j++) + { + printf(" "); + } + + if (j < 8) + { + printf(" "); + } + +#ifdef CONFIG_SYSTEM_TIME64 + printf("Time 0x%" PRIx64 "\n", nb->ne_time); +#else + printf("Time 0x%" PRIx32 "\n", nb->ne_time); +#endif + } + + free(nbtab); +} +#endif + +#ifdef CONFIG_NET_ARP +static void dump_arp(void) +{ + FAR struct arp_entry_s *arptab; + FAR char buffer[INET_ADDRSTRLEN]; + size_t allocsize; + ssize_t nentries; + int i; + int j; + + printf("\nIPv4 ARP Table"); + + /* Allocate a buffer to hold the ARP table */ + + allocsize = CONFIG_NET_ARPTAB_SIZE * sizeof(struct arp_entry_s); + arptab = (FAR struct arp_entry_s *)malloc(allocsize); + if (arptab == NULL) + { + fprintf(stderr, "\nERROR: Failed to allocate ARP table\n"); + return; + } + + /* Get the ARP table */ + + nentries = netlib_get_arptable(arptab, CONFIG_NET_ARPTAB_SIZE); + if (nentries < 0) + { + fprintf(stderr, "\nERROR: netlib_get_arptable failed: %d\n", + (int)nentries); + return; + } + + printf(" (Entries: %ld)\n", (long)nentries); + + /* Show each ARP table entry */ + + for (i = 0; i < nentries; i++) + { + FAR struct arp_entry_s *arp = &arptab[i]; + + (void)inet_ntop(AF_INET6, &arp->at_ipaddr, buffer, INET_ADDRSTRLEN); + printf(" Dest: %s MAC Addr: ", buffer); + + for (j = 0; j < ETHER_ADDR_LEN; j++) + { + if (j == (ETHER_ADDR_LEN - 1)) + { + printf("%02x", arp->at_ethaddr); + } + else + { + printf("%02x.", arp->at_ethaddr); + } + } + +#ifdef CONFIG_SYSTEM_TIME64 + printf("Time 0x%" PRIx64 "\n", arp->at_time); +#else + printf("Time 0x%" PRIx32 "\n", arp->at_time); +#endif + } + + free(arptab); +} +#endif + +#if CONFIG_NET_ROUTE +static void dump_route(sa_family_t family) +{ + FAR struct rtentry *rttab; + FAR char buffer[ROUTE_BUFSIZE]; + size_t allocsize; + ssize_t nentries; + int i; + + printf("\nIPv%c Routing Table", family == AF_INET ? '4' : '6'); + + /* Allocate a buffer to hold the routing table */ + + allocsize = MAX_ROUTES * sizeof(struct rtentry); + rttab = (FAR struct rtentry *)malloc(allocsize); + if (rttab == NULL) + { + fprintf(stderr, "\nERROR: Failed to allocate routing table\n"); + return; + } + + /* Get the routing table */ + + nentries = netlib_get_route(rttab, MAX_ROUTES, family); + if (nentries < 0) + { + fprintf(stderr, "\nERROR: netlib_get_route failed: %d\n", + (int)nentries); + return; + } + + printf(" (Entries: %ld)\n", (long)nentries); + + /* Show each routing table entry */ + + for (i = 0; i < nentries; i++) + { + FAR struct rtentry *rte = &rttab[i]; + + (void)inet_ntop(rte->rt_dst.ss_family, &rte->rt_dst.ss_data, buffer, + ROUTE_BUFSIZE); + printf(" Dest: %s ", buffer); + + (void)inet_ntop(rte->rt_gateway.ss_family, &rte->rt_gateway.ss_data, + buffer, ROUTE_BUFSIZE); + printf("Gateway: %s ", buffer); + + (void)inet_ntop(rte->rt_genmask.ss_family, &rte->rt_genmask.ss_data, + buffer, ROUTE_BUFSIZE); + printf("GenMASK: %s ", buffer); + printf("Flags: %04x\n", rte->rt_flags); + } + + free(rttab); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * netlink_route_main + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + dump_devices(AF_PACKET); + +#ifdef CONFIG_NET_IPv6 + dump_neighbor(); +#endif + +#ifdef CONFIG_NET_ARP + dump_arp(); +#endif + +#if CONFIG_NET_ROUTE +#ifdef CONFIG_NET_IPv4 + dump_route(AF_INET); +#endif +#ifdef CONFIG_NET_IPv6 + dump_route(AF_INET6); +#endif +#endif + + return EXIT_SUCCESS; +} + +#endif /* CONFIG_NETLINK_ROUTE */ diff --git a/include/netutils/netlib.h b/include/netutils/netlib.h index 79caa7604..e4010b6e6 100644 --- a/include/netutils/netlib.h +++ b/include/netutils/netlib.h @@ -321,8 +321,7 @@ struct neighbor_entry_s; ssize_t netlib_get_nbtable(FAR struct neighbor_entry_s *nbtab, unsigned int nentries); #endif - -#endif +#endif /* CONFIG_NET_IPv6 */ #ifdef CONFIG_NETDEV_WIRELESS_IOCTL int netlib_getessid(FAR const char *ifname, FAR char *essid, size_t idlen); diff --git a/netutils/netlib/netlib_getarptab.c b/netutils/netlib/netlib_getarptab.c index c80f94e1e..39c3c66cd 100644 --- a/netutils/netlib/netlib_getarptab.c +++ b/netutils/netlib/netlib_getarptab.c @@ -146,7 +146,7 @@ ssize_t netlib_get_arptable(FAR struct arp_entry_s *arptab, ret = bind(fd, (FAR const struct sockaddr *)&addr, sizeof( struct sockaddr_nl)); - if (fd < 0) + if (ret < 0) { int errcode = errno; fprintf(stderr, "ERROR: bind() failed: %d\n", errcode); diff --git a/netutils/netlib/netlib_getdevs.c b/netutils/netlib/netlib_getdevs.c index 5106bd44b..52e3d982a 100644 --- a/netutils/netlib/netlib_getdevs.c +++ b/netutils/netlib/netlib_getdevs.c @@ -107,7 +107,7 @@ ssize_t netlib_get_devices(FAR struct netlib_device_s *devlist, unsigned int thiseq; ssize_t nsent; ssize_t nrecvd; - size_t ncopied; + size_t ncopied = 0; pid_t pid; bool enddump; int fd; @@ -133,7 +133,7 @@ ssize_t netlib_get_devices(FAR struct netlib_device_s *devlist, ret = bind(fd, (FAR const struct sockaddr *)&addr, sizeof( struct sockaddr_nl)); - if (fd < 0) + if (ret < 0) { int errcode = errno; fprintf(stderr, "ERROR: bind() failed: %d\n", errcode); @@ -179,8 +179,7 @@ ssize_t netlib_get_devices(FAR struct netlib_device_s *devlist, /* Verify the data and transfer the device list to the caller */ - if (nrecvd != sizeof(struct netlib_recvfrom_response_s) || - resp.hdr.nlmsg_len < sizeof(struct nlmsghdr) || + if (resp.hdr.nlmsg_len < sizeof(struct nlmsghdr) || resp.hdr.nlmsg_len != nrecvd) { fprintf(stderr, "ERROR: Bad message\n"); @@ -211,14 +210,23 @@ ssize_t netlib_get_devices(FAR struct netlib_device_s *devlist, case RTM_NEWLINK: { FAR struct rtattr *attr; - int len; + unsigned int attrlen; + + /* Verify the expected message length */ + + if (nrecvd != sizeof(struct netlib_recvfrom_response_s)) + { + fprintf(stderr, "ERROR: Bad massage size: %ld\n", (long)nrecvd); + goto errout_with_socket; + } /* Decode the response */ - attr = &resp.attr; - len = RTA_PAYLOAD(attr); + attr = &resp.attr; + attrlen = resp.hdr.nlmsg_len - sizeof(struct nlmsghdr) - + sizeof(struct ifinfomsg); - for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) + for (; RTA_OK(attr, attrlen); attr = RTA_NEXT(attr, attrlen)) { switch (attr->rta_type) { diff --git a/netutils/netlib/netlib_getnbtab.c b/netutils/netlib/netlib_getnbtab.c index 39fcc14c5..acb070ca0 100644 --- a/netutils/netlib/netlib_getnbtab.c +++ b/netutils/netlib/netlib_getnbtab.c @@ -147,7 +147,7 @@ ssize_t netlib_get_nbtable(FAR struct neighbor_entry_s *nbtab, ret = bind(fd, (FAR const struct sockaddr *)&addr, sizeof( struct sockaddr_nl)); - if (fd < 0) + if (ret < 0) { int errcode = errno; fprintf(stderr, "ERROR: bind() failed: %d\n", errcode); diff --git a/netutils/netlib/netlib_getroute.c b/netutils/netlib/netlib_getroute.c index 0529c564c..954f6fffd 100644 --- a/netutils/netlib/netlib_getroute.c +++ b/netutils/netlib/netlib_getroute.c @@ -53,6 +53,12 @@ #if defined(CONFIG_NETLINK_ROUTE) && defined(CONFIG_NET_ROUTE) +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#define RXBUFFER_SIZE 64 + /**************************************************************************** * Private Types ****************************************************************************/ @@ -80,7 +86,7 @@ static int copy_address(FAR struct sockaddr_storage *dest, FAR void *src, unsigned int addrlen, unsigned int maxaddr, sa_family_t family) { - DEBUGASSERT(addrlen == maxaddr); + DEBUGASSERT(addrlen <= maxaddr); if (addrlen > maxaddr) { fprintf(stderr, "ERROR: Bad address length: %u\n", addrlen); @@ -118,7 +124,6 @@ ssize_t netlib_get_route(FAR struct rtentry *rtelist, unsigned int nentries, sa_family_t family) { struct netlib_sendto_request_s req; - struct netlib_recvfrom_response_s resp; struct sockaddr_nl addr; static unsigned int seqno = 0; unsigned int thiseq; @@ -131,6 +136,12 @@ ssize_t netlib_get_route(FAR struct rtentry *rtelist, int fd; int ret; + union + { + char rxbuffer[RXBUFFER_SIZE]; + struct netlib_recvfrom_response_s resp; + } u; + /* Create a NetLink socket with NETLINK_ROUTE protocol */ fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); @@ -151,7 +162,7 @@ ssize_t netlib_get_route(FAR struct rtentry *rtelist, ret = bind(fd, (FAR const struct sockaddr *)&addr, sizeof( struct sockaddr_nl)); - if (fd < 0) + if (ret < 0) { int errcode = errno; fprintf(stderr, "ERROR: bind() failed: %d\n", errcode); @@ -188,7 +199,7 @@ ssize_t netlib_get_route(FAR struct rtentry *rtelist, { /* Receive the next device response */ - nrecvd = recv(fd, &resp, sizeof(struct netlib_recvfrom_response_s), 0); + nrecvd = recv(fd, &u.rxbuffer, RXBUFFER_SIZE, 0); if (nrecvd < 0) { int errcode = errno; @@ -199,9 +210,8 @@ ssize_t netlib_get_route(FAR struct rtentry *rtelist, /* Verify the data and transfer the device list to the caller */ - if (nrecvd != sizeof(struct netlib_recvfrom_response_s) || - resp.hdr.nlmsg_len < sizeof(struct nlmsghdr) || - resp.hdr.nlmsg_len != nrecvd) + if (u.resp.hdr.nlmsg_len < sizeof(struct nlmsghdr) || + u.resp.hdr.nlmsg_len != nrecvd) { fprintf(stderr, "ERROR: Bad message\n"); ret = -EIO; @@ -213,7 +223,7 @@ ssize_t netlib_get_route(FAR struct rtentry *rtelist, * always be true). */ - if (resp.hdr.nlmsg_seq != thiseq) + if (u.resp.hdr.nlmsg_seq != thiseq) { fprintf(stderr, "ERROR: Bad sequence number in response\n"); ret = -EIO; @@ -222,7 +232,7 @@ ssize_t netlib_get_route(FAR struct rtentry *rtelist, /* This should be a routing table response */ - if (resp.rte.rtm_table != RT_TABLE_MAIN) + if (u.resp.rte.rtm_table != RT_TABLE_MAIN) { fprintf(stderr, "ERROR: Not a routing table response\n"); ret = -EIO; @@ -231,7 +241,7 @@ ssize_t netlib_get_route(FAR struct rtentry *rtelist, /* Copy the routing table entry to the caller's buffer */ - switch (resp.hdr.nlmsg_type) + switch (u.resp.hdr.nlmsg_type) { case NLMSG_DONE: enddump = true; @@ -244,19 +254,27 @@ ssize_t netlib_get_route(FAR struct rtentry *rtelist, { FAR struct rtentry *dest; FAR struct rtattr *attr; - int len; + unsigned int paylen; - DEBUGASSERT(resp.rte.rtm_family == family); + /* Verify the expected message length */ + + if (nrecvd <= sizeof(struct netlib_recvfrom_response_s) || + u.resp.rte.rtm_family != family) + { + fprintf(stderr, "ERROR: Bad massage size: %ld\n", (long)nrecvd); + goto errout_with_socket; + } /* Decode the response */ dest = &rtelist[ncopied]; memset(dest, 0, sizeof(struct rtentry)); - attr = &resp.attr; - len = RTA_PAYLOAD(attr); + attr = &u.resp.attr; + paylen = u.resp.hdr.nlmsg_len - sizeof(struct nlmsghdr) - + sizeof(struct rtmsg); - for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) + for (; RTA_OK(attr, paylen); attr = RTA_NEXT(attr, paylen)) { unsigned int attrlen = RTA_PAYLOAD(attr); @@ -306,7 +324,7 @@ ssize_t netlib_get_route(FAR struct rtentry *rtelist, default: fprintf(stderr, "ERROR: Message type %u, length %lu\n", - resp.hdr.nlmsg_type, (unsigned long)resp.hdr.nlmsg_len); + u.resp.hdr.nlmsg_type, (unsigned long)u.resp.hdr.nlmsg_len); ret = -EIO; goto errout_with_socket; }