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