2 * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4 * Copyright (c) 2016-2018 The strace developers.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <linux/sock_diag.h>
37 #include "static_assert.h"
39 #include "xlat/netlink_sk_meminfo_indices.h"
42 fetch_nlattr(struct tcb *const tcp, struct nlattr *const nlattr,
43 const kernel_ulong_t addr, const unsigned int len,
46 if (len < sizeof(struct nlattr)) {
47 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
51 if (tfetch_obj(tcp, addr, nlattr))
56 printaddr_comment(addr);
65 print_nlattr(const struct nlattr *const nla,
66 const struct xlat *const table,
67 const char *const dflt)
69 static_assert(NLA_TYPE_MASK == ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER),
70 "wrong NLA_TYPE_MASK");
72 tprintf("{nla_len=%u, nla_type=", nla->nla_len);
73 if (nla->nla_type & NLA_F_NESTED) {
74 print_xlat(NLA_F_NESTED);
77 if (nla->nla_type & NLA_F_NET_BYTEORDER) {
78 print_xlat(NLA_F_NET_BYTEORDER);
81 printxval(table, nla->nla_type & NLA_TYPE_MASK, dflt);
86 decode_nlattr_with_data(struct tcb *const tcp,
87 const struct nlattr *const nla,
88 const kernel_ulong_t addr,
89 const unsigned int len,
90 const struct xlat *const table,
91 const char *const dflt,
92 const nla_decoder_t *const decoders,
93 const unsigned int size,
94 const void *const opaque_data)
96 const unsigned int nla_len = MIN(nla->nla_len, len);
98 if (nla_len > NLA_HDRLEN)
101 print_nlattr(nla, table, dflt);
103 if (nla_len > NLA_HDRLEN) {
104 const unsigned int idx = size ? nla->nla_type : 0;
108 || (size && idx >= size)
111 tcp, addr + NLA_HDRLEN,
112 nla_len - NLA_HDRLEN,
114 : (const void *) (uintptr_t) nla->nla_type)
116 printstr_ex(tcp, addr + NLA_HDRLEN,
117 nla_len - NLA_HDRLEN, QUOTE_FORCE_HEX);
123 decode_nlattr(struct tcb *const tcp,
126 const struct xlat *const table,
127 const char *const dflt,
128 const nla_decoder_t *const decoders,
129 const unsigned int size,
130 const void *const opaque_data)
133 bool is_array = false;
136 if (decoders && !size && opaque_data)
137 error_func_msg("[xlat %p, dflt \"%s\", decoders %p] "
138 "size is zero (going to pass nla_type as "
139 "decoder argument), but opaque data (%p) is not "
141 table, dflt, decoders, opaque_data);
143 for (elt = 0; fetch_nlattr(tcp, &nla, addr, len, is_array); elt++) {
144 if (abbrev(tcp) && elt == max_strlen) {
149 const unsigned int nla_len = NLA_ALIGN(nla.nla_len);
150 kernel_ulong_t next_addr = 0;
151 unsigned int next_len = 0;
153 if (nla.nla_len >= NLA_HDRLEN) {
154 next_len = (len >= nla_len) ? len - nla_len : 0;
156 if (next_len && addr + nla_len > addr)
157 next_addr = addr + nla_len;
160 if (!is_array && next_addr) {
165 decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt,
166 decoders, size, opaque_data);
182 decode_nla_str(struct tcb *const tcp,
183 const kernel_ulong_t addr,
184 const unsigned int len,
185 const void *const opaque_data)
187 printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
193 decode_nla_strn(struct tcb *const tcp,
194 const kernel_ulong_t addr,
195 const unsigned int len,
196 const void *const opaque_data)
198 printstrn(tcp, addr, len);
204 decode_nla_meminfo(struct tcb *const tcp,
205 const kernel_ulong_t addr,
206 const unsigned int len,
207 const void *const opaque_data)
210 const size_t nmemb = len / sizeof(mem);
215 unsigned int count = 0;
216 print_array_ex(tcp, addr, nmemb, &mem, sizeof(mem),
217 tfetch_mem, print_uint32_array_member, &count,
218 PAF_PRINT_INDICES | PAF_INDEX_XLAT_VALUE_INDEXED
220 ARRSZ_PAIR(netlink_sk_meminfo_indices),
227 decode_nla_fd(struct tcb *const tcp,
228 const kernel_ulong_t addr,
229 const unsigned int len,
230 const void *const opaque_data)
234 if (len < sizeof(fd))
236 else if (!umove_or_printaddr(tcp, addr, &fd))
243 decode_nla_uid(struct tcb *const tcp,
244 const kernel_ulong_t addr,
245 const unsigned int len,
246 const void *const opaque_data)
250 if (len < sizeof(uid))
252 else if (!umove_or_printaddr(tcp, addr, &uid))
259 decode_nla_gid(struct tcb *const tcp,
260 const kernel_ulong_t addr,
261 const unsigned int len,
262 const void *const opaque_data)
264 return decode_nla_uid(tcp, addr, len, opaque_data);
268 decode_nla_ifindex(struct tcb *const tcp,
269 const kernel_ulong_t addr,
270 const unsigned int len,
271 const void *const opaque_data)
275 if (len < sizeof(ifindex))
277 else if (!umove_or_printaddr(tcp, addr, &ifindex))
278 print_ifindex(ifindex);
284 decode_nla_xval(struct tcb *const tcp,
285 const kernel_ulong_t addr,
287 const void *const opaque_data)
289 const struct decode_nla_xlat_opts * const opts = opaque_data;
292 uint8_t bytes[sizeof(uint64_t)];
293 } data = { .val = 0 };
295 if (len > sizeof(data) || len < opts->size)
299 len = MIN(len, opts->size);
301 const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
303 if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs)) {
304 if (opts->process_fn)
305 data.val = opts->process_fn(data.val);
307 tprints(opts->prefix);
308 printxval_dispatch_ex(opts->xlat, opts->xlat_size, data.val,
309 opts->dflt, opts->xt, opts->style);
311 tprints(opts->suffix);
318 process_host_order(uint64_t val)
324 decode_nla_ether_proto(struct tcb *const tcp,
325 const kernel_ulong_t addr,
326 const unsigned int len,
327 const void *const opaque_data)
329 const struct decode_nla_xlat_opts opts = {
330 .xlat = ethernet_protocols,
331 .xlat_size = ethernet_protocols_size,
332 .dflt = "ETHER_P_???",
336 .process_fn = process_host_order,
339 return decode_nla_xval(tcp, addr, len, &opts);
343 decode_nla_ip_proto(struct tcb *const tcp,
344 const kernel_ulong_t addr,
345 const unsigned int len,
346 const void *const opaque_data)
348 const struct decode_nla_xlat_opts opts = {
349 .xlat = inet_protocols,
350 .xlat_size = inet_protocols_size,
352 .dflt = "IPPROTO_???",
356 return decode_nla_xval(tcp, addr, len, &opts);
360 decode_nla_flags(struct tcb *const tcp,
361 const kernel_ulong_t addr,
363 const void *const opaque_data)
365 const struct decode_nla_xlat_opts * const opts = opaque_data;
368 uint8_t bytes[sizeof(uint64_t)];
369 } data = { .flags = 0 };
371 if (len > sizeof(data) || len < opts->size)
375 len = MIN(len, opts->size);
377 const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
379 if (opts->xt == XT_INDEXED)
380 error_func_msg("indexed xlats are currently incompatible with "
383 if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs)) {
384 if (opts->process_fn)
385 data.flags = opts->process_fn(data.flags);
387 tprints(opts->prefix);
388 printflags_ex(data.flags, opts->dflt, opts->style, opts->xlat,
391 tprints(opts->suffix);
398 decode_nla_be16(struct tcb *const tcp,
399 const kernel_ulong_t addr,
400 const unsigned int len,
401 const void *const opaque_data)
405 if (len < sizeof(num))
407 else if (!umove_or_printaddr(tcp, addr, &num))
408 tprintf("htons(%u)", ntohs(num));
414 decode_nla_be64(struct tcb *const tcp,
415 const kernel_ulong_t addr,
416 const unsigned int len,
417 const void *const opaque_data)
419 #if defined HAVE_BE64TOH || defined be64toh
422 if (len < sizeof(num))
424 else if (!umove_or_printaddr(tcp, addr, &num))
425 tprintf("htobe64(%" PRIu64 ")", be64toh(num));
433 #define DECODE_NLA_INTEGER(name, type, fmt) \
435 decode_nla_ ## name(struct tcb *const tcp, \
436 const kernel_ulong_t addr, \
437 const unsigned int len, \
438 const void *const opaque_data) \
442 if (len < sizeof(num)) \
444 if (!umove_or_printaddr(tcp, addr, &num)) \
449 DECODE_NLA_INTEGER(x8, uint8_t, "%#" PRIx8)
450 DECODE_NLA_INTEGER(x16, uint16_t, "%#" PRIx16)
451 DECODE_NLA_INTEGER(x32, uint32_t, "%#" PRIx32)
452 DECODE_NLA_INTEGER(x64, uint64_t, "%#" PRIx64)
453 DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
454 DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
455 DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)
456 DECODE_NLA_INTEGER(u64, uint64_t, "%" PRIu64)
457 DECODE_NLA_INTEGER(s8, int8_t, "%" PRId8)
458 DECODE_NLA_INTEGER(s16, int16_t, "%" PRId16)
459 DECODE_NLA_INTEGER(s32, int32_t, "%" PRId32)
460 DECODE_NLA_INTEGER(s64, int64_t, "%" PRId64)