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.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
31 #include "netlink_route.h"
33 #include "print_fields.h"
36 #ifdef HAVE_LINUX_IF_LINK_H
37 # include <linux/if_link.h>
39 #include <linux/rtnetlink.h>
41 #include "xlat/rtnl_ifla_brport_attrs.h"
42 #include "xlat/rtnl_ifla_events.h"
43 #include "xlat/rtnl_ifla_info_attrs.h"
44 #include "xlat/rtnl_ifla_port_attrs.h"
45 #include "xlat/rtnl_ifla_vf_port_attrs.h"
46 #include "xlat/rtnl_ifla_xdp_attrs.h"
47 #include "xlat/rtnl_link_attrs.h"
48 #include "xlat/xdp_flags.h"
51 decode_rtnl_link_stats(struct tcb *const tcp,
52 const kernel_ulong_t addr,
53 const unsigned int len,
54 const void *const opaque_data)
56 struct rtnl_link_stats st;
57 const unsigned int min_size =
58 offsetofend(struct rtnl_link_stats, tx_compressed);
59 const unsigned int def_size = sizeof(st);
60 const unsigned int size =
61 (len >= def_size) ? def_size :
62 ((len == min_size) ? min_size : 0);
67 if (!umoven_or_printaddr(tcp, addr, size, &st)) {
68 PRINT_FIELD_U("{", st, rx_packets);
69 PRINT_FIELD_U(", ", st, tx_packets);
70 PRINT_FIELD_U(", ", st, rx_bytes);
71 PRINT_FIELD_U(", ", st, tx_bytes);
72 PRINT_FIELD_U(", ", st, rx_errors);
73 PRINT_FIELD_U(", ", st, tx_errors);
74 PRINT_FIELD_U(", ", st, rx_dropped);
75 PRINT_FIELD_U(", ", st, tx_dropped);
76 PRINT_FIELD_U(", ", st, multicast);
77 PRINT_FIELD_U(", ", st, collisions);
79 PRINT_FIELD_U(", ", st, rx_length_errors);
80 PRINT_FIELD_U(", ", st, rx_over_errors);
81 PRINT_FIELD_U(", ", st, rx_crc_errors);
82 PRINT_FIELD_U(", ", st, rx_frame_errors);
83 PRINT_FIELD_U(", ", st, rx_fifo_errors);
84 PRINT_FIELD_U(", ", st, rx_missed_errors);
86 PRINT_FIELD_U(", ", st, tx_aborted_errors);
87 PRINT_FIELD_U(", ", st, tx_carrier_errors);
88 PRINT_FIELD_U(", ", st, tx_fifo_errors);
89 PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
90 PRINT_FIELD_U(", ", st, tx_window_errors);
92 PRINT_FIELD_U(", ", st, rx_compressed);
93 PRINT_FIELD_U(", ", st, tx_compressed);
94 #ifdef HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER
96 PRINT_FIELD_U(", ", st, rx_nohandler);
105 decode_ifla_bridge_id(struct tcb *const tcp,
106 const kernel_ulong_t addr,
107 const unsigned int len,
108 const void *const opaque_data)
110 #ifdef HAVE_STRUCT_IFLA_BRIDGE_ID
111 struct ifla_bridge_id id;
113 if (len < sizeof(id))
115 else if (!umove_or_printaddr(tcp, addr, &id)) {
116 tprintf("{prio=[%u, %u], addr=%02x:%02x:%02x:%02x:%02x:%02x}",
117 id.prio[0], id.prio[1],
118 id.addr[0], id.addr[1], id.addr[2],
119 id.addr[3], id.addr[4], id.addr[5]);
128 static const nla_decoder_t ifla_brport_nla_decoders[] = {
129 [IFLA_BRPORT_STATE] = decode_nla_u8,
130 [IFLA_BRPORT_PRIORITY] = decode_nla_u16,
131 [IFLA_BRPORT_COST] = decode_nla_u32,
132 [IFLA_BRPORT_MODE] = decode_nla_u8,
133 [IFLA_BRPORT_GUARD] = decode_nla_u8,
134 [IFLA_BRPORT_PROTECT] = decode_nla_u8,
135 [IFLA_BRPORT_FAST_LEAVE] = decode_nla_u8,
136 [IFLA_BRPORT_LEARNING] = decode_nla_u8,
137 [IFLA_BRPORT_UNICAST_FLOOD] = decode_nla_u8,
138 [IFLA_BRPORT_PROXYARP] = decode_nla_u8,
139 [IFLA_BRPORT_LEARNING_SYNC] = decode_nla_u8,
140 [IFLA_BRPORT_PROXYARP_WIFI] = decode_nla_u8,
141 [IFLA_BRPORT_ROOT_ID] = decode_ifla_bridge_id,
142 [IFLA_BRPORT_BRIDGE_ID] = decode_ifla_bridge_id,
143 [IFLA_BRPORT_DESIGNATED_PORT] = decode_nla_u16,
144 [IFLA_BRPORT_DESIGNATED_COST] = decode_nla_u16,
145 [IFLA_BRPORT_ID] = decode_nla_u16,
146 [IFLA_BRPORT_NO] = decode_nla_u16,
147 [IFLA_BRPORT_TOPOLOGY_CHANGE_ACK] = decode_nla_u8,
148 [IFLA_BRPORT_CONFIG_PENDING] = decode_nla_u8,
149 [IFLA_BRPORT_MESSAGE_AGE_TIMER] = decode_nla_u64,
150 [IFLA_BRPORT_FORWARD_DELAY_TIMER] = decode_nla_u64,
151 [IFLA_BRPORT_HOLD_TIMER] = decode_nla_u64,
152 [IFLA_BRPORT_FLUSH] = NULL,
153 [IFLA_BRPORT_MULTICAST_ROUTER] = decode_nla_u8,
154 [IFLA_BRPORT_PAD] = NULL,
155 [IFLA_BRPORT_MCAST_FLOOD] = decode_nla_u8,
156 [IFLA_BRPORT_MCAST_TO_UCAST] = decode_nla_u8,
157 [IFLA_BRPORT_VLAN_TUNNEL] = decode_nla_u8,
158 [IFLA_BRPORT_BCAST_FLOOD] = decode_nla_u8
162 decode_ifla_protinfo(struct tcb *const tcp,
163 const kernel_ulong_t addr,
164 const unsigned int len,
165 const void *const opaque_data)
167 decode_nlattr(tcp, addr, len, rtnl_ifla_brport_attrs,
168 "IFLA_BRPORT_???", ifla_brport_nla_decoders,
169 ARRAY_SIZE(ifla_brport_nla_decoders), opaque_data);
175 decode_rtnl_link_ifmap(struct tcb *const tcp,
176 const kernel_ulong_t addr,
177 const unsigned int len,
178 const void *const opaque_data)
180 struct rtnl_link_ifmap map;
181 const unsigned int sizeof_ifmap =
182 offsetofend(struct rtnl_link_ifmap, port);
184 if (len < sizeof_ifmap)
186 else if (!umoven_or_printaddr(tcp, addr, sizeof_ifmap, &map)) {
187 PRINT_FIELD_X("{", map, mem_start);
188 PRINT_FIELD_X(", ", map, mem_end);
189 PRINT_FIELD_X(", ", map, base_addr);
190 PRINT_FIELD_U(", ", map, irq);
191 PRINT_FIELD_U(", ", map, dma);
192 PRINT_FIELD_U(", ", map, port);
199 static const nla_decoder_t ifla_linkinfo_nla_decoders[] = {
200 [IFLA_INFO_KIND] = decode_nla_str,
201 [IFLA_INFO_DATA] = NULL, /* unimplemented */
202 [IFLA_INFO_XSTATS] = NULL, /* unimplemented */
203 [IFLA_INFO_SLAVE_KIND] = decode_nla_str,
204 [IFLA_INFO_SLAVE_DATA] = NULL, /* unimplemented */
208 decode_ifla_linkinfo(struct tcb *const tcp,
209 const kernel_ulong_t addr,
210 const unsigned int len,
211 const void *const opaque_data)
213 decode_nlattr(tcp, addr, len, rtnl_ifla_info_attrs,
214 "IFLA_INFO_???", ifla_linkinfo_nla_decoders,
215 ARRAY_SIZE(ifla_linkinfo_nla_decoders), opaque_data);
221 decode_rtnl_link_stats64(struct tcb *const tcp,
222 const kernel_ulong_t addr,
223 const unsigned int len,
224 const void *const opaque_data)
226 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64
227 struct rtnl_link_stats64 st;
228 const unsigned int min_size =
229 offsetofend(struct rtnl_link_stats64, tx_compressed);
230 const unsigned int def_size = sizeof(st);
231 const unsigned int size =
232 (len >= def_size) ? def_size :
233 ((len == min_size) ? min_size : 0);
238 if (!umoven_or_printaddr(tcp, addr, size, &st)) {
239 PRINT_FIELD_U("{", st, rx_packets);
240 PRINT_FIELD_U(", ", st, tx_packets);
241 PRINT_FIELD_U(", ", st, rx_bytes);
242 PRINT_FIELD_U(", ", st, tx_bytes);
243 PRINT_FIELD_U(", ", st, rx_errors);
244 PRINT_FIELD_U(", ", st, tx_errors);
245 PRINT_FIELD_U(", ", st, rx_dropped);
246 PRINT_FIELD_U(", ", st, tx_dropped);
247 PRINT_FIELD_U(", ", st, multicast);
248 PRINT_FIELD_U(", ", st, collisions);
250 PRINT_FIELD_U(", ", st, rx_length_errors);
251 PRINT_FIELD_U(", ", st, rx_over_errors);
252 PRINT_FIELD_U(", ", st, rx_crc_errors);
253 PRINT_FIELD_U(", ", st, rx_frame_errors);
254 PRINT_FIELD_U(", ", st, rx_fifo_errors);
255 PRINT_FIELD_U(", ", st, rx_missed_errors);
257 PRINT_FIELD_U(", ", st, tx_aborted_errors);
258 PRINT_FIELD_U(", ", st, tx_carrier_errors);
259 PRINT_FIELD_U(", ", st, tx_fifo_errors);
260 PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
261 PRINT_FIELD_U(", ", st, tx_window_errors);
263 PRINT_FIELD_U(", ", st, rx_compressed);
264 PRINT_FIELD_U(", ", st, tx_compressed);
265 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER
267 PRINT_FIELD_U(", ", st, rx_nohandler);
279 decode_ifla_port_vsi(struct tcb *const tcp,
280 const kernel_ulong_t addr,
281 const unsigned int len,
282 const void *const opaque_data)
284 #ifdef HAVE_STRUCT_IFLA_PORT_VSI
285 struct ifla_port_vsi vsi;
287 if (len < sizeof(vsi))
289 else if (!umove_or_printaddr(tcp, addr, &vsi)) {
290 PRINT_FIELD_U("{", vsi, vsi_mgr_id);
291 PRINT_FIELD_STRING(", ", vsi, vsi_type_id,
292 sizeof(vsi.vsi_type_id), QUOTE_FORCE_HEX);
293 PRINT_FIELD_U(", ", vsi, vsi_type_version);
303 static const nla_decoder_t ifla_port_nla_decoders[] = {
304 [IFLA_PORT_VF] = decode_nla_u32,
305 [IFLA_PORT_PROFILE] = decode_nla_str,
306 [IFLA_PORT_VSI_TYPE] = decode_ifla_port_vsi,
307 [IFLA_PORT_INSTANCE_UUID] = NULL, /* default parser */
308 [IFLA_PORT_HOST_UUID] = NULL, /* default parser */
309 [IFLA_PORT_REQUEST] = decode_nla_u8,
310 [IFLA_PORT_RESPONSE] = decode_nla_u16
314 decode_ifla_port(struct tcb *const tcp,
315 const kernel_ulong_t addr,
316 const unsigned int len,
317 const void *const opaque_data)
319 decode_nlattr(tcp, addr, len, rtnl_ifla_port_attrs,
320 "IFLA_VF_PORT_???", ifla_port_nla_decoders,
321 ARRAY_SIZE(ifla_port_nla_decoders), opaque_data);
326 static const nla_decoder_t ifla_vf_port_nla_decoders[] = {
327 [IFLA_VF_PORT] = decode_ifla_port
331 decode_ifla_vf_ports(struct tcb *const tcp,
332 const kernel_ulong_t addr,
333 const unsigned int len,
334 const void *const opaque_data)
336 decode_nlattr(tcp, addr, len, rtnl_ifla_vf_port_attrs,
337 "IFLA_VF_PORT_???", ifla_vf_port_nla_decoders,
338 ARRAY_SIZE(ifla_vf_port_nla_decoders), opaque_data);
344 decode_ifla_xdp_flags(struct tcb *const tcp,
345 const kernel_ulong_t addr,
346 const unsigned int len,
347 const void *const opaque_data)
351 if (len < sizeof(flags))
353 else if (!umove_or_printaddr(tcp, addr, &flags))
354 printflags(xdp_flags, flags, "XDP_FLAGS_???");
359 static const nla_decoder_t ifla_xdp_nla_decoders[] = {
360 [IFLA_XDP_FD] = decode_nla_fd,
361 [IFLA_XDP_ATTACHED] = decode_nla_u8,
362 [IFLA_XDP_FLAGS] = decode_ifla_xdp_flags,
363 [IFLA_XDP_PROG_ID] = decode_nla_u32
367 decode_ifla_xdp(struct tcb *const tcp,
368 const kernel_ulong_t addr,
369 const unsigned int len,
370 const void *const opaque_data)
372 decode_nlattr(tcp, addr, len, rtnl_ifla_xdp_attrs,
373 "IFLA_XDP_???", ifla_xdp_nla_decoders,
374 ARRAY_SIZE(ifla_xdp_nla_decoders), opaque_data);
380 decode_ifla_event(struct tcb *const tcp,
381 const kernel_ulong_t addr,
382 const unsigned int len,
383 const void *const opaque_data)
387 if (len < sizeof(ev))
389 else if (!umove_or_printaddr(tcp, addr, &ev))
390 printxval(rtnl_ifla_events, ev, "IFLA_EVENT_???");
395 static const nla_decoder_t ifinfomsg_nla_decoders[] = {
396 [IFLA_ADDRESS] = NULL, /* unimplemented */
397 [IFLA_BROADCAST] = NULL, /* unimplemented */
398 [IFLA_IFNAME] = decode_nla_str,
399 [IFLA_MTU] = decode_nla_u32,
400 [IFLA_LINK] = decode_nla_u32,
401 [IFLA_QDISC] = decode_nla_str,
402 [IFLA_STATS] = decode_rtnl_link_stats,
403 [IFLA_COST] = NULL, /* unused */
404 [IFLA_PRIORITY] = NULL, /* unused */
405 [IFLA_MASTER] = decode_nla_u32,
406 [IFLA_WIRELESS] = NULL, /* unimplemented */
407 [IFLA_PROTINFO] = decode_ifla_protinfo,
408 [IFLA_TXQLEN] = decode_nla_u32,
409 [IFLA_MAP] = decode_rtnl_link_ifmap,
410 [IFLA_WEIGHT] = decode_nla_u32,
411 [IFLA_OPERSTATE] = decode_nla_u8,
412 [IFLA_LINKMODE] = decode_nla_u8,
413 [IFLA_LINKINFO] = decode_ifla_linkinfo,
414 [IFLA_NET_NS_PID] = decode_nla_u32,
415 [IFLA_IFALIAS] = decode_nla_str,
416 [IFLA_NUM_VF] = decode_nla_u32,
417 [IFLA_VFINFO_LIST] = NULL, /* unimplemented */
418 [IFLA_STATS64] = decode_rtnl_link_stats64,
419 [IFLA_VF_PORTS] = decode_ifla_vf_ports,
420 [IFLA_PORT_SELF] = decode_ifla_port,
421 [IFLA_AF_SPEC] = NULL, /* unimplemented */
422 [IFLA_GROUP] = decode_nla_u32,
423 [IFLA_NET_NS_FD] = decode_nla_fd,
424 [IFLA_EXT_MASK] = decode_nla_u32,
425 [IFLA_PROMISCUITY] = decode_nla_u32,
426 [IFLA_NUM_TX_QUEUES] = decode_nla_u32,
427 [IFLA_NUM_RX_QUEUES] = decode_nla_u32,
428 [IFLA_CARRIER] = decode_nla_u8,
429 [IFLA_PHYS_PORT_ID] = NULL, /* default parser */
430 [IFLA_CARRIER_CHANGES] = decode_nla_u32,
431 [IFLA_PHYS_SWITCH_ID] = NULL, /* default parser */
432 [IFLA_LINK_NETNSID] = decode_nla_s32,
433 [IFLA_PHYS_PORT_NAME] = decode_nla_str,
434 [IFLA_PROTO_DOWN] = decode_nla_u8,
435 [IFLA_GSO_MAX_SEGS] = decode_nla_u32,
436 [IFLA_GSO_MAX_SIZE] = decode_nla_u32,
438 [IFLA_XDP] = decode_ifla_xdp,
439 [IFLA_EVENT] = decode_ifla_event,
440 [IFLA_NEW_NETNSID] = decode_nla_s32,
441 [IFLA_IF_NETNSID] = decode_nla_s32,
442 [IFLA_CARRIER_UP_COUNT] = decode_nla_u32,
443 [IFLA_CARRIER_DOWN_COUNT] = decode_nla_u32,
444 [IFLA_NEW_IFINDEX] = decode_nla_s32,
447 DECL_NETLINK_ROUTE_DECODER(decode_ifinfomsg)
449 struct ifinfomsg ifinfo = { .ifi_family = family };
450 size_t offset = sizeof(ifinfo.ifi_family);
451 bool decode_nla = false;
453 PRINT_FIELD_XVAL("{", ifinfo, ifi_family, addrfams, "AF_???");
456 if (len >= sizeof(ifinfo)) {
457 if (!umoven_or_printaddr(tcp, addr + offset,
458 sizeof(ifinfo) - offset,
459 (char *) &ifinfo + offset)) {
460 PRINT_FIELD_XVAL("", ifinfo, ifi_type,
461 arp_hardware_types, "ARPHRD_???");
462 PRINT_FIELD_IFINDEX(", ", ifinfo, ifi_index);
463 PRINT_FIELD_FLAGS(", ", ifinfo, ifi_flags,
464 iffflags, "IFF_???");
465 PRINT_FIELD_X(", ", ifinfo, ifi_change);
472 offset = NLMSG_ALIGN(sizeof(ifinfo));
473 if (decode_nla && len > offset) {
475 decode_nlattr(tcp, addr + offset, len - offset,
476 rtnl_link_attrs, "IFLA_???",
477 ifinfomsg_nla_decoders,
478 ARRAY_SIZE(ifinfomsg_nla_decoders), NULL);