• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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