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) {
106 || nla->nla_type >= size
107 || !decoders[nla->nla_type]
108 || !decoders[nla->nla_type](tcp, addr + NLA_HDRLEN,
109 nla_len - NLA_HDRLEN,
111 printstr_ex(tcp, addr + NLA_HDRLEN,
112 nla_len - NLA_HDRLEN, QUOTE_FORCE_HEX);
118 decode_nlattr(struct tcb *const tcp,
121 const struct xlat *const table,
122 const char *const dflt,
123 const nla_decoder_t *const decoders,
124 const unsigned int size,
125 const void *const opaque_data)
128 bool is_array = false;
131 for (elt = 0; fetch_nlattr(tcp, &nla, addr, len, is_array); elt++) {
132 if (abbrev(tcp) && elt == max_strlen) {
137 const unsigned int nla_len = NLA_ALIGN(nla.nla_len);
138 kernel_ulong_t next_addr = 0;
139 unsigned int next_len = 0;
141 if (nla.nla_len >= NLA_HDRLEN) {
142 next_len = (len >= nla_len) ? len - nla_len : 0;
144 if (next_len && addr + nla_len > addr)
145 next_addr = addr + nla_len;
148 if (!is_array && next_addr) {
153 decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt,
154 decoders, size, opaque_data);
170 decode_nla_str(struct tcb *const tcp,
171 const kernel_ulong_t addr,
172 const unsigned int len,
173 const void *const opaque_data)
175 printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
181 decode_nla_strn(struct tcb *const tcp,
182 const kernel_ulong_t addr,
183 const unsigned int len,
184 const void *const opaque_data)
186 printstrn(tcp, addr, len);
192 decode_nla_meminfo(struct tcb *const tcp,
193 const kernel_ulong_t addr,
194 const unsigned int len,
195 const void *const opaque_data)
198 const size_t nmemb = len / sizeof(mem);
203 unsigned int count = 0;
204 print_array_ex(tcp, addr, nmemb, &mem, sizeof(mem),
205 tfetch_mem, print_uint32_array_member, &count,
206 PAF_PRINT_INDICES | PAF_INDEX_XLAT_VALUE_INDEXED
208 ARRSZ_PAIR(netlink_sk_meminfo_indices),
215 decode_nla_fd(struct tcb *const tcp,
216 const kernel_ulong_t addr,
217 const unsigned int len,
218 const void *const opaque_data)
222 if (len < sizeof(fd))
224 else if (!umove_or_printaddr(tcp, addr, &fd))
231 decode_nla_ifindex(struct tcb *const tcp,
232 const kernel_ulong_t addr,
233 const unsigned int len,
234 const void *const opaque_data)
238 if (len < sizeof(ifindex))
240 else if (!umove_or_printaddr(tcp, addr, &ifindex))
241 print_ifindex(ifindex);
247 decode_nla_xval(struct tcb *const tcp,
248 const kernel_ulong_t addr,
249 const unsigned int len,
250 const void *const opaque_data)
252 const struct decode_nla_xlat_opts * const opts = opaque_data;
255 uint8_t bytes[sizeof(uint64_t)];
257 const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
261 if (len > sizeof(data))
263 else if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs))
264 printxval_dispatch_ex(opts->xlat, opts->xlat_size, data.val,
265 opts->dflt, opts->xt, opts->style);
271 decode_nla_ip_proto(struct tcb *const tcp,
272 const kernel_ulong_t addr,
273 const unsigned int len,
274 const void *const opaque_data)
276 static const struct decode_nla_xlat_opts opts = {
277 .xlat = inet_protocols, .dflt = "IPPROTO_???",
280 return decode_nla_xval(tcp, addr, len, &opts);
284 decode_nla_be16(struct tcb *const tcp,
285 const kernel_ulong_t addr,
286 const unsigned int len,
287 const void *const opaque_data)
291 if (len < sizeof(num))
293 else if (!umove_or_printaddr(tcp, addr, &num))
294 tprintf("htons(%u)", ntohs(num));
300 decode_nla_be64(struct tcb *const tcp,
301 const kernel_ulong_t addr,
302 const unsigned int len,
303 const void *const opaque_data)
305 #if defined HAVE_BE64TOH || defined be64toh
308 if (len < sizeof(num))
310 else if (!umove_or_printaddr(tcp, addr, &num))
311 tprintf("htobe64(%" PRIu64 ")", be64toh(num));
319 #define DECODE_NLA_INTEGER(name, type, fmt) \
321 decode_nla_ ## name(struct tcb *const tcp, \
322 const kernel_ulong_t addr, \
323 const unsigned int len, \
324 const void *const opaque_data) \
328 if (len < sizeof(num)) \
330 if (!umove_or_printaddr(tcp, addr, &num)) \
335 DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
336 DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
337 DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)
338 DECODE_NLA_INTEGER(u64, uint64_t, "%" PRIu64)
339 DECODE_NLA_INTEGER(s8, int8_t, "%" PRId8)
340 DECODE_NLA_INTEGER(s16, int16_t, "%" PRId16)
341 DECODE_NLA_INTEGER(s32, int32_t, "%" PRId32)
342 DECODE_NLA_INTEGER(s64, int64_t, "%" PRId64)