|  | /* | 
|  | * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com> | 
|  | * Copyright (c) 2017-2018 The strace developers. | 
|  | * All rights reserved. | 
|  | * | 
|  | * 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. The name of the author may not be used to endorse or promote products | 
|  | *    derived from this software without specific prior written permission. | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "tests.h" | 
|  | #include <stdio.h> | 
|  | #include <stdint.h> | 
|  | #include <string.h> | 
|  | #include <unistd.h> | 
|  | #include <sys/socket.h> | 
|  | #include <netinet/in.h> | 
|  | #include "test_netlink.h" | 
|  | #ifdef HAVE_STRUCT_DCBMSG | 
|  | # include <linux/dcbnl.h> | 
|  | #endif | 
|  | #ifdef HAVE_LINUX_FIB_RULES_H | 
|  | # include <linux/fib_rules.h> | 
|  | #endif | 
|  | #ifdef HAVE_LINUX_IF_ADDR_H | 
|  | # include <linux/if_addr.h> | 
|  | #endif | 
|  | #ifdef HAVE_STRUCT_IFADDRLBLMSG | 
|  | # include <linux/if_addrlabel.h> | 
|  | #endif | 
|  | #include <linux/if_arp.h> | 
|  | #include <linux/if_bridge.h> | 
|  | #include <linux/ip.h> | 
|  | #ifdef HAVE_LINUX_NEIGHBOUR_H | 
|  | # include <linux/neighbour.h> | 
|  | #endif | 
|  | #ifdef HAVE_STRUCT_NETCONFMSG | 
|  | # include <linux/netconf.h> | 
|  | #endif | 
|  | #include <linux/rtnetlink.h> | 
|  |  | 
|  | #define TEST_NL_ROUTE(fd_, nlh0_, type_, obj_, print_family_, ...)	\ | 
|  | do {								\ | 
|  | /* family and string */					\ | 
|  | TEST_NETLINK((fd_), (nlh0_),				\ | 
|  | type_, NLM_F_REQUEST,			\ | 
|  | sizeof(obj_) - 1,				\ | 
|  | &(obj_), sizeof(obj_) - 1,			\ | 
|  | (print_family_);				\ | 
|  | printf(", ...}"));				\ | 
|  | \ | 
|  | /* sizeof(obj_) */					\ | 
|  | TEST_NETLINK((fd_), (nlh0_),				\ | 
|  | type_, NLM_F_REQUEST,			\ | 
|  | sizeof(obj_), &(obj_), sizeof(obj_),	\ | 
|  | (print_family_);				\ | 
|  | __VA_ARGS__);				\ | 
|  | \ | 
|  | /* short read of sizeof(obj_) */			\ | 
|  | TEST_NETLINK((fd_), (nlh0_),				\ | 
|  | type_, NLM_F_REQUEST,			\ | 
|  | sizeof(obj_), &(obj_), sizeof(obj_) - 1,	\ | 
|  | (print_family_);				\ | 
|  | printf(", %p}",				\ | 
|  | NLMSG_DATA(TEST_NETLINK_nlh) + 1));	\ | 
|  | } while (0) | 
|  |  | 
|  | static void | 
|  | test_nlmsg_type(const int fd) | 
|  | { | 
|  | long rc; | 
|  | struct nlmsghdr nlh = { | 
|  | .nlmsg_len = sizeof(nlh), | 
|  | .nlmsg_type = RTM_GETLINK, | 
|  | .nlmsg_flags = NLM_F_REQUEST, | 
|  | }; | 
|  |  | 
|  | rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); | 
|  | printf("sendto(%d, {len=%u, type=RTM_GETLINK" | 
|  | ", flags=NLM_F_REQUEST, seq=0, pid=0}" | 
|  | ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", | 
|  | fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); | 
|  | } | 
|  |  | 
|  | static void | 
|  | test_nlmsg_flags(const int fd) | 
|  | { | 
|  | long rc; | 
|  | struct nlmsghdr nlh = { | 
|  | .nlmsg_len = sizeof(nlh), | 
|  | }; | 
|  |  | 
|  | nlh.nlmsg_type = RTM_GETLINK; | 
|  | nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; | 
|  | rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); | 
|  | printf("sendto(%d, {len=%u, type=RTM_GETLINK" | 
|  | ", flags=NLM_F_REQUEST|NLM_F_DUMP, seq=0, pid=0}" | 
|  | ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", | 
|  | fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); | 
|  |  | 
|  | nlh.nlmsg_type = RTM_DELACTION; | 
|  | nlh.nlmsg_flags = NLM_F_ROOT; | 
|  | rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); | 
|  | printf("sendto(%d, {len=%u, type=RTM_DELACTION" | 
|  | ", flags=NLM_F_ROOT, seq=0, pid=0}" | 
|  | ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", | 
|  | fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); | 
|  |  | 
|  | nlh.nlmsg_type = RTM_NEWLINK; | 
|  | nlh.nlmsg_flags = NLM_F_ECHO | NLM_F_REPLACE; | 
|  | rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); | 
|  | printf("sendto(%d, {len=%u, type=RTM_NEWLINK" | 
|  | ", flags=NLM_F_ECHO|NLM_F_REPLACE, seq=0, pid=0}" | 
|  | ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", | 
|  | fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); | 
|  |  | 
|  | nlh.nlmsg_type = RTM_DELLINK; | 
|  | nlh.nlmsg_flags = NLM_F_NONREC; | 
|  | rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0); | 
|  | printf("sendto(%d, {len=%u, type=RTM_DELLINK" | 
|  | ", flags=NLM_F_NONREC, seq=0, pid=0}" | 
|  | ", %u, MSG_DONTWAIT, NULL, 0) = %s\n", | 
|  | fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc)); | 
|  | } | 
|  |  | 
|  | static void | 
|  | test_nlmsg_done(const int fd) | 
|  | { | 
|  | const int num = 0xabcdefad; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(num)); | 
|  |  | 
|  | TEST_NETLINK(fd, nlh0, NLMSG_DONE, NLM_F_REQUEST, | 
|  | sizeof(num), &num, sizeof(num), | 
|  | printf("%d", num)); | 
|  | } | 
|  |  | 
|  | static void | 
|  | test_rtnl_unspec(const int fd) | 
|  | { | 
|  | uint8_t family = 0; | 
|  | char buf[sizeof(family) + 4]; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(buf)); | 
|  |  | 
|  | /* unspecified family only */ | 
|  | TEST_NETLINK_(fd, nlh0, | 
|  | 0xffff, "0xffff /* RTM_??? */", | 
|  | NLM_F_REQUEST, "NLM_F_REQUEST", | 
|  | sizeof(family), &family, sizeof(family), | 
|  | printf("{family=AF_UNSPEC}")); | 
|  |  | 
|  | /* unknown family only */ | 
|  | family = 0xff; | 
|  | TEST_NETLINK_(fd, nlh0, | 
|  | 0xffff, "0xffff /* RTM_??? */", | 
|  | NLM_F_REQUEST, "NLM_F_REQUEST", | 
|  | sizeof(family), &family, sizeof(family), | 
|  | printf("{family=0xff /* AF_??? */}")); | 
|  |  | 
|  | /* short read of family */ | 
|  | TEST_NETLINK_(fd, nlh0, | 
|  | 0xffff, "0xffff /* RTM_??? */", | 
|  | NLM_F_REQUEST, "NLM_F_REQUEST", | 
|  | sizeof(family), &family, sizeof(family) - 1, | 
|  | printf("%p", NLMSG_DATA(TEST_NETLINK_nlh))); | 
|  |  | 
|  | /* unspecified family and string */ | 
|  | family = 0; | 
|  | memcpy(buf, &family, sizeof(family)); | 
|  | memcpy(buf + sizeof(family), "1234", 4); | 
|  | TEST_NETLINK_(fd, nlh0, | 
|  | 0xffff, "0xffff /* RTM_??? */", | 
|  | NLM_F_REQUEST, "NLM_F_REQUEST", | 
|  | sizeof(buf), buf, sizeof(buf), | 
|  | printf("{family=AF_UNSPEC, \"\\x31\\x32\\x33\\x34\"}")); | 
|  |  | 
|  | /* unknown family and string */ | 
|  | family = 0xfd; | 
|  | memcpy(buf, &family, sizeof(family)); | 
|  | TEST_NETLINK_(fd, nlh0, | 
|  | 0xffff, "0xffff /* RTM_??? */", | 
|  | NLM_F_REQUEST, "NLM_F_REQUEST", | 
|  | sizeof(buf), buf, sizeof(buf), | 
|  | printf("{family=%#x /* AF_??? */" | 
|  | ", \"\\x31\\x32\\x33\\x34\"}", family)); | 
|  | } | 
|  |  | 
|  | static void | 
|  | test_rtnl_link(const int fd) | 
|  | { | 
|  | const struct ifinfomsg ifinfo = { | 
|  | .ifi_family = AF_UNIX, | 
|  | .ifi_type = ARPHRD_LOOPBACK, | 
|  | .ifi_index = ifindex_lo(), | 
|  | .ifi_flags = IFF_UP, | 
|  | .ifi_change = 0xfabcdeba | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(ifinfo)); | 
|  |  | 
|  | TEST_NL_ROUTE(fd, nlh0, RTM_GETLINK, ifinfo, | 
|  | printf("{ifi_family=AF_UNIX"), | 
|  | printf(", ifi_type=ARPHRD_LOOPBACK" | 
|  | ", ifi_index=" IFINDEX_LO_STR | 
|  | ", ifi_flags=IFF_UP"); | 
|  | PRINT_FIELD_X(", ", ifinfo, ifi_change); | 
|  | printf("}")); | 
|  | } | 
|  |  | 
|  | static void | 
|  | test_rtnl_addr(const int fd) | 
|  | { | 
|  | const struct ifaddrmsg msg = { | 
|  | .ifa_family = AF_UNIX, | 
|  | .ifa_prefixlen = 0xde, | 
|  | .ifa_flags = IFA_F_SECONDARY, | 
|  | .ifa_scope = RT_SCOPE_UNIVERSE, | 
|  | .ifa_index = ifindex_lo() | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NL_ROUTE(fd, nlh0, RTM_GETADDR, msg, | 
|  | printf("{ifa_family=AF_UNIX"), | 
|  | PRINT_FIELD_U(", ", msg, ifa_prefixlen); | 
|  | printf(", ifa_flags=IFA_F_SECONDARY" | 
|  | ", ifa_scope=RT_SCOPE_UNIVERSE" | 
|  | ", ifa_index=" IFINDEX_LO_STR); | 
|  | printf("}")); | 
|  | } | 
|  |  | 
|  | static void | 
|  | test_rtnl_route(const int fd) | 
|  | { | 
|  | static const struct rtmsg msg = { | 
|  | .rtm_family = AF_UNIX, | 
|  | .rtm_dst_len = 0xaf, | 
|  | .rtm_src_len = 0xda, | 
|  | .rtm_tos = IPTOS_LOWDELAY, | 
|  | .rtm_table = RT_TABLE_DEFAULT, | 
|  | .rtm_protocol = RTPROT_KERNEL, | 
|  | .rtm_scope = RT_SCOPE_UNIVERSE, | 
|  | .rtm_type = RTN_LOCAL, | 
|  | .rtm_flags = RTM_F_NOTIFY | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NL_ROUTE(fd, nlh0, RTM_GETROUTE, msg, | 
|  | printf("{rtm_family=AF_UNIX"), | 
|  | PRINT_FIELD_U(", ", msg, rtm_dst_len); | 
|  | PRINT_FIELD_U(", ", msg, rtm_src_len); | 
|  | printf(", rtm_tos=IPTOS_LOWDELAY" | 
|  | ", rtm_table=RT_TABLE_DEFAULT" | 
|  | ", rtm_protocol=RTPROT_KERNEL" | 
|  | ", rtm_scope=RT_SCOPE_UNIVERSE" | 
|  | ", rtm_type=RTN_LOCAL" | 
|  | ", rtm_flags=RTM_F_NOTIFY}")); | 
|  | } | 
|  |  | 
|  | #ifdef HAVE_LINUX_FIB_RULES_H | 
|  | static void | 
|  | test_rtnl_rule(const int fd) | 
|  | { | 
|  | struct rtmsg msg = { | 
|  | .rtm_family = AF_UNIX, | 
|  | .rtm_dst_len = 0xaf, | 
|  | .rtm_src_len = 0xda, | 
|  | .rtm_tos = IPTOS_LOWDELAY, | 
|  | .rtm_table = RT_TABLE_UNSPEC, | 
|  | .rtm_type = FR_ACT_TO_TBL, | 
|  | .rtm_flags = FIB_RULE_INVERT | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NL_ROUTE(fd, nlh0, RTM_GETRULE, msg, | 
|  | printf("{family=AF_UNIX"), | 
|  | printf(", dst_len=%u, src_len=%u" | 
|  | ", tos=IPTOS_LOWDELAY" | 
|  | ", table=RT_TABLE_UNSPEC" | 
|  | ", action=FR_ACT_TO_TBL" | 
|  | ", flags=FIB_RULE_INVERT}", | 
|  | msg.rtm_dst_len, | 
|  | msg.rtm_src_len)); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | static void | 
|  | test_rtnl_neigh(const int fd) | 
|  | { | 
|  | const struct ndmsg msg = { | 
|  | .ndm_family = AF_UNIX, | 
|  | .ndm_ifindex = ifindex_lo(), | 
|  | .ndm_state = NUD_PERMANENT, | 
|  | .ndm_flags = NTF_PROXY, | 
|  | .ndm_type = RTN_UNSPEC | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NL_ROUTE(fd, nlh0, RTM_GETNEIGH, msg, | 
|  | printf("{ndm_family=AF_UNIX"), | 
|  | printf(", ndm_ifindex=" IFINDEX_LO_STR | 
|  | ", ndm_state=NUD_PERMANENT" | 
|  | ", ndm_flags=NTF_PROXY" | 
|  | ", ndm_type=RTN_UNSPEC}")); | 
|  | } | 
|  |  | 
|  | static void | 
|  | test_rtnl_neightbl(const int fd) | 
|  | { | 
|  | static const struct ndtmsg msg = { | 
|  | .ndtm_family = AF_NETLINK | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NETLINK(fd, nlh0, | 
|  | RTM_GETNEIGHTBL, NLM_F_REQUEST, | 
|  | sizeof(msg), &msg, sizeof(msg), | 
|  | printf("{ndtm_family=AF_NETLINK}")); | 
|  | } | 
|  |  | 
|  | static void | 
|  | test_rtnl_tc(const int fd) | 
|  | { | 
|  | const struct tcmsg msg = { | 
|  | .tcm_family = AF_UNIX, | 
|  | .tcm_ifindex = ifindex_lo(), | 
|  | .tcm_handle = 0xfadcdafb, | 
|  | .tcm_parent = 0xafbcadab, | 
|  | .tcm_info = 0xbcaedafa | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NL_ROUTE(fd, nlh0, RTM_GETQDISC, msg, | 
|  | printf("{tcm_family=AF_UNIX"), | 
|  | printf(", tcm_ifindex=" IFINDEX_LO_STR); | 
|  | PRINT_FIELD_U(", ", msg, tcm_handle); | 
|  | PRINT_FIELD_U(", ", msg, tcm_parent); | 
|  | PRINT_FIELD_U(", ", msg, tcm_info); | 
|  | printf("}")); | 
|  | } | 
|  |  | 
|  | static void | 
|  | test_rtnl_tca(const int fd) | 
|  | { | 
|  | struct tcamsg msg = { | 
|  | .tca_family = AF_INET | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NETLINK(fd, nlh0, | 
|  | RTM_GETACTION, NLM_F_REQUEST, | 
|  | sizeof(msg), &msg, sizeof(msg), | 
|  | printf("{tca_family=AF_INET}")); | 
|  | } | 
|  |  | 
|  | #ifdef HAVE_STRUCT_IFADDRLBLMSG | 
|  | static void | 
|  | test_rtnl_addrlabel(const int fd) | 
|  | { | 
|  | const struct ifaddrlblmsg msg = { | 
|  | .ifal_family = AF_UNIX, | 
|  | .ifal_prefixlen = 0xaf, | 
|  | .ifal_flags = 0xbd, | 
|  | .ifal_index = ifindex_lo(), | 
|  | .ifal_seq = 0xfadcdafb | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NL_ROUTE(fd, nlh0, RTM_GETADDRLABEL, msg, | 
|  | printf("{ifal_family=AF_UNIX"), | 
|  | PRINT_FIELD_U(", ", msg, ifal_prefixlen); | 
|  | PRINT_FIELD_U(", ", msg, ifal_flags); | 
|  | printf(", ifal_index=" IFINDEX_LO_STR); | 
|  | PRINT_FIELD_U(", ", msg, ifal_seq); | 
|  | printf("}")); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_STRUCT_DCBMSG | 
|  | static void | 
|  | test_rtnl_dcb(const int fd) | 
|  | { | 
|  | static const struct dcbmsg msg = { | 
|  | .dcb_family = AF_UNIX, | 
|  | .cmd = DCB_CMD_UNDEFINED | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NL_ROUTE(fd, nlh0, RTM_GETDCB, msg, | 
|  | printf("{dcb_family=AF_UNIX"), | 
|  | printf(", cmd=DCB_CMD_UNDEFINED}")); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_STRUCT_NETCONFMSG | 
|  | static void | 
|  | test_rtnl_netconf(const int fd) | 
|  | { | 
|  | static const struct netconfmsg msg = { | 
|  | .ncm_family = AF_INET | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NETLINK(fd, nlh0, | 
|  | RTM_GETNETCONF, NLM_F_REQUEST, | 
|  | sizeof(msg), &msg, sizeof(msg), | 
|  | printf("{ncm_family=AF_INET}")); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_STRUCT_BR_PORT_MSG | 
|  | static void | 
|  | test_rtnl_mdb(const int fd) | 
|  | { | 
|  | const struct br_port_msg msg = { | 
|  | .family = AF_UNIX, | 
|  | .ifindex = ifindex_lo() | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NL_ROUTE(fd, nlh0, RTM_GETMDB, msg, | 
|  | printf("{family=AF_UNIX"), | 
|  | printf(", ifindex=" IFINDEX_LO_STR "}")); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifdef RTM_NEWNSID | 
|  | static void | 
|  | test_rtnl_nsid(const int fd) | 
|  | { | 
|  | static const struct rtgenmsg msg = { | 
|  | .rtgen_family = AF_UNIX | 
|  | }; | 
|  | void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg)); | 
|  |  | 
|  | TEST_NETLINK(fd, nlh0, | 
|  | RTM_GETNSID, NLM_F_REQUEST, | 
|  | sizeof(msg), &msg, sizeof(msg), | 
|  | printf("{rtgen_family=AF_UNIX}")); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | int main(void) | 
|  | { | 
|  | skip_if_unavailable("/proc/self/fd/"); | 
|  |  | 
|  | int fd = create_nl_socket(NETLINK_ROUTE); | 
|  |  | 
|  | test_nlmsg_type(fd); | 
|  | test_nlmsg_flags(fd); | 
|  | test_nlmsg_done(fd); | 
|  | test_rtnl_unspec(fd); | 
|  | test_rtnl_link(fd); | 
|  | test_rtnl_addr(fd); | 
|  | test_rtnl_route(fd); | 
|  | #ifdef HAVE_LINUX_FIB_RULES_H | 
|  | test_rtnl_rule(fd); | 
|  | #endif | 
|  | test_rtnl_neigh(fd); | 
|  | test_rtnl_neightbl(fd); | 
|  | test_rtnl_tc(fd); | 
|  | test_rtnl_tca(fd); | 
|  | #ifdef HAVE_STRUCT_IFADDRLBLMSG | 
|  | test_rtnl_addrlabel(fd); | 
|  | #endif | 
|  | #ifdef HAVE_STRUCT_DCBMSG | 
|  | test_rtnl_dcb(fd); | 
|  | #endif | 
|  | #ifdef HAVE_STRUCT_NETCONFMSG | 
|  | test_rtnl_netconf(fd); | 
|  | #endif | 
|  | #ifdef HAVE_STRUCT_BR_PORT_MSG | 
|  | test_rtnl_mdb(fd); | 
|  | #endif | 
|  | #ifdef RTM_NEWNSID | 
|  | test_rtnl_nsid(fd); | 
|  | #endif | 
|  |  | 
|  | printf("+++ exited with 0 +++\n"); | 
|  |  | 
|  | return 0; | 
|  | } |