(root)/
strace-6.5/
tests-mx32/
nlattr_ndmsg.c
       1  /*
       2   * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
       3   * Copyright (c) 2017-2023 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: GPL-2.0-or-later
       7   */
       8  
       9  #include "tests.h"
      10  
      11  #include <stdio.h>
      12  #include <netinet/in.h>
      13  #include <arpa/inet.h>
      14  #include "test_nlattr.h"
      15  #include <linux/neighbour.h>
      16  #include <linux/rtnetlink.h>
      17  
      18  static const unsigned int hdrlen = sizeof(struct ndmsg);
      19  
      20  static void
      21  init_ndmsg(struct nlmsghdr *const nlh, const unsigned int msg_len)
      22  {
      23  	SET_STRUCT(struct nlmsghdr, nlh,
      24  		.nlmsg_len = msg_len,
      25  		.nlmsg_type = RTM_GETNEIGH,
      26  		.nlmsg_flags = NLM_F_DUMP
      27  	);
      28  
      29  	struct ndmsg *const msg = NLMSG_DATA(nlh);
      30  	SET_STRUCT(struct ndmsg, msg,
      31  		.ndm_family = AF_UNIX,
      32  		.ndm_ifindex = ifindex_lo(),
      33  		.ndm_state = NUD_PERMANENT,
      34  		.ndm_flags = NTF_PROXY,
      35  		.ndm_type = RTN_UNSPEC
      36  	);
      37  }
      38  
      39  static void
      40  print_ndmsg(const unsigned int msg_len)
      41  {
      42  	printf("{nlmsg_len=%u, nlmsg_type=RTM_GETNEIGH, nlmsg_flags=NLM_F_DUMP"
      43  	       ", nlmsg_seq=0, nlmsg_pid=0}, {ndm_family=AF_UNIX"
      44  	       ", ndm_ifindex=" IFINDEX_LO_STR
      45  	       ", ndm_state=NUD_PERMANENT"
      46  	       ", ndm_flags=NTF_PROXY"
      47  	       ", ndm_type=RTN_UNSPEC}",
      48  	       msg_len);
      49  }
      50  
      51  static void
      52  init_ndmsg_nfea(struct nlmsghdr *const nlh, const unsigned int msg_len)
      53  {
      54  	init_ndmsg(nlh, msg_len);
      55  
      56  	struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen);
      57  	SET_STRUCT(struct nlattr, nla,
      58  		.nla_len = msg_len - NLMSG_SPACE(hdrlen),
      59  		.nla_type = NDA_FDB_EXT_ATTRS,
      60  	);
      61  }
      62  
      63  static void
      64  print_ndmsg_nfea(const unsigned int msg_len)
      65  {
      66  	print_ndmsg(msg_len);
      67  	printf(", [{nla_len=%u, nla_type=NDA_FDB_EXT_ATTRS}",
      68  	       msg_len - NLMSG_SPACE(hdrlen));
      69  }
      70  
      71  int
      72  main(void)
      73  {
      74  	skip_if_unavailable("/proc/self/fd/");
      75  
      76  	const int fd = create_nl_socket(NETLINK_ROUTE);
      77  	void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen),
      78  				   NLA_HDRLEN + sizeof(struct nda_cacheinfo));
      79  
      80  	static char pattern[4096];
      81  	fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
      82  
      83  	const unsigned int nla_type = 0xffff & NLA_TYPE_MASK;
      84  	char nla_type_str[256];
      85  	sprintf(nla_type_str, "%#x /* NDA_??? */", nla_type);
      86  	TEST_NLATTR_(fd, nlh0, hdrlen,
      87  		     init_ndmsg, print_ndmsg,
      88  		     nla_type, nla_type_str,
      89  		     4, pattern, 4,
      90  		     print_quoted_hex(pattern, 4));
      91  
      92  	TEST_NLATTR(fd, nlh0, hdrlen,
      93  		    init_ndmsg, print_ndmsg,
      94  		    NDA_DST, 4, pattern, 4,
      95  		    print_quoted_hex(pattern, 4));
      96  
      97  	static const struct nda_cacheinfo ci = {
      98  		.ndm_confirmed = 0xabcdedad,
      99  		.ndm_used = 0xbcdaedad,
     100  		.ndm_updated = 0xcdbadeda,
     101  		.ndm_refcnt = 0xdeadbeda
     102  	};
     103  
     104  	TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
     105  			   init_ndmsg, print_ndmsg,
     106  			   NDA_CACHEINFO, pattern, ci,
     107  			   printf("{");
     108  			   PRINT_FIELD_U(ci, ndm_confirmed);
     109  			   printf(", ");
     110  			   PRINT_FIELD_U(ci, ndm_used);
     111  			   printf(", ");
     112  			   PRINT_FIELD_U(ci, ndm_updated);
     113  			   printf(", ");
     114  			   PRINT_FIELD_U(ci, ndm_refcnt);
     115  			   printf("}"));
     116  
     117  	const uint16_t port = 0xabcd;
     118  	TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
     119  			   init_ndmsg, print_ndmsg,
     120  			   NDA_PORT, pattern, port,
     121  			   printf("htons(%u)", ntohs(port)));
     122  
     123  	static const uint8_t mac[6] = "\xf8\xc2\x49\x13\x57\xbd";
     124  	TEST_NLATTR(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg,
     125  		    NDA_LLADDR, sizeof(mac) - 1, mac, sizeof(mac) - 1,
     126  		    for (unsigned int i = 0; i < sizeof(mac) - 1; ++i)
     127  			printf("%s%02x", i ? ":" : "", mac[i]));
     128  
     129  	TEST_NLATTR(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg,
     130  		    NDA_LLADDR, sizeof(mac), mac, sizeof(mac),
     131  		    for (unsigned int i = 0; i < sizeof(mac); ++i)
     132  			printf("%s%02x", i ? ":" : "", mac[i]));
     133  
     134  	/* u32 attrs */
     135  	static const struct strval16 u32_attrs[] = {
     136  		{ ENUM_KNOWN(0x4, NDA_PROBES) },
     137  		{ ENUM_KNOWN(0x7, NDA_VNI) },
     138  		{ ENUM_KNOWN(0xa, NDA_LINK_NETNSID) },
     139  		{ ENUM_KNOWN(0xb, NDA_SRC_VNI) },
     140  		{ ENUM_KNOWN(0xd, NDA_NH_ID) },
     141  	};
     142  	void *nlh_u32 = midtail_alloc(NLMSG_SPACE(hdrlen), sizeof(uint32_t));
     143  
     144  	for (size_t i = 0; i < ARRAY_SIZE(u32_attrs); i++) {
     145  		check_u32_nlattr(fd, nlh_u32, hdrlen, init_ndmsg, print_ndmsg,
     146  				u32_attrs[i].val, u32_attrs[i].str, pattern, 0);
     147  	}
     148  
     149  	/* NDA_FDB_EXT_ATTRS: unknown, undecoded */
     150  	static const struct strval16 nfea_unk_attrs[] = {
     151  		{ ENUM_KNOWN(0, NFEA_UNSPEC) },
     152  		{ ENUM_KNOWN(0x2, NFEA_DONT_REFRESH) },
     153  		{ ARG_XLAT_UNKNOWN(0x3, "NFEA_???") },
     154  		{ ARG_XLAT_UNKNOWN(0x1ace, "NFEA_???") },
     155  	};
     156  	static const uint32_t dummy = BE_LE(0xbadc0ded, 0xed0ddcba);
     157  
     158  	for (size_t i = 0; i < ARRAY_SIZE(nfea_unk_attrs); i++) {
     159  		TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
     160  				    init_ndmsg_nfea, print_ndmsg_nfea,
     161  				    nfea_unk_attrs[i].val,
     162  				    nfea_unk_attrs[i].str,
     163  				    sizeof(dummy), &dummy, sizeof(dummy), 1,
     164  				    printf("\"\\xba\\xdc\\x0d\\xed\""));
     165  	}
     166  
     167  	/* NDA_FDB_EXT_ATTRS: NFEA_ACTIVITY_NOTIFY */
     168  	static const struct strval8 fan_flags[] = {
     169  		{ ARG_STR(0) },
     170  		{ ARG_XLAT_KNOWN(0x1, "FDB_NOTIFY_BIT") },
     171  		{ ARG_XLAT_KNOWN(0xef, "FDB_NOTIFY_BIT"
     172  				       "|FDB_NOTIFY_INACTIVE_BIT|0xec") },
     173  		{ ARG_XLAT_UNKNOWN(0xfc, "FDB_NOTIFY_???") },
     174  	};
     175  
     176  	for (size_t i = 0; i < ARRAY_SIZE(fan_flags); i++) {
     177  		TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
     178  				    init_ndmsg_nfea, print_ndmsg_nfea,
     179  				    NFEA_ACTIVITY_NOTIFY,
     180  				    "NFEA_ACTIVITY_NOTIFY",
     181  				    1, &fan_flags[i].val, 1, 1,
     182  				    printf("%s", fan_flags[i].str));
     183  	}
     184  
     185  	/* NDA_FLAGS_EXT */
     186  	static const struct strval32 ntfe_flags[] = {
     187  		{ ARG_STR(0) },
     188  		{ ARG_XLAT_KNOWN(0x1, "NTF_EXT_MANAGED") },
     189  		{ ARG_XLAT_KNOWN(0x2, "NTF_EXT_LOCKED") },
     190  		{ ARG_XLAT_KNOWN(0xdeadbeef, "NTF_EXT_MANAGED|NTF_EXT_LOCKED"
     191  					     "|0xdeadbeec") },
     192  		{ ARG_XLAT_UNKNOWN(0xfeedcafc, "NTF_EXT_???") },
     193  	};
     194  
     195  	for (size_t i = 0; i < ARRAY_SIZE(ntfe_flags); i++) {
     196  		TEST_NLATTR(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg,
     197  			    NDA_FLAGS_EXT, 4, &ntfe_flags[i].val, 4,
     198  			    printf("%s", ntfe_flags[i].str));
     199  	}
     200  
     201  	/* NDA_NDM_STATE_MASK */
     202  	static const struct strval16 states_flags[] = {
     203  		{ ARG_XLAT_KNOWN(0, "NUD_NONE") },
     204  		{ ARG_XLAT_KNOWN(0x1, "NUD_INCOMPLETE") },
     205  		{ ARG_XLAT_KNOWN(0xabed, "NUD_INCOMPLETE|NUD_STALE|NUD_DELAY"
     206  					 "|NUD_FAILED|NUD_NOARP|NUD_PERMANENT"
     207  					 "|0xab00") },
     208  		{ ARG_XLAT_UNKNOWN(0xff00, "NUD_???") },
     209  	};
     210  
     211  	for (size_t i = 0; i < ARRAY_SIZE(states_flags); i++) {
     212  		TEST_NLATTR(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg,
     213  			    NDA_NDM_STATE_MASK, 2, &states_flags[i].val, 2,
     214  			    printf("%s", states_flags[i].str));
     215  	}
     216  
     217  	/* NDA_NDM_FLAGS_MASK */
     218  	static const struct strval8 ndm_flags[] = {
     219  		{ ARG_STR(0) },
     220  		{ ARG_XLAT_KNOWN(0x1, "NTF_USE") },
     221  		{ ARG_XLAT_KNOWN(0xbe, "NTF_SELF|NTF_MASTER|NTF_PROXY"
     222  					"|NTF_EXT_LEARNED|NTF_OFFLOADED"
     223  					"|NTF_ROUTER") },
     224  	};
     225  
     226  	for (size_t i = 0; i < ARRAY_SIZE(ndm_flags); i++) {
     227  		TEST_NLATTR(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg,
     228  			    NDA_NDM_FLAGS_MASK, 1, &ndm_flags[i].val, 1,
     229  			    printf("%s", ndm_flags[i].str));
     230  	}
     231  
     232  	puts("+++ exited with 0 +++");
     233  	return 0;
     234  }