• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
3  * Copyright (c) 2017 The strace developers.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "tests.h"
30 
31 #include <stdio.h>
32 #include <stddef.h>
33 #include "test_nlattr.h"
34 
35 #include <linux/if.h>
36 #include <linux/if_arp.h>
37 #ifdef HAVE_LINUX_IF_LINK_H
38 # include <linux/if_link.h>
39 #endif
40 #include <linux/rtnetlink.h>
41 
42 #ifndef IFLA_LINKINFO
43 # define IFLA_LINKINFO 18
44 #endif
45 #ifndef IFLA_VF_PORTS
46 # define IFLA_VF_PORTS 24
47 #endif
48 #define IFLA_LINK_NETNSID 37
49 
50 #ifndef IFLA_INFO_KIND
51 # define IFLA_INFO_KIND 1
52 #endif
53 
54 #ifndef IFLA_VF_PORT
55 # define IFLA_VF_PORT 1
56 #endif
57 
58 static void
init_ifinfomsg(struct nlmsghdr * const nlh,const unsigned int msg_len)59 init_ifinfomsg(struct nlmsghdr *const nlh, const unsigned int msg_len)
60 {
61 	SET_STRUCT(struct nlmsghdr, nlh,
62 		.nlmsg_len = msg_len,
63 		.nlmsg_type = RTM_GETLINK,
64 		.nlmsg_flags = NLM_F_DUMP
65 	);
66 
67 	struct ifinfomsg *const msg = NLMSG_DATA(nlh);
68 	SET_STRUCT(struct ifinfomsg, msg,
69 		.ifi_family = AF_UNIX,
70 		.ifi_type = ARPHRD_LOOPBACK,
71 		.ifi_index = ifindex_lo(),
72 		.ifi_flags = IFF_UP,
73 	);
74 }
75 
76 static void
print_ifinfomsg(const unsigned int msg_len)77 print_ifinfomsg(const unsigned int msg_len)
78 {
79 	printf("{len=%u, type=RTM_GETLINK, flags=NLM_F_DUMP"
80 	       ", seq=0, pid=0}, {ifi_family=AF_UNIX"
81 	       ", ifi_type=ARPHRD_LOOPBACK"
82 	       ", ifi_index=" IFINDEX_LO_STR
83 	       ", ifi_flags=IFF_UP, ifi_change=0}",
84 	       msg_len);
85 }
86 
87 int
main(void)88 main(void)
89 {
90 	skip_if_unavailable("/proc/self/fd/");
91 
92 	const int fd = create_nl_socket(NETLINK_ROUTE);
93 	const unsigned int hdrlen = sizeof(struct ifinfomsg);
94 	void *nlh0 = tail_alloc(NLMSG_SPACE(hdrlen));
95 
96 	static char pattern[4096];
97 	fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
98 
99 	const unsigned int nla_type = 0xffff & NLA_TYPE_MASK;
100 	char nla_type_str[256];
101 	sprintf(nla_type_str, "%#x /* IFLA_??? */", nla_type);
102 	TEST_NLATTR_(fd, nlh0, hdrlen,
103 		     init_ifinfomsg, print_ifinfomsg,
104 		     nla_type, nla_type_str,
105 		     4, pattern, 4,
106 		     print_quoted_hex(pattern, 4));
107 
108 	const int32_t netnsid = 0xacbdabda;
109 	TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
110 			   init_ifinfomsg, print_ifinfomsg,
111 			   IFLA_LINK_NETNSID, pattern, netnsid,
112 			   printf("%d", netnsid));
113 
114 	static const struct rtnl_link_stats st = {
115 		.rx_packets = 0xabcdefac,
116 		.tx_packets = 0xbcdacdab,
117 		.rx_bytes = 0xcdbafaab,
118 		.tx_bytes = 0xdafabadb,
119 		.rx_errors = 0xeabcdaeb,
120 		.tx_errors = 0xfefabeab,
121 		.rx_dropped = 0xadbafafb,
122 		.tx_dropped = 0xbdffabda,
123 		.multicast = 0xcdabdfea,
124 		.collisions = 0xefadbaeb,
125 		.rx_length_errors = 0xfabffabd,
126 		.rx_over_errors = 0xafbafabc,
127 		.rx_crc_errors = 0xbfdabdad,
128 		.rx_frame_errors = 0xcfdabfad,
129 		.rx_fifo_errors = 0xddfdebad,
130 		.rx_missed_errors = 0xefabdcba,
131 		.tx_aborted_errors = 0xefdadbfa,
132 		.tx_carrier_errors = 0xfaefbada,
133 		.tx_fifo_errors = 0xaebdffab,
134 		.tx_heartbeat_errors = 0xbadebaaf,
135 		.tx_window_errors = 0xcdafbada,
136 		.rx_compressed = 0xdeffadbd,
137 		.tx_compressed = 0xefdadfab
138 	};
139 	TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
140 			   init_ifinfomsg, print_ifinfomsg,
141 			   IFLA_STATS, pattern, st,
142 			   PRINT_FIELD_U("{", st, rx_packets);
143 			   PRINT_FIELD_U(", ", st, tx_packets);
144 			   PRINT_FIELD_U(", ", st, rx_bytes);
145 			   PRINT_FIELD_U(", ", st, tx_bytes);
146 			   PRINT_FIELD_U(", ", st, rx_errors);
147 			   PRINT_FIELD_U(", ", st, tx_errors);
148 			   PRINT_FIELD_U(", ", st, rx_dropped);
149 			   PRINT_FIELD_U(", ", st, tx_dropped);
150 			   PRINT_FIELD_U(", ", st, multicast);
151 			   PRINT_FIELD_U(", ", st, collisions);
152 			   PRINT_FIELD_U(", ", st, rx_length_errors);
153 			   PRINT_FIELD_U(", ", st, rx_over_errors);
154 			   PRINT_FIELD_U(", ", st, rx_crc_errors);
155 			   PRINT_FIELD_U(", ", st, rx_frame_errors);
156 			   PRINT_FIELD_U(", ", st, rx_fifo_errors);
157 			   PRINT_FIELD_U(", ", st, rx_missed_errors);
158 			   PRINT_FIELD_U(", ", st, tx_aborted_errors);
159 			   PRINT_FIELD_U(", ", st, tx_carrier_errors);
160 			   PRINT_FIELD_U(", ", st, tx_fifo_errors);
161 			   PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
162 			   PRINT_FIELD_U(", ", st, tx_window_errors);
163 			   PRINT_FIELD_U(", ", st, rx_compressed);
164 			   PRINT_FIELD_U(", ", st, tx_compressed);
165 #ifdef HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER
166 			   PRINT_FIELD_U(", ", st, rx_nohandler);
167 #endif
168 			   printf("}"));
169 
170 #ifdef HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER
171 	const unsigned int sizeof_stats =
172 		offsetofend(struct rtnl_link_stats, tx_compressed);
173 	TEST_NLATTR(fd, nlh0, hdrlen,
174 		    init_ifinfomsg, print_ifinfomsg,
175 		    IFLA_STATS, sizeof_stats, &st, sizeof_stats,
176 		    PRINT_FIELD_U("{", st, rx_packets);
177 		    PRINT_FIELD_U(", ", st, tx_packets);
178 		    PRINT_FIELD_U(", ", st, rx_bytes);
179 		    PRINT_FIELD_U(", ", st, tx_bytes);
180 		    PRINT_FIELD_U(", ", st, rx_errors);
181 		    PRINT_FIELD_U(", ", st, tx_errors);
182 		    PRINT_FIELD_U(", ", st, rx_dropped);
183 		    PRINT_FIELD_U(", ", st, tx_dropped);
184 		    PRINT_FIELD_U(", ", st, multicast);
185 		    PRINT_FIELD_U(", ", st, collisions);
186 		    PRINT_FIELD_U(", ", st, rx_length_errors);
187 		    PRINT_FIELD_U(", ", st, rx_over_errors);
188 		    PRINT_FIELD_U(", ", st, rx_crc_errors);
189 		    PRINT_FIELD_U(", ", st, rx_frame_errors);
190 		    PRINT_FIELD_U(", ", st, rx_fifo_errors);
191 		    PRINT_FIELD_U(", ", st, rx_missed_errors);
192 		    PRINT_FIELD_U(", ", st, tx_aborted_errors);
193 		    PRINT_FIELD_U(", ", st, tx_carrier_errors);
194 		    PRINT_FIELD_U(", ", st, tx_fifo_errors);
195 		    PRINT_FIELD_U(", ", st, tx_heartbeat_errors);
196 		    PRINT_FIELD_U(", ", st, tx_window_errors);
197 		    PRINT_FIELD_U(", ", st, rx_compressed);
198 		    PRINT_FIELD_U(", ", st, tx_compressed);
199 		    printf("}"));
200 #endif /* HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER */
201 
202 	static const struct rtnl_link_ifmap map = {
203 		.mem_start = 0xadcbefedefbcdedb,
204 		.mem_end = 0xefcbeabdecdcdefa,
205 		.base_addr = 0xaddbeabdfaacdbae,
206 		.irq = 0xefaf,
207 		.dma = 0xab,
208 		.port = 0xcd
209 	};
210 	const unsigned int sizeof_ifmap =
211 		offsetofend(struct rtnl_link_ifmap, port);
212 	const unsigned int plen = sizeof_ifmap - 1 > DEFAULT_STRLEN
213 				  ? DEFAULT_STRLEN
214 				  : (int) sizeof_ifmap - 1;
215 	/* len < sizeof_ifmap */
216 	TEST_NLATTR(fd, nlh0, hdrlen,
217 		    init_ifinfomsg, print_ifinfomsg,
218 		    IFLA_MAP, plen, pattern, plen,
219 		    print_quoted_hex(pattern, plen));
220 
221 	/* short read of sizeof_ifmap */
222 	TEST_NLATTR(fd, nlh0, hdrlen,
223 		    init_ifinfomsg, print_ifinfomsg,
224 		    IFLA_MAP, sizeof_ifmap, &map, sizeof_ifmap - 1,
225 		    printf("%p", RTA_DATA(TEST_NLATTR_nla)));
226 
227 	/* sizeof_ifmap */
228 	TEST_NLATTR(fd, nlh0, hdrlen,
229 		    init_ifinfomsg, print_ifinfomsg,
230 		    IFLA_MAP, sizeof_ifmap, &map, sizeof_ifmap,
231 		    PRINT_FIELD_X("{", map, mem_start);
232 		    PRINT_FIELD_X(", ", map, mem_end);
233 		    PRINT_FIELD_X(", ", map, base_addr);
234 		    PRINT_FIELD_U(", ", map, irq);
235 		    PRINT_FIELD_U(", ", map, dma);
236 		    PRINT_FIELD_U(", ", map, port);
237 		    printf("}"));
238 
239 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64
240 	static const struct rtnl_link_stats64 st64 = {
241 		.rx_packets = 0xadcbefedefbcdedb,
242 		.tx_packets = 0xbdabdedabdcdeabd,
243 		.rx_bytes = 0xcdbaefbaeadfabec,
244 		.tx_bytes = 0xdbaedbafabbeacdb,
245 		.rx_errors = 0xefabfdaefabaefab,
246 		.tx_errors = 0xfaebfabfabbaeabf,
247 		.rx_dropped = 0xacdbaedbadbabeba,
248 		.tx_dropped = 0xbcdeffebdabeadbe,
249 		.multicast = 0xeeffbaeabaeffabe,
250 		.collisions = 0xffbaefcefbafacef,
251 		.rx_length_errors = 0xaabbdeabceffdecb,
252 		.rx_over_errors = 0xbbdcdadebadeaeed,
253 		.rx_crc_errors= 0xccdeabecefaedbef,
254 		.rx_frame_errors = 0xddbedaedebcedaef,
255 		.rx_fifo_errors = 0xeffbadefafdaeaab,
256 		.rx_missed_errors = 0xfefaebccceadeecd,
257 		.tx_aborted_errors = 0xabcdadefcdadef,
258 		.tx_carrier_errors = 0xbccdafaeeaaefe,
259 		.tx_fifo_errors = 0xcddefdbedeadce,
260 		.tx_heartbeat_errors = 0xedaededdadcdea,
261 		.tx_window_errors = 0xfdacdeaccedcda,
262 		.rx_compressed = 0xacdbbcacdbccef,
263 		.tx_compressed = 0xbcdadefcdedfea
264 	};
265 	TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
266 			   init_ifinfomsg, print_ifinfomsg,
267 			   IFLA_STATS64, pattern, st64,
268 			   PRINT_FIELD_U("{", st64, rx_packets);
269 			   PRINT_FIELD_U(", ", st64, tx_packets);
270 			   PRINT_FIELD_U(", ", st64, rx_bytes);
271 			   PRINT_FIELD_U(", ", st64, tx_bytes);
272 			   PRINT_FIELD_U(", ", st64, rx_errors);
273 			   PRINT_FIELD_U(", ", st64, tx_errors);
274 			   PRINT_FIELD_U(", ", st64, rx_dropped);
275 			   PRINT_FIELD_U(", ", st64, tx_dropped);
276 			   PRINT_FIELD_U(", ", st64, multicast);
277 			   PRINT_FIELD_U(", ", st64, collisions);
278 			   PRINT_FIELD_U(", ", st64, rx_length_errors);
279 			   PRINT_FIELD_U(", ", st64, rx_over_errors);
280 			   PRINT_FIELD_U(", ", st64, rx_crc_errors);
281 			   PRINT_FIELD_U(", ", st64, rx_frame_errors);
282 			   PRINT_FIELD_U(", ", st64, rx_fifo_errors);
283 			   PRINT_FIELD_U(", ", st64, rx_missed_errors);
284 			   PRINT_FIELD_U(", ", st64, tx_aborted_errors);
285 			   PRINT_FIELD_U(", ", st64, tx_carrier_errors);
286 			   PRINT_FIELD_U(", ", st64, tx_fifo_errors);
287 			   PRINT_FIELD_U(", ", st64, tx_heartbeat_errors);
288 			   PRINT_FIELD_U(", ", st64, tx_window_errors);
289 			   PRINT_FIELD_U(", ", st64, rx_compressed);
290 			   PRINT_FIELD_U(", ", st64, tx_compressed);
291 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER
292 			   PRINT_FIELD_U(", ", st64, rx_nohandler);
293 #endif
294 			   printf("}"));
295 
296 #ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER
297 	const unsigned int sizeof_stats64 =
298 		offsetofend(struct rtnl_link_stats64, tx_compressed);
299 	TEST_NLATTR(fd, nlh0, hdrlen,
300 		    init_ifinfomsg, print_ifinfomsg,
301 		    IFLA_STATS64, sizeof_stats64, &st64, sizeof_stats64,
302 		    PRINT_FIELD_U("{", st64, rx_packets);
303 		    PRINT_FIELD_U(", ", st64, tx_packets);
304 		    PRINT_FIELD_U(", ", st64, rx_bytes);
305 		    PRINT_FIELD_U(", ", st64, tx_bytes);
306 		    PRINT_FIELD_U(", ", st64, rx_errors);
307 		    PRINT_FIELD_U(", ", st64, tx_errors);
308 		    PRINT_FIELD_U(", ", st64, rx_dropped);
309 		    PRINT_FIELD_U(", ", st64, tx_dropped);
310 		    PRINT_FIELD_U(", ", st64, multicast);
311 		    PRINT_FIELD_U(", ", st64, collisions);
312 		    PRINT_FIELD_U(", ", st64, rx_length_errors);
313 		    PRINT_FIELD_U(", ", st64, rx_over_errors);
314 		    PRINT_FIELD_U(", ", st64, rx_crc_errors);
315 		    PRINT_FIELD_U(", ", st64, rx_frame_errors);
316 		    PRINT_FIELD_U(", ", st64, rx_fifo_errors);
317 		    PRINT_FIELD_U(", ", st64, rx_missed_errors);
318 		    PRINT_FIELD_U(", ", st64, tx_aborted_errors);
319 		    PRINT_FIELD_U(", ", st64, tx_carrier_errors);
320 		    PRINT_FIELD_U(", ", st64, tx_fifo_errors);
321 		    PRINT_FIELD_U(", ", st64, tx_heartbeat_errors);
322 		    PRINT_FIELD_U(", ", st64, tx_window_errors);
323 		    PRINT_FIELD_U(", ", st64, rx_compressed);
324 		    PRINT_FIELD_U(", ", st64, tx_compressed);
325 		    printf("}"));
326 #endif /* HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER */
327 #endif /* HAVE_STRUCT_RTNL_LINK_STATS64 */
328 
329 	struct nlattr nla = {
330 		.nla_len = sizeof(nla),
331 		.nla_type = IFLA_INFO_KIND,
332 	};
333 	TEST_NLATTR(fd, nlh0, hdrlen,
334 		    init_ifinfomsg, print_ifinfomsg,
335 		    IFLA_LINKINFO, sizeof(nla), &nla, sizeof(nla),
336 		    printf("{nla_len=%u, nla_type=IFLA_INFO_KIND}",
337 			   nla.nla_len));
338 
339 	nla.nla_type = IFLA_VF_PORT;
340 	TEST_NLATTR(fd, nlh0, hdrlen,
341 		    init_ifinfomsg, print_ifinfomsg,
342 		    IFLA_VF_PORTS, sizeof(nla), &nla, sizeof(nla),
343 		    printf("{nla_len=%u, nla_type=IFLA_VF_PORT}",
344 			   nla.nla_len));
345 
346 	puts("+++ exited with 0 +++");
347 	return 0;
348 }
349