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 }