1 /*
2 * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3 * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
4 * Copyright (c) 2016-2023 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9
10 #include "defs.h"
11 #include "netlink.h"
12 #include "nlattr.h"
13 #include <linux/audit.h>
14 #include <linux/rtnetlink.h>
15 #include <linux/xfrm.h>
16 #include <linux/cryptouser.h>
17 #include <linux/netfilter/ipset/ip_set.h>
18 #include <linux/netfilter/nf_tables.h>
19 #include <linux/netfilter/nf_tables_compat.h>
20 #include <linux/netfilter/nfnetlink.h>
21 #include <linux/netfilter/nfnetlink_acct.h>
22 #include <linux/netfilter/nfnetlink_conntrack.h>
23 #include <linux/netfilter/nfnetlink_cthelper.h>
24 #include <linux/netfilter/nfnetlink_cttimeout.h>
25 #include <linux/netfilter/nfnetlink_hook.h>
26 #include <linux/netfilter/nfnetlink_log.h>
27 #include <linux/netfilter/nfnetlink_queue.h>
28 #include <linux/netfilter/nfnetlink_osf.h>
29 #include "xlat/netlink_ack_flags.h"
30 #include "xlat/netlink_delete_flags.h"
31 #include "xlat/netlink_flags.h"
32 #include "xlat/netlink_get_flags.h"
33 #include "xlat/netlink_new_flags.h"
34 #include "xlat/netlink_protocols.h"
35 #include "xlat/netlink_types.h"
36 #include "xlat/nf_acct_msg_types.h"
37 #include "xlat/nf_cthelper_msg_types.h"
38 #include "xlat/nf_ctnetlink_exp_msg_types.h"
39 #include "xlat/nf_ctnetlink_msg_types.h"
40 #include "xlat/nf_cttimeout_msg_types.h"
41 #include "xlat/nf_hook_msg_types.h"
42 #include "xlat/nf_ipset_msg_types.h"
43 #include "xlat/nf_nft_compat_msg_types.h"
44 #include "xlat/nf_nftables_msg_types.h"
45 #include "xlat/nf_osf_msg_types.h"
46 #include "xlat/nf_queue_msg_types.h"
47 #include "xlat/nf_ulog_msg_types.h"
48 #include "xlat/nl_audit_types.h"
49 #include "xlat/nl_crypto_types.h"
50 #include "xlat/nl_netfilter_subsys_ids.h"
51 #include "xlat/nl_selinux_types.h"
52 #include "xlat/nl_sock_diag_types.h"
53 #include "xlat/nl_xfrm_types.h"
54 #include "xlat/nlmsgerr_attrs.h"
55
56 /*
57 * Fetch a struct nlmsghdr from the given address.
58 */
59 static bool
60 fetch_nlmsghdr(struct tcb *const tcp, struct nlmsghdr *const nlmsghdr,
61 const kernel_ulong_t addr, const kernel_ulong_t len,
62 const bool in_array)
63 {
64 if (len < sizeof(struct nlmsghdr)) {
65 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
66 return false;
67 }
68
69 if (tfetch_obj(tcp, addr, nlmsghdr))
70 return true;
71
72 if (in_array) {
73 tprint_more_data_follows();
74 printaddr_comment(addr);
75 } else {
76 printaddr(addr);
77 }
78
79 return false;
80 }
81
82 static int
83 get_fd_nl_family(struct tcb *const tcp, const int fd)
84 {
85 const unsigned long inode = getfdinode(tcp, fd);
86 if (!inode)
87 return -1;
88
89 const char *const details = get_sockaddr_by_inode(tcp, fd, inode);
90 if (!details)
91 return -1;
92
93 const char *const nl_details = STR_STRIP_PREFIX(details, "NETLINK:[");
94 if (nl_details == details)
95 return -1;
96
97 const struct xlat_data *xlats = netlink_protocols->data;
98 for (uint32_t idx = 0; idx < netlink_protocols->size; idx++) {
99 if (!netlink_protocols->data[idx].str)
100 continue;
101
102 const char *name = STR_STRIP_PREFIX(xlats[idx].str, "NETLINK_");
103 if (!strncmp(nl_details, name, strlen(name)))
104 return xlats[idx].val;
105 }
106
107 if (*nl_details >= '0' && *nl_details <= '9')
108 return atoi(nl_details);
109
110 return -1;
111 }
112
113 static void
114 decode_nlmsg_type_default(struct tcb *tcp, const struct xlat *const xlat,
115 const uint16_t type,
116 const char *const dflt)
117 {
118 printxval(xlat, type, dflt);
119 }
120
121 static void
122 decode_nlmsg_type_generic(struct tcb *tcp, const struct xlat *const xlat,
123 const uint16_t type,
124 const char *const dflt)
125 {
126 printxval(genl_families_xlat(tcp), type, dflt);
127 }
128
129 static const struct {
130 const struct xlat *const xlat;
131 const char *const dflt;
132 } nf_nlmsg_types[] = {
133 [NFNL_SUBSYS_CTNETLINK] = {
134 nf_ctnetlink_msg_types,
135 "IPCTNL_MSG_CT_???"
136 },
137 [NFNL_SUBSYS_CTNETLINK_EXP] = {
138 nf_ctnetlink_exp_msg_types,
139 "IPCTNL_MSG_EXP_???"
140 },
141 [NFNL_SUBSYS_QUEUE] = { nf_queue_msg_types, "NFQNL_MSG_???" },
142 [NFNL_SUBSYS_ULOG] = { nf_ulog_msg_types, "NFULNL_MSG_???" },
143 [NFNL_SUBSYS_OSF] = { nf_osf_msg_types, "OSF_MSG_???" },
144 [NFNL_SUBSYS_IPSET] = { nf_ipset_msg_types, "IPSET_CMD_???" },
145 [NFNL_SUBSYS_ACCT] = { nf_acct_msg_types, "NFNL_MSG_ACCT_???" },
146 [NFNL_SUBSYS_CTNETLINK_TIMEOUT] = {
147 nf_cttimeout_msg_types,
148 "IPCTNL_MSG_TIMEOUT_???"
149 },
150 [NFNL_SUBSYS_CTHELPER] = {
151 nf_cthelper_msg_types,
152 "NFNL_MSG_CTHELPER_???"
153 },
154 [NFNL_SUBSYS_NFTABLES] = { nf_nftables_msg_types, "NFT_MSG_???" },
155 [NFNL_SUBSYS_NFT_COMPAT] = {
156 nf_nft_compat_msg_types,
157 "NFNL_MSG_COMPAT_???"
158 },
159 [NFNL_SUBSYS_HOOK] = { nf_hook_msg_types, "NFT_MSG_HOOK_???" },
160 };
161
162 static void
163 decode_nlmsg_type_netfilter(struct tcb *tcp, const struct xlat *const xlat,
164 const uint16_t type,
165 const char *const dflt)
166 {
167 /* Reserved control nfnetlink messages first. */
168 const char *const text = xlookup(nl_netfilter_msg_types, type);
169 if (text) {
170 print_xlat_ex(type, text, XLAT_STYLE_DEFAULT);
171 return;
172 }
173
174 /*
175 * Other netfilter message types are split
176 * in two pieces: 8 bits subsystem and 8 bits type.
177 */
178 const uint8_t subsys_id = (uint8_t) (type >> 8);
179 const uint8_t msg_type = (uint8_t) type;
180
181 tprint_flags_begin();
182 tprint_shift_begin();
183 printxval(xlat, subsys_id, dflt);
184 tprint_shift();
185 PRINT_VAL_U(8);
186 tprint_shift_end();
187
188 tprint_flags_or();
189 if (subsys_id < ARRAY_SIZE(nf_nlmsg_types))
190 printxval(nf_nlmsg_types[subsys_id].xlat,
191 msg_type, nf_nlmsg_types[subsys_id].dflt);
192 else
193 PRINT_VAL_X(msg_type);
194 tprint_flags_end();
195 }
196
197 typedef void (*nlmsg_types_decoder_t)(struct tcb *, const struct xlat *,
198 uint16_t type,
199 const char *dflt);
200
201 static const struct {
202 const nlmsg_types_decoder_t decoder;
203 const struct xlat *const xlat;
204 const char *const dflt;
205 } nlmsg_types[] = {
206 [NETLINK_AUDIT] = { NULL, nl_audit_types, "AUDIT_???" },
207 [NETLINK_CRYPTO] = { NULL, nl_crypto_types, "CRYPTO_MSG_???" },
208 [NETLINK_GENERIC] = {
209 decode_nlmsg_type_generic,
210 NULL,
211 "GENERIC_FAMILY_???"
212 },
213 [NETLINK_NETFILTER] = {
214 decode_nlmsg_type_netfilter,
215 nl_netfilter_subsys_ids,
216 "NFNL_SUBSYS_???"
217 },
218 [NETLINK_ROUTE] = { NULL, nl_route_types, "RTM_???" },
219 [NETLINK_SELINUX] = { NULL, nl_selinux_types, "SELNL_MSG_???" },
220 [NETLINK_SOCK_DIAG] = { NULL, nl_sock_diag_types, "SOCK_DIAG_???" },
221 [NETLINK_XFRM] = { NULL, nl_xfrm_types, "XFRM_MSG_???" }
222 };
223
224 /*
225 * As all valid netlink families are positive integers, use unsigned int
226 * for family here to filter out -1.
227 */
228 static void
229 decode_nlmsg_type(struct tcb *tcp, const uint16_t type,
230 const unsigned int family)
231 {
232 nlmsg_types_decoder_t decoder = decode_nlmsg_type_default;
233 const struct xlat *xlat = netlink_types;
234 const char *dflt = "NLMSG_???";
235
236 /*
237 * type < NLMSG_MIN_TYPE are reserved control messages
238 * that need no family-specific decoding.
239 */
240 if (type >= NLMSG_MIN_TYPE && family < ARRAY_SIZE(nlmsg_types)) {
241 if (nlmsg_types[family].decoder)
242 decoder = nlmsg_types[family].decoder;
243 if (nlmsg_types[family].xlat)
244 xlat = nlmsg_types[family].xlat;
245 if (nlmsg_types[family].dflt)
246 dflt = nlmsg_types[family].dflt;
247 }
248
249 decoder(tcp, xlat, type, dflt);
250 }
251
252 static const struct xlat *
253 decode_nlmsg_flags_crypto(const uint16_t type)
254 {
255 switch (type) {
256 case CRYPTO_MSG_NEWALG:
257 return netlink_new_flags;
258 case CRYPTO_MSG_DELALG:
259 case CRYPTO_MSG_DELRNG:
260 return netlink_delete_flags;
261 case CRYPTO_MSG_GETALG:
262 return netlink_get_flags;
263 }
264
265 return NULL;
266 }
267
268 static const struct xlat *
269 decode_nlmsg_flags_netfilter(const uint16_t type)
270 {
271 const uint8_t subsys_id = (uint8_t) (type >> 8);
272 const uint8_t msg_type = (uint8_t) type;
273
274 switch (subsys_id) {
275 case NFNL_SUBSYS_CTNETLINK:
276 switch (msg_type) {
277 case IPCTNL_MSG_CT_NEW:
278 return netlink_new_flags;
279 case IPCTNL_MSG_CT_GET:
280 case IPCTNL_MSG_CT_GET_CTRZERO:
281 case IPCTNL_MSG_CT_GET_STATS_CPU:
282 case IPCTNL_MSG_CT_GET_STATS:
283 case IPCTNL_MSG_CT_GET_DYING:
284 case IPCTNL_MSG_CT_GET_UNCONFIRMED:
285 return netlink_get_flags;
286 case IPCTNL_MSG_CT_DELETE:
287 return netlink_delete_flags;
288 }
289 break;
290 case NFNL_SUBSYS_CTNETLINK_EXP:
291 switch (msg_type) {
292 case IPCTNL_MSG_EXP_NEW:
293 return netlink_new_flags;
294 case IPCTNL_MSG_EXP_GET:
295 case IPCTNL_MSG_EXP_GET_STATS_CPU:
296 return netlink_get_flags;
297 case IPCTNL_MSG_EXP_DELETE:
298 return netlink_delete_flags;
299 }
300 break;
301 case NFNL_SUBSYS_ACCT:
302 switch (msg_type) {
303 case NFNL_MSG_ACCT_NEW:
304 return netlink_new_flags;
305 case NFNL_MSG_ACCT_GET:
306 case NFNL_MSG_ACCT_GET_CTRZERO:
307 return netlink_get_flags;
308 case NFNL_MSG_ACCT_DEL:
309 return netlink_delete_flags;
310 }
311 break;
312 case NFNL_SUBSYS_CTNETLINK_TIMEOUT:
313 switch (msg_type) {
314 case IPCTNL_MSG_TIMEOUT_NEW:
315 return netlink_new_flags;
316 case IPCTNL_MSG_TIMEOUT_GET:
317 return netlink_get_flags;
318 case IPCTNL_MSG_TIMEOUT_DELETE:
319 return netlink_delete_flags;
320 }
321 break;
322 case NFNL_SUBSYS_CTHELPER:
323 switch (msg_type) {
324 case NFNL_MSG_CTHELPER_NEW:
325 return netlink_new_flags;
326 case NFNL_MSG_CTHELPER_GET:
327 return netlink_get_flags;
328 case NFNL_MSG_CTHELPER_DEL:
329 return netlink_delete_flags;
330 }
331 break;
332 case NFNL_SUBSYS_NFTABLES:
333 switch (msg_type) {
334 case NFT_MSG_NEWTABLE:
335 case NFT_MSG_NEWCHAIN:
336 case NFT_MSG_NEWRULE:
337 case NFT_MSG_NEWSET:
338 case NFT_MSG_NEWSETELEM:
339 case NFT_MSG_NEWGEN:
340 case NFT_MSG_NEWOBJ:
341 case NFT_MSG_NEWFLOWTABLE:
342 return netlink_new_flags;
343 case NFT_MSG_GETTABLE:
344 case NFT_MSG_GETCHAIN:
345 case NFT_MSG_GETRULE:
346 case NFT_MSG_GETSET:
347 case NFT_MSG_GETSETELEM:
348 case NFT_MSG_GETGEN:
349 case NFT_MSG_GETOBJ:
350 case NFT_MSG_GETOBJ_RESET:
351 case NFT_MSG_GETFLOWTABLE:
352 case NFT_MSG_GETRULE_RESET:
353 case NFT_MSG_GETSETELEM_RESET:
354 return netlink_get_flags;
355 case NFT_MSG_DELTABLE:
356 case NFT_MSG_DELCHAIN:
357 case NFT_MSG_DELRULE:
358 case NFT_MSG_DELSET:
359 case NFT_MSG_DELSETELEM:
360 case NFT_MSG_DELOBJ:
361 case NFT_MSG_DELFLOWTABLE:
362 case NFT_MSG_DESTROYTABLE:
363 case NFT_MSG_DESTROYCHAIN:
364 case NFT_MSG_DESTROYRULE:
365 case NFT_MSG_DESTROYSET:
366 case NFT_MSG_DESTROYSETELEM:
367 case NFT_MSG_DESTROYOBJ:
368 case NFT_MSG_DESTROYFLOWTABLE:
369 return netlink_delete_flags;
370 }
371 break;
372 case NFNL_SUBSYS_NFT_COMPAT:
373 switch (msg_type) {
374 case NFNL_MSG_COMPAT_GET:
375 return netlink_get_flags;
376 }
377 break;
378 case NFNL_SUBSYS_HOOK:
379 switch (msg_type) {
380 case NFNL_MSG_HOOK_GET:
381 return netlink_get_flags;
382 }
383 break;
384 }
385
386 return NULL;
387 }
388
389 static const struct xlat *
390 decode_nlmsg_flags_route(const uint16_t type)
391 {
392 /* RTM_DELACTION uses NLM_F_ROOT flags */
393 if (type == RTM_DELACTION)
394 return netlink_get_flags;
395 switch (type & 3) {
396 case 0:
397 return netlink_new_flags;
398 case 1:
399 return netlink_delete_flags;
400 case 2:
401 return netlink_get_flags;
402 }
403
404 return NULL;
405 }
406
407 static const struct xlat *
408 decode_nlmsg_flags_sock_diag(const uint16_t type)
409 {
410 return netlink_get_flags;
411 }
412
413 static const struct xlat *
414 decode_nlmsg_flags_xfrm(const uint16_t type)
415 {
416 switch (type) {
417 case XFRM_MSG_NEWSA:
418 case XFRM_MSG_NEWPOLICY:
419 case XFRM_MSG_NEWAE:
420 case XFRM_MSG_NEWSADINFO:
421 case XFRM_MSG_NEWSPDINFO:
422 return netlink_new_flags;
423 case XFRM_MSG_DELSA:
424 case XFRM_MSG_DELPOLICY:
425 return netlink_delete_flags;
426 case XFRM_MSG_GETSA:
427 case XFRM_MSG_GETPOLICY:
428 case XFRM_MSG_GETAE:
429 case XFRM_MSG_GETSADINFO:
430 case XFRM_MSG_GETSPDINFO:
431 return netlink_get_flags;
432 }
433
434 return NULL;
435 }
436
437 typedef const struct xlat *(*nlmsg_flags_decoder_t)(const uint16_t type);
438
439 static const nlmsg_flags_decoder_t nlmsg_flags[] = {
440 [NETLINK_CRYPTO] = decode_nlmsg_flags_crypto,
441 [NETLINK_NETFILTER] = decode_nlmsg_flags_netfilter,
442 [NETLINK_ROUTE] = decode_nlmsg_flags_route,
443 [NETLINK_SOCK_DIAG] = decode_nlmsg_flags_sock_diag,
444 [NETLINK_XFRM] = decode_nlmsg_flags_xfrm
445 };
446
447 /*
448 * As all valid netlink families are positive integers, use unsigned int
449 * for family here to filter out -1.
450 */
451 static void
452 decode_nlmsg_flags(const uint16_t flags, const uint16_t type,
453 const unsigned int family)
454 {
455 const struct xlat *table = NULL;
456
457 if (type < NLMSG_MIN_TYPE) {
458 if (type == NLMSG_ERROR)
459 table = netlink_ack_flags;
460 } else if (family < ARRAY_SIZE(nlmsg_flags) && nlmsg_flags[family])
461 table = nlmsg_flags[family](type);
462
463 tprint_flags_begin();
464 printflags_ex(flags, "NLM_F_???", XLAT_STYLE_DEFAULT,
465 netlink_flags, table, NULL);
466 tprint_flags_end();
467 }
468
469 static void
470 print_nlmsghdr(struct tcb *tcp,
471 const int fd,
472 const int family,
473 const struct nlmsghdr *const nlmsghdr)
474 {
475 /* print the whole structure regardless of its nlmsg_len */
476
477 tprint_struct_begin();
478 PRINT_FIELD_U(*nlmsghdr, nlmsg_len);
479
480 tprint_struct_next();
481 PRINT_FIELD_OBJ_TCB_VAL(*nlmsghdr, nlmsg_type, tcp,
482 decode_nlmsg_type, family);
483
484 tprint_struct_next();
485 PRINT_FIELD_OBJ_VAL(*nlmsghdr, nlmsg_flags, decode_nlmsg_flags,
486 nlmsghdr->nlmsg_type, family);
487
488 tprint_struct_next();
489 PRINT_FIELD_U(*nlmsghdr, nlmsg_seq);
490
491 tprint_struct_next();
492 PRINT_FIELD_TGID(*nlmsghdr, nlmsg_pid, tcp);
493 tprint_struct_end();
494 }
495
496 static bool
497 print_cookie(struct tcb *const tcp, void *const elem_buf,
498 const size_t elem_size, void *const opaque_data)
499 {
500 PRINT_VAL_U(*(uint8_t *) elem_buf);
501
502 return true;
503 }
504
505 static bool
506 decode_nlmsgerr_attr_cookie(struct tcb *const tcp,
507 const kernel_ulong_t addr,
508 const unsigned int len,
509 const void *const opaque_data)
510 {
511 uint8_t cookie;
512 const size_t nmemb = len / sizeof(cookie);
513
514 print_array(tcp, addr, nmemb, &cookie, sizeof(cookie),
515 tfetch_mem, print_cookie, 0);
516
517 return true;
518 }
519
520 static const nla_decoder_t nlmsgerr_nla_decoders[] = {
521 [NLMSGERR_ATTR_MSG] = decode_nla_str,
522 [NLMSGERR_ATTR_OFFS] = decode_nla_u32,
523 [NLMSGERR_ATTR_COOKIE] = decode_nlmsgerr_attr_cookie
524 };
525
526 static void
527 decode_nlmsghdr_with_payload(struct tcb *const tcp,
528 const int fd,
529 const int family,
530 const struct nlmsghdr *const nlmsghdr,
531 const kernel_ulong_t addr,
532 const kernel_ulong_t len);
533
534 static void
535 decode_nlmsgerr(struct tcb *const tcp,
536 const int fd,
537 const int family,
538 kernel_ulong_t addr,
539 unsigned int len,
540 const bool capped)
541 {
542 struct nlmsgerr err;
543
544 if (len < sizeof(err)) {
545 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
546 return;
547 }
548
549 if (umove_or_printaddr(tcp, addr, &err))
550 return;
551
552 addr += offsetof(struct nlmsgerr, msg);
553 len -= offsetof(struct nlmsgerr, msg);
554
555 /*
556 * If err.msg.nlmsg_len < sizeof(err.msg), then it is
557 * invalid and sizeof(err.msg) would be used instead.
558 */
559 const unsigned int nlmsg_len =
560 MAX(sizeof(err.msg), err.msg.nlmsg_len);
561
562 /*
563 * A valid nlmsg_len can exceed sizeof(err.msg),
564 * an invalid nlmsg_len can exceed len.
565 */
566 const unsigned int payload =
567 MIN(len, capped ? sizeof(err.msg) : nlmsg_len);
568
569 if (len > payload)
570 tprint_array_begin();
571
572 tprint_struct_begin();
573
574 PRINT_FIELD_ERR_D(err, error);
575 tprint_struct_next();
576
577 tprints_field_name("msg");
578 decode_nlmsghdr_with_payload(tcp, fd, family,
579 &err.msg, addr, payload);
580
581 tprint_struct_end();
582
583 if (len > payload) {
584 tprint_array_next();
585 decode_nlattr(tcp, addr + payload,
586 len - payload, nlmsgerr_attrs,
587 "NLMSGERR_ATTR_???",
588 nlmsgerr_nla_decoders,
589 ARRAY_SIZE(nlmsgerr_nla_decoders),
590 NULL);
591 tprint_array_end();
592 }
593 }
594
595 static const netlink_decoder_t netlink_decoders[] = {
596 [NETLINK_CRYPTO] = decode_netlink_crypto,
597 [NETLINK_NETFILTER] = decode_netlink_netfilter,
598 [NETLINK_ROUTE] = decode_netlink_route,
599 [NETLINK_SELINUX] = decode_netlink_selinux,
600 [NETLINK_SOCK_DIAG] = decode_netlink_sock_diag
601 };
602
603 static void
604 decode_payload(struct tcb *const tcp,
605 const int fd,
606 const int family,
607 const struct nlmsghdr *const nlmsghdr,
608 const kernel_ulong_t addr,
609 const unsigned int len)
610 {
611 if (nlmsghdr->nlmsg_type == NLMSG_ERROR) {
612 decode_nlmsgerr(tcp, fd, family, addr, len,
613 nlmsghdr->nlmsg_flags & NLM_F_CAPPED);
614 return;
615 }
616
617 /*
618 * While most of NLMSG_DONE messages indeed have payloads
619 * containing just a single integer, there are few exceptions,
620 * so pass payloads of NLMSG_DONE messages to family-specific
621 * netlink payload decoders.
622 *
623 * Other types of reserved control messages need no family-specific
624 * netlink payload decoding.
625 */
626 if ((nlmsghdr->nlmsg_type >= NLMSG_MIN_TYPE
627 || nlmsghdr->nlmsg_type == NLMSG_DONE)
628 && (unsigned int) family < ARRAY_SIZE(netlink_decoders)
629 && netlink_decoders[family]
630 && netlink_decoders[family](tcp, nlmsghdr, addr, len)) {
631 return;
632 }
633
634 if (nlmsghdr->nlmsg_type == NLMSG_DONE && len == sizeof(int)) {
635 int num;
636
637 if (!umove_or_printaddr(tcp, addr, &num))
638 PRINT_VAL_D(num);
639 return;
640 }
641
642 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
643 }
644
645 static void
646 decode_nlmsghdr_with_payload(struct tcb *const tcp,
647 const int fd,
648 const int family,
649 const struct nlmsghdr *const nlmsghdr,
650 const kernel_ulong_t addr,
651 const kernel_ulong_t len)
652 {
653 const unsigned int nlmsg_len = MIN(nlmsghdr->nlmsg_len, len);
654
655 if (nlmsg_len > NLMSG_HDRLEN)
656 tprint_array_begin();
657
658 print_nlmsghdr(tcp, fd, family, nlmsghdr);
659
660 if (nlmsg_len > NLMSG_HDRLEN) {
661 tprint_array_next();
662 decode_payload(tcp, fd, family, nlmsghdr, addr + NLMSG_HDRLEN,
663 nlmsg_len - NLMSG_HDRLEN);
664 tprint_array_end();
665 }
666 }
667
668 void
669 decode_netlink(struct tcb *const tcp,
670 const int fd,
671 kernel_ulong_t addr,
672 kernel_ulong_t len)
673 {
674 const int family = get_fd_nl_family(tcp, fd);
675
676 if (family == NETLINK_KOBJECT_UEVENT) {
677 decode_netlink_kobject_uevent(tcp, addr, len);
678 return;
679 }
680
681 struct nlmsghdr nlmsghdr;
682 bool is_array = false;
683
684 for (unsigned int elt = 0;
685 fetch_nlmsghdr(tcp, &nlmsghdr, addr, len, is_array);
686 ++elt) {
687 if (abbrev(tcp) && elt == max_strlen) {
688 tprint_more_data_follows();
689 break;
690 }
691
692 unsigned int nlmsg_len = NLMSG_ALIGN(nlmsghdr.nlmsg_len);
693 kernel_ulong_t next_addr = 0;
694 kernel_ulong_t next_len = 0;
695
696 if (nlmsghdr.nlmsg_len >= NLMSG_HDRLEN) {
697 next_len = (len >= nlmsg_len) ? len - nlmsg_len : 0;
698
699 if (next_len && addr + nlmsg_len > addr)
700 next_addr = addr + nlmsg_len;
701 }
702
703 if (!is_array && next_addr) {
704 tprint_array_begin();
705 is_array = true;
706 }
707
708 decode_nlmsghdr_with_payload(tcp, fd, family,
709 &nlmsghdr, addr, len);
710
711 if (!next_addr)
712 break;
713
714 tprint_array_next();
715 addr = next_addr;
716 len = next_len;
717 }
718
719 if (is_array) {
720 tprint_array_end();
721 }
722 }