498 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			498 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * 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;
 | |
| }
 |