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