]> granicus.if.org Git - strace/blob - netlink_sock_diag.c
Rename PRINT_FIELD_QUOTED_STRING to PRINT_FIELD_STRING
[strace] / netlink_sock_diag.c
1 /*
2  * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3  * Copyright (c) 2017 JingPiao Chen <chenjingpiao@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 "defs.h"
31 #include "netlink.h"
32 #include "nlattr.h"
33 #include "print_fields.h"
34
35 #include <arpa/inet.h>
36 #include <linux/filter.h>
37
38 #include <linux/inet_diag.h>
39 #include <linux/netlink_diag.h>
40 #include <linux/packet_diag.h>
41 #ifdef AF_SMC
42 # include <linux/smc_diag.h>
43 #endif
44 #include <linux/sock_diag.h>
45 #include <linux/unix_diag.h>
46
47 #include "xlat/inet_diag_attrs.h"
48 #include "xlat/inet_diag_extended_flags.h"
49 #include "xlat/inet_diag_req_attrs.h"
50
51 #include "xlat/tcp_states.h"
52 #include "xlat/tcp_state_flags.h"
53
54 #include "xlat/netlink_diag_attrs.h"
55 #include "xlat/netlink_diag_show.h"
56 #include "xlat/netlink_socket_flags.h"
57 #include "xlat/netlink_states.h"
58
59 #include "xlat/packet_diag_attrs.h"
60 #include "xlat/packet_diag_info_flags.h"
61 #include "xlat/packet_diag_show.h"
62
63 #ifdef AF_SMC
64 # include "xlat/smc_diag_attrs.h"
65 # include "xlat/smc_diag_extended_flags.h"
66 # include "xlat/smc_link_group_roles.h"
67 # include "xlat/smc_states.h"
68 #endif
69
70 #include "xlat/unix_diag_attrs.h"
71 #include "xlat/unix_diag_show.h"
72
73 static void
74 decode_family(struct tcb *const tcp, const uint8_t family,
75               const kernel_ulong_t addr, const kernel_ulong_t len)
76 {
77         tprints("{family=");
78         printxval(addrfams, family, "AF_???");
79         if (len > sizeof(family)) {
80                 tprints(", ");
81                 printstr_ex(tcp, addr + sizeof(family),
82                             len - sizeof(family), QUOTE_FORCE_HEX);
83         }
84         tprints("}");
85 }
86
87 static void
88 decode_unix_diag_req(struct tcb *const tcp,
89                      const struct nlmsghdr *const nlmsghdr,
90                      const uint8_t family,
91                      const kernel_ulong_t addr,
92                      const kernel_ulong_t len)
93 {
94         struct unix_diag_req req = { .sdiag_family = family };
95         const size_t offset = sizeof(req.sdiag_family);
96
97         PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
98         tprints(", ");
99         if (len >= sizeof(req)) {
100                 if (!umoven_or_printaddr(tcp, addr + offset,
101                                          sizeof(req) - offset,
102                                          (void *) &req + offset)) {
103                         PRINT_FIELD_U("", req, sdiag_protocol);
104                         PRINT_FIELD_FLAGS(", ", req, udiag_states,
105                                           tcp_state_flags, "1<<TCP_???");
106                         PRINT_FIELD_U(", ", req, udiag_ino);
107                         PRINT_FIELD_FLAGS(", ", req, udiag_show,
108                                           unix_diag_show, "UDIAG_SHOW_???");
109                         PRINT_FIELD_COOKIE(", ", req, udiag_cookie);
110                 }
111         } else
112                 tprints("...");
113         tprints("}");
114 }
115
116 static bool
117 print_meminfo(struct tcb *const tcp,
118               void *const elem_buf,
119               const size_t elem_size,
120               void *const opaque_data)
121 {
122         tprintf("%" PRIu32, *(uint32_t *) elem_buf);
123
124         return true;
125 }
126
127 static bool
128 decode_meminfo(struct tcb *const tcp,
129                const kernel_ulong_t addr,
130                const kernel_ulong_t len,
131                const void *const opaque_data)
132 {
133         uint32_t mem;
134         size_t nmemb = len / sizeof(mem);
135
136         if (!nmemb)
137                 return false;
138
139         if (nmemb > SK_MEMINFO_VARS)
140                 nmemb = SK_MEMINFO_VARS;
141
142         print_array(tcp, addr, nmemb, &mem, sizeof(mem),
143                     umoven_or_printaddr, print_meminfo, 0);
144
145         return true;
146 }
147
148 static bool
149 decode_unix_diag_vfs(struct tcb *const tcp,
150                      const kernel_ulong_t addr,
151                      const kernel_ulong_t len,
152                      const void *const opaque_data)
153 {
154         struct unix_diag_vfs uv;
155
156         if (len < sizeof(uv))
157                 return false;
158         if (umove_or_printaddr(tcp, addr, &uv))
159                 return true;
160
161         PRINT_FIELD_DEV("{", uv, udiag_vfs_dev);
162         PRINT_FIELD_U(", ", uv, udiag_vfs_ino);
163         tprints("}");
164
165         return true;
166 }
167
168 static bool
169 print_inode(struct tcb *const tcp,
170             void *const elem_buf,
171             const size_t elem_size,
172             void *const opaque_data)
173 {
174         tprintf("%" PRIu32, *(uint32_t *) elem_buf);
175
176         return true;
177 }
178
179 static bool
180 decode_unix_diag_inode(struct tcb *const tcp,
181                        const kernel_ulong_t addr,
182                        const kernel_ulong_t len,
183                        const void *const opaque_data)
184 {
185         uint32_t inode;
186         const size_t nmemb = len / sizeof(inode);
187
188         if (!nmemb)
189                 return false;
190
191         print_array(tcp, addr, nmemb, &inode, sizeof(inode),
192                     umoven_or_printaddr, print_inode, 0);
193
194         return true;
195 }
196
197 static bool
198 decode_unix_diag_rqlen(struct tcb *const tcp,
199                        const kernel_ulong_t addr,
200                        const kernel_ulong_t len,
201                        const void *const opaque_data)
202 {
203         struct unix_diag_rqlen rql;
204
205         if (len < sizeof(rql))
206                 return false;
207         if (umove_or_printaddr(tcp, addr, &rql))
208                 return true;
209
210         PRINT_FIELD_U("{", rql, udiag_rqueue);
211         PRINT_FIELD_U(", ", rql, udiag_wqueue);
212         tprints("}");
213
214         return true;
215 }
216
217 static const nla_decoder_t unix_diag_msg_nla_decoders[] = {
218         [UNIX_DIAG_NAME]        = decode_nla_str,
219         [UNIX_DIAG_VFS]         = decode_unix_diag_vfs,
220         [UNIX_DIAG_PEER]        = decode_nla_u32,
221         [UNIX_DIAG_ICONS]       = decode_unix_diag_inode,
222         [UNIX_DIAG_RQLEN]       = decode_unix_diag_rqlen,
223         [UNIX_DIAG_MEMINFO]     = decode_meminfo,
224         [UNIX_DIAG_SHUTDOWN]    = decode_nla_u8
225 };
226
227 static void
228 decode_unix_diag_msg(struct tcb *const tcp,
229                      const struct nlmsghdr *const nlmsghdr,
230                      const uint8_t family,
231                      const kernel_ulong_t addr,
232                      const kernel_ulong_t len)
233 {
234         struct unix_diag_msg msg = { .udiag_family = family };
235         size_t offset = sizeof(msg.udiag_family);
236         bool decode_nla = false;
237
238         PRINT_FIELD_XVAL("{", msg, udiag_family, addrfams, "AF_???");
239         tprints(", ");
240         if (len >= sizeof(msg)) {
241                 if (!umoven_or_printaddr(tcp, addr + offset,
242                                          sizeof(msg) - offset,
243                                          (void *) &msg + offset)) {
244                         PRINT_FIELD_XVAL("", msg, udiag_type,
245                                          socktypes, "SOCK_???");
246                         PRINT_FIELD_XVAL(", ", msg, udiag_state,
247                                          tcp_states, "TCP_???");
248                         PRINT_FIELD_U(", ", msg, udiag_ino);
249                         PRINT_FIELD_COOKIE(", ", msg, udiag_cookie);
250                         decode_nla = true;
251                 }
252         } else
253                 tprints("...");
254         tprints("}");
255
256         offset = NLMSG_ALIGN(sizeof(msg));
257         if (decode_nla && len > offset) {
258                 tprints(", ");
259                 decode_nlattr(tcp, addr + offset, len - offset,
260                               unix_diag_attrs, "UNIX_DIAG_???",
261                               unix_diag_msg_nla_decoders,
262                               ARRAY_SIZE(unix_diag_msg_nla_decoders), NULL);
263         }
264 }
265
266 static void
267 decode_netlink_diag_req(struct tcb *const tcp,
268                         const struct nlmsghdr *const nlmsghdr,
269                         const uint8_t family,
270                         const kernel_ulong_t addr,
271                         const kernel_ulong_t len)
272 {
273         struct netlink_diag_req req = { .sdiag_family = family };
274         const size_t offset = sizeof(req.sdiag_family);
275
276         PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
277         tprints(", ");
278         if (len >= sizeof(req)) {
279                 if (!umoven_or_printaddr(tcp, addr + offset,
280                                          sizeof(req) - offset,
281                                          (void *) &req + offset)) {
282                         if (NDIAG_PROTO_ALL == req.sdiag_protocol)
283                                 tprintf("%s=%s",
284                                         "sdiag_protocol", "NDIAG_PROTO_ALL");
285                         else
286                                 PRINT_FIELD_XVAL("", req, sdiag_protocol,
287                                                  netlink_protocols,
288                                                  "NETLINK_???");
289                         PRINT_FIELD_U(", ", req, ndiag_ino);
290                         PRINT_FIELD_FLAGS(", ", req, ndiag_show,
291                                           netlink_diag_show, "NDIAG_SHOW_???");
292                         PRINT_FIELD_COOKIE(", ", req, ndiag_cookie);
293                 }
294         } else
295                 tprints("...");
296         tprints("}");
297 }
298
299 static bool
300 print_group(struct tcb *const tcp,
301             void *const elem_buf,
302             const size_t elem_size,
303             void *const opaque_data)
304 {
305         if (elem_size < sizeof(kernel_ulong_t))
306                 tprintf("%#0*x", (int) elem_size * 2 + 2,
307                         *(unsigned int *) elem_buf);
308         else
309                 tprintf("%#0*" PRI_klx, (int) elem_size * 2 + 2,
310                         *(kernel_ulong_t *) elem_buf);
311
312         return true;
313 }
314
315 static bool
316 decode_netlink_diag_groups(struct tcb *const tcp,
317                            const kernel_ulong_t addr,
318                            const kernel_ulong_t len,
319                            const void *const opaque_data)
320 {
321         kernel_ulong_t buf;
322         const size_t nmemb = len / current_wordsize;
323
324         if (!nmemb)
325                 return false;
326
327         print_array(tcp, addr, nmemb, &buf, current_wordsize,
328                     umoven_or_printaddr, print_group, 0);
329
330         return true;
331 }
332
333 static bool
334 decode_netlink_diag_ring(struct tcb *const tcp,
335                          const kernel_ulong_t addr,
336                          const kernel_ulong_t len,
337                          const void *const opaque_data)
338 {
339         struct netlink_diag_ring ndr;
340
341         if (len < sizeof(ndr))
342                 return false;
343         if (umove_or_printaddr(tcp, addr, &ndr))
344                 return true;
345
346         PRINT_FIELD_U("{", ndr, ndr_block_size);
347         PRINT_FIELD_U(", ", ndr, ndr_block_nr);
348         PRINT_FIELD_U(", ", ndr, ndr_frame_size);
349         PRINT_FIELD_U(", ", ndr, ndr_frame_nr);
350         tprints("}");
351
352         return true;
353 }
354
355 static bool
356 decode_netlink_diag_flags(struct tcb *const tcp,
357                           const kernel_ulong_t addr,
358                           const kernel_ulong_t len,
359                           const void *const opaque_data)
360 {
361         uint32_t flags;
362
363         if (len < sizeof(flags))
364                 return false;
365         if (umove_or_printaddr(tcp, addr, &flags))
366                 return true;
367
368         printflags(netlink_socket_flags, flags, "NDIAG_FLAG_???");
369
370         return true;
371 }
372
373 static const nla_decoder_t netlink_diag_msg_nla_decoders[] = {
374         [NETLINK_DIAG_MEMINFO]  = decode_meminfo,
375         [NETLINK_DIAG_GROUPS]   = decode_netlink_diag_groups,
376         [NETLINK_DIAG_RX_RING]  = decode_netlink_diag_ring,
377         [NETLINK_DIAG_TX_RING]  = decode_netlink_diag_ring,
378         [NETLINK_DIAG_FLAGS]    = decode_netlink_diag_flags
379 };
380
381 static void
382 decode_netlink_diag_msg(struct tcb *const tcp,
383                         const struct nlmsghdr *const nlmsghdr,
384                         const uint8_t family,
385                         const kernel_ulong_t addr,
386                         const kernel_ulong_t len)
387 {
388         struct netlink_diag_msg msg = { .ndiag_family = family };
389         size_t offset = sizeof(msg.ndiag_family);
390         bool decode_nla = false;
391
392         PRINT_FIELD_XVAL("{", msg, ndiag_family, addrfams, "AF_???");
393         tprints(", ");
394         if (len >= sizeof(msg)) {
395                 if (!umoven_or_printaddr(tcp, addr + offset,
396                                          sizeof(msg) - offset,
397                                          (void *) &msg + offset)) {
398                         PRINT_FIELD_XVAL("", msg, ndiag_type,
399                                          socktypes, "SOCK_???");
400                         PRINT_FIELD_XVAL(", ", msg, ndiag_protocol,
401                                          netlink_protocols, "NETLINK_???");
402                         PRINT_FIELD_XVAL(", ", msg, ndiag_state,
403                                          netlink_states, "NETLINK_???");
404                         PRINT_FIELD_U(", ", msg, ndiag_portid);
405                         PRINT_FIELD_U(", ", msg, ndiag_dst_portid);
406                         PRINT_FIELD_U(", ", msg, ndiag_dst_group);
407                         PRINT_FIELD_U(", ", msg, ndiag_ino);
408                         PRINT_FIELD_COOKIE(", ", msg, ndiag_cookie);
409                         decode_nla = true;
410                 }
411         } else
412                 tprints("...");
413         tprints("}");
414
415         offset = NLA_ALIGN(sizeof(msg));
416         if (decode_nla && len > offset) {
417                 tprints(", ");
418                 decode_nlattr(tcp, addr + offset, len - offset,
419                               netlink_diag_attrs, "NETLINK_DIAG_???",
420                               netlink_diag_msg_nla_decoders,
421                               ARRAY_SIZE(netlink_diag_msg_nla_decoders), NULL);
422         }
423 }
424
425 static void
426 decode_packet_diag_req(struct tcb *const tcp,
427                        const struct nlmsghdr *const nlmsghdr,
428                        const uint8_t family,
429                        const kernel_ulong_t addr,
430                        const kernel_ulong_t len)
431 {
432         struct packet_diag_req req = { .sdiag_family = family };
433         const size_t offset = sizeof(req.sdiag_family);
434
435         PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
436         tprints(", ");
437         if (len >= sizeof(req)) {
438                 if (!umoven_or_printaddr(tcp, addr + offset,
439                                          sizeof(req) - offset,
440                                          (void *) &req + offset)) {
441                         PRINT_FIELD_XVAL("", req, sdiag_protocol,
442                                          ethernet_protocols, "ETH_P_???");
443                         PRINT_FIELD_U(", ", req, pdiag_ino);
444                         PRINT_FIELD_FLAGS(", ", req, pdiag_show,
445                                           packet_diag_show, "PACKET_SHOW_???");
446                         PRINT_FIELD_COOKIE(", ", req, pdiag_cookie);
447                 }
448         } else
449                 tprints("...");
450         tprints("}");
451 }
452
453 static bool
454 decode_packet_diag_info(struct tcb *const tcp,
455                         const kernel_ulong_t addr,
456                         const kernel_ulong_t len,
457                         const void *const opaque_data)
458 {
459         struct packet_diag_info pinfo;
460
461         if (len < sizeof(pinfo))
462                 return false;
463         if (umove_or_printaddr(tcp, addr, &pinfo))
464                 return true;
465
466         PRINT_FIELD_U("{", pinfo, pdi_index);
467         PRINT_FIELD_U(", ", pinfo, pdi_version);
468         PRINT_FIELD_U(", ", pinfo, pdi_reserve);
469         PRINT_FIELD_U(", ", pinfo, pdi_copy_thresh);
470         PRINT_FIELD_U(", ", pinfo, pdi_tstamp);
471         PRINT_FIELD_FLAGS(", ", pinfo, pdi_flags,
472                           packet_diag_info_flags, "PDI_???");
473         tprints("}");
474
475         return true;
476 }
477
478 static bool
479 print_packet_diag_mclist(struct tcb *const tcp, void *const elem_buf,
480                          const size_t elem_size, void *const opaque_data)
481 {
482         struct packet_diag_mclist *dml = elem_buf;
483         uint16_t alen = dml->pdmc_alen > sizeof(dml->pdmc_addr) ?
484                 sizeof(dml->pdmc_addr) : dml->pdmc_alen;
485
486         PRINT_FIELD_IFINDEX("{", *dml, pdmc_index);
487         PRINT_FIELD_U(", ", *dml, pdmc_count);
488         PRINT_FIELD_U(", ", *dml, pdmc_type);
489         PRINT_FIELD_U(", ", *dml, pdmc_alen);
490         PRINT_FIELD_STRING(", ", *dml, pdmc_addr, alen, QUOTE_FORCE_HEX);
491         tprints("}");
492
493         return true;
494 }
495
496 static bool
497 decode_packet_diag_mclist(struct tcb *const tcp,
498                           const kernel_ulong_t addr,
499                           const kernel_ulong_t len,
500                           const void *const opaque_data)
501 {
502         struct packet_diag_mclist dml;
503         const size_t nmemb = len / sizeof(dml);
504
505         if (!nmemb)
506                 return false;
507
508         print_array(tcp, addr, nmemb, &dml, sizeof(dml),
509                     umoven_or_printaddr, print_packet_diag_mclist, 0);
510
511         return true;
512 }
513
514 static bool
515 decode_packet_diag_ring(struct tcb *const tcp,
516                         const kernel_ulong_t addr,
517                         const kernel_ulong_t len,
518                         const void *const opaque_data)
519 {
520         struct packet_diag_ring pdr;
521
522         if (len < sizeof(pdr))
523                 return false;
524         if (umove_or_printaddr(tcp, addr, &pdr))
525                 return true;
526
527         PRINT_FIELD_U("{", pdr, pdr_block_size);
528         PRINT_FIELD_U(", ", pdr, pdr_block_nr);
529         PRINT_FIELD_U(", ", pdr, pdr_frame_size);
530         PRINT_FIELD_U(", ", pdr, pdr_frame_nr);
531         PRINT_FIELD_U(", ", pdr, pdr_retire_tmo);
532         PRINT_FIELD_U(", ", pdr, pdr_sizeof_priv);
533         PRINT_FIELD_U(", ", pdr, pdr_features);
534         tprints("}");
535
536         return true;
537 }
538
539 static bool
540 decode_packet_diag_filter(struct tcb *const tcp,
541                           const kernel_ulong_t addr,
542                           const kernel_ulong_t len,
543                           const void *const opaque_data)
544 {
545         const kernel_ulong_t nmemb = len / sizeof(struct sock_filter);
546         if (!nmemb || (unsigned short) nmemb != nmemb)
547                 return false;
548
549         print_sock_fprog(tcp, addr, nmemb);
550
551         return true;
552 }
553
554 static const nla_decoder_t packet_diag_msg_nla_decoders[] = {
555         [PACKET_DIAG_INFO]      = decode_packet_diag_info,
556         [PACKET_DIAG_MCLIST]    = decode_packet_diag_mclist,
557         [PACKET_DIAG_RX_RING]   = decode_packet_diag_ring,
558         [PACKET_DIAG_TX_RING]   = decode_packet_diag_ring,
559         [PACKET_DIAG_FANOUT]    = decode_nla_u32,
560         [PACKET_DIAG_UID]       = decode_nla_u32,
561         [PACKET_DIAG_MEMINFO]   = decode_meminfo,
562         [PACKET_DIAG_FILTER]    = decode_packet_diag_filter
563 };
564
565 static void
566 decode_packet_diag_msg(struct tcb *const tcp,
567                        const struct nlmsghdr *const nlmsghdr,
568                        const uint8_t family,
569                        const kernel_ulong_t addr,
570                        const kernel_ulong_t len)
571 {
572         struct packet_diag_msg msg = { .pdiag_family = family };
573         size_t offset = sizeof(msg.pdiag_family);
574         bool decode_nla = false;
575
576         PRINT_FIELD_XVAL("{", msg, pdiag_family, addrfams, "AF_???");
577         tprints(", ");
578         if (len >= sizeof(msg)) {
579                 if (!umoven_or_printaddr(tcp, addr + offset,
580                                          sizeof(msg) - offset,
581                                          (void *) &msg + offset)) {
582                         PRINT_FIELD_XVAL("", msg, pdiag_type,
583                                          socktypes, "SOCK_???");
584                         PRINT_FIELD_U(", ", msg, pdiag_num);
585                         PRINT_FIELD_U(", ", msg, pdiag_ino);
586                         PRINT_FIELD_COOKIE(", ", msg, pdiag_cookie);
587                         decode_nla = true;
588                 }
589         } else
590                 tprints("...");
591         tprints("}");
592
593         offset = NLA_ALIGN(sizeof(msg));
594         if (decode_nla && len > offset) {
595                 tprints(", ");
596                 decode_nlattr(tcp, addr + offset, len - offset,
597                               packet_diag_attrs, "PACKET_DIAG_???",
598                               packet_diag_msg_nla_decoders,
599                               ARRAY_SIZE(packet_diag_msg_nla_decoders), NULL);
600         }
601 }
602
603 static void
604 print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
605 {
606         PRINT_FIELD_NET_PORT("{", *id, idiag_sport);
607         PRINT_FIELD_NET_PORT(", ", *id, idiag_dport);
608         PRINT_FIELD_INET_ADDR(", ", *id, idiag_src, family);
609         PRINT_FIELD_INET_ADDR(", ", *id, idiag_dst, family);
610         PRINT_FIELD_IFINDEX(", ", *id, idiag_if);
611         PRINT_FIELD_COOKIE(", ", *id, idiag_cookie);
612         tprints("}");
613 }
614
615 #define PRINT_FIELD_INET_DIAG_SOCKID(prefix_, where_, field_, af_)      \
616         do {                                                            \
617                 STRACE_PRINTF("%s%s=", (prefix_), #field_);             \
618                 print_inet_diag_sockid(&(where_).field_, (af_));        \
619         } while (0)
620
621 static void
622 decode_inet_diag_req_compat(struct tcb *const tcp,
623                             const struct nlmsghdr *const nlmsghdr,
624                             const uint8_t family,
625                             const kernel_ulong_t addr,
626                             const kernel_ulong_t len)
627 {
628         struct inet_diag_req req = { .idiag_family = family };
629         size_t offset = sizeof(req.idiag_family);
630         bool decode_nla = false;
631
632         PRINT_FIELD_XVAL("{", req, idiag_family, addrfams, "AF_???");
633         tprints(", ");
634         if (len >= sizeof(req)) {
635                 if (!umoven_or_printaddr(tcp, addr + offset,
636                                          sizeof(req) - offset,
637                                          (void *) &req + offset)) {
638                         PRINT_FIELD_U("", req, idiag_src_len);
639                         PRINT_FIELD_U(", ", req, idiag_dst_len);
640                         PRINT_FIELD_FLAGS(", ", req, idiag_ext,
641                                           inet_diag_extended_flags,
642                                           "1<<INET_DIAG_\?\?\?-1");
643                         PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id,
644                                                      req.idiag_family);
645                         PRINT_FIELD_FLAGS(", ", req, idiag_states,
646                                           tcp_state_flags, "1<<TCP_???");
647                         PRINT_FIELD_U(", ", req, idiag_dbs);
648                         decode_nla = true;
649                 }
650         } else
651                 tprints("...");
652         tprints("}");
653
654         offset = NLA_ALIGN(sizeof(req));
655         if (decode_nla && len > offset) {
656                 tprints(", ");
657                 decode_nlattr(tcp, addr + offset, len - offset,
658                               inet_diag_req_attrs, "INET_DIAG_REQ_???",
659                               NULL, 0, NULL);
660         }
661 }
662
663 static void
664 decode_inet_diag_req_v2(struct tcb *const tcp,
665                         const struct nlmsghdr *const nlmsghdr,
666                         const uint8_t family,
667                         const kernel_ulong_t addr,
668                         const kernel_ulong_t len)
669 {
670         struct inet_diag_req_v2 req = { .sdiag_family = family };
671         size_t offset = sizeof(req.sdiag_family);
672         bool decode_nla = false;
673
674         PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
675         tprints(", ");
676         if (len >= sizeof(req)) {
677                 if (!umoven_or_printaddr(tcp, addr + offset,
678                                          sizeof(req) - offset,
679                                          (void *) &req + offset)) {
680                         PRINT_FIELD_XVAL("", req, sdiag_protocol,
681                                          inet_protocols, "IPPROTO_???");
682                         PRINT_FIELD_FLAGS(", ", req, idiag_ext,
683                                           inet_diag_extended_flags,
684                                           "1<<INET_DIAG_\?\?\?-1");
685                         PRINT_FIELD_FLAGS(", ", req, idiag_states,
686                                           tcp_state_flags, "1<<TCP_???");
687                         PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id,
688                                                      req.sdiag_family);
689                         decode_nla = true;
690                 }
691         } else
692                 tprints("...");
693         tprints("}");
694
695         offset = NLA_ALIGN(sizeof(req));
696         if (decode_nla && len > offset) {
697                 tprints(", ");
698                 decode_nlattr(tcp, addr + offset, len - offset,
699                               inet_diag_req_attrs, "INET_DIAG_REQ_???",
700                               NULL, 0, NULL);
701         }
702 }
703
704 static void
705 decode_inet_diag_req(struct tcb *const tcp,
706                      const struct nlmsghdr *const nlmsghdr,
707                      const uint8_t family,
708                      const kernel_ulong_t addr,
709                      const kernel_ulong_t len)
710 {
711         if (nlmsghdr->nlmsg_type == TCPDIAG_GETSOCK
712             || nlmsghdr->nlmsg_type == DCCPDIAG_GETSOCK)
713                 return decode_inet_diag_req_compat(tcp, nlmsghdr,
714                                                    family, addr, len);
715         else
716                 return decode_inet_diag_req_v2(tcp, nlmsghdr,
717                                                family, addr, len);
718 }
719
720 static bool
721 decode_inet_diag_meminfo(struct tcb *const tcp,
722                          const kernel_ulong_t addr,
723                          const kernel_ulong_t len,
724                          const void *const opaque_data)
725 {
726         struct inet_diag_meminfo minfo;
727
728         if (len < sizeof(minfo))
729                 return false;
730         if (umove_or_printaddr(tcp, addr, &minfo))
731                 return true;
732
733         PRINT_FIELD_U("{", minfo, idiag_rmem);
734         PRINT_FIELD_U(", ", minfo, idiag_wmem);
735         PRINT_FIELD_U(", ", minfo, idiag_fmem);
736         PRINT_FIELD_U(", ", minfo, idiag_tmem);
737         tprints("}");
738
739         return true;
740 }
741
742 static bool
743 decode_tcpvegas_info(struct tcb *const tcp,
744                      const kernel_ulong_t addr,
745                      const kernel_ulong_t len,
746                      const void *const opaque_data)
747 {
748         struct tcpvegas_info vegas;
749
750         if (len < sizeof(vegas))
751                 return false;
752         if (umove_or_printaddr(tcp, addr, &vegas))
753                 return true;
754
755         PRINT_FIELD_U("{", vegas, tcpv_enabled);
756         PRINT_FIELD_U(", ", vegas, tcpv_rttcnt);
757         PRINT_FIELD_U(", ", vegas, tcpv_rtt);
758         PRINT_FIELD_U(", ", vegas, tcpv_minrtt);
759         tprints("}");
760
761         return true;
762 }
763
764 static bool
765 decode_tcp_dctcp_info(struct tcb *const tcp,
766                       const kernel_ulong_t addr,
767                       const kernel_ulong_t len,
768                       const void *const opaque_data)
769 {
770         struct tcp_dctcp_info dctcp;
771
772         if (len < sizeof(dctcp))
773                 return false;
774         if (umove_or_printaddr(tcp, addr, &dctcp))
775                 return true;
776
777         PRINT_FIELD_U("{", dctcp, dctcp_enabled);
778         PRINT_FIELD_U(", ", dctcp, dctcp_ce_state);
779         PRINT_FIELD_U(", ", dctcp, dctcp_alpha);
780         PRINT_FIELD_U(", ", dctcp, dctcp_ab_ecn);
781         PRINT_FIELD_U(", ", dctcp, dctcp_ab_tot);
782         tprints("}");
783
784         return true;
785 }
786
787 static bool
788 decode_tcp_bbr_info(struct tcb *const tcp,
789                     const kernel_ulong_t addr,
790                     const kernel_ulong_t len,
791                     const void *const opaque_data)
792 {
793         struct tcp_bbr_info bbr;
794
795         if (len < sizeof(bbr))
796                 return false;
797         if (umove_or_printaddr(tcp, addr, &bbr))
798                 return true;
799
800         PRINT_FIELD_X("{", bbr, bbr_bw_lo);
801         PRINT_FIELD_X(", ", bbr, bbr_bw_hi);
802         PRINT_FIELD_U(", ", bbr, bbr_min_rtt);
803         PRINT_FIELD_U(", ", bbr, bbr_pacing_gain);
804         PRINT_FIELD_U(", ", bbr, bbr_cwnd_gain);
805         tprints("}");
806
807         return true;
808 }
809
810 static const nla_decoder_t inet_diag_msg_nla_decoders[] = {
811         [INET_DIAG_MEMINFO]     = decode_inet_diag_meminfo,
812         [INET_DIAG_INFO]        = NULL,                 /* unimplemented */
813         [INET_DIAG_VEGASINFO]   = decode_tcpvegas_info,
814         [INET_DIAG_CONG]        = decode_nla_str,
815         [INET_DIAG_TOS]         = decode_nla_u8,
816         [INET_DIAG_TCLASS]      = decode_nla_u8,
817         [INET_DIAG_SKMEMINFO]   = decode_meminfo,
818         [INET_DIAG_SHUTDOWN]    = decode_nla_u8,
819         [INET_DIAG_DCTCPINFO]   = decode_tcp_dctcp_info,
820         [INET_DIAG_PROTOCOL]    = decode_nla_u8,
821         [INET_DIAG_SKV6ONLY]    = decode_nla_u8,
822         [INET_DIAG_LOCALS]      = NULL,                 /* unimplemented */
823         [INET_DIAG_PEERS]       = NULL,                 /* unimplemented */
824         [INET_DIAG_PAD]         = NULL,
825         [INET_DIAG_MARK]        = decode_nla_u32,
826         [INET_DIAG_BBRINFO]     = decode_tcp_bbr_info
827 };
828
829 static void
830 decode_inet_diag_msg(struct tcb *const tcp,
831                      const struct nlmsghdr *const nlmsghdr,
832                      const uint8_t family,
833                      const kernel_ulong_t addr,
834                      const kernel_ulong_t len)
835 {
836         struct inet_diag_msg msg = { .idiag_family = family };
837         size_t offset = sizeof(msg.idiag_family);
838         bool decode_nla = false;
839
840         PRINT_FIELD_XVAL("{", msg, idiag_family, addrfams, "AF_???");
841         tprints(", ");
842         if (len >= sizeof(msg)) {
843                 if (!umoven_or_printaddr(tcp, addr + offset,
844                                          sizeof(msg) - offset,
845                                          (void *) &msg + offset)) {
846                         PRINT_FIELD_XVAL("", msg, idiag_state,
847                                          tcp_states, "TCP_???");
848                         PRINT_FIELD_U(", ", msg, idiag_timer);
849                         PRINT_FIELD_U(", ", msg, idiag_retrans);
850                         PRINT_FIELD_INET_DIAG_SOCKID(", ", msg, id,
851                                                      msg.idiag_family);
852                         PRINT_FIELD_U(", ", msg, idiag_expires);
853                         PRINT_FIELD_U(", ", msg, idiag_rqueue);
854                         PRINT_FIELD_U(", ", msg, idiag_wqueue);
855                         PRINT_FIELD_U(", ", msg, idiag_uid);
856                         PRINT_FIELD_U(", ", msg, idiag_inode);
857                         decode_nla = true;
858                 }
859         } else
860                 tprints("...");
861         tprints("}");
862
863         offset = NLA_ALIGN(sizeof(msg));
864         if (decode_nla && len > offset) {
865                 tprints(", ");
866                 decode_nlattr(tcp, addr + offset, len - offset,
867                               inet_diag_attrs, "INET_DIAG_???",
868                               inet_diag_msg_nla_decoders,
869                               ARRAY_SIZE(inet_diag_msg_nla_decoders), NULL);
870         }
871 }
872
873 #ifdef AF_SMC
874 static void
875 decode_smc_diag_req(struct tcb *const tcp,
876                     const struct nlmsghdr *const nlmsghdr,
877                     const uint8_t family,
878                     const kernel_ulong_t addr,
879                     const kernel_ulong_t len)
880 {
881         struct smc_diag_req req = { .diag_family = family };
882         const size_t offset = sizeof(req.diag_family);
883
884         PRINT_FIELD_XVAL("{", req, diag_family, addrfams, "AF_???");
885         tprints(", ");
886         if (len >= sizeof(req)) {
887                 if (!umoven_or_printaddr(tcp, addr + offset,
888                                          sizeof(req) - offset,
889                                          (void *) &req + offset)) {
890                         PRINT_FIELD_FLAGS("", req, diag_ext,
891                                           smc_diag_extended_flags,
892                                           "1<<SMC_DIAG_\?\?\?-1");
893                         /*
894                          * AF_SMC protocol family socket handler
895                          * keeping the AF_INET sock address.
896                          */
897                         PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id, AF_INET);
898                 }
899         } else
900                 tprints("...");
901         tprints("}");
902 }
903
904 static void
905 print_smc_diag_cursor(const struct smc_diag_cursor *const cursor)
906 {
907         PRINT_FIELD_U("{", *cursor, reserved);
908         PRINT_FIELD_U(", ", *cursor, wrap);
909         PRINT_FIELD_U(", ", *cursor, count);
910         tprints("}");
911 }
912
913 #define PRINT_FIELD_SMC_DIAG_CURSOR(prefix_, where_, field_)            \
914         do {                                                            \
915                 tprintf("%s%s=", (prefix_), #field_);                   \
916                 print_smc_diag_cursor(&(where_).field_);                \
917         } while (0)
918
919 static bool
920 decode_smc_diag_conninfo(struct tcb *const tcp,
921                          const kernel_ulong_t addr,
922                          const kernel_ulong_t len,
923                          const void *const opaque_data)
924 {
925         struct smc_diag_conninfo cinfo;
926
927         if (len < sizeof(cinfo))
928                 return false;
929         if (umove_or_printaddr(tcp, addr, &cinfo))
930                 return true;
931
932         PRINT_FIELD_U("{", cinfo, token);
933         PRINT_FIELD_U(", ", cinfo, sndbuf_size);
934         PRINT_FIELD_U(", ", cinfo, rmbe_size);
935         PRINT_FIELD_U(", ", cinfo, peer_rmbe_size);
936         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, rx_prod);
937         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, rx_cons);
938         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_prod);
939         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_cons);
940         PRINT_FIELD_0X(", ", cinfo, rx_prod_flags);
941         PRINT_FIELD_0X(", ", cinfo, rx_conn_state_flags);
942         PRINT_FIELD_0X(", ", cinfo, tx_prod_flags);
943         PRINT_FIELD_0X(", ", cinfo, tx_conn_state_flags);
944         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_prep);
945         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_sent);
946         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_fin);
947         tprints("}");
948
949         return true;
950 }
951
952 static bool
953 decode_smc_diag_lgrinfo(struct tcb *const tcp,
954                         const kernel_ulong_t addr,
955                         const kernel_ulong_t len,
956                         const void *const opaque_data)
957 {
958         struct smc_diag_lgrinfo linfo;
959
960         if (len < sizeof(linfo))
961                 return false;
962         if (umove_or_printaddr(tcp, addr, &linfo))
963                 return true;
964
965         tprints("{lnk[0]={");
966         PRINT_FIELD_U("", linfo.lnk[0], link_id);
967         PRINT_FIELD_STRING(", ", linfo.lnk[0], ibname,
968                            sizeof(linfo.lnk[0].ibname),
969                            QUOTE_0_TERMINATED);
970         PRINT_FIELD_U(", ", linfo.lnk[0], ibport);
971         PRINT_FIELD_STRING(", ", linfo.lnk[0], gid,
972                            sizeof(linfo.lnk[0].gid),
973                            QUOTE_0_TERMINATED);
974         PRINT_FIELD_STRING(", ", linfo.lnk[0], peer_gid,
975                            sizeof(linfo.lnk[0].peer_gid),
976                            QUOTE_0_TERMINATED);
977         PRINT_FIELD_XVAL("}, ", linfo, role, smc_link_group_roles, "SMC_???");
978         tprints("}");
979
980         return true;
981 }
982
983 static const nla_decoder_t smc_diag_msg_nla_decoders[] = {
984         [SMC_DIAG_CONNINFO]     = decode_smc_diag_conninfo,
985         [SMC_DIAG_LGRINFO]      = decode_smc_diag_lgrinfo,
986         [SMC_DIAG_SHUTDOWN]     = decode_nla_u8
987 };
988
989 static void
990 decode_smc_diag_msg(struct tcb *const tcp,
991                     const struct nlmsghdr *const nlmsghdr,
992                     const uint8_t family,
993                     const kernel_ulong_t addr,
994                     const kernel_ulong_t len)
995 {
996         struct smc_diag_msg msg = { .diag_family = family };
997         size_t offset = sizeof(msg.diag_family);
998         bool decode_nla = false;
999
1000         PRINT_FIELD_XVAL("{", msg, diag_family, addrfams, "AF_???");
1001         tprints(", ");
1002         if (len >= sizeof(msg)) {
1003                 if (!umoven_or_printaddr(tcp, addr + offset,
1004                                          sizeof(msg) - offset,
1005                                          (void *) &msg + offset)) {
1006                         PRINT_FIELD_XVAL("", msg, diag_state,
1007                                          smc_states, "SMC_???");
1008                         PRINT_FIELD_U(", ", msg, diag_fallback);
1009                         PRINT_FIELD_U(", ", msg, diag_shutdown);
1010                         /*
1011                          * AF_SMC protocol family socket handler
1012                          * keeping the AF_INET sock address.
1013                          */
1014                         PRINT_FIELD_INET_DIAG_SOCKID(", ", msg, id, AF_INET);
1015                         PRINT_FIELD_U(", ", msg, diag_uid);
1016                         PRINT_FIELD_U(", ", msg, diag_inode);
1017                         decode_nla = true;
1018                 }
1019         } else
1020                 tprints("...");
1021         tprints("}");
1022
1023         offset = NLA_ALIGN(sizeof(msg));
1024         if (decode_nla && len > offset) {
1025                 tprints(", ");
1026                 decode_nlattr(tcp, addr + offset, len - offset,
1027                               smc_diag_attrs, "SMC_DIAG_???",
1028                               smc_diag_msg_nla_decoders,
1029                               ARRAY_SIZE(smc_diag_msg_nla_decoders), NULL);
1030         }
1031 }
1032 #endif
1033
1034 typedef void (*netlink_diag_decoder_t)(struct tcb *,
1035                                        const struct nlmsghdr *,
1036                                        uint8_t family,
1037                                        kernel_ulong_t addr,
1038                                        kernel_ulong_t len);
1039
1040 static const struct {
1041         const netlink_diag_decoder_t request, response;
1042 } diag_decoders[] = {
1043         [AF_INET] = { decode_inet_diag_req, decode_inet_diag_msg },
1044         [AF_INET6] = { decode_inet_diag_req, decode_inet_diag_msg },
1045         [AF_NETLINK] = { decode_netlink_diag_req, decode_netlink_diag_msg },
1046         [AF_PACKET] = { decode_packet_diag_req, decode_packet_diag_msg },
1047 #ifdef AF_SMC
1048         [AF_SMC] = { decode_smc_diag_req, decode_smc_diag_msg },
1049 #endif
1050         [AF_UNIX] = { decode_unix_diag_req, decode_unix_diag_msg }
1051 };
1052
1053 bool
1054 decode_netlink_sock_diag(struct tcb *const tcp,
1055                          const struct nlmsghdr *const nlmsghdr,
1056                          const kernel_ulong_t addr,
1057                          const kernel_ulong_t len)
1058 {
1059         uint8_t family;
1060
1061         if (nlmsghdr->nlmsg_type == NLMSG_DONE)
1062                 return false;
1063
1064         if (!umove_or_printaddr(tcp, addr, &family)) {
1065                 if (family < ARRAY_SIZE(diag_decoders)
1066                     && len > sizeof(family)) {
1067                         const netlink_diag_decoder_t decoder =
1068                                 (nlmsghdr->nlmsg_flags & NLM_F_REQUEST)
1069                                 ? diag_decoders[family].request
1070                                 : diag_decoders[family].response;
1071
1072                         if (decoder) {
1073                                 decoder(tcp, nlmsghdr, family, addr, len);
1074                                 return true;
1075                         }
1076                 }
1077
1078                 decode_family(tcp, family, addr, len);
1079         }
1080
1081         return true;
1082 }