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