]> granicus.if.org Git - strace/blob - rtnl_link.c
tests: check decoding of ndmsg netlink attributes
[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-2017 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_link_attrs.h"
42
43 static bool
44 decode_rtnl_link_stats(struct tcb *const tcp,
45                        const kernel_ulong_t addr,
46                        const unsigned int len,
47                        const void *const opaque_data)
48 {
49         struct rtnl_link_stats st;
50         const unsigned int min_size =
51                 offsetofend(struct rtnl_link_stats, tx_compressed);
52         const unsigned int size = len < sizeof(st) ? min_size : sizeof(st);
53
54         if (len < min_size)
55                 return false;
56         else if (!umoven_or_printaddr(tcp, addr, size, &st)) {
57                 PRINT_FIELD_U("{", st, rx_packets);
58                 PRINT_FIELD_U(", ", st, tx_packets);
59                 PRINT_FIELD_U(", ", st, rx_bytes);
60                 PRINT_FIELD_U(", ", st, tx_bytes);
61                 PRINT_FIELD_U(", ", st, rx_errors);
62                 PRINT_FIELD_U(", ", st, tx_errors);
63                 PRINT_FIELD_U(", ", st, rx_dropped);
64                 PRINT_FIELD_U(", ", st, tx_dropped);
65                 PRINT_FIELD_U(", ", st, multicast);
66                 PRINT_FIELD_U(", ", st, collisions);
67
68                 PRINT_FIELD_U(", ", st, rx_length_errors);
69                 PRINT_FIELD_U(", ", st, rx_over_errors);
70                 PRINT_FIELD_U(", ", st, rx_crc_errors);
71                 PRINT_FIELD_U(", ", st, rx_frame_errors);
72                 PRINT_FIELD_U(", ", st, rx_fifo_errors);
73                 PRINT_FIELD_U(", ", st, rx_missed_errors);
74
75                 PRINT_FIELD_U(", ", st, tx_aborted_errors);
76                 PRINT_FIELD_U(", ", st, tx_carrier_errors);
77                 PRINT_FIELD_U(", ", st, tx_fifo_errors);
78                 PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
79                 PRINT_FIELD_U(", ", st, tx_window_errors);
80
81                 PRINT_FIELD_U(", ", st, rx_compressed);
82                 PRINT_FIELD_U(", ", st, tx_compressed);
83 #ifdef HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER
84                 if (len >= sizeof(st))
85                         PRINT_FIELD_U(", ", st, rx_nohandler);
86 #endif
87                 tprints("}");
88         }
89
90         return true;
91 }
92
93 static bool
94 decode_rtnl_link_ifmap(struct tcb *const tcp,
95                        const kernel_ulong_t addr,
96                        const unsigned int len,
97                        const void *const opaque_data)
98 {
99         struct rtnl_link_ifmap map;
100         const unsigned int sizeof_ifmap =
101                 offsetofend(struct rtnl_link_ifmap, port);
102
103         if (len < sizeof_ifmap)
104                 return false;
105         else if (!umoven_or_printaddr(tcp, addr, sizeof_ifmap, &map)) {
106                 PRINT_FIELD_X("{", map, mem_start);
107                 PRINT_FIELD_X(", ", map, mem_end);
108                 PRINT_FIELD_X(", ", map, base_addr);
109                 PRINT_FIELD_U(", ", map, irq);
110                 PRINT_FIELD_U(", ", map, dma);
111                 PRINT_FIELD_U(", ", map, port);
112                 tprints("}");
113         }
114
115         return true;
116 }
117
118 static bool
119 decode_rtnl_link_stats64(struct tcb *const tcp,
120                          const kernel_ulong_t addr,
121                          const unsigned int len,
122                          const void *const opaque_data)
123 {
124 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64
125         struct rtnl_link_stats64 st;
126         const unsigned int min_size =
127                 offsetofend(struct rtnl_link_stats64, tx_compressed);
128         const unsigned int size = len < sizeof(st) ? min_size : sizeof(st);
129
130         if (len < min_size)
131                 return false;
132         else if (!umoven_or_printaddr(tcp, addr, size, &st)) {
133                 PRINT_FIELD_U("{", st, rx_packets);
134                 PRINT_FIELD_U(", ", st, tx_packets);
135                 PRINT_FIELD_U(", ", st, rx_bytes);
136                 PRINT_FIELD_U(", ", st, tx_bytes);
137                 PRINT_FIELD_U(", ", st, rx_errors);
138                 PRINT_FIELD_U(", ", st, tx_errors);
139                 PRINT_FIELD_U(", ", st, rx_dropped);
140                 PRINT_FIELD_U(", ", st, tx_dropped);
141                 PRINT_FIELD_U(", ", st, multicast);
142                 PRINT_FIELD_U(", ", st, collisions);
143
144                 PRINT_FIELD_U(", ", st, rx_length_errors);
145                 PRINT_FIELD_U(", ", st, rx_over_errors);
146                 PRINT_FIELD_U(", ", st, rx_crc_errors);
147                 PRINT_FIELD_U(", ", st, rx_frame_errors);
148                 PRINT_FIELD_U(", ", st, rx_fifo_errors);
149                 PRINT_FIELD_U(", ", st, rx_missed_errors);
150
151                 PRINT_FIELD_U(", ", st, tx_aborted_errors);
152                 PRINT_FIELD_U(", ", st, tx_carrier_errors);
153                 PRINT_FIELD_U(", ", st, tx_fifo_errors);
154                 PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
155                 PRINT_FIELD_U(", ", st, tx_window_errors);
156
157                 PRINT_FIELD_U(", ", st, rx_compressed);
158                 PRINT_FIELD_U(", ", st, tx_compressed);
159 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER
160                 if (len >= sizeof(st))
161                         PRINT_FIELD_U(", ", st, rx_nohandler);
162 #endif
163                 tprints("}");
164         }
165
166         return true;
167 #else
168         return false;
169 #endif
170 }
171
172 static const nla_decoder_t ifinfomsg_nla_decoders[] = {
173         [IFLA_ADDRESS]          = NULL, /* unimplemented */
174         [IFLA_BROADCAST]        = NULL, /* unimplemented */
175         [IFLA_IFNAME]           = decode_nla_str,
176         [IFLA_MTU]              = decode_nla_u32,
177         [IFLA_LINK]             = decode_nla_u32,
178         [IFLA_QDISC]            = decode_nla_str,
179         [IFLA_STATS]            = decode_rtnl_link_stats,
180         [IFLA_COST]             = NULL, /* unused */
181         [IFLA_PRIORITY]         = NULL, /* unused */
182         [IFLA_MASTER]           = decode_nla_u32,
183         [IFLA_WIRELESS]         = NULL, /* unimplemented */
184         [IFLA_PROTINFO]         = NULL, /* unimplemented */
185         [IFLA_TXQLEN]           = decode_nla_u32,
186         [IFLA_MAP]              = decode_rtnl_link_ifmap,
187         [IFLA_WEIGHT]           = decode_nla_u32,
188         [IFLA_OPERSTATE]        = decode_nla_u8,
189         [IFLA_LINKMODE]         = decode_nla_u8,
190         [IFLA_LINKINFO]         = NULL, /* unimplemented */
191         [IFLA_NET_NS_PID]       = decode_nla_u32,
192         [IFLA_IFALIAS]          = decode_nla_str,
193         [IFLA_NUM_VF]           = decode_nla_u32,
194         [IFLA_VFINFO_LIST]      = NULL, /* unimplemented */
195         [IFLA_STATS64]          = decode_rtnl_link_stats64,
196         [IFLA_VF_PORTS]         = NULL, /* unimplemented */
197         [IFLA_PORT_SELF]        = NULL, /* unimplemented */
198         [IFLA_AF_SPEC]          = NULL, /* unimplemented */
199         [IFLA_GROUP]            = decode_nla_u32,
200         [IFLA_NET_NS_FD]        = decode_nla_u32,
201         [IFLA_EXT_MASK]         = decode_nla_u32,
202         [IFLA_PROMISCUITY]      = decode_nla_u32,
203         [IFLA_NUM_TX_QUEUES]    = decode_nla_u32,
204         [IFLA_NUM_RX_QUEUES]    = decode_nla_u32,
205         [IFLA_CARRIER]          = decode_nla_u8,
206         [IFLA_PHYS_PORT_ID]     = NULL, /* default parser */
207         [IFLA_CARRIER_CHANGES]  = decode_nla_u32,
208         [IFLA_PHYS_SWITCH_ID]   = NULL, /* default parser */
209         [IFLA_LINK_NETNSID]     = decode_nla_s32,
210         [IFLA_PHYS_PORT_NAME]   = decode_nla_str,
211         [IFLA_PROTO_DOWN]       = decode_nla_u8,
212         [IFLA_GSO_MAX_SEGS]     = decode_nla_u32,
213         [IFLA_GSO_MAX_SIZE]     = decode_nla_u32,
214         [IFLA_PAD]              = NULL,
215         [IFLA_XDP]              = NULL, /* unimplemented */
216         [IFLA_EVENT]            = decode_nla_u32
217 };
218
219 DECL_NETLINK_ROUTE_DECODER(decode_ifinfomsg)
220 {
221         struct ifinfomsg ifinfo = { .ifi_family = family };
222         size_t offset = sizeof(ifinfo.ifi_family);
223         bool decode_nla = false;
224
225         PRINT_FIELD_XVAL("{", ifinfo, ifi_family, addrfams, "AF_???");
226
227         tprints(", ");
228         if (len >= sizeof(ifinfo)) {
229                 if (!umoven_or_printaddr(tcp, addr + offset,
230                                          sizeof(ifinfo) - offset,
231                                          (void *) &ifinfo + offset)) {
232                         PRINT_FIELD_XVAL("", ifinfo, ifi_type,
233                                          arp_hardware_types, "ARPHRD_???");
234                         PRINT_FIELD_IFINDEX(", ", ifinfo, ifi_index);
235                         PRINT_FIELD_FLAGS(", ", ifinfo, ifi_flags,
236                                           iffflags, "IFF_???");
237                         PRINT_FIELD_X(", ", ifinfo, ifi_change);
238                         decode_nla = true;
239                 }
240         } else
241                 tprints("...");
242         tprints("}");
243
244         offset = NLMSG_ALIGN(sizeof(ifinfo));
245         if (decode_nla && len > offset) {
246                 tprints(", ");
247                 decode_nlattr(tcp, addr + offset, len - offset,
248                               rtnl_link_attrs, "IFLA_???",
249                               ifinfomsg_nla_decoders,
250                               ARRAY_SIZE(ifinfomsg_nla_decoders), NULL);
251         }
252 }