]> granicus.if.org Git - strace/blob - rtnl_link.c
netlink_smc_diag: add SMC_DIAG_FALLBACK attribute support
[strace] / rtnl_link.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
765 decode_ifla_inet6_token(struct tcb *const tcp,
766                         const kernel_ulong_t addr,
767                         const unsigned int len,
768                         const void *const opaque_data)
769 {
770         struct in6_addr in6;
771
772         if (len < sizeof(in6))
773                 return false;
774         else if (!umove_or_printaddr(tcp, addr, &in6))
775                 print_inet_addr(AF_INET6, &in6, sizeof(in6), NULL);
776
777         return true;
778 }
779
780 static bool
781 decode_ifla_inet6_agm(struct tcb *const tcp,
782                       const kernel_ulong_t addr,
783                       const unsigned int len,
784                       const void *const opaque_data)
785 {
786         const struct decode_nla_xlat_opts opts = {
787                 ARRSZ_PAIR(in6_addr_gen_mode), "IN6_ADDR_GEN_MODE_???",
788                 .xt = XT_INDEXED,
789                 .size = 1,
790         };
791
792         return decode_nla_xval(tcp, addr, len, &opts);
793 }
794
795 static const nla_decoder_t ifla_inet6_nla_decoders[] = {
796         [IFLA_INET6_FLAGS]              = decode_ifla_inet6_flags,
797         [IFLA_INET6_CONF]               = decode_ifla_inet6_conf,
798         [IFLA_INET6_STATS]              = decode_ifla_inet6_stats,
799         [IFLA_INET6_MCAST]              = NULL, /* unused */
800         [IFLA_INET6_CACHEINFO]          = decode_ifla_inet6_cacheinfo,
801         [IFLA_INET6_ICMP6STATS]         = decode_ifla_inet6_icmp6_stats,
802         [IFLA_INET6_TOKEN]              = decode_ifla_inet6_token,
803         [IFLA_INET6_ADDR_GEN_MODE]      = decode_ifla_inet6_agm,
804 };
805
806 static const struct nla_decoder_table_desc {
807         const struct xlat *xlat;
808         const char *dflt;
809         const nla_decoder_t *table;
810         size_t size;
811 } ifla_af_spec_protos[] = {
812         [AF_INET]       = {
813                 rtnl_ifla_af_spec_inet_attrs, "IFLA_INET_???",
814                 ARRSZ_PAIR(ifla_inet_nla_decoders),
815         },
816         [AF_INET6]      = {
817                 rtnl_ifla_af_spec_inet6_attrs, "IFLA_INET6_???",
818                 ARRSZ_PAIR(ifla_inet6_nla_decoders),
819         },
820 };
821
822 static bool
823 decode_ifla_af(struct tcb *const tcp,
824                const kernel_ulong_t addr,
825                const unsigned int len,
826                const void *const opaque_data)
827 {
828         uintptr_t proto = (uintptr_t) opaque_data;
829         const struct nla_decoder_table_desc *desc
830                 = proto < ARRAY_SIZE(ifla_af_spec_protos)
831                         ? ifla_af_spec_protos + proto : NULL;
832
833         if (!desc || !desc->table)
834                 return false;
835
836         decode_nlattr(tcp, addr, len,
837                       desc->xlat, desc->dflt, desc->table, desc->size, NULL);
838
839         return true;
840 }
841
842 static bool
843 decode_ifla_af_spec(struct tcb *const tcp,
844                     const kernel_ulong_t addr,
845                     const unsigned int len,
846                     const void *const opaque_data)
847 {
848         nla_decoder_t af_spec_decoder = &decode_ifla_af;
849
850         decode_nlattr(tcp, addr, len, addrfams, "AF_???",
851                       &af_spec_decoder, 0, opaque_data);
852
853         return true;
854 }
855
856 static const nla_decoder_t ifinfomsg_nla_decoders[] = {
857         [IFLA_ADDRESS]          = NULL, /* unimplemented */
858         [IFLA_BROADCAST]        = NULL, /* unimplemented */
859         [IFLA_IFNAME]           = decode_nla_str,
860         [IFLA_MTU]              = decode_nla_u32,
861         [IFLA_LINK]             = decode_nla_u32,
862         [IFLA_QDISC]            = decode_nla_str,
863         [IFLA_STATS]            = decode_rtnl_link_stats,
864         [IFLA_COST]             = NULL, /* unused */
865         [IFLA_PRIORITY]         = NULL, /* unused */
866         [IFLA_MASTER]           = decode_nla_u32,
867         [IFLA_WIRELESS]         = NULL, /* unimplemented */
868         [IFLA_PROTINFO]         = decode_ifla_protinfo,
869         [IFLA_TXQLEN]           = decode_nla_u32,
870         [IFLA_MAP]              = decode_rtnl_link_ifmap,
871         [IFLA_WEIGHT]           = decode_nla_u32,
872         [IFLA_OPERSTATE]        = decode_nla_u8,
873         [IFLA_LINKMODE]         = decode_nla_u8,
874         [IFLA_LINKINFO]         = decode_ifla_linkinfo,
875         [IFLA_NET_NS_PID]       = decode_nla_u32,
876         [IFLA_IFALIAS]          = decode_nla_str,
877         [IFLA_NUM_VF]           = decode_nla_u32,
878         [IFLA_VFINFO_LIST]      = NULL, /* unimplemented */
879         [IFLA_STATS64]          = decode_rtnl_link_stats64,
880         [IFLA_VF_PORTS]         = decode_ifla_vf_ports,
881         [IFLA_PORT_SELF]        = decode_ifla_port,
882         [IFLA_AF_SPEC]          = decode_ifla_af_spec,
883         [IFLA_GROUP]            = decode_nla_u32,
884         [IFLA_NET_NS_FD]        = decode_nla_fd,
885         [IFLA_EXT_MASK]         = decode_nla_u32,
886         [IFLA_PROMISCUITY]      = decode_nla_u32,
887         [IFLA_NUM_TX_QUEUES]    = decode_nla_u32,
888         [IFLA_NUM_RX_QUEUES]    = decode_nla_u32,
889         [IFLA_CARRIER]          = decode_nla_u8,
890         [IFLA_PHYS_PORT_ID]     = NULL, /* default parser */
891         [IFLA_CARRIER_CHANGES]  = decode_nla_u32,
892         [IFLA_PHYS_SWITCH_ID]   = NULL, /* default parser */
893         [IFLA_LINK_NETNSID]     = decode_nla_s32,
894         [IFLA_PHYS_PORT_NAME]   = decode_nla_str,
895         [IFLA_PROTO_DOWN]       = decode_nla_u8,
896         [IFLA_GSO_MAX_SEGS]     = decode_nla_u32,
897         [IFLA_GSO_MAX_SIZE]     = decode_nla_u32,
898         [IFLA_PAD]              = NULL,
899         [IFLA_XDP]              = decode_ifla_xdp,
900         [IFLA_EVENT]            = decode_ifla_event,
901         [IFLA_NEW_NETNSID]      = decode_nla_s32,
902         [IFLA_IF_NETNSID]       = decode_nla_s32,
903         [IFLA_CARRIER_UP_COUNT] = decode_nla_u32,
904         [IFLA_CARRIER_DOWN_COUNT]       = decode_nla_u32,
905         [IFLA_NEW_IFINDEX]      = decode_nla_ifindex,
906 };
907
908 DECL_NETLINK_ROUTE_DECODER(decode_ifinfomsg)
909 {
910         struct ifinfomsg ifinfo = { .ifi_family = family };
911         size_t offset = sizeof(ifinfo.ifi_family);
912         bool decode_nla = false;
913
914         PRINT_FIELD_XVAL("{", ifinfo, ifi_family, addrfams, "AF_???");
915
916         tprints(", ");
917         if (len >= sizeof(ifinfo)) {
918                 if (!umoven_or_printaddr(tcp, addr + offset,
919                                          sizeof(ifinfo) - offset,
920                                          (char *) &ifinfo + offset)) {
921                         PRINT_FIELD_XVAL_SORTED_SIZED("", ifinfo, ifi_type,
922                                                       arp_hardware_types,
923                                                       arp_hardware_types_size,
924                                                       "ARPHRD_???");
925                         PRINT_FIELD_IFINDEX(", ", ifinfo, ifi_index);
926                         PRINT_FIELD_FLAGS(", ", ifinfo, ifi_flags,
927                                           iffflags, "IFF_???");
928                         PRINT_FIELD_X(", ", ifinfo, ifi_change);
929                         decode_nla = true;
930                 }
931         } else
932                 tprints("...");
933         tprints("}");
934
935         offset = NLMSG_ALIGN(sizeof(ifinfo));
936         if (decode_nla && len > offset) {
937                 tprints(", ");
938                 decode_nlattr(tcp, addr + offset, len - offset,
939                               rtnl_link_attrs, "IFLA_???",
940                               ARRSZ_PAIR(ifinfomsg_nla_decoders), NULL);
941         }
942 }