(root)/
strace-6.5/
tests-mx32/
nlattr_inet_diag_req_v2.c
       1  /*
       2   * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
       3   * Copyright (c) 2017-2022 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 <string.h>
      13  #include <sys/socket.h>
      14  #include <arpa/inet.h>
      15  #include <net/if.h>
      16  #include <netinet/tcp.h>
      17  #include "test_nlattr.h"
      18  #include <linux/inet_diag.h>
      19  #include <linux/rtnetlink.h>
      20  #include <linux/sock_diag.h>
      21  
      22  static const char address[] = "10.11.12.13";
      23  static const unsigned int hdrlen = sizeof(struct inet_diag_req_v2);
      24  static void *nlh0;
      25  static char pattern[4096];
      26  
      27  static void
      28  init_inet_diag_req_v2(struct nlmsghdr *const nlh, const unsigned int msg_len)
      29  {
      30  	SET_STRUCT(struct nlmsghdr, nlh,
      31  		.nlmsg_len = msg_len,
      32  		.nlmsg_type = SOCK_DIAG_BY_FAMILY,
      33  		.nlmsg_flags = NLM_F_REQUEST
      34  	);
      35  
      36  	struct inet_diag_req_v2 *const req = NLMSG_DATA(nlh);
      37  	SET_STRUCT(struct inet_diag_req_v2, req,
      38  		.sdiag_family = AF_INET,
      39  		.idiag_ext = 1 << (INET_DIAG_CONG - 1),
      40  		.sdiag_protocol = IPPROTO_TCP,
      41  		.idiag_states = 1 << TCP_CLOSE,
      42  		.id.idiag_if = ifindex_lo()
      43  	);
      44  
      45  	if (!inet_pton(AF_INET, address, req->id.idiag_src) ||
      46  	    !inet_pton(AF_INET, address, req->id.idiag_dst))
      47  		perror_msg_and_skip("inet_pton");
      48  }
      49  
      50  static void
      51  print_inet_diag_req_v2(const unsigned int msg_len)
      52  {
      53  	printf("{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
      54  	       ", nlmsg_flags=NLM_F_REQUEST, nlmsg_seq=0, nlmsg_pid=0}"
      55  	       ", {sdiag_family=AF_INET, sdiag_protocol=IPPROTO_TCP"
      56  	       ", idiag_ext=1<<(INET_DIAG_CONG-1)"
      57  	       ", idiag_states=1<<TCP_CLOSE"
      58  	       ", id={idiag_sport=htons(0), idiag_dport=htons(0)"
      59  	       ", idiag_src=inet_addr(\"%s\")"
      60  	       ", idiag_dst=inet_addr(\"%s\")"
      61  	       ", idiag_if=" IFINDEX_LO_STR
      62  	       ", idiag_cookie=[0, 0]}}",
      63  	       msg_len, address, address);
      64  }
      65  
      66  static void
      67  test_unk_attrs(const int fd)
      68  {
      69  	static const struct strval16 unk_attrs[] = {
      70  		{ ENUM_KNOWN(0, INET_DIAG_REQ_NONE) },
      71  		{ ENUM_KNOWN(0x2, INET_DIAG_REQ_SK_BPF_STORAGES) },
      72  		{ ARG_XLAT_UNKNOWN(0x4, "INET_DIAG_REQ_???") },
      73  		{ ARG_XLAT_UNKNOWN(0x1ace, "INET_DIAG_REQ_???") },
      74  	};
      75  	static const char buf[4] = { 0xde, 0xad, 0xfa, 0xce };
      76  
      77  	for (size_t i = 0; i < ARRAY_SIZE(unk_attrs); i++) {
      78  		TEST_NLATTR_(fd, nlh0, hdrlen,
      79  			     init_inet_diag_req_v2, print_inet_diag_req_v2,
      80  			     unk_attrs[i].val, unk_attrs[i].str,
      81  			     sizeof(buf), buf, sizeof(buf),
      82  			     print_quoted_hex(buf, sizeof(buf)));
      83  	}
      84  }
      85  
      86  static void
      87  test_inet_diag_bc_op(const int fd)
      88  {
      89  	static const struct inet_diag_bc_op op = {
      90  		.code = INET_DIAG_BC_S_COND,
      91  		.yes = 0xaf,
      92  		.no = 0xafcd
      93  	};
      94  	TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
      95  			   init_inet_diag_req_v2, print_inet_diag_req_v2,
      96  			   INET_DIAG_REQ_BYTECODE, pattern, op,
      97  			   printf("{code=INET_DIAG_BC_S_COND");
      98  			   printf(", ");
      99  			   PRINT_FIELD_U(op, yes);
     100  			   printf(", ");
     101  			   PRINT_FIELD_U(op, no);
     102  			   printf("}"));
     103  }
     104  
     105  static void
     106  print_inet_diag_bc_op(const char *const code)
     107  {
     108  	printf("{code=%s, yes=0, no=0}, ", code);
     109  }
     110  
     111  static void
     112  test_inet_diag_bc_s_cond(const int fd)
     113  {
     114  	static const struct inet_diag_bc_op op = {
     115  		.code = INET_DIAG_BC_S_COND,
     116  	};
     117  	static const struct inet_diag_hostcond cond = {
     118  		.family = AF_UNSPEC,
     119  		.prefix_len = 0xad,
     120  		.port = 0xadfa
     121  	};
     122  	char buf[sizeof(op) + sizeof(cond)];
     123  	memcpy(buf, &op, sizeof(op));
     124  
     125  	const unsigned int plen = sizeof(cond) - 1 > DEFAULT_STRLEN ?
     126  		sizeof(op) + DEFAULT_STRLEN : sizeof(buf) - 1;
     127  	memcpy(buf + sizeof(op), &pattern, sizeof(cond));
     128  	TEST_NLATTR(fd, nlh0, hdrlen,
     129  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     130  		    INET_DIAG_REQ_BYTECODE,
     131  		    plen, buf, plen,
     132  		    print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
     133  		    print_quoted_hex(buf + sizeof(op), plen - sizeof(op)));
     134  
     135  	TEST_NLATTR(fd, nlh0, hdrlen,
     136  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     137  		    INET_DIAG_REQ_BYTECODE,
     138  		    sizeof(buf), buf, sizeof(buf) - 1,
     139  		    print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
     140  		    printf("%p", RTA_DATA(TEST_NLATTR_nla) + sizeof(op)));
     141  
     142  	memcpy(buf + sizeof(op), &cond, sizeof(cond));
     143  	TEST_NLATTR(fd, nlh0, hdrlen,
     144  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     145  		    INET_DIAG_REQ_BYTECODE,
     146  		    sizeof(buf), buf, sizeof(buf),
     147  		    print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
     148  		    printf("{family=AF_UNSPEC");
     149  		    printf(", ");
     150  		    PRINT_FIELD_U(cond, prefix_len);
     151  		    printf(", ");
     152  		    PRINT_FIELD_U(cond, port);
     153  		    printf("}"));
     154  }
     155  
     156  static void
     157  print_inet_diag_hostcond(const char *const family)
     158  {
     159  	printf("{family=%s, prefix_len=0, port=0, ", family);
     160  }
     161  
     162  static void
     163  test_in_addr(const int fd)
     164  {
     165  	static const struct inet_diag_bc_op op = {
     166  		.code = INET_DIAG_BC_S_COND,
     167  	};
     168  	static const struct inet_diag_hostcond cond = {
     169  		.family = AF_INET,
     170  	};
     171  	struct in_addr addr;
     172  	if (!inet_pton(AF_INET, address, &addr))
     173  		perror_msg_and_skip("inet_pton");
     174  
     175  	char buf[sizeof(op) + sizeof(cond) + sizeof(addr)];
     176  	memcpy(buf, &op, sizeof(op));
     177  	memcpy(buf + sizeof(op), &cond, sizeof(cond));
     178  
     179  	const unsigned int plen = sizeof(addr) - 1 > DEFAULT_STRLEN ?
     180  		sizeof(cond) + sizeof(cond) + DEFAULT_STRLEN : sizeof(buf) - 1;
     181  	memcpy(buf + sizeof(op) + sizeof(cond), &pattern, sizeof(addr));
     182  	TEST_NLATTR(fd, nlh0, hdrlen,
     183  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     184  		    INET_DIAG_REQ_BYTECODE,
     185  		    plen, buf, plen,
     186  		    print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
     187  		    print_inet_diag_hostcond("AF_INET");
     188  		    printf("addr=");
     189  		    print_quoted_hex(pattern, plen - sizeof(op) - sizeof(cond));
     190  		    printf("}"));
     191  
     192  	TEST_NLATTR(fd, nlh0, hdrlen,
     193  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     194  		    INET_DIAG_REQ_BYTECODE,
     195  		    sizeof(buf), buf, sizeof(buf) - 1,
     196  		    print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
     197  		    print_inet_diag_hostcond("AF_INET");
     198  		    printf("addr=%p}",
     199  			   RTA_DATA(TEST_NLATTR_nla)
     200  			   + sizeof(op) + sizeof(cond)));
     201  
     202  	memcpy(buf + sizeof(op) + sizeof(cond), &addr, sizeof(addr));
     203  	TEST_NLATTR(fd, nlh0, hdrlen,
     204  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     205  		    INET_DIAG_REQ_BYTECODE,
     206  		    sizeof(buf), buf, sizeof(buf),
     207  		    print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
     208  		    print_inet_diag_hostcond("AF_INET");
     209  		    printf("addr=inet_addr(\"%s\")}", address));
     210  }
     211  
     212  static void
     213  test_in6_addr(const int fd)
     214  {
     215  	const char address6[] = "12:34:56:78:90:ab:cd:ef";
     216  	static const struct inet_diag_bc_op op = {
     217  		.code = INET_DIAG_BC_S_COND,
     218  	};
     219  	static const struct inet_diag_hostcond cond = {
     220  		.family = AF_INET6,
     221  	};
     222  	struct in6_addr addr;
     223  	if (!inet_pton(AF_INET6, address6, &addr))
     224  		perror_msg_and_skip("inet_pton");
     225  
     226  	char buf[sizeof(op) + sizeof(cond) + sizeof(addr)];
     227  	memcpy(buf, &op, sizeof(op));
     228  	memcpy(buf + sizeof(op), &cond, sizeof(cond));
     229  
     230  	const unsigned int plen = sizeof(addr) - 1 > DEFAULT_STRLEN ?
     231  		sizeof(cond) + sizeof(cond) + DEFAULT_STRLEN : sizeof(buf) - 1;
     232  	memcpy(buf + sizeof(op) + sizeof(cond), &pattern, sizeof(addr));
     233  	TEST_NLATTR(fd, nlh0, hdrlen,
     234  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     235  		    INET_DIAG_REQ_BYTECODE,
     236  		    plen, buf, plen,
     237  		    print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
     238  		    print_inet_diag_hostcond("AF_INET6");
     239  		    printf("addr=");
     240  		    print_quoted_hex(pattern, plen - sizeof(op) - sizeof(cond));
     241  		    printf("}"));
     242  
     243  	TEST_NLATTR(fd, nlh0, hdrlen,
     244  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     245  		    INET_DIAG_REQ_BYTECODE,
     246  		    sizeof(buf), buf, sizeof(buf) - 1,
     247  		    print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
     248  		    print_inet_diag_hostcond("AF_INET6");
     249  		    printf("addr=%p}",
     250  			   RTA_DATA(TEST_NLATTR_nla)
     251  			   + sizeof(op) + sizeof(cond)));
     252  
     253  	memcpy(buf + sizeof(op) + sizeof(cond), &addr, sizeof(addr));
     254  	TEST_NLATTR(fd, nlh0, hdrlen,
     255  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     256  		    INET_DIAG_REQ_BYTECODE,
     257  		    sizeof(buf), buf, sizeof(buf),
     258  		    print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
     259  		    print_inet_diag_hostcond("AF_INET6");
     260  		    printf("inet_pton(AF_INET6, \"%s\", &addr)}", address6));
     261  }
     262  
     263  static void
     264  test_inet_diag_bc_dev_cond(const int fd)
     265  {
     266  	static const struct inet_diag_bc_op op = {
     267  		.code = INET_DIAG_BC_DEV_COND,
     268  	};
     269  	const uint32_t ifindex = ifindex_lo();
     270  	char buf[sizeof(op) + sizeof(ifindex)];
     271  	memcpy(buf, &op, sizeof(op));
     272  	memcpy(buf + sizeof(op), pattern, sizeof(ifindex));
     273  
     274  	TEST_NLATTR(fd, nlh0, hdrlen,
     275  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     276  		    INET_DIAG_REQ_BYTECODE,
     277  		    sizeof(buf) - 1, buf, sizeof(buf) - 1,
     278  		    print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND");
     279  		    print_quoted_hex(pattern, sizeof(ifindex) - 1));
     280  
     281  	TEST_NLATTR(fd, nlh0, hdrlen,
     282  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     283  		    INET_DIAG_REQ_BYTECODE,
     284  		    sizeof(buf), buf, sizeof(buf) - 1,
     285  		    print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND");
     286  		    printf("%p", RTA_DATA(TEST_NLATTR_nla) + sizeof(op)));
     287  
     288  	memcpy(buf + sizeof(op), &ifindex, sizeof(ifindex));
     289  	TEST_NLATTR(fd, nlh0, hdrlen,
     290  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     291  		    INET_DIAG_REQ_BYTECODE,
     292  		    sizeof(buf), buf, sizeof(buf),
     293  		    print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND");
     294  		    printf(IFINDEX_LO_STR));
     295  }
     296  
     297  static void
     298  test_inet_diag_bc_s_le(const int fd)
     299  {
     300  	static const struct inet_diag_bc_op op[] = {
     301  		{
     302  			.code = INET_DIAG_BC_S_LE,
     303  		},
     304  		{
     305  			.code = INET_DIAG_BC_DEV_COND,
     306  			.yes = 0xaf,
     307  			.no = 0xafcd
     308  		}
     309  	};
     310  
     311  	char buf[sizeof(op)];
     312  	memcpy(buf, op, sizeof(op[0]));
     313  	memcpy(buf + sizeof(op[0]), pattern, sizeof(op[1]));
     314  
     315  	const unsigned int plen = sizeof(op[1]) - 1 > DEFAULT_STRLEN ?
     316  		sizeof(op[0]) + DEFAULT_STRLEN : sizeof(buf) - 1;
     317  	TEST_NLATTR(fd, nlh0, hdrlen,
     318  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     319  		    INET_DIAG_REQ_BYTECODE,
     320  		    plen, buf, plen,
     321  		    print_inet_diag_bc_op("INET_DIAG_BC_S_LE");
     322  		    print_quoted_hex(buf + sizeof(op[0]), plen - sizeof(op[0])));
     323  
     324  	TEST_NLATTR(fd, nlh0, hdrlen,
     325  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     326  		    INET_DIAG_REQ_BYTECODE,
     327  		    sizeof(buf), buf, sizeof(buf) - 1,
     328  		    print_inet_diag_bc_op("INET_DIAG_BC_S_LE");
     329  		    printf("%p", RTA_DATA(TEST_NLATTR_nla) + sizeof(op[0])));
     330  
     331  	memcpy(buf + sizeof(op[0]), &op[1], sizeof(op[1]));
     332  	TEST_NLATTR(fd, nlh0, hdrlen,
     333  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     334  		    INET_DIAG_REQ_BYTECODE,
     335  		    sizeof(buf), buf, sizeof(buf),
     336  		    print_inet_diag_bc_op("INET_DIAG_BC_S_LE");
     337  		    printf("{code=INET_DIAG_BC_DEV_COND");
     338  		    printf(", ");
     339  		    PRINT_FIELD_U(op[1], yes);
     340  		    printf(", ");
     341  		    PRINT_FIELD_U(op[1], no);
     342  		    printf("}"));
     343  };
     344  
     345  static void
     346  test_inet_diag_bc_mark_cond(const int fd)
     347  {
     348  	static const struct inet_diag_bc_op op = {
     349  		.code = INET_DIAG_BC_MARK_COND,
     350  	};
     351  	static const struct inet_diag_markcond markcond = {
     352  		.mark = 0xafbcafcd,
     353  		.mask = 0xbafaacda
     354  	};
     355  	char buf[sizeof(op) + sizeof(markcond)];
     356  	memcpy(buf, &op, sizeof(op));
     357  	memcpy(buf + sizeof(op), pattern, sizeof(markcond));
     358  
     359  	const unsigned int plen = sizeof(markcond) - 1 > DEFAULT_STRLEN ?
     360  		sizeof(markcond) + DEFAULT_STRLEN : sizeof(buf) - 1;
     361  	TEST_NLATTR(fd, nlh0, hdrlen,
     362  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     363  		    INET_DIAG_REQ_BYTECODE,
     364  		    plen, buf, plen,
     365  		    print_inet_diag_bc_op("INET_DIAG_BC_MARK_COND");
     366  		    print_quoted_hex(buf + sizeof(op), plen - sizeof(op)));
     367  
     368  	TEST_NLATTR(fd, nlh0, hdrlen,
     369  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     370  		    INET_DIAG_REQ_BYTECODE,
     371  		    sizeof(buf), buf, sizeof(buf) - 1,
     372  		    print_inet_diag_bc_op("INET_DIAG_BC_MARK_COND");
     373  		    printf("%p", RTA_DATA(TEST_NLATTR_nla) + sizeof(op)));
     374  
     375  	memcpy(buf + sizeof(op), &markcond, sizeof(markcond));
     376  	TEST_NLATTR(fd, nlh0, hdrlen,
     377  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     378  		    INET_DIAG_REQ_BYTECODE,
     379  		    sizeof(buf), buf, sizeof(buf),
     380  		    print_inet_diag_bc_op("INET_DIAG_BC_MARK_COND");
     381  		    printf("{");
     382  		    PRINT_FIELD_U(markcond, mark);
     383  		    printf(", ");
     384  		    PRINT_FIELD_U(markcond, mask);
     385  		    printf("}"));
     386  }
     387  
     388  static void
     389  test_inet_diag_bc_nop(const int fd)
     390  {
     391  	static const struct inet_diag_bc_op op = {
     392  		.code = INET_DIAG_BC_AUTO,
     393  	};
     394  	char buf[sizeof(op) + 4];
     395  	memcpy(buf, &op, sizeof(op));
     396  	memcpy(buf + sizeof(op), pattern, 4);
     397  
     398  	TEST_NLATTR(fd, nlh0, hdrlen,
     399  		    init_inet_diag_req_v2, print_inet_diag_req_v2,
     400  		    INET_DIAG_REQ_BYTECODE,
     401  		    sizeof(buf), buf, sizeof(buf),
     402  		    print_inet_diag_bc_op("INET_DIAG_BC_AUTO");
     403  		    print_quoted_hex(buf + sizeof(op),
     404  				     sizeof(buf) - sizeof(op)));
     405  }
     406  
     407  static void
     408  test_inet_diag_proto(const int fd)
     409  {
     410  	static const struct strval32 protos[] = {
     411  		{ 0, "IPPROTO_IP" },
     412  		{ 3, "0x3 /* IPPROTO_??? */" },
     413  		{ 6, "IPPROTO_TCP" },
     414  		{ 255, "IPPROTO_RAW" },
     415  		{ 256, "0x100 /* IPPROTO_??? */" },
     416  		{ 262, "IPPROTO_MPTCP" },
     417  		{ 0xcafeface, "0xcafeface /* IPPROTO_??? */" },
     418  	};
     419  
     420  	for (size_t i = 0; i < ARRAY_SIZE(protos); i++) {
     421  		TEST_NLATTR(fd, nlh0, hdrlen,
     422  			    init_inet_diag_req_v2, print_inet_diag_req_v2,
     423  			    INET_DIAG_REQ_PROTOCOL,
     424  			    sizeof(uint32_t), &protos[i].val, sizeof(uint32_t),
     425  			    printf("%s", protos[i].str));
     426  	}
     427  }
     428  
     429  int
     430  main(void)
     431  {
     432  	skip_if_unavailable("/proc/self/fd/");
     433  
     434  	int fd = create_nl_socket(NETLINK_SOCK_DIAG);
     435  	nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), NLA_HDRLEN +
     436  			sizeof(struct inet_diag_bc_op) +
     437  				sizeof(struct inet_diag_hostcond) +
     438  				sizeof(struct in6_addr) + DEFAULT_STRLEN);
     439  	fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
     440  
     441  	test_unk_attrs(fd);
     442  	test_inet_diag_bc_op(fd);
     443  	test_inet_diag_bc_s_cond(fd);
     444  	test_in_addr(fd);
     445  	test_in6_addr(fd);
     446  	test_inet_diag_bc_dev_cond(fd);
     447  	test_inet_diag_bc_s_le(fd);
     448  	test_inet_diag_bc_mark_cond(fd);
     449  	test_inet_diag_bc_nop(fd);
     450  	test_inet_diag_proto(fd);
     451  
     452  	printf("+++ exited with 0 +++\n");
     453  	return 0;
     454  }