]> granicus.if.org Git - strace/blob - netlink_packet_diag.c
tests: workaround systemd-nspawn habit of disabling unimplemented syscalls
[strace] / netlink_packet_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-2018 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 "netlink_sock_diag.h"
13 #include "nlattr.h"
14 #include "print_fields.h"
15
16 #include <linux/filter.h>
17 #include <linux/sock_diag.h>
18 #include <linux/packet_diag.h>
19
20 #include "xlat/af_packet_versions.h"
21 #include "xlat/packet_diag_attrs.h"
22 #include "xlat/packet_diag_info_flags.h"
23 #include "xlat/packet_diag_show.h"
24
25 DECL_NETLINK_DIAG_DECODER(decode_packet_diag_req)
26 {
27         struct packet_diag_req req = { .sdiag_family = family };
28         const size_t offset = sizeof(req.sdiag_family);
29
30         PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
31         tprints(", ");
32         if (len >= sizeof(req)) {
33                 if (!umoven_or_printaddr(tcp, addr + offset,
34                                          sizeof(req) - offset,
35                                          (char *) &req + offset)) {
36                         /*
37                          * AF_PACKET currently doesn't support protocol values
38                          * other than 0.
39                          */
40                         PRINT_FIELD_X("", req, sdiag_protocol);
41                         PRINT_FIELD_U(", ", req, pdiag_ino);
42                         PRINT_FIELD_FLAGS(", ", req, pdiag_show,
43                                           packet_diag_show, "PACKET_SHOW_???");
44                         PRINT_FIELD_COOKIE(", ", req, pdiag_cookie);
45                 }
46         } else
47                 tprints("...");
48         tprints("}");
49 }
50
51 static bool
52 decode_packet_diag_info(struct tcb *const tcp,
53                         const kernel_ulong_t addr,
54                         const unsigned int len,
55                         const void *const opaque_data)
56 {
57         struct packet_diag_info pinfo;
58
59         if (len < sizeof(pinfo))
60                 return false;
61         if (umove_or_printaddr(tcp, addr, &pinfo))
62                 return true;
63
64         PRINT_FIELD_IFINDEX("{", pinfo, pdi_index);
65         PRINT_FIELD_XVAL(", ", pinfo, pdi_version, af_packet_versions,
66                          "TPACKET_???");
67         PRINT_FIELD_U(", ", pinfo, pdi_reserve);
68         PRINT_FIELD_U(", ", pinfo, pdi_copy_thresh);
69         PRINT_FIELD_U(", ", pinfo, pdi_tstamp);
70         PRINT_FIELD_FLAGS(", ", pinfo, pdi_flags,
71                           packet_diag_info_flags, "PDI_???");
72         tprints("}");
73
74         return true;
75 }
76
77 static bool
78 print_packet_diag_mclist(struct tcb *const tcp, void *const elem_buf,
79                          const size_t elem_size, void *const opaque_data)
80 {
81         struct packet_diag_mclist *dml = elem_buf;
82         uint16_t alen = MIN(dml->pdmc_alen, sizeof(dml->pdmc_addr));
83
84         PRINT_FIELD_IFINDEX("{", *dml, pdmc_index);
85         PRINT_FIELD_U(", ", *dml, pdmc_count);
86         PRINT_FIELD_U(", ", *dml, pdmc_type);
87         PRINT_FIELD_U(", ", *dml, pdmc_alen);
88         PRINT_FIELD_STRING(", ", *dml, pdmc_addr, alen, QUOTE_FORCE_HEX);
89         tprints("}");
90
91         return true;
92 }
93
94 static bool
95 decode_packet_diag_mclist(struct tcb *const tcp,
96                           const kernel_ulong_t addr,
97                           const unsigned int len,
98                           const void *const opaque_data)
99 {
100         struct packet_diag_mclist dml;
101         const size_t nmemb = len / sizeof(dml);
102
103         if (!nmemb)
104                 return false;
105
106         print_array(tcp, addr, nmemb, &dml, sizeof(dml),
107                     tfetch_mem, print_packet_diag_mclist, 0);
108
109         return true;
110 }
111
112 static bool
113 decode_packet_diag_ring(struct tcb *const tcp,
114                         const kernel_ulong_t addr,
115                         const unsigned int len,
116                         const void *const opaque_data)
117 {
118         struct packet_diag_ring pdr;
119
120         if (len < sizeof(pdr))
121                 return false;
122         if (umove_or_printaddr(tcp, addr, &pdr))
123                 return true;
124
125         PRINT_FIELD_U("{", pdr, pdr_block_size);
126         PRINT_FIELD_U(", ", pdr, pdr_block_nr);
127         PRINT_FIELD_U(", ", pdr, pdr_frame_size);
128         PRINT_FIELD_U(", ", pdr, pdr_frame_nr);
129         PRINT_FIELD_U(", ", pdr, pdr_retire_tmo);
130         PRINT_FIELD_U(", ", pdr, pdr_sizeof_priv);
131         PRINT_FIELD_U(", ", pdr, pdr_features);
132         tprints("}");
133
134         return true;
135 }
136
137 static bool
138 decode_packet_diag_filter(struct tcb *const tcp,
139                           const kernel_ulong_t addr,
140                           const unsigned int len,
141                           const void *const opaque_data)
142 {
143         const unsigned int nmemb = len / sizeof(struct sock_filter);
144         if (!nmemb || (unsigned short) nmemb != nmemb)
145                 return false;
146
147         print_sock_fprog(tcp, addr, nmemb);
148
149         return true;
150 }
151
152 static const nla_decoder_t packet_diag_msg_nla_decoders[] = {
153         [PACKET_DIAG_INFO]      = decode_packet_diag_info,
154         [PACKET_DIAG_MCLIST]    = decode_packet_diag_mclist,
155         [PACKET_DIAG_RX_RING]   = decode_packet_diag_ring,
156         [PACKET_DIAG_TX_RING]   = decode_packet_diag_ring,
157         [PACKET_DIAG_FANOUT]    = decode_nla_u32,
158         [PACKET_DIAG_UID]       = decode_nla_uid,
159         [PACKET_DIAG_MEMINFO]   = decode_nla_meminfo,
160         [PACKET_DIAG_FILTER]    = decode_packet_diag_filter
161 };
162
163 DECL_NETLINK_DIAG_DECODER(decode_packet_diag_msg)
164 {
165         struct packet_diag_msg msg = { .pdiag_family = family };
166         size_t offset = sizeof(msg.pdiag_family);
167         bool decode_nla = false;
168
169         PRINT_FIELD_XVAL("{", msg, pdiag_family, addrfams, "AF_???");
170         tprints(", ");
171         if (len >= sizeof(msg)) {
172                 if (!umoven_or_printaddr(tcp, addr + offset,
173                                          sizeof(msg) - offset,
174                                          (char *) &msg + offset)) {
175                         PRINT_FIELD_XVAL("", msg, pdiag_type,
176                                          socktypes, "SOCK_???");
177                         PRINT_FIELD_XVAL(", ", msg, pdiag_num,
178                                          ethernet_protocols, "ETH_P_???");
179                         PRINT_FIELD_U(", ", msg, pdiag_ino);
180                         PRINT_FIELD_COOKIE(", ", msg, pdiag_cookie);
181                         decode_nla = true;
182                 }
183         } else
184                 tprints("...");
185         tprints("}");
186
187         offset = NLMSG_ALIGN(sizeof(msg));
188         if (decode_nla && len > offset) {
189                 tprints(", ");
190                 decode_nlattr(tcp, addr + offset, len - offset,
191                               packet_diag_attrs, "PACKET_DIAG_???",
192                               packet_diag_msg_nla_decoders,
193                               ARRAY_SIZE(packet_diag_msg_nla_decoders), NULL);
194         }
195 }