(root)/
strace-6.5/
tests/
nlattr_cachereport.c
       1  /*
       2   * Copyright (c) 2021 Eugene Syromyatnikov <evgsyr@gmail.com>
       3   * All rights reserved.
       4   *
       5   * SPDX-License-Identifier: GPL-2.0-or-later
       6   */
       7  
       8  #include "tests.h"
       9  
      10  #include <inttypes.h>
      11  #include <stdbool.h>
      12  #include <stdint.h>
      13  #include <stdio.h>
      14  #include <unistd.h>
      15  
      16  #include "test_netlink.h"
      17  #include "test_nlattr.h"
      18  
      19  #include <linux/ip.h>
      20  #include <linux/rtnetlink.h>
      21  #include <linux/mroute.h>
      22  #include <linux/mroute6.h>
      23  
      24  #include "xlat.h"
      25  #include "xlat/addrfams.h"
      26  
      27  static uint8_t af;
      28  static char af_str[256];
      29  
      30  /* uses global "af" variable */
      31  static void
      32  init_rtgen(struct nlmsghdr *const nlh, const unsigned int msg_len)
      33  {
      34  	SET_STRUCT(struct nlmsghdr, nlh,
      35  		.nlmsg_len = msg_len,
      36  		.nlmsg_type = RTM_NEWCACHEREPORT,
      37  		.nlmsg_flags = NLM_F_EXCL|NLM_F_APPEND,
      38  	);
      39  
      40  	struct rtgenmsg *const msg = NLMSG_DATA(nlh);
      41  	SET_STRUCT(struct rtgenmsg, msg,
      42  		.rtgen_family = af,
      43  	);
      44  }
      45  
      46  static void
      47  print_rtgen(const unsigned int msg_len)
      48  {
      49  	printf("{nlmsg_len=%u, nlmsg_type=" XLAT_FMT ", nlmsg_flags=" XLAT_FMT
      50  	       ", nlmsg_seq=0, nlmsg_pid=0}, {rtgen_family=%s}",
      51  	       msg_len, XLAT_ARGS(RTM_NEWCACHEREPORT),
      52  	       XLAT_ARGS(NLM_F_EXCL|NLM_F_APPEND), af_str);
      53  }
      54  
      55  int
      56  main(void)
      57  {
      58  	static const uint8_t unknown_msg[] = { 0xab, 0xac, 0xdb, 0xcd };
      59  
      60  	skip_if_unavailable("/proc/self/fd/");
      61  
      62  	const int fd = create_nl_socket(NETLINK_ROUTE);
      63  
      64  	const unsigned int hdrlen = sizeof(struct rtgenmsg);
      65  	void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), NLA_HDRLEN + 16);
      66  
      67  	static char pattern[4096];
      68  	fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
      69  
      70  
      71  	/* unknown AF_* */
      72  	static uint8_t skip_afs[] = { RTNL_FAMILY_IPMR, RTNL_FAMILY_IP6MR };
      73  	struct {
      74  		struct rtgenmsg ATTRIBUTE_ALIGNED(NLMSG_ALIGNTO) hdr;
      75  		struct {
      76  			char str[sizeof(unknown_msg)];
      77  		} ATTRIBUTE_ALIGNED(NLMSG_ALIGNTO) payload;
      78  	} buf;
      79  	memcpy(buf.payload.str, unknown_msg, sizeof(unknown_msg));
      80  	size_t pos = 0;
      81  	for (size_t i = 0; i < 256; i++) {
      82  		if (pos < ARRAY_SIZE(skip_afs) && skip_afs[pos] == i) {
      83  			pos += 1;
      84  			continue;
      85  		}
      86  
      87  		buf.hdr.rtgen_family = i;
      88  		TEST_NETLINK_(fd, nlh0, RTM_NEWCACHEREPORT,
      89  			      XLAT_KNOWN(0x60, "RTM_NEWCACHEREPORT"),
      90  			      NLM_F_REPLACE,
      91  			      XLAT_KNOWN(0x100, "NLM_F_REPLACE"),
      92  			      sizeof(buf), &buf, sizeof(buf),
      93  			      printf("{rtgen_family=%s}"
      94  				     ", \"\\xab\\xac\\xdb\\xcd\"",
      95  				     sprintxval(addrfams, i,
      96  						"RTNL_FAMILY_???")));
      97  	}
      98  
      99  
     100  	/* RTNL_FAMILY_IPMR */
     101  	af = RTNL_FAMILY_IPMR;
     102  	snprintf(af_str, sizeof(af_str), XLAT_FMT, XLAT_ARGS(RTNL_FAMILY_IPMR));
     103  
     104  	/* RTNL_FAMILY_IPMR: unknown, undecoded */
     105  	static const struct strval16 unk_attrs[] = {
     106  		{ ENUM_KNOWN(0, IPMRA_CREPORT_UNSPEC) },
     107  		{ ENUM_KNOWN(0x5, IPMRA_CREPORT_PKT) },
     108  		{ ARG_XLAT_UNKNOWN(0x7, "IPMRA_CREPORT_???") },
     109  		{ ARG_XLAT_UNKNOWN(0x1ead, "IPMRA_CREPORT_???") },
     110  	};
     111  
     112  	for (size_t i = 0; i < ARRAY_SIZE(unk_attrs); i++) {
     113  		TEST_NLATTR_(fd, nlh0, hdrlen, init_rtgen, print_rtgen,
     114  			     unk_attrs[i].val, unk_attrs[i].str,
     115  			     16, pattern, 16,
     116  			     print_quoted_hex(pattern, 16));
     117  	}
     118  
     119  	/* RTNL_FAMILY_IPMR: IPMRA_CREPORT_MSGTYPE */
     120  	static const struct strval8 mr_msg_types[] = {
     121  		{ ARG_XLAT_UNKNOWN(0, "IGMPMSG_???") },
     122  		{ ARG_XLAT_KNOWN(0x1, "IGMPMSG_NOCACHE") },
     123  		{ ARG_XLAT_KNOWN(0x2, "IGMPMSG_WRONGVIF") },
     124  		{ ARG_XLAT_KNOWN(0x3, "IGMPMSG_WHOLEPKT") },
     125  		{ ARG_XLAT_KNOWN(0x4, "IGMPMSG_WRVIFWHOLE") },
     126  		{ ARG_XLAT_UNKNOWN(0x5, "IGMPMSG_???") },
     127  		{ ARG_XLAT_UNKNOWN(0xca, "IGMPMSG_???") },
     128  	};
     129  	for (size_t i = 0; i < ARRAY_SIZE(mr_msg_types); i++) {
     130  		TEST_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     131  				       init_rtgen, print_rtgen,
     132  				       IPMRA_CREPORT_MSGTYPE,
     133  				       XLAT_KNOWN(0x1, "IPMRA_CREPORT_MSGTYPE"),
     134  				       pattern, mr_msg_types[i].val, 1,
     135  				       print_quoted_hex,
     136  				       printf("%s", mr_msg_types[i].str));
     137  	}
     138  
     139  	/* RTNL_FAMILY_IPMR: u32 */
     140  	static const struct strval16 u32_mr_attrs[] = {
     141  		{ ENUM_KNOWN(0x2, IPMRA_CREPORT_VIF_ID) },
     142  		{ ENUM_KNOWN(0x6, IPMRA_CREPORT_TABLE) },
     143  	};
     144  	void *nlh_u32 = midtail_alloc(NLMSG_SPACE(hdrlen),
     145  				      NLA_HDRLEN + sizeof(uint32_t));
     146  	for (size_t i = 0; i < ARRAY_SIZE(u32_mr_attrs); i++) {
     147  		check_u32_nlattr(fd, nlh_u32, hdrlen, init_rtgen, print_rtgen,
     148  				 u32_mr_attrs[i].val, u32_mr_attrs[i].str,
     149  				 pattern, 0);
     150  	}
     151  
     152  	/* RTNL_FAMILY_IPMR: in_addr */
     153  	static const struct strval16 in_addr_attrs[] = {
     154  		{ ENUM_KNOWN(0x3, IPMRA_CREPORT_SRC_ADDR) },
     155  		{ ENUM_KNOWN(0x4, IPMRA_CREPORT_DST_ADDR) },
     156  	};
     157  	static uint32_t ipv4_addr = BE32(0xdeadface);
     158  	for (size_t i = 0; i < ARRAY_SIZE(in_addr_attrs); i++) {
     159  		TEST_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     160  				       init_rtgen, print_rtgen,
     161  				       in_addr_attrs[i].val,
     162  				       in_addr_attrs[i].str,
     163  				       pattern, ipv4_addr, 4,
     164  				       print_quoted_hex,
     165  				       printf(XLAT_KNOWN_FMT(
     166  					      "\"\\xde\\xad\\xfa\\xce\"",
     167  					      "inet_addr(\"222.173.250.206\")"))
     168  				       );
     169  	}
     170  
     171  
     172  	/* RTNL_FAMILY_IP6MR */
     173  	af = RTNL_FAMILY_IP6MR;
     174  	snprintf(af_str, sizeof(af_str), XLAT_FMT,
     175  		 XLAT_ARGS(RTNL_FAMILY_IP6MR));
     176  
     177  	/* RTNL_FAMILY_IP6MR: unknown, undecoded */
     178  	static const struct strval16 unk6_attrs[] = {
     179  		{ ENUM_KNOWN(0, IP6MRA_CREPORT_UNSPEC) },
     180  		{ ENUM_KNOWN(0x5, IP6MRA_CREPORT_PKT) },
     181  		{ ARG_XLAT_UNKNOWN(0x6, "IP6MRA_CREPORT_???") },
     182  		{ ARG_XLAT_UNKNOWN(0x1ead, "IP6MRA_CREPORT_???") },
     183  	};
     184  
     185  	for (size_t i = 0; i < ARRAY_SIZE(unk6_attrs); i++) {
     186  		TEST_NLATTR_(fd, nlh0, hdrlen, init_rtgen, print_rtgen,
     187  			     unk6_attrs[i].val, unk6_attrs[i].str,
     188  			     16, pattern, 16,
     189  			     print_quoted_hex(pattern, 16));
     190  	}
     191  
     192  	/* RTNL_FAMILY_IP6MR: IP6MRA_CREPORT_MSGTYPE */
     193  	static const struct strval8 mr6_msg_types[] = {
     194  		{ ARG_XLAT_UNKNOWN(0, "MRT6MSG_???") },
     195  		{ ARG_XLAT_KNOWN(0x1, "MRT6MSG_NOCACHE") },
     196  		{ ARG_XLAT_KNOWN(0x2, "MRT6MSG_WRONGMIF") },
     197  		{ ARG_XLAT_KNOWN(0x3, "MRT6MSG_WHOLEPKT") },
     198  		{ ARG_XLAT_UNKNOWN(0x4, "MRT6MSG_???") },
     199  		{ ARG_XLAT_UNKNOWN(0xca, "MRT6MSG_???") },
     200  	};
     201  	for (size_t i = 0; i < ARRAY_SIZE(mr6_msg_types); i++) {
     202  		TEST_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     203  				       init_rtgen, print_rtgen,
     204  				       IP6MRA_CREPORT_MSGTYPE,
     205  				       XLAT_KNOWN(0x1,
     206  						  "IP6MRA_CREPORT_MSGTYPE"),
     207  				       pattern, mr6_msg_types[i].val, 1,
     208  				       print_quoted_hex,
     209  				       printf("%s", mr6_msg_types[i].str));
     210  	}
     211  
     212  	/* RTNL_FAMILY_IP6MR: u32 */
     213  	static const struct strval16 u32_mr6_attrs[] = {
     214  		{ ENUM_KNOWN(0x2, IP6MRA_CREPORT_MIF_ID) },
     215  	};
     216  	for (size_t i = 0; i < ARRAY_SIZE(u32_mr6_attrs); i++) {
     217  		check_u32_nlattr(fd, nlh_u32, hdrlen, init_rtgen, print_rtgen,
     218  				 u32_mr6_attrs[i].val, u32_mr6_attrs[i].str,
     219  				 pattern, 0);
     220  	}
     221  
     222  	/* RTNL_FAMILY_IPMR: in6_addr */
     223  	static const struct strval16 in6_addr_attrs[] = {
     224  		{ ENUM_KNOWN(0x3, IP6MRA_CREPORT_SRC_ADDR) },
     225  		{ ENUM_KNOWN(0x4, IP6MRA_CREPORT_DST_ADDR) },
     226  	};
     227  	uint8_t ipv6_addr[16] = {
     228  		0xba, 0xdc, 0x0d, 0xed, 0xfa, 0xce, 0xbe, 0xef,
     229  		0xde, 0xca, 0xfe, 0xed, 0xde, 0xad, 0xfe, 0xed,
     230  	};
     231  	for (size_t i = 0; i < ARRAY_SIZE(in6_addr_attrs); i++) {
     232  		TEST_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
     233  				       init_rtgen, print_rtgen,
     234  				       in6_addr_attrs[i].val,
     235  				       in6_addr_attrs[i].str,
     236  				       pattern, ipv6_addr, 16,
     237  				       print_quoted_hex,
     238  				       printf(XLAT_KNOWN_FMT(
     239  					      "\"\\xba\\xdc\\x0d\\xed"
     240  					      "\\xfa\\xce\\xbe\\xef"
     241  					      "\\xde\\xca\\xfe\\xed"
     242  					      "\\xde\\xad\\xfe\\xed\"",
     243  					      "inet_pton(AF_INET6"
     244  					      ", \"badc:ded:face:beef"
     245  					      ":deca:feed:dead:feed\")")));
     246  	}
     247  
     248  	puts("+++ exited with 0 +++");
     249  	return 0;
     250  }