(root)/
strace-6.5/
tests-m32/
nlattr_ifla_af_spec.c
       1  /*
       2   * IFLA_AF_SPEC netlink attribute decoding check.
       3   *
       4   * Copyright (c) 2018-2022 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  
      12  #include <inttypes.h>
      13  #include <stdio.h>
      14  #include <stddef.h>
      15  #include "test_nlattr.h"
      16  
      17  #include <linux/if.h>
      18  #include <linux/if_arp.h>
      19  #include <linux/if_bridge.h>
      20  #include <linux/if_link.h>
      21  #include <linux/rtnetlink.h>
      22  
      23  #include "xlat.h"
      24  #include "xlat/addrfams.h"
      25  
      26  #define XLAT_MACROS_ONLY
      27  #include "xlat/rtnl_ifla_af_spec_inet_attrs.h"
      28  #include "xlat/rtnl_ifla_af_spec_inet6_attrs.h"
      29  #undef XLAT_MACROS_ONLY
      30  
      31  static uint8_t msg_af = AF_UNIX;
      32  static char msg_af_str[32] = "AF_UNIX";
      33  
      34  #define IFLA_AF msg_af
      35  #define IFLA_AF_STR msg_af_str
      36  #define IFLA_ATTR IFLA_AF_SPEC
      37  #include "nlattr_ifla.h"
      38  
      39  #include "nlattr_ifla_af_inet6.h"
      40  
      41  #define AF_SPEC_FUNCS(family_)						\
      42  	static void							\
      43  	init_##family_##_msg(struct nlmsghdr *const nlh,		\
      44  			     const unsigned int msg_len)		\
      45  	{								\
      46  		init_ifinfomsg(nlh, msg_len);				\
      47  									\
      48  		struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen);		\
      49  		nla += 1;						\
      50  		SET_STRUCT(struct nlattr, nla,				\
      51  			.nla_len = msg_len - NLMSG_SPACE(hdrlen)	\
      52  				  - NLA_HDRLEN,				\
      53  			.nla_type = family_,				\
      54  		);							\
      55  	}								\
      56  									\
      57  	static void							\
      58  	print_##family_##_msg(const unsigned int msg_len)		\
      59  	{								\
      60  		print_ifinfomsg(msg_len);				\
      61  		printf(", [{nla_len=%u, nla_type=" #family_ "}",	\
      62  		       msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN);	\
      63  	}								\
      64  	/* end of AF_SPEC_FUNCS definition */
      65  
      66  AF_SPEC_FUNCS(AF_INET)
      67  AF_SPEC_FUNCS(AF_INET6)
      68  AF_SPEC_FUNCS(AF_MCTP)
      69  
      70  AF_SPEC_FUNCS(IFLA_BRIDGE_VLAN_TUNNEL_INFO)
      71  
      72  static void
      73  print_inet_conf_val(uint32_t *val, size_t idx)
      74  {
      75  	static const char * const strs[] = {
      76  		"IPV4_DEVCONF_FORWARDING-1",
      77  		"IPV4_DEVCONF_MC_FORWARDING-1",
      78  	};
      79  
      80  	print_arr_val(val, idx, idx < ARRAY_SIZE(strs) ? strs[idx] : NULL);
      81  }
      82  
      83  int
      84  main(void)
      85  {
      86  	static const uint8_t unknown_msg[] = { 0xab, 0xac, 0xdb, 0xcd };
      87  
      88  	skip_if_unavailable("/proc/self/fd/");
      89  
      90  	const int fd = create_nl_socket(NETLINK_ROUTE);
      91  
      92  	const unsigned int hdrlen = sizeof(struct ifinfomsg);
      93  	void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), 3 * NLA_HDRLEN + 256);
      94  
      95  	static char pattern[4096];
      96  	fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
      97  
      98  
      99  	/* unknown AF_* */
     100  	static uint8_t skip_afs[] = { AF_INET, AF_INET6, AF_MCTP };
     101  	size_t pos = 0;
     102  	static uint8_t skip_afs_msg[] = { AF_BRIDGE };
     103  	size_t pos2 = 0;
     104  	for (size_t j = 0; j < 64; j++) {
     105  		if (pos2 < ARRAY_SIZE(skip_afs_msg) && skip_afs_msg[pos2] == j)
     106  		{
     107  			pos2 += 1;
     108  			continue;
     109  		}
     110  
     111  		msg_af = j;
     112  		msg_af_str[0] = '\0';
     113  		strncat(msg_af_str, sprintxval(addrfams, j, "AF_???"),
     114  			sizeof(msg_af_str) - 1);
     115  		pos = 0;
     116  
     117  		for (size_t i = 0; i < 64; i++) {
     118  			if (pos < ARRAY_SIZE(skip_afs) && skip_afs[pos] == i) {
     119  				pos += 1;
     120  				continue;
     121  			}
     122  
     123  			const char *af_str = sprintxval(addrfams, i, "AF_???");
     124  			TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     125  						   init_ifinfomsg,
     126  						   print_ifinfomsg,
     127  						   i, af_str, pattern,
     128  						   unknown_msg,
     129  						   print_quoted_hex, 1,
     130  						   printf("\"\\xab\\xac\\xdb"
     131  							  "\\xcd\""));
     132  		}
     133  	}
     134  
     135  	/* AF_INET */
     136  	TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     137  				      init_AF_INET_msg, print_AF_INET_msg,
     138  				      0, "IFLA_INET_UNSPEC", pattern,
     139  				      unknown_msg, print_quoted_hex, 2,
     140  				      printf("\"\\xab\\xac\\xdb\\xcd\""));
     141  	TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     142  				      init_AF_INET_msg, print_AF_INET_msg,
     143  				      2, "0x2 /* IFLA_INET_??? */", pattern,
     144  				      unknown_msg, print_quoted_hex, 2,
     145  				      printf("\"\\xab\\xac\\xdb\\xcd\""));
     146  
     147  	/* AF_INET: IFLA_INET_CONF */
     148  	uint32_t inet_conf_vals[] = { 0xdeadc0de, 0xda7aface };
     149  	TEST_NESTED_NLATTR_ARRAY_EX(fd, nlh0, hdrlen,
     150  				    init_AF_INET_msg, print_AF_INET_msg,
     151  				    IFLA_INET_CONF, pattern,
     152  				    inet_conf_vals, 2, print_inet_conf_val);
     153  
     154  	/* AF_BRIDGE */
     155  	msg_af = AF_BRIDGE;
     156  	strcpy(msg_af_str, "AF_BRIDGE");
     157  
     158  	/* AF_BRIDGE: unknown, unimplemented */
     159  	static const struct strval16 unk_attrs[] = {
     160  		{ ENUM_KNOWN(0x4, IFLA_BRIDGE_MRP) },
     161  		{ ENUM_KNOWN(0x5, IFLA_BRIDGE_CFM) },
     162  		{ ENUM_KNOWN(0x6, IFLA_BRIDGE_MST) },
     163  		{ ARG_XLAT_UNKNOWN(0x7, "IFLA_BRIDGE_???") },
     164  		{ ARG_XLAT_UNKNOWN(0xbad, "IFLA_BRIDGE_???") },
     165  	};
     166  	for (size_t i = 0; i < ARRAY_SIZE(unk_attrs); i++) {
     167  		TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     168  					      init_ifinfomsg, print_ifinfomsg,
     169  					      unk_attrs[i].val,
     170  					      unk_attrs[i].str,
     171  					      pattern, unknown_msg,
     172  					      print_quoted_hex, 1,
     173  					      printf("\"\\xab\\xac\\xdb\\xcd\"")
     174  					      );
     175  	}
     176  
     177  	/* AF_BRIDGE: IFLA_BRIDGE_FLAGS */
     178  	static const struct strval16 bridge_flags[] = {
     179  		{ ARG_STR(0) },
     180  		{ ARG_STR(BRIDGE_FLAGS_MASTER) },
     181  		{ ARG_STR(BRIDGE_FLAGS_SELF) },
     182  		{ ARG_STR(BRIDGE_FLAGS_MASTER|BRIDGE_FLAGS_SELF) },
     183  		{ ARG_STR(0x4) " /* BRIDGE_FLAGS_??? */" },
     184  		{ 0xcafe, "BRIDGE_FLAGS_SELF|0xcafc" },
     185  		{ ARG_STR(0x7eac) " /* BRIDGE_FLAGS_??? */" },
     186  	};
     187  	for (size_t i = 0; i < ARRAY_SIZE(bridge_flags); i++) {
     188  		TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     189  					      init_ifinfomsg, print_ifinfomsg,
     190  					      IFLA_BRIDGE_FLAGS,
     191  					      "IFLA_BRIDGE_FLAGS",
     192  					      pattern, bridge_flags[i].val,
     193  					      print_quoted_hex, 1,
     194  					      printf("%s", bridge_flags[i].str)
     195  					      );
     196  	}
     197  
     198  	/* AF_BRIDGE: IFLA_BRIDGE_MODE */
     199  	static const struct strval16 bridge_modes[] = {
     200  		{ ARG_STR(BRIDGE_MODE_VEB) },
     201  		{ ARG_STR(BRIDGE_MODE_VEPA) },
     202  		{ ARG_STR(0x2) " /* BRIDGE_MODE_??? */" },
     203  		{ ARG_STR(0x3) " /* BRIDGE_MODE_??? */" },
     204  		{ ARG_STR(0xcafe) " /* BRIDGE_MODE_??? */" },
     205  		{ ARG_STR(0xfffe) " /* BRIDGE_MODE_??? */" },
     206  		{ ARG_STR(BRIDGE_MODE_UNDEF) },
     207  	};
     208  	for (size_t i = 0; i < ARRAY_SIZE(bridge_flags); i++) {
     209  		TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     210  					      init_ifinfomsg, print_ifinfomsg,
     211  					      IFLA_BRIDGE_MODE,
     212  					      "IFLA_BRIDGE_MODE",
     213  					      pattern, bridge_modes[i].val,
     214  					      print_quoted_hex, 1,
     215  					      printf("%s", bridge_modes[i].str)
     216  					      );
     217  	}
     218  
     219  	/* AF_BRIDGE: IFLA_BRIDGE_VLAN_INFO */
     220  	static const struct {
     221  		struct bridge_vlan_info val;
     222  		const char *str;
     223  	} bridge_vis[] = {
     224  		{ { 0, 0 }, "{flags=0, vid=0}" },
     225  		{ { 1, 1 }, "{flags=BRIDGE_VLAN_INFO_MASTER, vid=1}" },
     226  		{ { 0x69, 0xface },
     227  		  "{flags=BRIDGE_VLAN_INFO_MASTER|BRIDGE_VLAN_INFO_RANGE_BEGIN"
     228  		  "|BRIDGE_VLAN_INFO_BRENTRY|BRIDGE_VLAN_INFO_ONLY_OPTS"
     229  		  ", vid=64206}" },
     230  		{ {0xef80, 0xfeed },
     231  		  "{flags=0xef80 /* BRIDGE_VLAN_INFO_??? */, vid=65261}" },
     232  		{ {0xcafe, 0xdead },
     233  		  "{flags=BRIDGE_VLAN_INFO_PVID|BRIDGE_VLAN_INFO_UNTAGGED"
     234  		  "|BRIDGE_VLAN_INFO_RANGE_BEGIN|BRIDGE_VLAN_INFO_RANGE_END"
     235  		  "|BRIDGE_VLAN_INFO_BRENTRY|BRIDGE_VLAN_INFO_ONLY_OPTS|0xca80"
     236  		  ", vid=57005}" },
     237  	};
     238  	char bvi_buf[12];
     239  
     240  	fill_memory_ex(bvi_buf, sizeof(bvi_buf), 'z', 0x80);
     241  
     242  	for (size_t i = 0; i < ARRAY_SIZE(bridge_vis); i++) {
     243  		TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     244  					      init_ifinfomsg, print_ifinfomsg,
     245  					      IFLA_BRIDGE_VLAN_INFO,
     246  					      "IFLA_BRIDGE_VLAN_INFO",
     247  					      pattern, bridge_vis[i].val,
     248  					      print_quoted_hex, 1,
     249  					      printf("%s", bridge_vis[i].str));
     250  
     251  		memcpy(bvi_buf, &bridge_vis[i].val, sizeof(bridge_vis[i].val));
     252  		TEST_NLATTR_(fd, nlh0 - NLA_HDRLEN, hdrlen + NLA_HDRLEN,
     253  			     init_ifinfomsg, print_ifinfomsg,
     254  			     IFLA_BRIDGE_VLAN_INFO, "IFLA_BRIDGE_VLAN_INFO",
     255  			     sizeof(bvi_buf), bvi_buf, sizeof(bvi_buf),
     256  			     printf("%s, \"\\x7e\\x7f\\x80\\x81\\x82"
     257  				    "\\x83\\x84\\x85\"]",
     258  				    bridge_vis[i].str));
     259  	}
     260  
     261  	/* AF_BRIDGE: IFLA_BRIDGE_TUNNEL_INFO: unknown, undecoded */
     262  	static const struct strval16 unk_bti_attrs[] = {
     263  		{ ENUM_KNOWN(0, IFLA_BRIDGE_VLAN_TUNNEL_UNSPEC) },
     264  		{ ARG_XLAT_UNKNOWN(0x4, "IFLA_BRIDGE_VLAN_TUNNEL_???") },
     265  		{ ARG_XLAT_UNKNOWN(0xbad, "IFLA_BRIDGE_VLAN_TUNNEL_???") },
     266  	};
     267  	for (size_t i = 0; i < ARRAY_SIZE(unk_bti_attrs); i++) {
     268  		TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     269  					      init_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
     270  					      print_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
     271  					      unk_bti_attrs[i].val,
     272  					      unk_bti_attrs[i].str,
     273  					      pattern, unknown_msg,
     274  					      print_quoted_hex, 2,
     275  					      printf("\"\\xab\\xac\\xdb\\xcd\"")
     276  					      );
     277  	}
     278  
     279  	/* AF_BRIDGE: IFLA_BRIDGE_TUNNEL_INFO: u32 attrs */
     280  	static const struct strval16 u32_bti_attrs[] = {
     281  		{ ENUM_KNOWN(0x1, IFLA_BRIDGE_VLAN_TUNNEL_ID) },
     282  	};
     283  	void *nlh_u32 = midtail_alloc(NLMSG_SPACE(hdrlen),
     284  				      NLA_HDRLEN + sizeof(uint32_t));
     285  	for (size_t i = 0; i < ARRAY_SIZE(u32_bti_attrs); i++) {
     286  		check_u32_nlattr(fd, nlh_u32, hdrlen,
     287  				 init_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
     288  				 print_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
     289  				 u32_bti_attrs[i].val, u32_bti_attrs[i].str,
     290  				 pattern, 2);
     291  	}
     292  
     293  	/* AF_BRIDGE: IFLA_BRIDGE_TUNNEL_INFO: u16 attrs */
     294  	static const struct strval16 u16_bti_attrs[] = {
     295  		{ ENUM_KNOWN(0x1, IFLA_BRIDGE_VLAN_TUNNEL_VID) },
     296  	};
     297  	void *nlh_u16 = midtail_alloc(NLMSG_SPACE(hdrlen),
     298  				      NLA_HDRLEN + sizeof(uint16_t));
     299  	for (size_t i = 0; i < ARRAY_SIZE(u16_bti_attrs); i++) {
     300  		check_u16_nlattr(fd, nlh_u16, hdrlen,
     301  				 init_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
     302  				 print_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
     303  				 u16_bti_attrs[i].val, u16_bti_attrs[i].str,
     304  				 pattern, 2);
     305  	}
     306  
     307  	/* AF_BRIDGE: IFLA_BRIDGE_TUNNEL_INFO: IFLA_BRIDGE_VLAN_TUNNEL_FLAGS */
     308  	static const struct strval16 bti_flags[] = {
     309  		{ ARG_STR(0) },
     310  		{ ARG_STR(BRIDGE_VLAN_INFO_MASTER) },
     311  		{ ARG_STR(BRIDGE_VLAN_INFO_PVID) },
     312  		{ ARG_STR(BRIDGE_VLAN_INFO_MASTER|BRIDGE_VLAN_INFO_PVID) },
     313  		{ ARG_STR(0xef80) " /* BRIDGE_VLAN_INFO_??? */" },
     314  		{ 0xcafe, "BRIDGE_VLAN_INFO_PVID|BRIDGE_VLAN_INFO_UNTAGGED"
     315  			  "|BRIDGE_VLAN_INFO_RANGE_BEGIN"
     316  			  "|BRIDGE_VLAN_INFO_RANGE_END|BRIDGE_VLAN_INFO_BRENTRY"
     317  			  "|BRIDGE_VLAN_INFO_ONLY_OPTS|0xca80" },
     318  	};
     319  	for (size_t i = 0; i < ARRAY_SIZE(bti_flags); i++) {
     320  		TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     321  					      init_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
     322  					      print_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
     323  					      IFLA_BRIDGE_VLAN_TUNNEL_FLAGS,
     324  					      "IFLA_BRIDGE_VLAN_TUNNEL_FLAGS",
     325  					      pattern, bti_flags[i].val,
     326  					      print_quoted_hex, 2,
     327  					      printf("%s", bti_flags[i].str)
     328  					      );
     329  	}
     330  
     331  	/* AF_INET6 */
     332  	msg_af = AF_UNIX;
     333  	strcpy(msg_af_str, "AF_UNIX");
     334  
     335  	check_ifla_af_inet6(fd, nlh0, hdrlen,
     336  			    init_AF_INET6_msg, print_AF_INET6_msg, pattern, 2);
     337  
     338  	/* AF_MCTP */
     339  	TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     340  				      init_AF_MCTP_msg, print_AF_MCTP_msg,
     341  				      0, "IFLA_MCTP_UNSPEC", pattern,
     342  				      unknown_msg, print_quoted_hex, 2,
     343  				      printf("\"\\xab\\xac\\xdb\\xcd\""));
     344  	TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     345  				      init_AF_MCTP_msg, print_AF_MCTP_msg,
     346  				      2, "0x2 /* IFLA_MCTP_??? */", pattern,
     347  				      unknown_msg, print_quoted_hex, 2,
     348  				      printf("\"\\xab\\xac\\xdb\\xcd\""));
     349  
     350  	/* AF_MCTP: IFLA_MCTP_NET */
     351  	check_u32_nlattr(fd, nlh0, hdrlen, init_AF_MCTP_msg, print_AF_MCTP_msg,
     352  			 1, "IFLA_MCTP_NET", pattern, 2);
     353  
     354  	puts("+++ exited with 0 +++");
     355  	return 0;
     356  }