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