Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

netlink.c 16KB

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