(root)/
strace-6.5/
tests/
netlink_sock_diag.c
       1  /*
       2   * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
       3   * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
       4   * Copyright (c) 2017-2021 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  #include <stdio.h>
      12  #include <string.h>
      13  #include <stdint.h>
      14  #include <unistd.h>
      15  #include <sys/socket.h>
      16  #include <arpa/inet.h>
      17  #include <netinet/tcp.h>
      18  #include "test_netlink.h"
      19  #include <linux/if_ether.h>
      20  #include <linux/inet_diag.h>
      21  #include <linux/netlink_diag.h>
      22  #include <linux/packet_diag.h>
      23  #ifdef AF_SMC
      24  # include <linux/smc_diag.h>
      25  #endif
      26  #include <linux/sock_diag.h>
      27  #include <linux/unix_diag.h>
      28  
      29  #define SMC_ACTIVE 1
      30  
      31  #define TEST_SOCK_DIAG(fd_, nlh0_,					\
      32  		       family_, type_, flags_,				\
      33  		       obj_, print_family_, ...)			\
      34  									\
      35  	do {								\
      36  		/* family only */					\
      37  		uint8_t family = (family_);				\
      38  		TEST_NETLINK_((fd_), (nlh0_),				\
      39  			      type_, #type_,				\
      40  			      flags_, #flags_,				\
      41  			      sizeof(family), &family, sizeof(family),	\
      42  			      printf("{family=%s}", #family_));		\
      43  									\
      44  		/* family and string */					\
      45  		char buf[sizeof(family) + 4];				\
      46  		memcpy(buf, &family, sizeof(family));			\
      47  		memcpy(buf + sizeof(family), "1234", 4);		\
      48  		TEST_NETLINK_((fd_), (nlh0_),				\
      49  			      type_, #type_,				\
      50  			      flags_, #flags_,				\
      51  			      sizeof(buf), buf, sizeof(buf),		\
      52  			      (print_family_);				\
      53  			      printf(", ...}"));			\
      54  									\
      55  		/* sizeof(obj_) */					\
      56  		TEST_NETLINK_((fd_), (nlh0_),				\
      57  			      type_, #type_,				\
      58  			      flags_, #flags_,				\
      59  			      sizeof(obj_), &(obj_), sizeof(obj_),	\
      60  			      (print_family_);				\
      61  			      __VA_ARGS__);				\
      62  									\
      63  		/* short read of sizeof(obj_) */			\
      64  		TEST_NETLINK_((fd_), (nlh0_),				\
      65  			      type_, #type_,				\
      66  			      flags_, #flags_,				\
      67  			      sizeof(obj_), &(obj_), sizeof(obj_) - 1,	\
      68  			      (print_family_);				\
      69  			      printf(", %p}",				\
      70  				     NLMSG_DATA(TEST_NETLINK_nlh) + 1));\
      71  	} while (0)
      72  
      73  static void
      74  test_nlmsg_type(const int fd)
      75  {
      76  	long rc;
      77  	struct nlmsghdr nlh = {
      78  		.nlmsg_len = sizeof(nlh),
      79  		.nlmsg_type = SOCK_DIAG_BY_FAMILY,
      80  		.nlmsg_flags = NLM_F_REQUEST,
      81  	};
      82  
      83  	rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
      84  	printf("sendto(%d, {nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
      85  	       ", nlmsg_flags=NLM_F_REQUEST, nlmsg_seq=0, nlmsg_pid=0}"
      86  	       ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
      87  	       fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
      88  }
      89  
      90  static void
      91  test_nlmsg_flags(const int fd)
      92  {
      93  	long rc;
      94  	struct nlmsghdr nlh = {
      95  		.nlmsg_len = sizeof(nlh),
      96  		.nlmsg_type = SOCK_DIAG_BY_FAMILY,
      97  		.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
      98  	};
      99  
     100  	rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
     101  	printf("sendto(%d, {nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
     102  	       ", nlmsg_flags=NLM_F_REQUEST|NLM_F_DUMP, nlmsg_seq=0"
     103  	       ", nlmsg_pid=0}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
     104  	       fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
     105  }
     106  
     107  static void
     108  test_odd_family_req(const int fd)
     109  {
     110  	uint8_t family = 0;
     111  	char buf[sizeof(family) + 4];
     112  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(buf));
     113  
     114  	/* unspecified family only */
     115  	TEST_NETLINK(fd, nlh0,
     116  		     SOCK_DIAG_BY_FAMILY,
     117  		     NLM_F_REQUEST,
     118  		     sizeof(family), &family, sizeof(family),
     119  		     printf("{family=AF_UNSPEC}"));
     120  
     121  	/* unknown family only */
     122  	family = 0xff;
     123  	TEST_NETLINK(fd, nlh0,
     124  		     SOCK_DIAG_BY_FAMILY,
     125  		     NLM_F_REQUEST,
     126  		     sizeof(family), &family, sizeof(family),
     127  		     printf("{family=%#x /* AF_??? */}", family));
     128  
     129  	/* short read of family */
     130  	TEST_NETLINK(fd, nlh0,
     131  		     SOCK_DIAG_BY_FAMILY,
     132  		     NLM_F_REQUEST,
     133  		     sizeof(family), &family, sizeof(family) - 1,
     134  		     printf("%p", NLMSG_DATA(TEST_NETLINK_nlh)));
     135  
     136  	/* unspecified family and string */
     137  	family = 0;
     138  	memcpy(buf, &family, sizeof(family));
     139  	memcpy(buf + sizeof(family), "1234", 4);
     140  	TEST_NETLINK(fd, nlh0,
     141  		     SOCK_DIAG_BY_FAMILY,
     142  		     NLM_F_REQUEST,
     143  		     sizeof(buf), buf, sizeof(buf),
     144  		     printf("{family=AF_UNSPEC, data=\"\\x31\\x32\\x33\\x34\"}"));
     145  
     146  	/* unknown family and string */
     147  	family = 0xfd;
     148  	memcpy(buf, &family, sizeof(family));
     149  	TEST_NETLINK(fd, nlh0,
     150  		     SOCK_DIAG_BY_FAMILY,
     151  		     NLM_F_REQUEST,
     152  		     sizeof(buf), buf, sizeof(buf),
     153  		     printf("{family=%#x /* AF_??? */"
     154  			    ", data=\"\\x31\\x32\\x33\\x34\"}", family));
     155  }
     156  
     157  static void
     158  test_odd_family_msg(const int fd)
     159  {
     160  	uint8_t family = 0;
     161  	char buf[sizeof(family) + 4];
     162  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(buf));
     163  
     164  	/* unspecified family only */
     165  	TEST_NETLINK(fd, nlh0,
     166  		     SOCK_DIAG_BY_FAMILY, NLM_F_DUMP,
     167  		     sizeof(family), &family, sizeof(family),
     168  		     printf("{family=AF_UNSPEC}"));
     169  
     170  	/* unknown family only */
     171  	family = 0xff;
     172  	TEST_NETLINK(fd, nlh0,
     173  		     SOCK_DIAG_BY_FAMILY, NLM_F_DUMP,
     174  		     sizeof(family), &family, sizeof(family),
     175  		     printf("{family=%#x /* AF_??? */}", family));
     176  
     177  	/* short read of family */
     178  	TEST_NETLINK(fd, nlh0,
     179  		     SOCK_DIAG_BY_FAMILY, NLM_F_DUMP,
     180  		     sizeof(family), &family, sizeof(family) - 1,
     181  		     printf("%p", NLMSG_DATA(TEST_NETLINK_nlh)));
     182  
     183  	/* unspecified family and string */
     184  	family = 0;
     185  	memcpy(buf, &family, sizeof(family));
     186  	memcpy(buf + sizeof(family), "1234", 4);
     187  	TEST_NETLINK(fd, nlh0,
     188  		     SOCK_DIAG_BY_FAMILY, NLM_F_DUMP,
     189  		     sizeof(buf), buf, sizeof(buf),
     190  		     printf("{family=AF_UNSPEC, data=\"\\x31\\x32\\x33\\x34\"}"));
     191  
     192  	/* unknown family and string */
     193  	family = 0xfd;
     194  	memcpy(buf, &family, sizeof(family));
     195  	TEST_NETLINK(fd, nlh0,
     196  		     SOCK_DIAG_BY_FAMILY, NLM_F_DUMP,
     197  		     sizeof(buf), buf, sizeof(buf),
     198  		     printf("{family=%#x /* AF_??? */"
     199  			    ", data=\"\\x31\\x32\\x33\\x34\"}", family));
     200  }
     201  
     202  static void
     203  test_unix_diag_req(const int fd)
     204  {
     205  	static const struct unix_diag_req req = {
     206  		.sdiag_family = AF_UNIX,
     207  		.sdiag_protocol = 253,
     208  		.udiag_states = 1 << TCP_ESTABLISHED | 1 << TCP_LISTEN,
     209  		.udiag_ino = 0xfacefeed,
     210  		.udiag_show = UDIAG_SHOW_NAME,
     211  		.udiag_cookie = { 0xdeadbeef, 0xbadc0ded }
     212  	};
     213  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(req));
     214  	TEST_SOCK_DIAG(fd, nlh0, AF_UNIX,
     215  		       SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
     216  		       printf("{sdiag_family=AF_UNIX"),
     217  		       printf(", ");
     218  		       PRINT_FIELD_U(req, sdiag_protocol);
     219  		       printf(", udiag_states=1<<TCP_ESTABLISHED|1<<TCP_LISTEN");
     220  		       printf(", ");
     221  		       PRINT_FIELD_U(req, udiag_ino);
     222  		       printf(", udiag_show=UDIAG_SHOW_NAME");
     223  		       printf(", ");
     224  		       PRINT_FIELD_COOKIE(req, udiag_cookie);
     225  		       printf("}"));
     226  }
     227  
     228  static void
     229  test_unix_diag_msg(const int fd)
     230  {
     231  	static const struct unix_diag_msg msg = {
     232  		.udiag_family = AF_UNIX,
     233  		.udiag_type = SOCK_STREAM,
     234  		.udiag_state = TCP_FIN_WAIT1,
     235  		.udiag_ino = 0xfacefeed,
     236  		.udiag_cookie = { 0xdeadbeef, 0xbadc0ded }
     237  	};
     238  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg));
     239  	TEST_SOCK_DIAG(fd, nlh0, AF_UNIX,
     240  		       SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, msg,
     241  		       printf("{udiag_family=AF_UNIX"),
     242  		       printf(", udiag_type=SOCK_STREAM"
     243  			      ", udiag_state=TCP_FIN_WAIT1");
     244  		       printf(", ");
     245  		       PRINT_FIELD_U(msg, udiag_ino);
     246  		       printf(", ");
     247  		       PRINT_FIELD_COOKIE(msg, udiag_cookie);
     248  		       printf("}"));
     249  }
     250  
     251  static void
     252  test_netlink_diag_req(const int fd)
     253  {
     254  	struct netlink_diag_req req = {
     255  		.sdiag_family = AF_NETLINK,
     256  		.sdiag_protocol = NDIAG_PROTO_ALL,
     257  		.ndiag_ino = 0xfacefeed,
     258  		.ndiag_show = NDIAG_SHOW_MEMINFO,
     259  		.ndiag_cookie = { 0xdeadbeef, 0xbadc0ded }
     260  	};
     261  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(req));
     262  	TEST_SOCK_DIAG(fd, nlh0, AF_NETLINK,
     263  		       SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
     264  		       printf("{sdiag_family=AF_NETLINK"),
     265  		       printf(", sdiag_protocol=NDIAG_PROTO_ALL");
     266  		       printf(", ");
     267  		       PRINT_FIELD_U(req, ndiag_ino);
     268  		       printf(", ndiag_show=NDIAG_SHOW_MEMINFO");
     269  		       printf(", ");
     270  		       PRINT_FIELD_COOKIE(req, ndiag_cookie);
     271  		       printf("}"));
     272  
     273  	req.sdiag_protocol = NETLINK_ROUTE;
     274  	req.ndiag_show = NDIAG_SHOW_GROUPS;
     275  	TEST_SOCK_DIAG(fd, nlh0, AF_NETLINK,
     276  		       SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
     277  		       printf("{sdiag_family=AF_NETLINK"),
     278  		       printf(", sdiag_protocol=NETLINK_ROUTE");
     279  		       printf(", ");
     280  		       PRINT_FIELD_U(req, ndiag_ino);
     281  		       printf(", ndiag_show=NDIAG_SHOW_GROUPS");
     282  		       printf(", ");
     283  		       PRINT_FIELD_COOKIE(req, ndiag_cookie);
     284  		       printf("}"));
     285  }
     286  
     287  static void
     288  test_netlink_diag_msg(const int fd)
     289  {
     290  	static const struct netlink_diag_msg msg = {
     291  		.ndiag_family = AF_NETLINK,
     292  		.ndiag_type = SOCK_RAW,
     293  		.ndiag_protocol = NETLINK_ROUTE,
     294  		.ndiag_state = NETLINK_CONNECTED,
     295  		.ndiag_portid = 0xbadc0ded,
     296  		.ndiag_dst_portid = 0xdeadbeef,
     297  		.ndiag_dst_group = 0xfacefeed,
     298  		.ndiag_ino = 0xdaeefacd,
     299  		.ndiag_cookie = { 0xbadc0ded, 0xdeadbeef }
     300  	};
     301  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg));
     302  	TEST_SOCK_DIAG(fd, nlh0, AF_NETLINK,
     303  		       SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, msg,
     304  		       printf("{ndiag_family=AF_NETLINK"),
     305  		       printf(", ndiag_type=SOCK_RAW"
     306  			      ", ndiag_protocol=NETLINK_ROUTE"
     307  			      ", ndiag_state=NETLINK_CONNECTED");
     308  		       printf(", ");
     309  		       PRINT_FIELD_U(msg, ndiag_portid);
     310  		       printf(", ");
     311  		       PRINT_FIELD_U(msg, ndiag_dst_portid);
     312  		       printf(", ");
     313  		       PRINT_FIELD_U(msg, ndiag_dst_group);
     314  		       printf(", ");
     315  		       PRINT_FIELD_U(msg, ndiag_ino);
     316  		       printf(", ");
     317  		       PRINT_FIELD_COOKIE(msg, ndiag_cookie);
     318  		       printf("}"));
     319  }
     320  
     321  static void
     322  test_packet_diag_req(const int fd)
     323  {
     324  	static const struct packet_diag_req req = {
     325  		.sdiag_family = AF_PACKET,
     326  		.sdiag_protocol = ETH_P_LOOP,
     327  		.pdiag_ino = 0xfacefeed,
     328  		.pdiag_show = PACKET_SHOW_INFO,
     329  		.pdiag_cookie = { 0xdeadbeef, 0xbadc0ded }
     330  	};
     331  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(req));
     332  	TEST_SOCK_DIAG(fd, nlh0, AF_PACKET,
     333  		       SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
     334  		       printf("{sdiag_family=AF_PACKET"),
     335  		       printf(", sdiag_protocol=%#x", req.sdiag_protocol);
     336  		       printf(", ");
     337  		       PRINT_FIELD_U(req, pdiag_ino);
     338  		       printf(", pdiag_show=PACKET_SHOW_INFO");
     339  		       printf(", ");
     340  		       PRINT_FIELD_COOKIE(req, pdiag_cookie);
     341  		       printf("}"));
     342  }
     343  
     344  static void
     345  test_packet_diag_msg(const int fd)
     346  {
     347  	static const struct packet_diag_msg msg = {
     348  		.pdiag_family = AF_PACKET,
     349  		.pdiag_type = SOCK_STREAM,
     350  		.pdiag_num = 0x9100,
     351  		.pdiag_ino = 0xfacefeed,
     352  		.pdiag_cookie = { 0xdeadbeef, 0xbadc0ded }
     353  	};
     354  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg));
     355  	TEST_SOCK_DIAG(fd, nlh0, AF_PACKET,
     356  		       SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, msg,
     357  		       printf("{pdiag_family=AF_PACKET"),
     358  		       printf(", pdiag_type=SOCK_STREAM");
     359  		       printf(", pdiag_num=ETH_P_QINQ1");
     360  		       printf(", ");
     361  		       PRINT_FIELD_U(msg, pdiag_ino);
     362  		       printf(", ");
     363  		       PRINT_FIELD_COOKIE(msg, pdiag_cookie);
     364  		       printf("}"));
     365  }
     366  
     367  static void
     368  test_inet_diag_sockid(const int fd)
     369  {
     370  	const char address[] = "12.34.56.78";
     371  	const char address6[] = "12:34:56:78:90:ab:cd:ef";
     372  	struct inet_diag_req_v2 req = {
     373  		.sdiag_family = AF_INET,
     374  		.idiag_ext = 1 << (INET_DIAG_CONG - 1),
     375  		.sdiag_protocol = IPPROTO_TCP,
     376  		.idiag_states = 1 << TCP_CLOSE,
     377  		.id = {
     378  			.idiag_sport = 0xfacd,
     379  			.idiag_dport = 0xdead,
     380  			.idiag_if = ifindex_lo(),
     381  			.idiag_cookie = { 0xdeadbeef, 0xbadc0ded }
     382  		},
     383  	};
     384  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(req));
     385  
     386  	if (!inet_pton(AF_INET, address, &req.id.idiag_src) ||
     387  	    !inet_pton(AF_INET, address, &req.id.idiag_dst))
     388  		perror_msg_and_skip("inet_pton");
     389  
     390  	TEST_NETLINK(fd, nlh0,
     391  		     SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST,
     392  		     sizeof(req), &req, sizeof(req),
     393  		     printf("{sdiag_family=AF_INET"),
     394  		     printf(", sdiag_protocol=IPPROTO_TCP"
     395  			    ", idiag_ext=1<<(INET_DIAG_CONG-1)"
     396  			    ", idiag_states=1<<TCP_CLOSE"
     397  			    ", id={idiag_sport=htons(%u)"
     398  			    ", idiag_dport=htons(%u)"
     399  			    ", idiag_src=inet_addr(\"%s\")"
     400  			    ", idiag_dst=inet_addr(\"%s\")",
     401  			    ntohs(req.id.idiag_sport),
     402  			    ntohs(req.id.idiag_dport),
     403  			    address, address);
     404  		     printf(", idiag_if=" IFINDEX_LO_STR);
     405  		     printf(", ");
     406  		     PRINT_FIELD_COOKIE(req.id, idiag_cookie);
     407  		     printf("}}"));
     408  
     409  	req.sdiag_family = AF_INET6;
     410  	if (!inet_pton(AF_INET6, address6, &req.id.idiag_src) ||
     411  	    !inet_pton(AF_INET6, address6, &req.id.idiag_dst))
     412  		perror_msg_and_skip("inet_pton");
     413  
     414  	TEST_NETLINK(fd, nlh0,
     415  		     SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST,
     416  		     sizeof(req), &req, sizeof(req),
     417  		     printf("{sdiag_family=AF_INET6"),
     418  		     printf(", sdiag_protocol=IPPROTO_TCP"
     419  			    ", idiag_ext=1<<(INET_DIAG_CONG-1)"
     420  			    ", idiag_states=1<<TCP_CLOSE"
     421  			    ", id={idiag_sport=htons(%u)"
     422  			    ", idiag_dport=htons(%u)"
     423  			    ", inet_pton(AF_INET6, \"%s\", &idiag_src)"
     424  			    ", inet_pton(AF_INET6, \"%s\", &idiag_dst)",
     425  			    ntohs(req.id.idiag_sport),
     426  			    ntohs(req.id.idiag_dport),
     427  			    address6, address6);
     428  		     printf(", idiag_if=" IFINDEX_LO_STR);
     429  		     printf(", ");
     430  		     PRINT_FIELD_COOKIE(req.id, idiag_cookie);
     431  		     printf("}}"));
     432  }
     433  
     434  static void
     435  test_inet_diag_req(const int fd)
     436  {
     437  	const char address[] = "12.34.56.78";
     438  	struct inet_diag_req req = {
     439  		.idiag_family = AF_INET,
     440  		.idiag_src_len = 0xde,
     441  		.idiag_dst_len = 0xba,
     442  		.idiag_ext = 1 << (INET_DIAG_TOS - 1),
     443  		.id = {
     444  			.idiag_sport = 0xdead,
     445  			.idiag_dport = 0xadcd,
     446  			.idiag_if = ifindex_lo(),
     447  			.idiag_cookie = { 0xdeadbeef, 0xbadc0ded }
     448  		},
     449  		.idiag_states = 1 << TCP_LAST_ACK,
     450  		.idiag_dbs = 0xfacefeed,
     451  	};
     452  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(req));
     453  
     454  	if (!inet_pton(AF_INET, address, &req.id.idiag_src) ||
     455  	    !inet_pton(AF_INET, address, &req.id.idiag_dst))
     456  		perror_msg_and_skip("inet_pton");
     457  
     458  	TEST_SOCK_DIAG(fd, nlh0, AF_INET,
     459  		       TCPDIAG_GETSOCK, NLM_F_REQUEST, req,
     460  		       printf("{idiag_family=AF_INET"),
     461  		       printf(", ");
     462  		       PRINT_FIELD_U(req, idiag_src_len);
     463  		       printf(", ");
     464  		       PRINT_FIELD_U(req, idiag_dst_len);
     465  		       printf(", idiag_ext=1<<(INET_DIAG_TOS-1)");
     466  		       printf(", id={idiag_sport=htons(%u)"
     467  			      ", idiag_dport=htons(%u)"
     468  			      ", idiag_src=inet_addr(\"%s\")"
     469  			      ", idiag_dst=inet_addr(\"%s\")",
     470  			      ntohs(req.id.idiag_sport),
     471  			      ntohs(req.id.idiag_dport),
     472  			      address, address);
     473  		       printf(", idiag_if=" IFINDEX_LO_STR);
     474  		       printf(", ");
     475  		       PRINT_FIELD_COOKIE(req.id, idiag_cookie);
     476  		       printf("}, idiag_states=1<<TCP_LAST_ACK");
     477  		       printf(", ");
     478  		       PRINT_FIELD_U(req, idiag_dbs);
     479  		       printf("}"));
     480  }
     481  
     482  static void
     483  test_inet_diag_req_v2(const int fd)
     484  {
     485  	const char address[] = "87.65.43.21";
     486  	struct inet_diag_req_v2 req = {
     487  		.sdiag_family = AF_INET,
     488  		.idiag_ext = 1 << (INET_DIAG_CONG - 1),
     489  		.sdiag_protocol = IPPROTO_TCP,
     490  		.idiag_states = 1 << TCP_CLOSE,
     491  		.id = {
     492  			.idiag_sport = 0xfacd,
     493  			.idiag_dport = 0xdead,
     494  			.idiag_if = ifindex_lo(),
     495  			.idiag_cookie = { 0xdeadbeef, 0xbadc0ded }
     496  		},
     497  	};
     498  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(req));
     499  
     500  	if (!inet_pton(AF_INET, address, &req.id.idiag_src) ||
     501  	    !inet_pton(AF_INET, address, &req.id.idiag_dst))
     502  		perror_msg_and_skip("inet_pton");
     503  
     504  	TEST_SOCK_DIAG(fd, nlh0, AF_INET,
     505  		       SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
     506  		       printf("{sdiag_family=AF_INET"),
     507  		       printf(", sdiag_protocol=IPPROTO_TCP"
     508  			      ", idiag_ext=1<<(INET_DIAG_CONG-1)"
     509  			      ", idiag_states=1<<TCP_CLOSE"
     510  			      ", id={idiag_sport=htons(%u)"
     511  			      ", idiag_dport=htons(%u)"
     512  			      ", idiag_src=inet_addr(\"%s\")"
     513  			      ", idiag_dst=inet_addr(\"%s\")",
     514  			      ntohs(req.id.idiag_sport),
     515  			      ntohs(req.id.idiag_dport),
     516  			      address, address);
     517  		       printf(", idiag_if=" IFINDEX_LO_STR);
     518  		       printf(", ");
     519  		       PRINT_FIELD_COOKIE(req.id, idiag_cookie);
     520  		       printf("}}"));
     521  }
     522  
     523  static void
     524  test_inet_diag_msg(const int fd)
     525  {
     526  	const char address[] = "11.22.33.44";
     527  	struct inet_diag_msg msg = {
     528  		.idiag_family = AF_INET,
     529  		.idiag_state = TCP_LISTEN,
     530  		.idiag_timer = 0xfa,
     531  		.idiag_retrans = 0xde,
     532  		.id = {
     533  			.idiag_sport = 0xfacf,
     534  			.idiag_dport = 0xdead,
     535  			.idiag_if = ifindex_lo(),
     536  			.idiag_cookie = { 0xdeadbeef, 0xbadc0ded }
     537  		},
     538  		.idiag_expires = 0xfacefeed,
     539  		.idiag_rqueue = 0xdeadbeef,
     540  		.idiag_wqueue = 0xadcdfafc,
     541  		.idiag_uid = 0xdecefaeb,
     542  		.idiag_inode = 0xbadc0ded,
     543  	};
     544  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg));
     545  
     546  	if (!inet_pton(AF_INET, address, &msg.id.idiag_src) ||
     547  	    !inet_pton(AF_INET, address, &msg.id.idiag_dst))
     548  		perror_msg_and_skip("inet_pton");
     549  
     550  	TEST_SOCK_DIAG(fd, nlh0, AF_INET,
     551  		       SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, msg,
     552  		       printf("{idiag_family=AF_INET"),
     553  		       printf(", idiag_state=TCP_LISTEN");
     554  		       printf(", ");
     555  		       PRINT_FIELD_U(msg, idiag_timer);
     556  		       printf(", ");
     557  		       PRINT_FIELD_U(msg, idiag_retrans);
     558  		       printf(", id={idiag_sport=htons(%u)"
     559  			      ", idiag_dport=htons(%u)"
     560  			      ", idiag_src=inet_addr(\"%s\")"
     561  			      ", idiag_dst=inet_addr(\"%s\")",
     562  			      ntohs(msg.id.idiag_sport),
     563  			      ntohs(msg.id.idiag_dport),
     564  			      address, address);
     565  		       printf(", idiag_if=" IFINDEX_LO_STR);
     566  		       printf(", ");
     567  		       PRINT_FIELD_COOKIE(msg.id, idiag_cookie);
     568  		       printf("}, ");
     569  		       PRINT_FIELD_U(msg, idiag_expires);
     570  		       printf(", ");
     571  		       PRINT_FIELD_U(msg, idiag_rqueue);
     572  		       printf(", ");
     573  		       PRINT_FIELD_U(msg, idiag_wqueue);
     574  		       printf(", ");
     575  		       PRINT_FIELD_U(msg, idiag_uid);
     576  		       printf(", ");
     577  		       PRINT_FIELD_U(msg, idiag_inode);
     578  		       printf("}"));
     579  }
     580  
     581  #ifdef AF_SMC
     582  static void
     583  test_smc_diag_req(const int fd)
     584  {
     585  	const char address[] = "43.21.56.78";
     586  	struct smc_diag_req req = {
     587  		.diag_family = AF_SMC,
     588  		.diag_ext = 1 << (SMC_DIAG_CONNINFO - 1),
     589  		.id = {
     590  			.idiag_sport = 0xdead,
     591  			.idiag_dport = 0xadcd,
     592  			.idiag_if = ifindex_lo(),
     593  			.idiag_cookie = { 0xdeadbeef, 0xbadc0ded },
     594  		},
     595  	};
     596  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(req));
     597  
     598  	if (!inet_pton(AF_INET, address, &req.id.idiag_src) ||
     599  	    !inet_pton(AF_INET, address, &req.id.idiag_dst))
     600  		perror_msg_and_skip("inet_pton");
     601  
     602  	TEST_SOCK_DIAG(fd, nlh0, AF_SMC,
     603  		       SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
     604  		       printf("{diag_family=AF_SMC"),
     605  		       printf(", diag_ext=1<<(SMC_DIAG_CONNINFO-1)");
     606  		       printf(", id={idiag_sport=htons(%u)"
     607  			      ", idiag_dport=htons(%u)"
     608  			      ", idiag_src=inet_addr(\"%s\")"
     609  			      ", idiag_dst=inet_addr(\"%s\")",
     610  			      ntohs(req.id.idiag_sport),
     611  			      ntohs(req.id.idiag_dport),
     612  			      address, address);
     613  		       printf(", idiag_if=" IFINDEX_LO_STR);
     614  		       printf(", ");
     615  		       PRINT_FIELD_COOKIE(req.id, idiag_cookie);
     616  		       printf("}}"));
     617  }
     618  
     619  static void
     620  test_smc_diag_msg(const int fd)
     621  {
     622  	const char address[] = "34.87.12.90";
     623  	struct smc_diag_msg msg = {
     624  		.diag_family = AF_SMC,
     625  		.diag_state = SMC_ACTIVE,
     626  		.diag_fallback = 0x1,
     627  		.diag_shutdown = 0xba,
     628  		.id = {
     629  			.idiag_sport = 0xdead,
     630  			.idiag_dport = 0xadcd,
     631  			.idiag_if = ifindex_lo(),
     632  			.idiag_cookie = { 0xdeadbeef, 0xbadc0ded },
     633  		},
     634  		.diag_uid = 0xadcdfafc,
     635  		.diag_inode = 0xbadc0ded,
     636  	};
     637  	void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(msg));
     638  
     639  	if (!inet_pton(AF_INET, address, &msg.id.idiag_src) ||
     640  	    !inet_pton(AF_INET, address, &msg.id.idiag_dst))
     641  		perror_msg_and_skip("inet_pton");
     642  
     643  	TEST_SOCK_DIAG(fd, nlh0, AF_SMC,
     644  		       SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, msg,
     645  		       printf("{diag_family=AF_SMC"),
     646  		       printf(", diag_state=SMC_ACTIVE");
     647  		       printf(", diag_fallback=SMC_DIAG_MODE_FALLBACK_TCP");
     648  		       printf(", ");
     649  		       PRINT_FIELD_U(msg, diag_shutdown);
     650  		       printf(", id={idiag_sport=htons(%u)"
     651  			      ", idiag_dport=htons(%u)"
     652  			      ", idiag_src=inet_addr(\"%s\")"
     653  			      ", idiag_dst=inet_addr(\"%s\")",
     654  			      ntohs(msg.id.idiag_sport),
     655  			      ntohs(msg.id.idiag_dport),
     656  			      address, address);
     657  		       printf(", idiag_if=" IFINDEX_LO_STR);
     658  		       printf(", ");
     659  		       PRINT_FIELD_COOKIE(msg.id, idiag_cookie);
     660  		       printf("}, ");
     661  		       PRINT_FIELD_U(msg, diag_uid);
     662  		       printf(", ");
     663  		       PRINT_FIELD_U(msg, diag_inode);
     664  		       printf("}"));
     665  }
     666  #endif
     667  
     668  int
     669  main(void)
     670  {
     671  	skip_if_unavailable("/proc/self/fd/");
     672  
     673  	int fd = create_nl_socket(NETLINK_SOCK_DIAG);
     674  
     675  	test_nlmsg_type(fd);
     676  	test_nlmsg_flags(fd);
     677  	test_odd_family_req(fd);
     678  	test_odd_family_msg(fd);
     679  	test_unix_diag_req(fd);
     680  	test_unix_diag_msg(fd);
     681  	test_netlink_diag_req(fd);
     682  	test_netlink_diag_msg(fd);
     683  	test_packet_diag_req(fd);
     684  	test_packet_diag_msg(fd);
     685  	test_inet_diag_sockid(fd);
     686  	test_inet_diag_req(fd);
     687  	test_inet_diag_req_v2(fd);
     688  	test_inet_diag_msg(fd);
     689  #ifdef AF_SMC
     690  	test_smc_diag_req(fd);
     691  	test_smc_diag_msg(fd);
     692  #endif
     693  
     694  	printf("+++ exited with 0 +++\n");
     695  
     696  	return 0;
     697  }