1 /*
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.
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_route.h"
32 #include "nlattr.h"
33 #include "print_fields.h"
34
35 #include "netlink.h"
36
37 #include <netinet/in.h>
38
39 #ifdef HAVE_LINUX_IF_LINK_H
40 # include <linux/if_link.h>
41 #endif
42 #include <linux/rtnetlink.h>
43
44 #include "xlat/in6_addr_gen_mode.h"
45 #include "xlat/inet_devconf_indices.h"
46 #include "xlat/inet6_devconf_indices.h"
47 #include "xlat/inet6_if_flags.h"
48 #include "xlat/rtnl_ifla_af_spec_inet_attrs.h"
49 #include "xlat/rtnl_ifla_af_spec_inet6_attrs.h"
50 #include "xlat/rtnl_ifla_brport_attrs.h"
51 #include "xlat/rtnl_ifla_events.h"
52 #include "xlat/rtnl_ifla_info_attrs.h"
53 #include "xlat/rtnl_ifla_info_data_bridge_attrs.h"
54 #include "xlat/rtnl_ifla_info_data_tun_attrs.h"
55 #include "xlat/rtnl_ifla_port_attrs.h"
56 #include "xlat/rtnl_ifla_vf_port_attrs.h"
57 #include "xlat/rtnl_ifla_xdp_attached_mode.h"
58 #include "xlat/rtnl_ifla_xdp_attrs.h"
59 #include "xlat/rtnl_link_attrs.h"
60 #include "xlat/snmp_icmp6_stats.h"
61 #include "xlat/snmp_ip_stats.h"
62 #include "xlat/tun_device_types.h"
63 #include "xlat/xdp_flags.h"
64
65 static bool
decode_rtnl_link_stats(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)66 decode_rtnl_link_stats(struct tcb *const tcp,
67 const kernel_ulong_t addr,
68 const unsigned int len,
69 const void *const opaque_data)
70 {
71 struct rtnl_link_stats st;
72 const unsigned int min_size =
73 offsetofend(struct rtnl_link_stats, tx_compressed);
74 const unsigned int def_size = sizeof(st);
75 const unsigned int size =
76 (len >= def_size) ? def_size :
77 ((len == min_size) ? min_size : 0);
78
79 if (!size)
80 return false;
81
82 if (!umoven_or_printaddr(tcp, addr, size, &st)) {
83 PRINT_FIELD_U("{", st, rx_packets);
84 PRINT_FIELD_U(", ", st, tx_packets);
85 PRINT_FIELD_U(", ", st, rx_bytes);
86 PRINT_FIELD_U(", ", st, tx_bytes);
87 PRINT_FIELD_U(", ", st, rx_errors);
88 PRINT_FIELD_U(", ", st, tx_errors);
89 PRINT_FIELD_U(", ", st, rx_dropped);
90 PRINT_FIELD_U(", ", st, tx_dropped);
91 PRINT_FIELD_U(", ", st, multicast);
92 PRINT_FIELD_U(", ", st, collisions);
93
94 PRINT_FIELD_U(", ", st, rx_length_errors);
95 PRINT_FIELD_U(", ", st, rx_over_errors);
96 PRINT_FIELD_U(", ", st, rx_crc_errors);
97 PRINT_FIELD_U(", ", st, rx_frame_errors);
98 PRINT_FIELD_U(", ", st, rx_fifo_errors);
99 PRINT_FIELD_U(", ", st, rx_missed_errors);
100
101 PRINT_FIELD_U(", ", st, tx_aborted_errors);
102 PRINT_FIELD_U(", ", st, tx_carrier_errors);
103 PRINT_FIELD_U(", ", st, tx_fifo_errors);
104 PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
105 PRINT_FIELD_U(", ", st, tx_window_errors);
106
107 PRINT_FIELD_U(", ", st, rx_compressed);
108 PRINT_FIELD_U(", ", st, tx_compressed);
109 #ifdef HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER
110 if (len >= def_size)
111 PRINT_FIELD_U(", ", st, rx_nohandler);
112 #endif
113 tprints("}");
114 }
115
116 return true;
117 }
118
119 static bool
decode_ifla_bridge_id(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)120 decode_ifla_bridge_id(struct tcb *const tcp,
121 const kernel_ulong_t addr,
122 const unsigned int len,
123 const void *const opaque_data)
124 {
125 struct {
126 uint8_t prio[2];
127 uint8_t addr[6];
128 } id;
129
130 if (len < sizeof(id))
131 return false;
132 else if (!umove_or_printaddr(tcp, addr, &id)) {
133 tprintf("{prio=[%u, %u]", id.prio[0], id.prio[1]);
134 PRINT_FIELD_MAC(", ", id, addr);
135 tprints("}");
136 }
137
138 return true;
139 }
140
141 static const nla_decoder_t ifla_brport_nla_decoders[] = {
142 [IFLA_BRPORT_STATE] = decode_nla_u8,
143 [IFLA_BRPORT_PRIORITY] = decode_nla_u16,
144 [IFLA_BRPORT_COST] = decode_nla_u32,
145 [IFLA_BRPORT_MODE] = decode_nla_u8,
146 [IFLA_BRPORT_GUARD] = decode_nla_u8,
147 [IFLA_BRPORT_PROTECT] = decode_nla_u8,
148 [IFLA_BRPORT_FAST_LEAVE] = decode_nla_u8,
149 [IFLA_BRPORT_LEARNING] = decode_nla_u8,
150 [IFLA_BRPORT_UNICAST_FLOOD] = decode_nla_u8,
151 [IFLA_BRPORT_PROXYARP] = decode_nla_u8,
152 [IFLA_BRPORT_LEARNING_SYNC] = decode_nla_u8,
153 [IFLA_BRPORT_PROXYARP_WIFI] = decode_nla_u8,
154 [IFLA_BRPORT_ROOT_ID] = decode_ifla_bridge_id,
155 [IFLA_BRPORT_BRIDGE_ID] = decode_ifla_bridge_id,
156 [IFLA_BRPORT_DESIGNATED_PORT] = decode_nla_u16,
157 [IFLA_BRPORT_DESIGNATED_COST] = decode_nla_u16,
158 [IFLA_BRPORT_ID] = decode_nla_u16,
159 [IFLA_BRPORT_NO] = decode_nla_u16,
160 [IFLA_BRPORT_TOPOLOGY_CHANGE_ACK] = decode_nla_u8,
161 [IFLA_BRPORT_CONFIG_PENDING] = decode_nla_u8,
162 [IFLA_BRPORT_MESSAGE_AGE_TIMER] = decode_nla_u64,
163 [IFLA_BRPORT_FORWARD_DELAY_TIMER] = decode_nla_u64,
164 [IFLA_BRPORT_HOLD_TIMER] = decode_nla_u64,
165 [IFLA_BRPORT_FLUSH] = NULL,
166 [IFLA_BRPORT_MULTICAST_ROUTER] = decode_nla_u8,
167 [IFLA_BRPORT_PAD] = NULL,
168 [IFLA_BRPORT_MCAST_FLOOD] = decode_nla_u8,
169 [IFLA_BRPORT_MCAST_TO_UCAST] = decode_nla_u8,
170 [IFLA_BRPORT_VLAN_TUNNEL] = decode_nla_u8,
171 [IFLA_BRPORT_BCAST_FLOOD] = decode_nla_u8,
172 [IFLA_BRPORT_GROUP_FWD_MASK] = decode_nla_u16,
173 [IFLA_BRPORT_NEIGH_SUPPRESS] = decode_nla_u8,
174 [IFLA_BRPORT_ISOLATED] = decode_nla_u8,
175 [IFLA_BRPORT_BACKUP_PORT] = decode_nla_ifindex,
176 };
177
178 static bool
decode_ifla_protinfo(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)179 decode_ifla_protinfo(struct tcb *const tcp,
180 const kernel_ulong_t addr,
181 const unsigned int len,
182 const void *const opaque_data)
183 {
184 decode_nlattr(tcp, addr, len, rtnl_ifla_brport_attrs,
185 "IFLA_BRPORT_???",
186 ARRSZ_PAIR(ifla_brport_nla_decoders), opaque_data);
187
188 return true;
189 }
190
191 static bool
decode_rtnl_link_ifmap(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)192 decode_rtnl_link_ifmap(struct tcb *const tcp,
193 const kernel_ulong_t addr,
194 const unsigned int len,
195 const void *const opaque_data)
196 {
197 struct rtnl_link_ifmap map;
198 const unsigned int sizeof_ifmap =
199 offsetofend(struct rtnl_link_ifmap, port);
200
201 if (len < sizeof_ifmap)
202 return false;
203 else if (!umoven_or_printaddr(tcp, addr, sizeof_ifmap, &map)) {
204 PRINT_FIELD_X("{", map, mem_start);
205 PRINT_FIELD_X(", ", map, mem_end);
206 PRINT_FIELD_X(", ", map, base_addr);
207 PRINT_FIELD_U(", ", map, irq);
208 PRINT_FIELD_U(", ", map, dma);
209 PRINT_FIELD_U(", ", map, port);
210 tprints("}");
211 }
212
213 return true;
214 }
215
216 bool
decode_nla_linkinfo_kind(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)217 decode_nla_linkinfo_kind(struct tcb *const tcp,
218 const kernel_ulong_t addr,
219 const unsigned int len,
220 const void *const opaque_data)
221 {
222 struct ifla_linkinfo_ctx *ctx = (void *) opaque_data;
223
224 memset(ctx->kind, '\0', sizeof(ctx->kind));
225
226 if (umovestr(tcp, addr, sizeof(ctx->kind), ctx->kind) <= 0) {
227 /*
228 * If we haven't seen NUL or an error occurred, set kind to
229 * an empty string.
230 */
231 ctx->kind[0] = '\0';
232 }
233
234 printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
235
236 return true;
237 }
238
239 bool
decode_nla_linkinfo_xstats_can(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)240 decode_nla_linkinfo_xstats_can(struct tcb *const tcp,
241 const kernel_ulong_t addr,
242 const unsigned int len,
243 const void *const opaque_data)
244 {
245 struct strace_can_device_stats {
246 uint32_t bus_error;
247 uint32_t error_warning;
248 uint32_t error_passive;
249 uint32_t bus_off;
250 uint32_t arbitration_lost;
251 uint32_t restarts;
252 } st;
253 const unsigned int def_size = sizeof(st);
254 const unsigned int size = (len >= def_size) ? def_size : 0;
255
256 if (!size)
257 return false;
258
259 if (umoven_or_printaddr(tcp, addr, size, &st))
260 return true;
261
262 PRINT_FIELD_U("{", st, bus_error);
263 PRINT_FIELD_U(", ", st, error_warning);
264 PRINT_FIELD_U(", ", st, error_passive);
265 PRINT_FIELD_U(", ", st, bus_off);
266 PRINT_FIELD_U(", ", st, arbitration_lost);
267 PRINT_FIELD_U(", ", st, restarts);
268 tprints("}");
269
270 return true;
271 }
272
273 bool
decode_nla_linkinfo_xstats(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)274 decode_nla_linkinfo_xstats(struct tcb *const tcp,
275 const kernel_ulong_t addr,
276 const unsigned int len,
277 const void *const opaque_data)
278 {
279 struct ifla_linkinfo_ctx *ctx = (void *) opaque_data;
280 nla_decoder_t func = NULL;
281
282 if (!strcmp(ctx->kind, "can"))
283 func = decode_nla_linkinfo_xstats_can;
284
285 if (func)
286 return func(tcp, addr, len, opaque_data);
287
288 return false;
289 }
290
291 static const nla_decoder_t ifla_info_data_bridge_nla_decoders[] = {
292 [IFLA_BR_UNSPEC] = NULL,
293 [IFLA_BR_FORWARD_DELAY] = decode_nla_u32,
294 [IFLA_BR_HELLO_TIME] = decode_nla_u32,
295 [IFLA_BR_MAX_AGE] = decode_nla_u32,
296 [IFLA_BR_AGEING_TIME] = decode_nla_u32,
297 [IFLA_BR_STP_STATE] = decode_nla_u32,
298 [IFLA_BR_PRIORITY] = decode_nla_u16,
299 [IFLA_BR_VLAN_FILTERING] = decode_nla_u8,
300 [IFLA_BR_VLAN_PROTOCOL] = decode_nla_ether_proto,
301 [IFLA_BR_GROUP_FWD_MASK] = decode_nla_x16,
302 [IFLA_BR_ROOT_ID] = decode_ifla_bridge_id,
303 [IFLA_BR_BRIDGE_ID] = decode_ifla_bridge_id,
304 [IFLA_BR_ROOT_PORT] = decode_nla_u16,
305 [IFLA_BR_ROOT_PATH_COST] = decode_nla_u32,
306 [IFLA_BR_TOPOLOGY_CHANGE] = decode_nla_u8,
307 [IFLA_BR_TOPOLOGY_CHANGE_DETECTED] = decode_nla_u8,
308 [IFLA_BR_HELLO_TIMER] = decode_nla_u64,
309 [IFLA_BR_TCN_TIMER] = decode_nla_u64,
310 [IFLA_BR_TOPOLOGY_CHANGE_TIMER] = decode_nla_u64,
311 [IFLA_BR_GC_TIMER] = decode_nla_u64,
312 [IFLA_BR_GROUP_ADDR] = NULL, /* MAC address */
313 [IFLA_BR_FDB_FLUSH] = NULL, /* unspecified */
314 [IFLA_BR_MCAST_ROUTER] = decode_nla_u8,
315 [IFLA_BR_MCAST_SNOOPING] = decode_nla_u8,
316 [IFLA_BR_MCAST_QUERY_USE_IFADDR] = decode_nla_u8,
317 [IFLA_BR_MCAST_QUERIER] = decode_nla_u8,
318 [IFLA_BR_MCAST_HASH_ELASTICITY] = decode_nla_u32,
319 [IFLA_BR_MCAST_HASH_MAX] = decode_nla_u32,
320 [IFLA_BR_MCAST_LAST_MEMBER_CNT] = decode_nla_u32,
321 [IFLA_BR_MCAST_STARTUP_QUERY_CNT] = decode_nla_u32,
322 [IFLA_BR_MCAST_LAST_MEMBER_INTVL] = decode_nla_u64,
323 [IFLA_BR_MCAST_MEMBERSHIP_INTVL] = decode_nla_u64,
324 [IFLA_BR_MCAST_QUERIER_INTVL] = decode_nla_u64,
325 [IFLA_BR_MCAST_QUERY_INTVL] = decode_nla_u64,
326 [IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = decode_nla_u64,
327 [IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = decode_nla_u64,
328 [IFLA_BR_NF_CALL_IPTABLES] = decode_nla_u8,
329 [IFLA_BR_NF_CALL_IP6TABLES] = decode_nla_u8,
330 [IFLA_BR_NF_CALL_ARPTABLES] = decode_nla_u8,
331 [IFLA_BR_VLAN_DEFAULT_PVID] = decode_nla_u16,
332 [IFLA_BR_PAD] = NULL,
333 [IFLA_BR_VLAN_STATS_ENABLED] = decode_nla_u8,
334 [IFLA_BR_MCAST_STATS_ENABLED] = decode_nla_u8,
335 [IFLA_BR_MCAST_IGMP_VERSION] = decode_nla_u8,
336 [IFLA_BR_MCAST_MLD_VERSION] = decode_nla_u8,
337 };
338
339 bool
decode_nla_linkinfo_data_bridge(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)340 decode_nla_linkinfo_data_bridge(struct tcb *const tcp,
341 const kernel_ulong_t addr,
342 const unsigned int len,
343 const void *const opaque_data)
344 {
345 decode_nlattr(tcp, addr, len, rtnl_ifla_info_data_bridge_attrs,
346 "IFLA_BR_???",
347 ARRSZ_PAIR(ifla_info_data_bridge_nla_decoders),
348 opaque_data);
349
350 return true;
351 }
352
353 static bool
decode_nla_tun_type(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)354 decode_nla_tun_type(struct tcb *const tcp,
355 const kernel_ulong_t addr,
356 const unsigned int len,
357 const void *const opaque_data)
358 {
359 const struct decode_nla_xlat_opts opts = {
360 .xlat = tun_device_types,
361 .xlat_size = ARRAY_SIZE(tun_device_types),
362 .xt = XT_INDEXED,
363 .dflt = "IFF_???",
364 .size = 1,
365 };
366
367 return decode_nla_xval(tcp, addr, len, &opts);
368 }
369
370 static const nla_decoder_t ifla_info_data_tun_nla_decoders[] = {
371 [IFLA_TUN_UNSPEC] = NULL,
372 [IFLA_TUN_OWNER] = decode_nla_uid,
373 [IFLA_TUN_GROUP] = decode_nla_gid,
374 [IFLA_TUN_TYPE] = decode_nla_tun_type,
375 [IFLA_TUN_PI] = decode_nla_u8,
376 [IFLA_TUN_VNET_HDR] = decode_nla_u8,
377 [IFLA_TUN_PERSIST] = decode_nla_u8,
378 [IFLA_TUN_MULTI_QUEUE] = decode_nla_u8,
379 [IFLA_TUN_NUM_QUEUES] = decode_nla_u32,
380 [IFLA_TUN_NUM_DISABLED_QUEUES] = decode_nla_u32,
381 };
382
383 bool
decode_nla_linkinfo_data_tun(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)384 decode_nla_linkinfo_data_tun(struct tcb *const tcp,
385 const kernel_ulong_t addr,
386 const unsigned int len,
387 const void *const opaque_data)
388 {
389 decode_nlattr(tcp, addr, len, rtnl_ifla_info_data_tun_attrs,
390 "IFLA_TUN_???",
391 ARRSZ_PAIR(ifla_info_data_tun_nla_decoders),
392 opaque_data);
393
394 return true;
395 }
396
397 bool
decode_nla_linkinfo_data(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)398 decode_nla_linkinfo_data(struct tcb *const tcp,
399 const kernel_ulong_t addr,
400 const unsigned int len,
401 const void *const opaque_data)
402 {
403 struct ifla_linkinfo_ctx *ctx = (void *) opaque_data;
404 nla_decoder_t func = NULL;
405
406 if (!strcmp(ctx->kind, "bridge"))
407 func = decode_nla_linkinfo_data_bridge;
408 else if (!strcmp(ctx->kind, "tun"))
409 func = decode_nla_linkinfo_data_tun;
410
411 if (func)
412 return func(tcp, addr, len, opaque_data);
413
414 return false;
415 }
416
417 static const nla_decoder_t ifla_linkinfo_nla_decoders[] = {
418 [IFLA_INFO_KIND] = decode_nla_linkinfo_kind,
419 [IFLA_INFO_DATA] = decode_nla_linkinfo_data,
420 [IFLA_INFO_XSTATS] = decode_nla_linkinfo_xstats,
421 [IFLA_INFO_SLAVE_KIND] = decode_nla_str,
422 [IFLA_INFO_SLAVE_DATA] = NULL, /* unimplemented */
423 };
424
425 static bool
decode_ifla_linkinfo(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)426 decode_ifla_linkinfo(struct tcb *const tcp,
427 const kernel_ulong_t addr,
428 const unsigned int len,
429 const void *const opaque_data)
430 {
431 struct ifla_linkinfo_ctx ctx = { .kind = "", };
432
433 decode_nlattr(tcp, addr, len, rtnl_ifla_info_attrs,
434 "IFLA_INFO_???", ARRSZ_PAIR(ifla_linkinfo_nla_decoders),
435 &ctx);
436
437 return true;
438 }
439
440 static bool
decode_rtnl_link_stats64(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)441 decode_rtnl_link_stats64(struct tcb *const tcp,
442 const kernel_ulong_t addr,
443 const unsigned int len,
444 const void *const opaque_data)
445 {
446 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64
447 struct rtnl_link_stats64 st;
448 const unsigned int min_size =
449 offsetofend(struct rtnl_link_stats64, tx_compressed);
450 const unsigned int def_size = sizeof(st);
451 const unsigned int size =
452 (len >= def_size) ? def_size :
453 ((len == min_size) ? min_size : 0);
454
455 if (!size)
456 return false;
457
458 if (!umoven_or_printaddr(tcp, addr, size, &st)) {
459 PRINT_FIELD_U("{", st, rx_packets);
460 PRINT_FIELD_U(", ", st, tx_packets);
461 PRINT_FIELD_U(", ", st, rx_bytes);
462 PRINT_FIELD_U(", ", st, tx_bytes);
463 PRINT_FIELD_U(", ", st, rx_errors);
464 PRINT_FIELD_U(", ", st, tx_errors);
465 PRINT_FIELD_U(", ", st, rx_dropped);
466 PRINT_FIELD_U(", ", st, tx_dropped);
467 PRINT_FIELD_U(", ", st, multicast);
468 PRINT_FIELD_U(", ", st, collisions);
469
470 PRINT_FIELD_U(", ", st, rx_length_errors);
471 PRINT_FIELD_U(", ", st, rx_over_errors);
472 PRINT_FIELD_U(", ", st, rx_crc_errors);
473 PRINT_FIELD_U(", ", st, rx_frame_errors);
474 PRINT_FIELD_U(", ", st, rx_fifo_errors);
475 PRINT_FIELD_U(", ", st, rx_missed_errors);
476
477 PRINT_FIELD_U(", ", st, tx_aborted_errors);
478 PRINT_FIELD_U(", ", st, tx_carrier_errors);
479 PRINT_FIELD_U(", ", st, tx_fifo_errors);
480 PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
481 PRINT_FIELD_U(", ", st, tx_window_errors);
482
483 PRINT_FIELD_U(", ", st, rx_compressed);
484 PRINT_FIELD_U(", ", st, tx_compressed);
485 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER
486 if (len >= def_size)
487 PRINT_FIELD_U(", ", st, rx_nohandler);
488 #endif
489 tprints("}");
490 }
491
492 return true;
493 #else
494 return false;
495 #endif
496 }
497
498 static bool
decode_ifla_port_vsi(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)499 decode_ifla_port_vsi(struct tcb *const tcp,
500 const kernel_ulong_t addr,
501 const unsigned int len,
502 const void *const opaque_data)
503 {
504 #ifdef HAVE_STRUCT_IFLA_PORT_VSI
505 struct ifla_port_vsi vsi;
506
507 if (len < sizeof(vsi))
508 return false;
509 else if (!umove_or_printaddr(tcp, addr, &vsi)) {
510 PRINT_FIELD_U("{", vsi, vsi_mgr_id);
511 PRINT_FIELD_STRING(", ", vsi, vsi_type_id,
512 sizeof(vsi.vsi_type_id), QUOTE_FORCE_HEX);
513 PRINT_FIELD_U(", ", vsi, vsi_type_version);
514 tprints("}");
515 }
516
517 return true;
518 #else
519 return false;
520 #endif
521 }
522
523 static const nla_decoder_t ifla_port_nla_decoders[] = {
524 [IFLA_PORT_VF] = decode_nla_u32,
525 [IFLA_PORT_PROFILE] = decode_nla_str,
526 [IFLA_PORT_VSI_TYPE] = decode_ifla_port_vsi,
527 [IFLA_PORT_INSTANCE_UUID] = NULL, /* default parser */
528 [IFLA_PORT_HOST_UUID] = NULL, /* default parser */
529 [IFLA_PORT_REQUEST] = decode_nla_u8,
530 [IFLA_PORT_RESPONSE] = decode_nla_u16
531 };
532
533 static bool
decode_ifla_port(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)534 decode_ifla_port(struct tcb *const tcp,
535 const kernel_ulong_t addr,
536 const unsigned int len,
537 const void *const opaque_data)
538 {
539 decode_nlattr(tcp, addr, len, rtnl_ifla_port_attrs,
540 "IFLA_VF_PORT_???", ARRSZ_PAIR(ifla_port_nla_decoders),
541 opaque_data);
542
543 return true;
544 }
545
546 static const nla_decoder_t ifla_vf_port_nla_decoders[] = {
547 [IFLA_VF_PORT] = decode_ifla_port
548 };
549
550 static bool
decode_ifla_vf_ports(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)551 decode_ifla_vf_ports(struct tcb *const tcp,
552 const kernel_ulong_t addr,
553 const unsigned int len,
554 const void *const opaque_data)
555 {
556 decode_nlattr(tcp, addr, len, rtnl_ifla_vf_port_attrs,
557 "IFLA_VF_PORT_???", ARRSZ_PAIR(ifla_vf_port_nla_decoders),
558 opaque_data);
559
560 return true;
561 }
562
563 static bool
decode_ifla_xdp_flags(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)564 decode_ifla_xdp_flags(struct tcb *const tcp,
565 const kernel_ulong_t addr,
566 const unsigned int len,
567 const void *const opaque_data)
568 {
569 uint32_t flags;
570
571 if (len < sizeof(flags))
572 return false;
573 else if (!umove_or_printaddr(tcp, addr, &flags))
574 printflags(xdp_flags, flags, "XDP_FLAGS_???");
575
576 return true;
577 }
578
579 bool
decode_ifla_xdp_attached(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)580 decode_ifla_xdp_attached(struct tcb *const tcp,
581 const kernel_ulong_t addr,
582 const unsigned int len,
583 const void *const opaque_data)
584 {
585 const struct decode_nla_xlat_opts opts = {
586 .xlat = rtnl_ifla_xdp_attached_mode,
587 .xlat_size = ARRAY_SIZE(rtnl_ifla_xdp_attached_mode),
588 .xt = XT_INDEXED,
589 .dflt = "XDP_ATTACHED_???",
590 .size = 1,
591 };
592
593 return decode_nla_xval(tcp, addr, len, &opts);
594 }
595
596 static const nla_decoder_t ifla_xdp_nla_decoders[] = {
597 [IFLA_XDP_FD] = decode_nla_fd,
598 [IFLA_XDP_ATTACHED] = decode_ifla_xdp_attached,
599 [IFLA_XDP_FLAGS] = decode_ifla_xdp_flags,
600 [IFLA_XDP_PROG_ID] = decode_nla_u32,
601 [IFLA_XDP_DRV_PROG_ID] = decode_nla_u32,
602 [IFLA_XDP_SKB_PROG_ID] = decode_nla_u32,
603 [IFLA_XDP_HW_PROG_ID] = decode_nla_u32,
604 };
605
606 static bool
decode_ifla_xdp(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)607 decode_ifla_xdp(struct tcb *const tcp,
608 const kernel_ulong_t addr,
609 const unsigned int len,
610 const void *const opaque_data)
611 {
612 decode_nlattr(tcp, addr, len, rtnl_ifla_xdp_attrs,
613 "IFLA_XDP_???", ARRSZ_PAIR(ifla_xdp_nla_decoders),
614 opaque_data);
615
616 return true;
617 }
618
619 static bool
decode_ifla_event(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)620 decode_ifla_event(struct tcb *const tcp,
621 const kernel_ulong_t addr,
622 const unsigned int len,
623 const void *const opaque_data)
624 {
625 uint32_t ev;
626
627 if (len < sizeof(ev))
628 return false;
629 else if (!umove_or_printaddr(tcp, addr, &ev))
630 printxval(rtnl_ifla_events, ev, "IFLA_EVENT_???");
631
632 return true;
633 }
634
635
636 static bool
decode_ifla_inet_conf(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)637 decode_ifla_inet_conf(struct tcb *const tcp,
638 const kernel_ulong_t addr,
639 const unsigned int len,
640 const void *const opaque_data)
641 {
642 int elem;
643 size_t cnt = len / sizeof(elem);
644
645 if (!cnt)
646 return false;
647
648 print_array_ex(tcp, addr, cnt, &elem, sizeof(elem),
649 tfetch_mem, print_int32_array_member, NULL,
650 PAF_PRINT_INDICES | PAF_INDEX_XLAT_VALUE_INDEXED
651 | XLAT_STYLE_FMT_D, ARRSZ_PAIR(inet_devconf_indices),
652 "IPV4_DEVCONF_???");
653
654 return true;
655 }
656
657 static const nla_decoder_t ifla_inet_nla_decoders[] = {
658 [IFLA_INET_CONF] = decode_ifla_inet_conf,
659 };
660
661 static bool
decode_ifla_inet6_flags(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)662 decode_ifla_inet6_flags(struct tcb *const tcp,
663 const kernel_ulong_t addr,
664 const unsigned int len,
665 const void *const opaque_data)
666 {
667 const struct decode_nla_xlat_opts opts = {
668 ARRSZ_PAIR(inet6_if_flags), "IF_???",
669 .size = 4,
670 };
671
672 return decode_nla_flags(tcp, addr, len, &opts);
673 }
674
675 static bool
decode_ifla_inet6_conf(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)676 decode_ifla_inet6_conf(struct tcb *const tcp,
677 const kernel_ulong_t addr,
678 const unsigned int len,
679 const void *const opaque_data)
680 {
681 int elem;
682 size_t cnt = len / sizeof(elem);
683
684 if (!cnt)
685 return false;
686
687 print_array_ex(tcp, addr, cnt, &elem, sizeof(elem),
688 tfetch_mem, print_int32_array_member, NULL,
689 PAF_PRINT_INDICES | PAF_INDEX_XLAT_VALUE_INDEXED
690 | XLAT_STYLE_FMT_D, ARRSZ_PAIR(inet6_devconf_indices),
691 "DEVCONF_???");
692
693 return true;
694 }
695
696 static bool
decode_ifla_inet6_stats(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)697 decode_ifla_inet6_stats(struct tcb *const tcp,
698 const kernel_ulong_t addr,
699 const unsigned int len,
700 const void *const opaque_data)
701 {
702 uint64_t elem;
703 size_t cnt = len / sizeof(elem);
704
705 if (!cnt)
706 return false;
707
708 print_array_ex(tcp, addr, cnt, &elem, sizeof(elem),
709 tfetch_mem, print_uint64_array_member, NULL,
710 PAF_PRINT_INDICES | PAF_INDEX_XLAT_VALUE_INDEXED
711 | XLAT_STYLE_FMT_U, ARRSZ_PAIR(snmp_ip_stats),
712 "IPSTATS_MIB_???");
713
714 return true;
715 }
716
717 static bool
decode_ifla_inet6_cacheinfo(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)718 decode_ifla_inet6_cacheinfo(struct tcb *const tcp,
719 const kernel_ulong_t addr,
720 const unsigned int len,
721 const void *const opaque_data)
722 {
723 struct {
724 uint32_t max_reasm_len;
725 uint32_t tstamp;
726 uint32_t reachable_time;
727 uint32_t retrans_time;
728 } ci;
729
730 if (len < sizeof(ci))
731 return false;
732 else if (!umove_or_printaddr(tcp, addr, &ci)) {
733 PRINT_FIELD_U("{", ci, max_reasm_len);
734 PRINT_FIELD_U(", ", ci, tstamp);
735 PRINT_FIELD_U(", ", ci, reachable_time);
736 PRINT_FIELD_U(", ", ci, retrans_time);
737 tprints("}");
738 }
739
740 return true;
741 }
742
743 static bool
decode_ifla_inet6_icmp6_stats(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)744 decode_ifla_inet6_icmp6_stats(struct tcb *const tcp,
745 const kernel_ulong_t addr,
746 const unsigned int len,
747 const void *const opaque_data)
748 {
749 uint64_t elem;
750 size_t cnt = len / sizeof(elem);
751
752 if (!cnt)
753 return false;
754
755 print_array_ex(tcp, addr, cnt, &elem, sizeof(elem),
756 tfetch_mem, print_uint64_array_member, NULL,
757 PAF_PRINT_INDICES | PAF_INDEX_XLAT_VALUE_INDEXED
758 | XLAT_STYLE_FMT_U, ARRSZ_PAIR(snmp_icmp6_stats),
759 "ICMP6_MIB_???");
760
761 return true;
762 }
763
764 static bool
decode_ifla_inet6_agm(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)765 decode_ifla_inet6_agm(struct tcb *const tcp,
766 const kernel_ulong_t addr,
767 const unsigned int len,
768 const void *const opaque_data)
769 {
770 const struct decode_nla_xlat_opts opts = {
771 ARRSZ_PAIR(in6_addr_gen_mode), "IN6_ADDR_GEN_MODE_???",
772 .xt = XT_INDEXED,
773 .size = 1,
774 };
775
776 return decode_nla_xval(tcp, addr, len, &opts);
777 }
778
779 static const nla_decoder_t ifla_inet6_nla_decoders[] = {
780 [IFLA_INET6_FLAGS] = decode_ifla_inet6_flags,
781 [IFLA_INET6_CONF] = decode_ifla_inet6_conf,
782 [IFLA_INET6_STATS] = decode_ifla_inet6_stats,
783 [IFLA_INET6_MCAST] = NULL, /* unused */
784 [IFLA_INET6_CACHEINFO] = decode_ifla_inet6_cacheinfo,
785 [IFLA_INET6_ICMP6STATS] = decode_ifla_inet6_icmp6_stats,
786 [IFLA_INET6_TOKEN] = decode_nla_in6_addr,
787 [IFLA_INET6_ADDR_GEN_MODE] = decode_ifla_inet6_agm,
788 };
789
790 static const struct nla_decoder_table_desc {
791 const struct xlat *xlat;
792 const char *dflt;
793 const nla_decoder_t *table;
794 size_t size;
795 } ifla_af_spec_protos[] = {
796 [AF_INET] = {
797 rtnl_ifla_af_spec_inet_attrs, "IFLA_INET_???",
798 ARRSZ_PAIR(ifla_inet_nla_decoders),
799 },
800 [AF_INET6] = {
801 rtnl_ifla_af_spec_inet6_attrs, "IFLA_INET6_???",
802 ARRSZ_PAIR(ifla_inet6_nla_decoders),
803 },
804 };
805
806 static bool
decode_ifla_af(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)807 decode_ifla_af(struct tcb *const tcp,
808 const kernel_ulong_t addr,
809 const unsigned int len,
810 const void *const opaque_data)
811 {
812 uintptr_t proto = (uintptr_t) opaque_data;
813 const struct nla_decoder_table_desc *desc
814 = proto < ARRAY_SIZE(ifla_af_spec_protos)
815 ? ifla_af_spec_protos + proto : NULL;
816
817 if (!desc || !desc->table)
818 return false;
819
820 decode_nlattr(tcp, addr, len,
821 desc->xlat, desc->dflt, desc->table, desc->size, NULL);
822
823 return true;
824 }
825
826 static bool
decode_ifla_af_spec(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)827 decode_ifla_af_spec(struct tcb *const tcp,
828 const kernel_ulong_t addr,
829 const unsigned int len,
830 const void *const opaque_data)
831 {
832 nla_decoder_t af_spec_decoder = &decode_ifla_af;
833
834 decode_nlattr(tcp, addr, len, addrfams, "AF_???",
835 &af_spec_decoder, 0, opaque_data);
836
837 return true;
838 }
839
840 static const nla_decoder_t ifinfomsg_nla_decoders[] = {
841 [IFLA_ADDRESS] = NULL, /* unimplemented */
842 [IFLA_BROADCAST] = NULL, /* unimplemented */
843 [IFLA_IFNAME] = decode_nla_str,
844 [IFLA_MTU] = decode_nla_u32,
845 [IFLA_LINK] = decode_nla_u32,
846 [IFLA_QDISC] = decode_nla_str,
847 [IFLA_STATS] = decode_rtnl_link_stats,
848 [IFLA_COST] = NULL, /* unused */
849 [IFLA_PRIORITY] = NULL, /* unused */
850 [IFLA_MASTER] = decode_nla_u32,
851 [IFLA_WIRELESS] = NULL, /* unimplemented */
852 [IFLA_PROTINFO] = decode_ifla_protinfo,
853 [IFLA_TXQLEN] = decode_nla_u32,
854 [IFLA_MAP] = decode_rtnl_link_ifmap,
855 [IFLA_WEIGHT] = decode_nla_u32,
856 [IFLA_OPERSTATE] = decode_nla_u8,
857 [IFLA_LINKMODE] = decode_nla_u8,
858 [IFLA_LINKINFO] = decode_ifla_linkinfo,
859 [IFLA_NET_NS_PID] = decode_nla_u32,
860 [IFLA_IFALIAS] = decode_nla_str,
861 [IFLA_NUM_VF] = decode_nla_u32,
862 [IFLA_VFINFO_LIST] = NULL, /* unimplemented */
863 [IFLA_STATS64] = decode_rtnl_link_stats64,
864 [IFLA_VF_PORTS] = decode_ifla_vf_ports,
865 [IFLA_PORT_SELF] = decode_ifla_port,
866 [IFLA_AF_SPEC] = decode_ifla_af_spec,
867 [IFLA_GROUP] = decode_nla_u32,
868 [IFLA_NET_NS_FD] = decode_nla_fd,
869 [IFLA_EXT_MASK] = decode_nla_u32,
870 [IFLA_PROMISCUITY] = decode_nla_u32,
871 [IFLA_NUM_TX_QUEUES] = decode_nla_u32,
872 [IFLA_NUM_RX_QUEUES] = decode_nla_u32,
873 [IFLA_CARRIER] = decode_nla_u8,
874 [IFLA_PHYS_PORT_ID] = NULL, /* default parser */
875 [IFLA_CARRIER_CHANGES] = decode_nla_u32,
876 [IFLA_PHYS_SWITCH_ID] = NULL, /* default parser */
877 [IFLA_LINK_NETNSID] = decode_nla_s32,
878 [IFLA_PHYS_PORT_NAME] = decode_nla_str,
879 [IFLA_PROTO_DOWN] = decode_nla_u8,
880 [IFLA_GSO_MAX_SEGS] = decode_nla_u32,
881 [IFLA_GSO_MAX_SIZE] = decode_nla_u32,
882 [IFLA_PAD] = NULL,
883 [IFLA_XDP] = decode_ifla_xdp,
884 [IFLA_EVENT] = decode_ifla_event,
885 [IFLA_NEW_NETNSID] = decode_nla_s32,
886 [IFLA_IF_NETNSID] = decode_nla_s32,
887 [IFLA_CARRIER_UP_COUNT] = decode_nla_u32,
888 [IFLA_CARRIER_DOWN_COUNT] = decode_nla_u32,
889 [IFLA_NEW_IFINDEX] = decode_nla_ifindex,
890 [IFLA_MIN_MTU] = decode_nla_u32,
891 [IFLA_MAX_MTU] = decode_nla_u32,
892 };
893
DECL_NETLINK_ROUTE_DECODER(decode_ifinfomsg)894 DECL_NETLINK_ROUTE_DECODER(decode_ifinfomsg)
895 {
896 struct ifinfomsg ifinfo = { .ifi_family = family };
897 size_t offset = sizeof(ifinfo.ifi_family);
898 bool decode_nla = false;
899
900 PRINT_FIELD_XVAL("{", ifinfo, ifi_family, addrfams, "AF_???");
901
902 tprints(", ");
903 if (len >= sizeof(ifinfo)) {
904 if (!umoven_or_printaddr(tcp, addr + offset,
905 sizeof(ifinfo) - offset,
906 (char *) &ifinfo + offset)) {
907 PRINT_FIELD_XVAL_SORTED_SIZED("", ifinfo, ifi_type,
908 arp_hardware_types,
909 arp_hardware_types_size,
910 "ARPHRD_???");
911 PRINT_FIELD_IFINDEX(", ", ifinfo, ifi_index);
912 PRINT_FIELD_FLAGS(", ", ifinfo, ifi_flags,
913 iffflags, "IFF_???");
914 PRINT_FIELD_X(", ", ifinfo, ifi_change);
915 decode_nla = true;
916 }
917 } else
918 tprints("...");
919 tprints("}");
920
921 offset = NLMSG_ALIGN(sizeof(ifinfo));
922 if (decode_nla && len > offset) {
923 tprints(", ");
924 decode_nlattr(tcp, addr + offset, len - offset,
925 rtnl_link_attrs, "IFLA_???",
926 ARRSZ_PAIR(ifinfomsg_nla_decoders), NULL);
927 }
928 }
929