]> granicus.if.org Git - strace/blob - rtnl_link.c
Add a common MAC address printing routine
[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 #ifdef HAVE_LINUX_IF_LINK_H
37 # include <linux/if_link.h>
38 #endif
39 #include <linux/rtnetlink.h>
40
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"
49
50 static bool
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)
55 {
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);
63
64         if (!size)
65                 return false;
66
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);
78
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);
85
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);
91
92                 PRINT_FIELD_U(", ", st, rx_compressed);
93                 PRINT_FIELD_U(", ", st, tx_compressed);
94 #ifdef HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER
95                 if (len >= def_size)
96                         PRINT_FIELD_U(", ", st, rx_nohandler);
97 #endif
98                 tprints("}");
99         }
100
101         return true;
102 }
103
104 static bool
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)
109 {
110 #ifdef HAVE_STRUCT_IFLA_BRIDGE_ID
111         struct ifla_bridge_id id;
112
113         if (len < sizeof(id))
114                 return false;
115         else if (!umove_or_printaddr(tcp, addr, &id)) {
116                 tprintf("{prio=[%u, %u]", id.prio[0], id.prio[1]);
117                 PRINT_FIELD_MAC(", ", id, addr);
118                 tprints("}");
119         }
120
121         return true;
122 #else
123         return false;
124 #endif
125 }
126
127 static const nla_decoder_t ifla_brport_nla_decoders[] = {
128         [IFLA_BRPORT_STATE]                     = decode_nla_u8,
129         [IFLA_BRPORT_PRIORITY]                  = decode_nla_u16,
130         [IFLA_BRPORT_COST]                      = decode_nla_u32,
131         [IFLA_BRPORT_MODE]                      = decode_nla_u8,
132         [IFLA_BRPORT_GUARD]                     = decode_nla_u8,
133         [IFLA_BRPORT_PROTECT]                   = decode_nla_u8,
134         [IFLA_BRPORT_FAST_LEAVE]                = decode_nla_u8,
135         [IFLA_BRPORT_LEARNING]                  = decode_nla_u8,
136         [IFLA_BRPORT_UNICAST_FLOOD]             = decode_nla_u8,
137         [IFLA_BRPORT_PROXYARP]                  = decode_nla_u8,
138         [IFLA_BRPORT_LEARNING_SYNC]             = decode_nla_u8,
139         [IFLA_BRPORT_PROXYARP_WIFI]             = decode_nla_u8,
140         [IFLA_BRPORT_ROOT_ID]                   = decode_ifla_bridge_id,
141         [IFLA_BRPORT_BRIDGE_ID]                 = decode_ifla_bridge_id,
142         [IFLA_BRPORT_DESIGNATED_PORT]           = decode_nla_u16,
143         [IFLA_BRPORT_DESIGNATED_COST]           = decode_nla_u16,
144         [IFLA_BRPORT_ID]                        = decode_nla_u16,
145         [IFLA_BRPORT_NO]                        = decode_nla_u16,
146         [IFLA_BRPORT_TOPOLOGY_CHANGE_ACK]       = decode_nla_u8,
147         [IFLA_BRPORT_CONFIG_PENDING]            = decode_nla_u8,
148         [IFLA_BRPORT_MESSAGE_AGE_TIMER]         = decode_nla_u64,
149         [IFLA_BRPORT_FORWARD_DELAY_TIMER]       = decode_nla_u64,
150         [IFLA_BRPORT_HOLD_TIMER]                = decode_nla_u64,
151         [IFLA_BRPORT_FLUSH]                     = NULL,
152         [IFLA_BRPORT_MULTICAST_ROUTER]          = decode_nla_u8,
153         [IFLA_BRPORT_PAD]                       = NULL,
154         [IFLA_BRPORT_MCAST_FLOOD]               = decode_nla_u8,
155         [IFLA_BRPORT_MCAST_TO_UCAST]            = decode_nla_u8,
156         [IFLA_BRPORT_VLAN_TUNNEL]               = decode_nla_u8,
157         [IFLA_BRPORT_BCAST_FLOOD]               = decode_nla_u8
158 };
159
160 static bool
161 decode_ifla_protinfo(struct tcb *const tcp,
162                      const kernel_ulong_t addr,
163                      const unsigned int len,
164                      const void *const opaque_data)
165 {
166         decode_nlattr(tcp, addr, len, rtnl_ifla_brport_attrs,
167                       "IFLA_BRPORT_???", ifla_brport_nla_decoders,
168                       ARRAY_SIZE(ifla_brport_nla_decoders), opaque_data);
169
170         return true;
171 }
172
173 static bool
174 decode_rtnl_link_ifmap(struct tcb *const tcp,
175                        const kernel_ulong_t addr,
176                        const unsigned int len,
177                        const void *const opaque_data)
178 {
179         struct rtnl_link_ifmap map;
180         const unsigned int sizeof_ifmap =
181                 offsetofend(struct rtnl_link_ifmap, port);
182
183         if (len < sizeof_ifmap)
184                 return false;
185         else if (!umoven_or_printaddr(tcp, addr, sizeof_ifmap, &map)) {
186                 PRINT_FIELD_X("{", map, mem_start);
187                 PRINT_FIELD_X(", ", map, mem_end);
188                 PRINT_FIELD_X(", ", map, base_addr);
189                 PRINT_FIELD_U(", ", map, irq);
190                 PRINT_FIELD_U(", ", map, dma);
191                 PRINT_FIELD_U(", ", map, port);
192                 tprints("}");
193         }
194
195         return true;
196 }
197
198 static const nla_decoder_t ifla_linkinfo_nla_decoders[] = {
199         [IFLA_INFO_KIND]        = decode_nla_str,
200         [IFLA_INFO_DATA]        = NULL, /* unimplemented */
201         [IFLA_INFO_XSTATS]      = NULL, /* unimplemented */
202         [IFLA_INFO_SLAVE_KIND]  = decode_nla_str,
203         [IFLA_INFO_SLAVE_DATA]  = NULL, /* unimplemented */
204 };
205
206 static bool
207 decode_ifla_linkinfo(struct tcb *const tcp,
208                      const kernel_ulong_t addr,
209                      const unsigned int len,
210                      const void *const opaque_data)
211 {
212         decode_nlattr(tcp, addr, len, rtnl_ifla_info_attrs,
213                       "IFLA_INFO_???", ifla_linkinfo_nla_decoders,
214                       ARRAY_SIZE(ifla_linkinfo_nla_decoders), opaque_data);
215
216         return true;
217 }
218
219 static bool
220 decode_rtnl_link_stats64(struct tcb *const tcp,
221                          const kernel_ulong_t addr,
222                          const unsigned int len,
223                          const void *const opaque_data)
224 {
225 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64
226         struct rtnl_link_stats64 st;
227         const unsigned int min_size =
228                 offsetofend(struct rtnl_link_stats64, tx_compressed);
229         const unsigned int def_size = sizeof(st);
230         const unsigned int size =
231                 (len >= def_size) ? def_size :
232                                     ((len == min_size) ? min_size : 0);
233
234         if (!size)
235                 return false;
236
237         if (!umoven_or_printaddr(tcp, addr, size, &st)) {
238                 PRINT_FIELD_U("{", st, rx_packets);
239                 PRINT_FIELD_U(", ", st, tx_packets);
240                 PRINT_FIELD_U(", ", st, rx_bytes);
241                 PRINT_FIELD_U(", ", st, tx_bytes);
242                 PRINT_FIELD_U(", ", st, rx_errors);
243                 PRINT_FIELD_U(", ", st, tx_errors);
244                 PRINT_FIELD_U(", ", st, rx_dropped);
245                 PRINT_FIELD_U(", ", st, tx_dropped);
246                 PRINT_FIELD_U(", ", st, multicast);
247                 PRINT_FIELD_U(", ", st, collisions);
248
249                 PRINT_FIELD_U(", ", st, rx_length_errors);
250                 PRINT_FIELD_U(", ", st, rx_over_errors);
251                 PRINT_FIELD_U(", ", st, rx_crc_errors);
252                 PRINT_FIELD_U(", ", st, rx_frame_errors);
253                 PRINT_FIELD_U(", ", st, rx_fifo_errors);
254                 PRINT_FIELD_U(", ", st, rx_missed_errors);
255
256                 PRINT_FIELD_U(", ", st, tx_aborted_errors);
257                 PRINT_FIELD_U(", ", st, tx_carrier_errors);
258                 PRINT_FIELD_U(", ", st, tx_fifo_errors);
259                 PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
260                 PRINT_FIELD_U(", ", st, tx_window_errors);
261
262                 PRINT_FIELD_U(", ", st, rx_compressed);
263                 PRINT_FIELD_U(", ", st, tx_compressed);
264 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER
265                 if (len >= def_size)
266                         PRINT_FIELD_U(", ", st, rx_nohandler);
267 #endif
268                 tprints("}");
269         }
270
271         return true;
272 #else
273         return false;
274 #endif
275 }
276
277 static bool
278 decode_ifla_port_vsi(struct tcb *const tcp,
279                      const kernel_ulong_t addr,
280                      const unsigned int len,
281                      const void *const opaque_data)
282 {
283 #ifdef HAVE_STRUCT_IFLA_PORT_VSI
284         struct ifla_port_vsi vsi;
285
286         if (len < sizeof(vsi))
287                 return false;
288         else if (!umove_or_printaddr(tcp, addr, &vsi)) {
289                 PRINT_FIELD_U("{", vsi, vsi_mgr_id);
290                 PRINT_FIELD_STRING(", ", vsi, vsi_type_id,
291                                    sizeof(vsi.vsi_type_id), QUOTE_FORCE_HEX);
292                 PRINT_FIELD_U(", ", vsi, vsi_type_version);
293                 tprints("}");
294         }
295
296         return true;
297 #else
298         return false;
299 #endif
300 }
301
302 static const nla_decoder_t ifla_port_nla_decoders[] = {
303         [IFLA_PORT_VF]                  = decode_nla_u32,
304         [IFLA_PORT_PROFILE]             = decode_nla_str,
305         [IFLA_PORT_VSI_TYPE]            = decode_ifla_port_vsi,
306         [IFLA_PORT_INSTANCE_UUID]       = NULL, /* default parser */
307         [IFLA_PORT_HOST_UUID]           = NULL, /* default parser */
308         [IFLA_PORT_REQUEST]             = decode_nla_u8,
309         [IFLA_PORT_RESPONSE]            = decode_nla_u16
310 };
311
312 static bool
313 decode_ifla_port(struct tcb *const tcp,
314                  const kernel_ulong_t addr,
315                  const unsigned int len,
316                  const void *const opaque_data)
317 {
318         decode_nlattr(tcp, addr, len, rtnl_ifla_port_attrs,
319                       "IFLA_VF_PORT_???", ifla_port_nla_decoders,
320                       ARRAY_SIZE(ifla_port_nla_decoders), opaque_data);
321
322         return true;
323 }
324
325 static const nla_decoder_t ifla_vf_port_nla_decoders[] = {
326         [IFLA_VF_PORT] = decode_ifla_port
327 };
328
329 static bool
330 decode_ifla_vf_ports(struct tcb *const tcp,
331                      const kernel_ulong_t addr,
332                      const unsigned int len,
333                      const void *const opaque_data)
334 {
335         decode_nlattr(tcp, addr, len, rtnl_ifla_vf_port_attrs,
336                       "IFLA_VF_PORT_???", ifla_vf_port_nla_decoders,
337                       ARRAY_SIZE(ifla_vf_port_nla_decoders), opaque_data);
338
339         return true;
340 }
341
342 static bool
343 decode_ifla_xdp_flags(struct tcb *const tcp,
344                       const kernel_ulong_t addr,
345                       const unsigned int len,
346                       const void *const opaque_data)
347 {
348         uint32_t flags;
349
350         if (len < sizeof(flags))
351                 return false;
352         else if (!umove_or_printaddr(tcp, addr, &flags))
353                 printflags(xdp_flags, flags, "XDP_FLAGS_???");
354
355         return true;
356 }
357
358 static const nla_decoder_t ifla_xdp_nla_decoders[] = {
359         [IFLA_XDP_FD]           = decode_nla_fd,
360         [IFLA_XDP_ATTACHED]     = decode_nla_u8,
361         [IFLA_XDP_FLAGS]        = decode_ifla_xdp_flags,
362         [IFLA_XDP_PROG_ID]      = decode_nla_u32
363 };
364
365 static bool
366 decode_ifla_xdp(struct tcb *const tcp,
367                 const kernel_ulong_t addr,
368                 const unsigned int len,
369                 const void *const opaque_data)
370 {
371         decode_nlattr(tcp, addr, len, rtnl_ifla_xdp_attrs,
372                       "IFLA_XDP_???", ifla_xdp_nla_decoders,
373                       ARRAY_SIZE(ifla_xdp_nla_decoders), opaque_data);
374
375         return true;
376 }
377
378 static bool
379 decode_ifla_event(struct tcb *const tcp,
380                   const kernel_ulong_t addr,
381                   const unsigned int len,
382                   const void *const opaque_data)
383 {
384         uint32_t ev;
385
386         if (len < sizeof(ev))
387                 return false;
388         else if (!umove_or_printaddr(tcp, addr, &ev))
389                 printxval(rtnl_ifla_events, ev, "IFLA_EVENT_???");
390
391         return true;
392 }
393
394 static const nla_decoder_t ifinfomsg_nla_decoders[] = {
395         [IFLA_ADDRESS]          = NULL, /* unimplemented */
396         [IFLA_BROADCAST]        = NULL, /* unimplemented */
397         [IFLA_IFNAME]           = decode_nla_str,
398         [IFLA_MTU]              = decode_nla_u32,
399         [IFLA_LINK]             = decode_nla_u32,
400         [IFLA_QDISC]            = decode_nla_str,
401         [IFLA_STATS]            = decode_rtnl_link_stats,
402         [IFLA_COST]             = NULL, /* unused */
403         [IFLA_PRIORITY]         = NULL, /* unused */
404         [IFLA_MASTER]           = decode_nla_u32,
405         [IFLA_WIRELESS]         = NULL, /* unimplemented */
406         [IFLA_PROTINFO]         = decode_ifla_protinfo,
407         [IFLA_TXQLEN]           = decode_nla_u32,
408         [IFLA_MAP]              = decode_rtnl_link_ifmap,
409         [IFLA_WEIGHT]           = decode_nla_u32,
410         [IFLA_OPERSTATE]        = decode_nla_u8,
411         [IFLA_LINKMODE]         = decode_nla_u8,
412         [IFLA_LINKINFO]         = decode_ifla_linkinfo,
413         [IFLA_NET_NS_PID]       = decode_nla_u32,
414         [IFLA_IFALIAS]          = decode_nla_str,
415         [IFLA_NUM_VF]           = decode_nla_u32,
416         [IFLA_VFINFO_LIST]      = NULL, /* unimplemented */
417         [IFLA_STATS64]          = decode_rtnl_link_stats64,
418         [IFLA_VF_PORTS]         = decode_ifla_vf_ports,
419         [IFLA_PORT_SELF]        = decode_ifla_port,
420         [IFLA_AF_SPEC]          = NULL, /* unimplemented */
421         [IFLA_GROUP]            = decode_nla_u32,
422         [IFLA_NET_NS_FD]        = decode_nla_fd,
423         [IFLA_EXT_MASK]         = decode_nla_u32,
424         [IFLA_PROMISCUITY]      = decode_nla_u32,
425         [IFLA_NUM_TX_QUEUES]    = decode_nla_u32,
426         [IFLA_NUM_RX_QUEUES]    = decode_nla_u32,
427         [IFLA_CARRIER]          = decode_nla_u8,
428         [IFLA_PHYS_PORT_ID]     = NULL, /* default parser */
429         [IFLA_CARRIER_CHANGES]  = decode_nla_u32,
430         [IFLA_PHYS_SWITCH_ID]   = NULL, /* default parser */
431         [IFLA_LINK_NETNSID]     = decode_nla_s32,
432         [IFLA_PHYS_PORT_NAME]   = decode_nla_str,
433         [IFLA_PROTO_DOWN]       = decode_nla_u8,
434         [IFLA_GSO_MAX_SEGS]     = decode_nla_u32,
435         [IFLA_GSO_MAX_SIZE]     = decode_nla_u32,
436         [IFLA_PAD]              = NULL,
437         [IFLA_XDP]              = decode_ifla_xdp,
438         [IFLA_EVENT]            = decode_ifla_event,
439         [IFLA_NEW_NETNSID]      = decode_nla_s32,
440         [IFLA_IF_NETNSID]       = decode_nla_s32,
441         [IFLA_CARRIER_UP_COUNT] = decode_nla_u32,
442         [IFLA_CARRIER_DOWN_COUNT]       = decode_nla_u32,
443         [IFLA_NEW_IFINDEX]      = decode_nla_ifindex,
444 };
445
446 DECL_NETLINK_ROUTE_DECODER(decode_ifinfomsg)
447 {
448         struct ifinfomsg ifinfo = { .ifi_family = family };
449         size_t offset = sizeof(ifinfo.ifi_family);
450         bool decode_nla = false;
451
452         PRINT_FIELD_XVAL("{", ifinfo, ifi_family, addrfams, "AF_???");
453
454         tprints(", ");
455         if (len >= sizeof(ifinfo)) {
456                 if (!umoven_or_printaddr(tcp, addr + offset,
457                                          sizeof(ifinfo) - offset,
458                                          (char *) &ifinfo + offset)) {
459                         PRINT_FIELD_XVAL("", ifinfo, ifi_type,
460                                          arp_hardware_types, "ARPHRD_???");
461                         PRINT_FIELD_IFINDEX(", ", ifinfo, ifi_index);
462                         PRINT_FIELD_FLAGS(", ", ifinfo, ifi_flags,
463                                           iffflags, "IFF_???");
464                         PRINT_FIELD_X(", ", ifinfo, ifi_change);
465                         decode_nla = true;
466                 }
467         } else
468                 tprints("...");
469         tprints("}");
470
471         offset = NLMSG_ALIGN(sizeof(ifinfo));
472         if (decode_nla && len > offset) {
473                 tprints(", ");
474                 decode_nlattr(tcp, addr + offset, len - offset,
475                               rtnl_link_attrs, "IFLA_???",
476                               ifinfomsg_nla_decoders,
477                               ARRAY_SIZE(ifinfomsg_nla_decoders), NULL);
478         }
479 }