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 <arpa/inet.h>
14 #include <linux/atalk.h>
15 #include <linux/mptcp.h>
16 #include <linux/tls.h>
17 #include <net/if.h>
18 #include <netinet/in.h>
19 #include <netinet/tcp.h>
20 #include "test_nlattr.h"
21 #include <linux/inet_diag.h>
22 #include <linux/sock_diag.h>
23
24
25 #ifndef HAVE_STRUCT_TCP_DIAG_MD5SIG
26 struct tcp_diag_md5sig {
27 __u8 tcpm_family;
28 __u8 tcpm_prefixlen;
29 __u16 tcpm_keylen;
30 __be32 tcpm_addr[4];
31 __u8 tcpm_key[80 /* TCP_MD5SIG_MAXKEYLEN */];
32 };
33 #endif
34
35 static const char * const sk_meminfo_strs[] = {
36 "SK_MEMINFO_RMEM_ALLOC",
37 "SK_MEMINFO_RCVBUF",
38 "SK_MEMINFO_WMEM_ALLOC",
39 "SK_MEMINFO_SNDBUF",
40 "SK_MEMINFO_FWD_ALLOC",
41 "SK_MEMINFO_WMEM_QUEUED",
42 "SK_MEMINFO_OPTMEM",
43 "SK_MEMINFO_BACKLOG",
44 "SK_MEMINFO_DROPS",
45 };
46
47 static const char address[] = "10.11.12.13";
48 static const unsigned int hdrlen = sizeof(struct inet_diag_msg);
49 static uint16_t attr1;
50 static const char *attr1_str = NULL;
51 static uint16_t attr2;
52 static const char *attr2_str = NULL;
53
54
55 static void
56 init_inet_diag_msg(struct nlmsghdr *const nlh, const unsigned int msg_len)
57 {
58 SET_STRUCT(struct nlmsghdr, nlh,
59 .nlmsg_len = msg_len,
60 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
61 .nlmsg_flags = NLM_F_DUMP
62 );
63
64 struct inet_diag_msg *const msg = NLMSG_DATA(nlh);
65 SET_STRUCT(struct inet_diag_msg, msg,
66 .idiag_family = AF_INET,
67 .idiag_state = TCP_LISTEN,
68 .id.idiag_if = ifindex_lo()
69 );
70
71 if (!inet_pton(AF_INET, address, msg->id.idiag_src) ||
72 !inet_pton(AF_INET, address, msg->id.idiag_dst))
73 perror_msg_and_skip("inet_pton");
74 }
75
76 static void
77 print_inet_diag_msg(const unsigned int msg_len)
78 {
79 printf("{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
80 ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
81 ", {idiag_family=AF_INET, idiag_state=TCP_LISTEN"
82 ", idiag_timer=0, idiag_retrans=0"
83 ", id={idiag_sport=htons(0), idiag_dport=htons(0)"
84 ", idiag_src=inet_addr(\"%s\")"
85 ", idiag_dst=inet_addr(\"%s\")"
86 ", idiag_if=" IFINDEX_LO_STR
87 ", idiag_cookie=[0, 0]}"
88 ", idiag_expires=0, idiag_rqueue=0, idiag_wqueue=0"
89 ", idiag_uid=0, idiag_inode=0}",
90 msg_len, address, address);
91 }
92
93 static void
94 init_inet_diag_nest_1(struct nlmsghdr *const nlh, const unsigned int msg_len)
95 {
96 init_inet_diag_msg(nlh, msg_len);
97
98 struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen);
99 SET_STRUCT(struct nlattr, nla,
100 .nla_len = msg_len - NLMSG_SPACE(hdrlen),
101 .nla_type = attr1,
102 );
103 }
104
105 static void
106 print_inet_diag_nest_1(const unsigned int msg_len)
107 {
108 print_inet_diag_msg(msg_len);
109 printf(", [{nla_len=%u, nla_type=%s}",
110 msg_len - NLMSG_SPACE(hdrlen), attr1_str);
111 }
112
113 static void
114 init_inet_diag_nest_2(struct nlmsghdr *const nlh, const unsigned int msg_len)
115 {
116 init_inet_diag_nest_1(nlh, msg_len);
117
118 struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen);
119 nla += 1;
120 SET_STRUCT(struct nlattr, nla,
121 .nla_len = msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN,
122 .nla_type = attr2,
123 );
124 }
125
126 static void
127 print_inet_diag_nest_2(const unsigned int msg_len)
128 {
129 print_inet_diag_nest_1(msg_len);
130 printf(", [{nla_len=%u, nla_type=%s}",
131 msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN, attr2_str);
132 }
133
134 static void
135 print_uint(const unsigned int *p, size_t i)
136 {
137 if (i >= ARRAY_SIZE(sk_meminfo_strs))
138 printf("[%zu /* SK_MEMINFO_??? */", i);
139 else
140 printf("[%s", sk_meminfo_strs[i]);
141
142 printf("]=%u", *p);
143 }
144
145 static const struct {
146 struct tcp_diag_md5sig val;
147 const char *str;
148 } md5sig_vecs[] = {
149 { { 0 },
150 "{tcpm_family=AF_UNSPEC, tcpm_prefixlen=0, tcpm_keylen=0"
151 ", tcpm_addr=\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"
152 "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", tcpm_key=\"\"}" },
153 { { AF_INET, 0x42, 1, { BE_LE(0xdeadface, 0xcefaadde) } },
154 "{tcpm_family=AF_INET, tcpm_prefixlen=66, tcpm_keylen=1"
155 ", tcpm_addr=inet_addr(\"222.173.250.206\")"
156 ", tcpm_key=\"\\x00\"}" },
157 { { AF_INET6, 0xbe, 42,
158 { BE_LE(0xdeadface, 0xcefaadde), BE_LE(0xcafe0000, 0xfeca),
159 BE_LE(0xface, 0xcefa0000), BE_LE(0xbadc0ded, 0xed0ddcba) },
160 "OH HAI THAR\0\1\2\3\4\5\6\7\3779876543210abcdefghijklmnopqrstuv" },
161 "{tcpm_family=AF_INET6, tcpm_prefixlen=190, tcpm_keylen=42"
162 ", inet_pton(AF_INET6, \"dead:face:cafe::face:badc:ded\", &tcpm_addr)"
163 ", tcpm_key=\"\\x4f\\x48\\x20\\x48\\x41\\x49\\x20\\x54\\x48\\x41"
164 "\\x52\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\xff\\x39\\x38\\x37"
165 "\\x36\\x35\\x34\\x33\\x32\\x31\\x30\\x61\\x62\\x63\\x64\\x65\\x66"
166 "\\x67\\x68\\x69\\x6a\\x6b\\x6c\"}" },
167 { { 46, 0, 45067,
168 { BE_LE(0xdeadface, 0xcefaadde), BE_LE(0xcafe0000, 0xfeca),
169 BE_LE(0xface, 0xcefa0000), BE_LE(0xbadc0ded, 0xed0ddcba) },
170 "OH HAI THAR\0\1\2\3\4\5\6\7\3779876543210abcdefghijklmnopqrstuv"
171 "xyz0123456789ABCDEFGHIJKLMNO" },
172 "{tcpm_family=0x2e /* AF_??? */, tcpm_prefixlen=0, tcpm_keylen=45067"
173 ", tcpm_addr=\"\\xde\\xad\\xfa\\xce\\xca\\xfe\\x00\\x00"
174 "\\x00\\x00\\xfa\\xce\\xba\\xdc\\x0d\\xed\""
175 ", tcpm_key=\"\\x4f\\x48\\x20\\x48\\x41\\x49\\x20\\x54\\x48\\x41"
176 "\\x52\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\xff\\x39\\x38\\x37"
177 "\\x36\\x35\\x34\\x33\\x32\\x31\\x30\\x61\\x62\\x63\\x64\\x65\\x66"
178 "\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\\x70\\x71\\x72\\x73"
179 "\\x74\\x75\\x76\\x78\\x79\\x7a\\x30\\x31\\x32\\x33\\x34\\x35\\x36"
180 "\\x37\\x38\\x39\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4a"
181 "\\x4b\\x4c\\x4d\\x4e\\x4f\"}" },
182 };
183
184 static void
185 print_md5sig(const struct tcp_diag_md5sig *p, size_t i)
186 {
187 printf("%s", md5sig_vecs[i].str);
188 }
189
190 static void
191 print_sa(const struct sockaddr_storage *p, size_t i)
192 {
193 static const char *strs[] = {
194 "{sa_family=AF_INET, sin_port=htons(42069)"
195 ", sin_addr=inet_addr(\"18.52.86.120\")}",
196 "{sa_family=AF_INET6, sin6_port=htons(23456)"
197 ", sin6_flowinfo=htonl(324508639)"
198 ", inet_pton(AF_INET6, \"1234:5678::9abc:def0\", &sin6_addr)"
199 ", sin6_scope_id=610839776}",
200 "{sa_family=AF_APPLETALK"
201 ", sa_data=\"i\\0" BE_LE("\\207e", "e\\207") "B\\0\\0\\0\\0\\0"
202 "\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"
203 "\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"
204 "\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"
205 "\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"
206 "\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"
207 "\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\"}"
208 };
209
210 printf("%s", strs[i]);
211 }
212
213 int
214 main(void)
215 {
216 skip_if_unavailable("/proc/self/fd/");
217
218 static const struct inet_diag_meminfo minfo = {
219 .idiag_rmem = 0xfadcacdb,
220 .idiag_wmem = 0xbdabcada,
221 .idiag_fmem = 0xbadbfafb,
222 .idiag_tmem = 0xfdacdadf
223 };
224 static const struct tcpvegas_info vegas = {
225 .tcpv_enabled = 0xfadcacdb,
226 .tcpv_rttcnt = 0xbdabcada,
227 .tcpv_rtt = 0xbadbfafb,
228 .tcpv_minrtt = 0xfdacdadf
229 };
230 static const struct tcp_dctcp_info dctcp = {
231 .dctcp_enabled = 0xfdac,
232 .dctcp_ce_state = 0xfadc,
233 .dctcp_alpha = 0xbdabcada,
234 .dctcp_ab_ecn = 0xbadbfafb,
235 .dctcp_ab_tot = 0xfdacdadf
236 };
237 static const struct tcp_bbr_info bbr = {
238 .bbr_bw_lo = 0xfdacdadf,
239 .bbr_bw_hi = 0xfadcacdb,
240 .bbr_min_rtt = 0xbdabcada,
241 .bbr_pacing_gain = 0xbadbfafb,
242 .bbr_cwnd_gain = 0xfdacdadf
243 };
244 static const uint32_t mem[] = { 0xaffacbad, 0xffadbcab };
245 static uint32_t bigmem[SK_MEMINFO_VARS + 1];
246 static const uint32_t mark = 0xabdfadca;
247
248 const int fd = create_nl_socket(NETLINK_SOCK_DIAG);
249 void *const nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen),
250 NLA_HDRLEN +
251 MAX(sizeof(bigmem), DEFAULT_STRLEN));
252
253 static char pattern[4096];
254 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
255
256 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
257 init_inet_diag_msg, print_inet_diag_msg,
258 INET_DIAG_MEMINFO, pattern, minfo,
259 printf("{");
260 PRINT_FIELD_U(minfo, idiag_rmem);
261 printf(", ");
262 PRINT_FIELD_U(minfo, idiag_wmem);
263 printf(", ");
264 PRINT_FIELD_U(minfo, idiag_fmem);
265 printf(", ");
266 PRINT_FIELD_U(minfo, idiag_tmem);
267 printf("}"));
268
269 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
270 init_inet_diag_msg, print_inet_diag_msg,
271 INET_DIAG_VEGASINFO, pattern, vegas,
272 printf("{");
273 PRINT_FIELD_U(vegas, tcpv_enabled);
274 printf(", ");
275 PRINT_FIELD_U(vegas, tcpv_rttcnt);
276 printf(", ");
277 PRINT_FIELD_U(vegas, tcpv_rtt);
278 printf(", ");
279 PRINT_FIELD_U(vegas, tcpv_minrtt);
280 printf("}"));
281
282
283 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
284 init_inet_diag_msg, print_inet_diag_msg,
285 INET_DIAG_DCTCPINFO, pattern, dctcp,
286 printf("{");
287 PRINT_FIELD_U(dctcp, dctcp_enabled);
288 printf(", ");
289 PRINT_FIELD_U(dctcp, dctcp_ce_state);
290 printf(", ");
291 PRINT_FIELD_U(dctcp, dctcp_alpha);
292 printf(", ");
293 PRINT_FIELD_U(dctcp, dctcp_ab_ecn);
294 printf(", ");
295 PRINT_FIELD_U(dctcp, dctcp_ab_tot);
296 printf("}"));
297
298 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
299 init_inet_diag_msg, print_inet_diag_msg,
300 INET_DIAG_BBRINFO, pattern, bbr,
301 printf("{");
302 PRINT_FIELD_X(bbr, bbr_bw_lo);
303 printf(", ");
304 PRINT_FIELD_X(bbr, bbr_bw_hi);
305 printf(", ");
306 PRINT_FIELD_U(bbr, bbr_min_rtt);
307 printf(", ");
308 PRINT_FIELD_U(bbr, bbr_pacing_gain);
309 printf(", ");
310 PRINT_FIELD_U(bbr, bbr_cwnd_gain);
311 printf("}"));
312
313 TEST_NLATTR_ARRAY(fd, nlh0, hdrlen,
314 init_inet_diag_msg, print_inet_diag_msg,
315 INET_DIAG_SKMEMINFO, pattern, mem, print_uint);
316
317 memcpy(bigmem, pattern, sizeof(bigmem));
318
319 TEST_NLATTR_ARRAY(fd, nlh0, hdrlen,
320 init_inet_diag_msg, print_inet_diag_msg,
321 INET_DIAG_SKMEMINFO, pattern, bigmem, print_uint);
322
323 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
324 init_inet_diag_msg, print_inet_diag_msg,
325 INET_DIAG_MARK, pattern, mark,
326 printf("%u", mark));
327
328 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
329 init_inet_diag_msg, print_inet_diag_msg,
330 INET_DIAG_CLASS_ID, pattern, mark,
331 printf("%u", mark));
332
333 static const struct strval8 shutdown_vecs[] = {
334 { ARG_STR(0) },
335 { 1, "0x1 /* RCV_SHUTDOWN */" },
336 { 2, "0x2 /* SEND_SHUTDOWN */" },
337 { 3, "0x3 /* RCV_SHUTDOWN|SEND_SHUTDOWN */" },
338 { 4, "0x4 /* ???_SHUTDOWN */" },
339 { 23, "0x17 /* RCV_SHUTDOWN|SEND_SHUTDOWN|0x14 */" },
340 { 252, "0xfc /* ???_SHUTDOWN */" },
341 };
342 TAIL_ALLOC_OBJECT_CONST_PTR(uint8_t, shutdown);
343 for (size_t i = 0; i < ARRAY_SIZE(shutdown_vecs); i++) {
344 *shutdown = shutdown_vecs[i].val;
345 TEST_NLATTR(fd, nlh0, hdrlen,
346 init_inet_diag_msg, print_inet_diag_msg,
347 INET_DIAG_SHUTDOWN,
348 sizeof(*shutdown), shutdown, sizeof(*shutdown),
349 printf("%s", shutdown_vecs[i].str));
350 }
351
352 char *const str = tail_alloc(DEFAULT_STRLEN);
353 fill_memory_ex(str, DEFAULT_STRLEN, '0', 10);
354 TEST_NLATTR(fd, nlh0, hdrlen,
355 init_inet_diag_msg, print_inet_diag_msg, INET_DIAG_CONG,
356 DEFAULT_STRLEN, str, DEFAULT_STRLEN,
357 printf("\"%.*s\"...", DEFAULT_STRLEN, str));
358 str[DEFAULT_STRLEN - 1] = '\0';
359 TEST_NLATTR(fd, nlh0, hdrlen,
360 init_inet_diag_msg, print_inet_diag_msg, INET_DIAG_CONG,
361 DEFAULT_STRLEN, str, DEFAULT_STRLEN,
362 printf("\"%s\"", str));
363
364 /* u8 INET_DIAG_* attrs */
365 static const struct strval16 u8_attrs[] = {
366 { ENUM_KNOWN(0x5, INET_DIAG_TOS) },
367 { ENUM_KNOWN(0x6, INET_DIAG_TCLASS) },
368 { ENUM_KNOWN(0xb, INET_DIAG_SKV6ONLY) },
369 };
370 void *nlh_u8 = midtail_alloc(NLMSG_SPACE(hdrlen), sizeof(uint8_t));
371
372 for (size_t i = 0; i < ARRAY_SIZE(u8_attrs); i++) {
373 check_u8_nlattr(fd, nlh_u8, hdrlen,
374 init_inet_diag_msg, print_inet_diag_msg,
375 u8_attrs[i].val, u8_attrs[i].str, pattern, 0);
376 }
377
378 /* u32 INET_DIAG_* attrs */
379 static const struct strval16 u32_attrs[] = {
380 { ENUM_KNOWN(0xf, INET_DIAG_MARK) },
381 { ENUM_KNOWN(0x11, INET_DIAG_CLASS_ID) },
382 };
383 void *nlh_u32 = midtail_alloc(NLMSG_SPACE(hdrlen), sizeof(uint32_t));
384
385 for (size_t i = 0; i < ARRAY_SIZE(u32_attrs); i++) {
386 check_u32_nlattr(fd, nlh_u32, hdrlen,
387 init_inet_diag_msg, print_inet_diag_msg,
388 u32_attrs[i].val, u32_attrs[i].str,
389 pattern, 0);
390 }
391
392 /* u64 INET_DIAG_* attrs */
393 static const struct strval16 u64_attrs[] = {
394 { ENUM_KNOWN(0x15, INET_DIAG_CGROUP_ID) },
395 };
396 void *nlh_u64 = midtail_alloc(NLMSG_SPACE(hdrlen), sizeof(uint64_t));
397
398 for (size_t i = 0; i < ARRAY_SIZE(u64_attrs); i++) {
399 check_u64_nlattr(fd, nlh_u64, hdrlen,
400 init_inet_diag_msg, print_inet_diag_msg,
401 u64_attrs[i].val, u64_attrs[i].str,
402 pattern, 0);
403 }
404
405 /* INET_DIAG_PROTOCOL */
406 static const struct strval8 protos[] = {
407 { 0, "IPPROTO_IP" },
408 { 2, "IPPROTO_IGMP" },
409 { 5, "0x5 /* IPPROTO_??? */" },
410 { 6, "IPPROTO_TCP" },
411 { 190, "0xbe /* IPPROTO_??? */" },
412 { 255, "IPPROTO_RAW" },
413 };
414
415 for (size_t i = 0; i < ARRAY_SIZE(protos); i++) {
416 TEST_NLATTR(fd, nlh0, hdrlen,
417 init_inet_diag_msg, print_inet_diag_msg,
418 INET_DIAG_PROTOCOL,
419 sizeof(uint8_t), &protos[i].val, sizeof(uint8_t),
420 printf("%s", protos[i].str));
421 }
422
423 /* INET_DIAG_MD5SIG */
424 struct tcp_diag_md5sig md5s_arr[ARRAY_SIZE(md5sig_vecs)];
425
426 for (size_t i = 0; i < ARRAY_SIZE(md5sig_vecs); i++) {
427 memcpy(md5s_arr + i, &md5sig_vecs[i].val, sizeof(md5s_arr[0]));
428
429 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
430 init_inet_diag_msg, print_inet_diag_msg,
431 INET_DIAG_MD5SIG, pattern,
432 md5sig_vecs[i].val,
433 printf("[%s]", md5sig_vecs[i].str));
434 }
435
436 TEST_NLATTR_ARRAY(fd, nlh0, hdrlen,
437 init_inet_diag_msg, print_inet_diag_msg,
438 INET_DIAG_MD5SIG, pattern, md5s_arr, print_md5sig);
439
440 /* INET_DIAG_ULP_INFO */
441 attr1 = INET_DIAG_ULP_INFO;
442 attr1_str = "INET_DIAG_ULP_INFO";
443
444 /* INET_DIAG_ULP_INFO: unknown, undecoded */
445 static const struct strval16 ulp_unk_attrs[] = {
446 { ENUM_KNOWN(0, INET_ULP_INFO_UNSPEC) },
447 { ARG_XLAT_UNKNOWN(0x4, "INET_ULP_INFO_???") },
448 { ARG_XLAT_UNKNOWN(0x1ace, "INET_ULP_INFO_???") },
449 };
450 static const uint32_t dummy = BE_LE(0xdeadc0de, 0xdec0adde);
451
452 for (size_t i = 0; i < ARRAY_SIZE(ulp_unk_attrs); i++) {
453 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
454 init_inet_diag_nest_1,
455 print_inet_diag_nest_1,
456 ulp_unk_attrs[i].val,
457 ulp_unk_attrs[i].str,
458 sizeof(dummy), &dummy, sizeof(dummy), 1,
459 printf("\"\\xde\\xad\\xc0\\xde\""));
460 }
461
462 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_NAME */
463 static const struct {
464 const char *val;
465 const char *str;
466 ssize_t sz;
467 } ulp_names[] = {
468 { "OH HAI", "\"OH HAI\"", 7 },
469 { "\0\0\0", "\"\\0\\0\\0\"", 4 },
470 { "\1\2\3\4\5\6\7\10\11\12\13\14",
471 "\"\\1\\2\\3\\4\\5\\6\\7\\10\\t\\n\\v\\f\"...", 12 },
472 };
473
474 for (size_t i = 0; i < ARRAY_SIZE(ulp_names); i++) {
475 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
476 init_inet_diag_nest_1,
477 print_inet_diag_nest_1,
478 INET_ULP_INFO_NAME, "INET_ULP_INFO_NAME",
479 ulp_names[i].sz, ulp_names[i].val,
480 ulp_names[i].sz, 1,
481 printf("%s", ulp_names[i].str));
482 }
483
484 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_TLS */
485 attr2 = INET_ULP_INFO_TLS;
486 attr2_str = "INET_ULP_INFO_TLS";
487
488 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_TLS: unknown, undecoded */
489 static const struct strval16 tls_unk_attrs[] = {
490 { ENUM_KNOWN(0, TLS_INFO_UNSPEC) },
491 { ENUM_KNOWN(0x6, TLS_INFO_RX_NO_PAD) },
492 { ARG_XLAT_UNKNOWN(0x7, "TLS_INFO_???") },
493 { ARG_XLAT_UNKNOWN(0x1ace, "TLS_INFO_???") },
494 };
495
496 for (size_t i = 0; i < ARRAY_SIZE(tls_unk_attrs); i++) {
497 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
498 init_inet_diag_nest_2,
499 print_inet_diag_nest_2,
500 tls_unk_attrs[i].val,
501 tls_unk_attrs[i].str,
502 sizeof(dummy), &dummy, sizeof(dummy), 2,
503 printf("\"\\xde\\xad\\xc0\\xde\""));
504 }
505
506 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_TLS: TLS_INFO_VERSION */
507 static const struct strval16 tls_vers[] = {
508 { ARG_XLAT_UNKNOWN(0, "TLS_???_VERSION") },
509 { ARG_XLAT_UNKNOWN(0x200, "TLS_???_VERSION") },
510 { ARG_XLAT_UNKNOWN(0x300, "TLS_???_VERSION") },
511 { ARG_XLAT_UNKNOWN(0x301, "TLS_???_VERSION") },
512 { ARG_XLAT_UNKNOWN(0x302, "TLS_???_VERSION") },
513 { ENUM_KNOWN(0x303, TLS_1_2_VERSION) },
514 { ENUM_KNOWN(0x304, TLS_1_3_VERSION) },
515 { ARG_XLAT_UNKNOWN(0x305, "TLS_???_VERSION") },
516 { ARG_XLAT_UNKNOWN(0xdead, "TLS_???_VERSION") },
517 };
518
519 for (size_t i = 0; i < ARRAY_SIZE(tls_vers); i++) {
520 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
521 init_inet_diag_nest_2,
522 print_inet_diag_nest_2,
523 TLS_INFO_VERSION, "TLS_INFO_VERSION",
524 2, &tls_vers[i].val, 2, 2,
525 printf("%s", tls_vers[i].str));
526 }
527
528 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_TLS: TLS_INFO_CIPHER */
529 static const struct strval16 tls_ciphers[] = {
530 { ARG_XLAT_UNKNOWN(0, "TLS_CIPHER_???") },
531 { ARG_XLAT_UNKNOWN(0x32, "TLS_CIPHER_???") },
532 { ENUM_KNOWN(0x33, TLS_CIPHER_AES_GCM_128) },
533 { ENUM_KNOWN(0x34, TLS_CIPHER_AES_GCM_256) },
534 { ENUM_KNOWN(0x35, TLS_CIPHER_AES_CCM_128) },
535 { ENUM_KNOWN(0x36, TLS_CIPHER_CHACHA20_POLY1305) },
536 { ENUM_KNOWN(0x37, TLS_CIPHER_SM4_GCM) },
537 { ENUM_KNOWN(0x38, TLS_CIPHER_SM4_CCM) },
538 { ENUM_KNOWN(0x39, TLS_CIPHER_ARIA_GCM_128) },
539 { ENUM_KNOWN(0x3a, TLS_CIPHER_ARIA_GCM_256) },
540 { ARG_XLAT_UNKNOWN(0x3b, "TLS_CIPHER_???") },
541 { ARG_XLAT_UNKNOWN(0xcafe, "TLS_CIPHER_???") },
542 };
543
544 for (size_t i = 0; i < ARRAY_SIZE(tls_ciphers); i++) {
545 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
546 init_inet_diag_nest_2,
547 print_inet_diag_nest_2,
548 TLS_INFO_CIPHER, "TLS_INFO_CIPHER",
549 2, &tls_ciphers[i].val, 2, 2,
550 printf("%s", tls_ciphers[i].str));
551 }
552
553 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_TLS: TLS_INFO_[RT]XCONF */
554 static const struct strval16 tls_cfg_attrs[] = {
555 { ENUM_KNOWN(0, TLS_INFO_TXCONF) },
556 { ENUM_KNOWN(0, TLS_INFO_RXCONF) },
557 };
558 static const struct strval16 tls_cfgs[] = {
559 { ARG_XLAT_UNKNOWN(0, "TLS_CONF_???") },
560 { ENUM_KNOWN(0x1, TLS_CONF_BASE) },
561 { ENUM_KNOWN(0x2, TLS_CONF_SW) },
562 { ENUM_KNOWN(0x3, TLS_CONF_HW) },
563 { ENUM_KNOWN(0x4, TLS_CONF_HW_RECORD) },
564 { ARG_XLAT_UNKNOWN(0x5, "TLS_CONF_???") },
565 { ARG_XLAT_UNKNOWN(0xface, "TLS_CONF_???") },
566 };
567
568 for (size_t i = 0; i < ARRAY_SIZE(tls_cfg_attrs); i++) {
569 for (size_t j = 0; j < ARRAY_SIZE(tls_cfgs); j++) {
570 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
571 init_inet_diag_nest_2,
572 print_inet_diag_nest_2,
573 tls_cfg_attrs[i].val,
574 tls_cfg_attrs[i].str,
575 2, &tls_cfgs[i].val, 2, 2,
576 printf("%s", tls_cfgs[i].str));
577 }
578 }
579
580 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_MPTCP */
581 attr2 = INET_ULP_INFO_MPTCP;
582 attr2_str = "INET_ULP_INFO_MPTCP";
583
584 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_MPTCP: unknown, undecoded */
585 static const struct strval16 mptcp_unk_attrs[] = {
586 { ENUM_KNOWN(0, MPTCP_SUBFLOW_ATTR_UNSPEC) },
587 { ENUM_KNOWN(0xb, MPTCP_SUBFLOW_ATTR_PAD) },
588 { ARG_XLAT_UNKNOWN(0xc, "MPTCP_SUBFLOW_ATTR_???") },
589 { ARG_XLAT_UNKNOWN(0x1ace, "MPTCP_SUBFLOW_ATTR_???") },
590 };
591
592 for (size_t i = 0; i < ARRAY_SIZE(mptcp_unk_attrs); i++) {
593 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
594 init_inet_diag_nest_2,
595 print_inet_diag_nest_2,
596 mptcp_unk_attrs[i].val,
597 mptcp_unk_attrs[i].str,
598 sizeof(dummy), &dummy, sizeof(dummy), 2,
599 printf("\"\\xde\\xad\\xc0\\xde\""));
600 }
601
602 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_MPTCP: u8 */
603 static const struct strval16 mptcp_u8_attrs[] = {
604 { ENUM_KNOWN(0x9, MPTCP_SUBFLOW_ATTR_ID_REM) },
605 { ENUM_KNOWN(0xa, MPTCP_SUBFLOW_ATTR_ID_LOC) },
606 };
607 void *nlh_n2_u8 = midtail_alloc(NLMSG_SPACE(hdrlen),
608 NLA_HDRLEN * 2 + sizeof(uint8_t));
609
610 for (size_t i = 0; i < ARRAY_SIZE(mptcp_u8_attrs); i++) {
611 check_u8_nlattr(fd, nlh_n2_u8, hdrlen,
612 init_inet_diag_nest_2,
613 print_inet_diag_nest_2,
614 mptcp_u8_attrs[i].val, mptcp_u8_attrs[i].str,
615 pattern, 2);
616 }
617
618 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_MPTCP: u16 */
619 static const struct strval16 mptcp_u16_attrs[] = {
620 { ENUM_KNOWN(0x7, MPTCP_SUBFLOW_ATTR_MAP_DATALEN) },
621 };
622 void *nlh_n2_u16 = midtail_alloc(NLMSG_SPACE(hdrlen),
623 NLA_HDRLEN * 2 + sizeof(uint16_t));
624
625 for (size_t i = 0; i < ARRAY_SIZE(mptcp_u16_attrs); i++) {
626 check_u16_nlattr(fd, nlh_n2_u16, hdrlen,
627 init_inet_diag_nest_2,
628 print_inet_diag_nest_2,
629 mptcp_u16_attrs[i].val, mptcp_u16_attrs[i].str,
630 pattern, 2);
631 }
632
633 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_MPTCP: u32 */
634 static const struct strval16 mptcp_u32_attrs[] = {
635 { ENUM_KNOWN(0x3, MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ) },
636 { ENUM_KNOWN(0x5, MPTCP_SUBFLOW_ATTR_MAP_SFSEQ) },
637 { ENUM_KNOWN(0x6, MPTCP_SUBFLOW_ATTR_SSN_OFFSET) },
638 };
639 void *nlh_n2_u32 = midtail_alloc(NLMSG_SPACE(hdrlen),
640 NLA_HDRLEN * 2 + sizeof(uint32_t));
641
642 for (size_t i = 0; i < ARRAY_SIZE(mptcp_u32_attrs); i++) {
643 check_u32_nlattr(fd, nlh_n2_u32, hdrlen,
644 init_inet_diag_nest_2,
645 print_inet_diag_nest_2,
646 mptcp_u32_attrs[i].val, mptcp_u32_attrs[i].str,
647 pattern, 2);
648 }
649
650 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_MPTCP: u64 */
651 static const struct strval16 mptcp_u64_attrs[] = {
652 { ENUM_KNOWN(0x4, MPTCP_SUBFLOW_ATTR_MAP_SEQ) },
653 };
654 void *nlh_n2_u64 = midtail_alloc(NLMSG_SPACE(hdrlen),
655 NLA_HDRLEN * 2 + sizeof(uint64_t));
656
657 for (size_t i = 0; i < ARRAY_SIZE(mptcp_u64_attrs); i++) {
658 check_u64_nlattr(fd, nlh_n2_u64, hdrlen,
659 init_inet_diag_nest_2,
660 print_inet_diag_nest_2,
661 mptcp_u64_attrs[i].val, mptcp_u64_attrs[i].str,
662 pattern, 2);
663 }
664
665 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_MPTCP: x32 */
666 static const struct strval16 mptcp_x32_attrs[] = {
667 { ENUM_KNOWN(0x1, MPTCP_SUBFLOW_ATTR_TOKEN_REM) },
668 { ENUM_KNOWN(0x2, MPTCP_SUBFLOW_ATTR_TOKEN_LOC) },
669 };
670
671 for (size_t i = 0; i < ARRAY_SIZE(mptcp_x32_attrs); i++) {
672 check_x32_nlattr(fd, nlh_u32, hdrlen,
673 init_inet_diag_nest_2,
674 print_inet_diag_nest_2,
675 mptcp_x32_attrs[i].val, mptcp_x32_attrs[i].str,
676 pattern, 2);
677 }
678
679 /* INET_DIAG_ULP_INFO: INET_ULP_INFO_MPTCP: MPTCP_SUBFLOW_ATTR_FLAGS */
680 static const struct strval32 mptcp_flags[] = {
681 { ARG_STR(0) },
682 { ARG_XLAT_KNOWN(0x1, "MPTCP_SUBFLOW_FLAG_MCAP_REM") },
683 { ARG_XLAT_KNOWN(0xdecaffed,
684 "MPTCP_SUBFLOW_FLAG_MCAP_REM"
685 "|MPTCP_SUBFLOW_FLAG_JOIN_REM"
686 "|MPTCP_SUBFLOW_FLAG_JOIN_LOC"
687 "|MPTCP_SUBFLOW_FLAG_BKUP_LOC"
688 "|MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED"
689 "|MPTCP_SUBFLOW_FLAG_CONNECTED"
690 "|MPTCP_SUBFLOW_FLAG_MAPVALID|0xdecafe00") },
691 { ARG_XLAT_UNKNOWN(0xfffffe00, "MPTCP_SUBFLOW_FLAG_???") },
692 };
693
694 for (size_t i = 0; i < ARRAY_SIZE(mptcp_flags); i++) {
695 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
696 init_inet_diag_nest_2,
697 print_inet_diag_nest_2,
698 MPTCP_SUBFLOW_ATTR_FLAGS,
699 "MPTCP_SUBFLOW_ATTR_FLAGS",
700 4, &mptcp_flags[i].val, 4, 2,
701 printf("%s", mptcp_flags[i].str));
702 }
703
704 /* INET_DIAG_SK_BPF_STORAGES */
705 attr1 = INET_DIAG_SK_BPF_STORAGES;
706 attr1_str = "INET_DIAG_SK_BPF_STORAGES";
707
708 /* INET_DIAG_SK_BPF_STORAGES: unknown, undecoded */
709 static const struct strval16 bpfsts_unk_attrs[] = {
710 { ENUM_KNOWN(0, SK_DIAG_BPF_STORAGE_REP_NONE) },
711 { ARG_XLAT_UNKNOWN(0x2, "SK_DIAG_BPF_STORAGE_???") },
712 { ARG_XLAT_UNKNOWN(0x1ace, "SK_DIAG_BPF_STORAGE_???") },
713 };
714
715 for (size_t i = 0; i < ARRAY_SIZE(bpfsts_unk_attrs); i++) {
716 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
717 init_inet_diag_nest_1,
718 print_inet_diag_nest_1,
719 bpfsts_unk_attrs[i].val,
720 bpfsts_unk_attrs[i].str,
721 sizeof(dummy), &dummy, sizeof(dummy), 1,
722 printf("\"\\xde\\xad\\xc0\\xde\""));
723 }
724
725 /* INET_DIAG_SK_BPF_STORAGES: SK_DIAG_BPF_STORAGE */
726 attr2 = SK_DIAG_BPF_STORAGE;
727 attr2_str = "SK_DIAG_BPF_STORAGE";
728
729 /* INET_DIAG_SK_BPF_STORAGES: SK_DIAG_BPF_STORAGE: unknown, undecoded */
730 static const struct strval16 bpfst_unk_attrs[] = {
731 { ENUM_KNOWN(0, SK_DIAG_BPF_STORAGE_NONE) },
732 { ENUM_KNOWN(0x1, SK_DIAG_BPF_STORAGE_NONE) },
733 { ARG_XLAT_UNKNOWN(0x4, "SK_DIAG_BPF_STORAGE_???") },
734 { ARG_XLAT_UNKNOWN(0x1ace, "SK_DIAG_BPF_STORAGE_???") },
735 };
736
737 for (size_t i = 0; i < ARRAY_SIZE(bpfst_unk_attrs); i++) {
738 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
739 init_inet_diag_nest_2,
740 print_inet_diag_nest_2,
741 bpfst_unk_attrs[i].val,
742 bpfst_unk_attrs[i].str,
743 sizeof(dummy), &dummy, sizeof(dummy), 2,
744 printf("\"\\xde\\xad\\xc0\\xde\""));
745 }
746
747 /* INET_DIAG_SK_BPF_STORAGES: SK_DIAG_BPF_STORAGE: u32 */
748 static const struct strval16 bpfst_u32_attrs[] = {
749 { ENUM_KNOWN(0x2, SK_DIAG_BPF_STORAGE_MAP_ID) },
750 };
751
752 for (size_t i = 0; i < ARRAY_SIZE(bpfst_u32_attrs); i++) {
753 check_u32_nlattr(fd, nlh_u32, hdrlen,
754 init_inet_diag_nest_2,
755 print_inet_diag_nest_2,
756 bpfst_u32_attrs[i].val, bpfst_u32_attrs[i].str,
757 pattern, 2);
758 }
759
760 /*
761 * INET_DIAG_SK_BPF_STORAGES: SK_DIAG_BPF_STORAGE:
762 * SK_DIAG_BPF_STORAGE_MAP_VALUE
763 */
764 static const struct {
765 ssize_t sz;
766 const char *val;
767 const char *str;
768 } bpfst_vals[] = {
769 { 1, "\xbe", "0xbe" },
770 { 2, BE_LE("\xde\xad", "\xad\xde"), "0xdead" },
771 { 3, "\xca\xff\xee", "\"\\xca\\xff\\xee\"" },
772 { 4, BE_LE("\xba\xdc\x0d\xed", "\xed\x0d\xdc\xba"),
773 "0xbadc0ded" },
774 { 5, "\x00\x09\x0a\x0b\x0c",
775 "\"\\x00\\x09\\x0a\\x0b\\x0c\"" },
776 { 6, "012345",
777 "\"\\x30\\x31\\x32\\x33\\x34\\x35\"" },
778 { 7, "abcdefg",
779 "\"\\x61\\x62\\x63\\x64\\x65\\x66\\x67\"" },
780 { 8, BE_LE("\xbe\xef\xfa\xce\xde\xad\xc0\xde",
781 "\xde\xc0\xad\xde\xce\xfa\xef\xbe"),
782 "0xbeeffacedeadc0de" },
783 { 9, "ABCDEFGHI",
784 "\"\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\"" },
785 { 10, "1234567890",
786 "\"\\x31\\x32\\x33\\x34\\x35"
787 "\\x36\\x37\\x38\\x39\\x30\"" },
788 { 12, "a1b2c3d4e5f6",
789 "\"\\x61\\x31\\x62\\x32\\x63\\x33"
790 "\\x64\\x34\\x65\\x35\\x66\\x36\"" },
791 { 16, "A1B2C3D4E5F6G7H8",
792 "\"\\x41\\x31\\x42\\x32\\x43\\x33\\x44\\x34"
793 "\\x45\\x35\\x46\\x36\\x47\\x37\\x48\\x38\"" },
794 { 36, "abcdefghijklmnopqrstuvwxyz0123456789",
795 "\"\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6a"
796 "\\x6b\\x6c\\x6d\\x6e\\x6f\\x70\\x71\\x72\\x73\\x74\\x75"
797 "\\x76\\x77\\x78\\x79\\x7a\\x30\\x31\\x32\\x33\\x34\\x35"
798 "\"..." },
799 };
800
801 for (size_t i = 0; i < ARRAY_SIZE(bpfst_vals); i++) {
802 TEST_NESTED_NLATTR_(fd, nlh0, hdrlen,
803 init_inet_diag_nest_2,
804 print_inet_diag_nest_2,
805 SK_DIAG_BPF_STORAGE_MAP_VALUE,
806 "SK_DIAG_BPF_STORAGE_MAP_VALUE",
807 bpfst_vals[i].sz, bpfst_vals[i].val,
808 bpfst_vals[i].sz, 2,
809 printf("%s", bpfst_vals[i].str));
810 }
811
812 /* INET_DIAG_SOCKOPT */
813 static const struct {
814 ssize_t sz;
815 const char *val;
816 const char *str;
817 } sockopts[] = {
818 { 1, "\xbe", "\"\\xbe\"" },
819 { 2, "\x00\x00", "{}" },
820 { 2, BE_LE("\xca\xa0", "\x53\x05"),
821 "{recverr=1, is_icsk=1, mc_loop=1, mc_all=1"
822 ", bind_address_no_port=1, defer_connect=1}" },
823 { 3, BE_LE("\x1e\xad", "\x78\xb5"),
824 "{hdrincl=1, mc_loop=1, transparent=1, mc_all=1"
825 ", bind_address_no_port=1, defer_connect=1"
826 ", unused=" BE_LE("0xd", "0x16") " /* bits 3..8 */}" },
827 { 4, "\xff\xff\x00\xff",
828 "{recverr=1, is_icsk=1, freebind=1, hdrincl=1, mc_loop=1"
829 ", transparent=1, mc_all=1, nodefrag=1"
830 ", bind_address_no_port=1, recverr_rfc4884=1, defer_connect=1"
831 ", unused=0x1f /* bits 3..8 */}"
832 ", /* bytes 2..3 */ \"\\x00\\xff\"" },
833 };
834
835 for (size_t i = 0; i < ARRAY_SIZE(sockopts); i++) {
836 TEST_NLATTR(fd, nlh0, hdrlen,
837 init_inet_diag_msg, print_inet_diag_msg,
838 INET_DIAG_SOCKOPT,
839 sockopts[i].sz, sockopts[i].val, sockopts[i].sz,
840 printf("%s", sockopts[i].str));
841 }
842
843 /* INET_DIAG_LOCALS, INET_DIAG_PEERS */
844 static const struct strval16 sa_attrs[] = {
845 { ENUM_KNOWN(0xc, INET_DIAG_LOCALS) },
846 { ENUM_KNOWN(0xd, INET_DIAG_PEERS) },
847 };
848 enum {
849 SA_CNT = 3,
850 SA_SZ = sizeof(struct sockaddr_storage) * SA_CNT,
851 };
852 void *nlh_sa = midtail_alloc(NLMSG_SPACE(hdrlen), SA_SZ);
853 struct sockaddr_storage buf[SA_CNT] = { { 0 } };
854
855 struct sockaddr_in *sa_in = (struct sockaddr_in *) (buf);
856 sa_in->sin_family = AF_INET;
857 sa_in->sin_port = htons(42069);
858 sa_in->sin_addr.s_addr = htonl(0x12345678);
859
860 struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *) (buf + 1);
861 sa_in6->sin6_family = AF_INET6;
862 sa_in6->sin6_port = htons(23456);
863 sa_in6->sin6_flowinfo = htonl(0x13579bdf);
864 sa_in6->sin6_scope_id = 0x2468ace0;
865 memcpy(sa_in6->sin6_addr.s6_addr,
866 "\x12\x34\x56\x78\0\0\0\0\0\0\0\0\x9a\xbc\xde\xf0",
867 sizeof(sa_in6->sin6_addr.s6_addr));
868
869 struct sockaddr_at *sa_at = (struct sockaddr_at *) (buf + 2);
870 sa_at->sat_family = AF_APPLETALK;
871 sa_at->sat_port = 0x69;
872 sa_at->sat_addr.s_net = 0x8765;
873 sa_at->sat_addr.s_node = 0x42;
874
875 for (size_t i = 0; i < ARRAY_SIZE(sa_attrs); i++) {
876 TEST_NLATTR_ARRAY_(fd, nlh_sa, hdrlen,
877 init_inet_diag_msg, print_inet_diag_msg,
878 sa_attrs[i].val, sa_attrs[i].str,
879 pattern, buf, print_sa);
880 }
881
882 puts("+++ exited with 0 +++");
883 return 0;
884 }