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.

This commit is contained in:
Gregory Nutt 2019-11-11 13:40:57 -06:00
parent 0276088d5a
commit 449290c8da
10 changed files with 529 additions and 28 deletions

12
examples/netlink_route/.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
/hello
/Make.dep
/.depend
/.built
/*.asm
/*.obj
/*.rel
/*.lst
/*.sym
/*.adb
/*.lib
/*.src

View File

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

View File

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

View File

@ -0,0 +1,49 @@
############################################################################
# apps/examples/netlink_route/Makefile
#
# Copyright (C) 2008, 2010-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# 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

View File

@ -0,0 +1,346 @@
/****************************************************************************
* examples/netlink_route/netlink_route_main.c
*
* Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sys/types.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
#include <sched.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/route.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/neighbor.h>
#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 */

View File

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

View File

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

View File

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

View File

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

View File

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