1 /*
2 * IFLA_LINKINFO netlink attribute decoding check.
3 *
4 * Copyright (c) 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 "tests.h"
31
32 #include <inttypes.h>
33 #include <stdio.h>
34 #include <stddef.h>
35 #include <arpa/inet.h>
36
37 #include "test_nlattr.h"
38
39 #include <linux/if.h>
40 #include <linux/if_arp.h>
41 #ifdef HAVE_LINUX_IF_LINK_H
42 # include <linux/if_link.h>
43 #endif
44 #include <linux/rtnetlink.h>
45
46 #define XLAT_MACROS_ONLY
47 # include <xlat/rtnl_link_attrs.h>
48 # include <xlat/rtnl_ifla_info_attrs.h>
49 #undef XLAT_MACROS_ONLY
50
51 #define IFLA_ATTR IFLA_LINKINFO
52 #include "nlattr_ifla.h"
53
54 #define COMMA ,
55 #define TEST_UNKNOWN_TUNNELS(fd_, nlh0_, objtype_, objtype_str_, \
56 obj_, objsz_, arrstrs_, ...) \
57 do { \
58 /* 64 is guestimate for maximum unknown type len */ \
59 char buf[8 * 2 + 64 + objsz_]; \
60 const char **arrstrs[] = arrstrs_; \
61 const char ***arrstrs_pos = arrstrs; \
62 const char **arrstr = *arrstrs_pos; \
63 const char *type = NULL; \
64 \
65 for (type = arrstr ? arrstr[0] : NULL; type && arrstr; \
66 type = (++arrstr)[0] ? arrstr[0] \
67 : (++arrstrs_pos)[0] \
68 ? (arrstr = arrstrs_pos[0])[0] \
69 : NULL) \
70 { \
71 size_t type_len = strlen(type) + 1; \
72 \
73 if (type_len > 64) \
74 error_msg_and_fail("Unexpectedly long " \
75 "unknown type: \"%s\" " \
76 "(length is %zu)", \
77 type, type_len); \
78 \
79 struct nlattr obj_nla = { \
80 .nla_len = NLA_HDRLEN + (objsz_), \
81 .nla_type = (objtype_), \
82 }; \
83 \
84 char *pos = buf; \
85 memcpy(pos, type, type_len); \
86 pos += NLA_ALIGN(type_len); \
87 memcpy(pos, &obj_nla, sizeof(obj_nla)); \
88 pos += sizeof(obj_nla); \
89 memcpy(pos, (obj_), (objsz_)); \
90 \
91 TEST_NLATTR_EX_((fd_), \
92 (nlh0_) - hdrlen - (pos - buf), \
93 hdrlen + NLA_HDRLEN, \
94 init_ifinfomsg, print_ifinfomsg, \
95 IFLA_INFO_KIND, "IFLA_INFO_KIND", \
96 type_len, objsz_ + (pos - buf), \
97 buf, objsz_ + (pos - buf), \
98 printf("\"%s\"}", type); \
99 printf(", {{nla_len=%zu" \
100 ", nla_type=%s}, ", \
101 (objsz_) + NLA_HDRLEN, \
102 (objtype_str_)); \
103 \
104 { __VA_ARGS__; } \
105 \
106 printf("}")); \
107 } \
108 } while (0)
109
110 #define TEST_LINKINFO_(fd_, nlh0_, nla_type_, nla_type_str_, tuntype_, \
111 obj_, objsz_, pattern_, fallback_func_, ...) \
112 do { \
113 size_t tuntype_len = strlen(tuntype_) + 1; \
114 char *buf = tail_alloc(NLA_ALIGN(tuntype_len) \
115 + NLA_HDRLEN + (objsz_)); \
116 char *pos = buf; \
117 \
118 struct nlattr obj_nla = { \
119 .nla_len = NLA_HDRLEN + (objsz_), \
120 .nla_type = (nla_type_), \
121 }; \
122 \
123 memcpy(pos, (tuntype_), tuntype_len); \
124 pos += NLA_ALIGN(tuntype_len); \
125 memcpy(pos, &obj_nla, sizeof(obj_nla)); \
126 pos += sizeof(obj_nla); \
127 memcpy(pos, &(obj_), (objsz_)); \
128 \
129 if (fallback_func_ == print_quoted_hex) { \
130 TEST_NLATTR_EX_((fd_), \
131 (nlh0_) - NLA_HDRLEN, \
132 hdrlen + NLA_HDRLEN, \
133 init_ifinfomsg, print_ifinfomsg, \
134 IFLA_INFO_KIND, "IFLA_INFO_KIND", \
135 tuntype_len, \
136 objsz_ + (pos - buf) - 1, \
137 buf, objsz_ + (pos - buf) - 1, \
138 printf("\"%s\"}", (tuntype_)); \
139 printf(", {{nla_len=%zu" \
140 ", nla_type=%s}, ", \
141 (objsz_) + NLA_HDRLEN, \
142 (nla_type_str_)); \
143 (fallback_func_)((obj_), \
144 (objsz_) - 1); \
145 printf("}")); \
146 } \
147 \
148 TEST_NLATTR_EX_((fd_), (nlh0_) - NLA_HDRLEN, \
149 hdrlen + NLA_HDRLEN, \
150 init_ifinfomsg, print_ifinfomsg, \
151 IFLA_INFO_KIND, "IFLA_INFO_KIND", \
152 tuntype_len, objsz_ + (pos - buf), \
153 buf, objsz_ + (pos - buf) - 1, \
154 printf("\"%s\"}", (tuntype_)); \
155 printf(", {{nla_len=%zu, nla_type=%s}, ", \
156 (objsz_) + NLA_HDRLEN, \
157 (nla_type_str_)); \
158 printf("%p}", \
159 RTA_DATA(NLMSG_ATTR(nlh, \
160 (hdrlen + NLA_HDRLEN + (pos - buf)))) \
161 ) \
162 ); \
163 \
164 TEST_NLATTR_EX_((fd_), (nlh0_) - NLA_HDRLEN, \
165 hdrlen + NLA_HDRLEN, \
166 init_ifinfomsg, print_ifinfomsg, \
167 IFLA_INFO_KIND, "IFLA_INFO_KIND", \
168 tuntype_len, objsz_ + (pos - buf), \
169 buf, objsz_ + (pos - buf), \
170 printf("\"%s\"}", (tuntype_)); \
171 printf(", {{nla_len=%zu, nla_type=%s}, ", \
172 (objsz_) + NLA_HDRLEN, \
173 (nla_type_str_)); \
174 \
175 { __VA_ARGS__; } \
176 \
177 printf("}")); \
178 } while (0)
179
180 #define TEST_LINKINFO(fd_, nlh0_, nla_type_, tuntype_, \
181 obj_, pattern_, fallback_func_, ...) \
182 TEST_LINKINFO_((fd_), (nlh0_), nla_type_, #nla_type_, (tuntype_), \
183 (obj_), sizeof(obj_), pattern_, fallback_func_, \
184 __VA_ARGS__)
185
186 #define TEST_NESTED_LINKINFO(fd_, nlh0_, \
187 nla_type_, nla_type_str_, tuntype_, \
188 subnla_type_, subnla_type_str_, \
189 obj_, pattern_, ...) \
190 do { \
191 size_t tuntype_len = strlen(tuntype_) + 1; \
192 struct { \
193 size_t sz; \
194 const char *str; \
195 } attrs[] = { __VA_ARGS__ }; \
196 size_t tunhdrlen; \
197 size_t buflen = NLA_ALIGN(tuntype_len) + NLA_HDRLEN; \
198 size_t attrsz = 0; \
199 \
200 for (size_t i = 0; i < ARRAY_SIZE(attrs); i++) \
201 attrsz += NLA_HDRLEN + NLA_ALIGN(attrs[i].sz); \
202 \
203 buflen += attrsz; \
204 \
205 char *buf = tail_alloc(buflen); \
206 char *pos = buf; \
207 \
208 struct nlattr nla = { \
209 .nla_len = NLA_HDRLEN + attrsz, \
210 .nla_type = (nla_type_), \
211 }; \
212 \
213 memcpy(pos, (tuntype_), tuntype_len); \
214 pos += NLA_ALIGN(tuntype_len); \
215 memcpy(pos, &nla, sizeof(nla)); \
216 pos += sizeof(nla); \
217 \
218 tunhdrlen = pos - buf; \
219 \
220 nla.nla_type = subnla_type_; \
221 \
222 for (size_t i = 0; i < ARRAY_SIZE(attrs); i++) { \
223 nla.nla_len = NLA_HDRLEN + attrs[i].sz; \
224 memcpy(pos, &nla, sizeof(nla)); \
225 pos += sizeof(nla); \
226 \
227 memcpy(pos, &(obj_), MIN(sizeof(obj_), attrs[i].sz)); \
228 \
229 if (attrs[i].sz > sizeof(obj_)) \
230 memcpy(pos + sizeof(obj_), \
231 &(pattern_), \
232 attrs[i].sz - sizeof(obj_)); \
233 \
234 pos += NLA_ALIGN(attrs[i].sz); \
235 } \
236 \
237 TEST_NLATTR_EX_((fd_), (nlh0_) - hdrlen - tunhdrlen, \
238 hdrlen + NLA_HDRLEN, \
239 init_ifinfomsg, print_ifinfomsg, \
240 IFLA_INFO_KIND, "IFLA_INFO_KIND", \
241 tuntype_len, buflen, \
242 buf, buflen, \
243 printf("\"%s\"}", (tuntype_)); \
244 printf(", {{nla_len=%zu, nla_type=%s}, [", \
245 attrsz + NLA_HDRLEN, \
246 (nla_type_str_)); \
247 \
248 for (size_t i = 0; i < ARRAY_SIZE(attrs); i++) \
249 printf("%s%s{nla_len=%zu" \
250 ", nla_type=%s}%s%s%s", \
251 i ? ", " : "", \
252 attrs[i].str ? "{": "", \
253 attrs[i].sz + NLA_HDRLEN, \
254 subnla_type_str_, \
255 attrs[i].str ? ", ": "", \
256 attrs[i].str ?: "", \
257 attrs[i].str ? "}" : ""); \
258 \
259 printf("]}")); \
260 } while (0)
261
262 int
main(void)263 main(void)
264 {
265 static const uint8_t unknown_msg[] = { 0xab, 0xac, 0xdb, 0xcd };
266 static const char *unsupported_tunnel_types[] = {
267 "batadv", "bond",
268 "caif", "cfhsi",
269 "dummy",
270 "erspan",
271 "geneve", "gre", "gretap", "gtp",
272 "hsr",
273 "ifb", "ip6erspan", "ip6gre", "ip6gretap", "ip6tnl",
274 "ipip", "ipoib", "ipvlan", "ipvtap",
275 "lowpan",
276 "macsec", "macvlan", "macvtap",
277 "netdevsim", "nlmon",
278 "openvswitch",
279 "ppp",
280 "rmnet",
281 "sit",
282 "team",
283 "vcan", "veth", "vlan", "vrf", "vsockmon",
284 "vti", "vti6", "vxcan", "vxlan",
285 NULL
286 };
287 static const char *unsupported_xstats_types[] = {
288 "bridge",
289 "tun",
290 NULL
291 };
292 static const char *unsupported_data_types[] = {
293 "can",
294 NULL
295 };
296
297 skip_if_unavailable("/proc/self/fd/");
298
299 const int fd = create_nl_socket(NETLINK_ROUTE);
300
301 const unsigned int hdrlen = sizeof(struct ifinfomsg);
302 void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), 2 * NLA_HDRLEN + 256);
303
304 static char pattern[4096];
305 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
306
307
308 /* unknown AF_INFO_* type */
309 TEST_NESTED_NLATTR_OBJECT(fd, nlh0, hdrlen,
310 init_ifinfomsg, print_ifinfomsg,
311 IFLA_INFO_UNSPEC, pattern, unknown_msg,
312 printf("\"\\xab\\xac\\xdb\\xcd\""));
313
314 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
315 init_ifinfomsg, print_ifinfomsg,
316 6, "0x6 /* IFLA_INFO_??? */", pattern,
317 unknown_msg, print_quoted_hex, 1,
318 printf("\"\\xab\\xac\\xdb\\xcd\""));
319
320
321 /* IFLA_INFO_KIND */
322 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
323 init_ifinfomsg, print_ifinfomsg,
324 IFLA_INFO_KIND, "IFLA_INFO_KIND", pattern,
325 unknown_msg, print_quoted_stringn, 1,
326 printf("\"\\253\\254\\333\\315\"..."));
327
328
329 /* IFLA_INFO_KIND + IFLA_INFO_UNSPEC */
330 TEST_UNKNOWN_TUNNELS(fd, nlh0, IFLA_INFO_UNSPEC, "IFLA_INFO_UNSPEC",
331 unknown_msg, sizeof(unknown_msg),
332 {unsupported_tunnel_types COMMA
333 unsupported_xstats_types COMMA
334 unsupported_data_types COMMA
335 NULL},
336 printf("\"\\xab\\xac\\xdb\\xcd\""));
337
338
339 /* IFLA_INFO_KIND + IFLA_INFO_KIND */
340 TEST_UNKNOWN_TUNNELS(fd, nlh0, IFLA_INFO_KIND, "IFLA_INFO_KIND",
341 unknown_msg, sizeof(unknown_msg),
342 {unsupported_tunnel_types COMMA
343 unsupported_xstats_types COMMA
344 unsupported_data_types COMMA
345 NULL},
346 printf("\"\\253\\254\\333\\315\"..."));
347
348
349 /* IFLA_INFO_KIND + IFLA_INFO_DATA */
350 TEST_UNKNOWN_TUNNELS(fd, nlh0, IFLA_INFO_DATA, "IFLA_INFO_DATA",
351 unknown_msg, sizeof(unknown_msg),
352 {unsupported_tunnel_types COMMA
353 unsupported_data_types COMMA
354 NULL},
355 printf("\"\\xab\\xac\\xdb\\xcd\""));
356
357 struct val_name {
358 unsigned int val;
359 const char *name;
360 };
361
362 static const uint64_t u64_val = 0xdeadc0defacefeedULL;
363 static const uint32_t u32_val = 0xbadc0dedU;
364 static const uint16_t u16_val = 0xdeed;
365 static const uint8_t u8_val = 0xa1;
366
367 /* bridge attrs */
368 static const struct val_name und_br_attrs[] = {
369 { 0, "IFLA_BR_UNSPEC" },
370 { 20, "IFLA_BR_GROUP_ADDR" },
371 { 21, "IFLA_BR_FDB_FLUSH" },
372 { 40, "IFLA_BR_PAD" },
373 { 45, "0x2d /* IFLA_BR_??? */" },
374 };
375
376 for (size_t k = 0; k < ARRAY_SIZE(und_br_attrs); k++) {
377 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "bridge",
378 und_br_attrs[k].val, und_br_attrs[k].name,
379 unknown_msg, pattern,
380 { 2, "\"\\xab\\xac\"" },
381 { 4, "\"\\xab\\xac\\xdb\\xcd\"" },
382 { 6,
383 "\"\\xab\\xac\\xdb\\xcd\\x61\\x62\"" },
384 { 8, "\"\\xab\\xac\\xdb\\xcd\\x61\\x62"
385 "\\x63\\x64\"" },
386 { 10, "\"\\xab\\xac\\xdb\\xcd\\x61\\x62"
387 "\\x63\\x64\\x65\\x66\"" });
388 }
389
390 static const struct val_name u64_br_attrs[] = {
391 { 16, "IFLA_BR_HELLO_TIMER" },
392 { 17, "IFLA_BR_TCN_TIMER" },
393 { 18, "IFLA_BR_TOPOLOGY_CHANGE_TIMER" },
394 { 19, "IFLA_BR_GC_TIMER" },
395 { 30, "IFLA_BR_MCAST_LAST_MEMBER_INTVL" },
396 { 31, "IFLA_BR_MCAST_MEMBERSHIP_INTVL" },
397 { 32, "IFLA_BR_MCAST_QUERIER_INTVL" },
398 { 33, "IFLA_BR_MCAST_QUERY_INTVL" },
399 { 34, "IFLA_BR_MCAST_QUERY_RESPONSE_INTVL" },
400 { 35, "IFLA_BR_MCAST_STARTUP_QUERY_INTVL" },
401 };
402
403 for (size_t k = 0; k < ARRAY_SIZE(u64_br_attrs); k++) {
404 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "bridge",
405 u64_br_attrs[k].val, u64_br_attrs[k].name,
406 u64_val, pattern,
407 { 7, "\""
408 #if WORDS_BIGENDIAN
409 "\\xde\\xad\\xc0\\xde\\xfa\\xce\\xfe"
410 #else
411 "\\xed\\xfe\\xce\\xfa\\xde\\xc0\\xad"
412 #endif
413 "\"" },
414 { 8, "16045693111314087661" },
415 { 9, "16045693111314087661" });
416 }
417
418 static const struct val_name u32_br_attrs[] = {
419 { 1, "IFLA_BR_FORWARD_DELAY" },
420 { 2, "IFLA_BR_HELLO_TIME" },
421 { 3, "IFLA_BR_MAX_AGE" },
422 { 4, "IFLA_BR_AGEING_TIME" },
423 { 5, "IFLA_BR_STP_STATE" },
424 { 13, "IFLA_BR_ROOT_PATH_COST" },
425 { 26, "IFLA_BR_MCAST_HASH_ELASTICITY" },
426 { 27, "IFLA_BR_MCAST_HASH_MAX" },
427 { 28, "IFLA_BR_MCAST_LAST_MEMBER_CNT" },
428 { 29, "IFLA_BR_MCAST_STARTUP_QUERY_CNT" },
429 };
430
431 for (size_t k = 0; k < ARRAY_SIZE(u32_br_attrs); k++) {
432 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "bridge",
433 u32_br_attrs[k].val, u32_br_attrs[k].name,
434 u32_val, pattern,
435 { 3, "\""
436 #if WORDS_BIGENDIAN
437 "\\xba\\xdc\\x0d"
438 #else
439 "\\xed\\x0d\\xdc"
440 #endif
441 "\"" },
442 { 4, "3134983661" },
443 { 5, "3134983661" });
444 }
445
446 static const struct val_name u16_br_attrs[] = {
447 { 6, "IFLA_BR_PRIORITY" },
448 { 12, "IFLA_BR_ROOT_PORT" },
449 { 39, "IFLA_BR_VLAN_DEFAULT_PVID" },
450 };
451
452 for (size_t k = 0; k < ARRAY_SIZE(u16_br_attrs); k++) {
453 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "bridge",
454 u16_br_attrs[k].val, u16_br_attrs[k].name,
455 u16_val, pattern,
456 { 1, "\""
457 #if WORDS_BIGENDIAN
458 "\\xde"
459 #else
460 "\\xed"
461 #endif
462 "\"" },
463 { 2, "57069" },
464 { 3, "57069" });
465 }
466
467
468 static const struct val_name x16_br_attrs[] = {
469 { 9, "IFLA_BR_GROUP_FWD_MASK" },
470 };
471
472 for (size_t k = 0; k < ARRAY_SIZE(x16_br_attrs); k++) {
473 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "bridge",
474 x16_br_attrs[k].val, x16_br_attrs[k].name,
475 u16_val, pattern,
476 { 1, "\""
477 #if WORDS_BIGENDIAN
478 "\\xde"
479 #else
480 "\\xed"
481 #endif
482 "\"" },
483 { 2, "0xdeed" },
484 { 3, "0xdeed" });
485 }
486
487 static const struct val_name u8_br_attrs[] = {
488 { 7, "IFLA_BR_VLAN_FILTERING" },
489 { 14, "IFLA_BR_TOPOLOGY_CHANGE" },
490 { 15, "IFLA_BR_TOPOLOGY_CHANGE_DETECTED" },
491 { 22, "IFLA_BR_MCAST_ROUTER" },
492 { 23, "IFLA_BR_MCAST_SNOOPING" },
493 { 24, "IFLA_BR_MCAST_QUERY_USE_IFADDR" },
494 { 25, "IFLA_BR_MCAST_QUERIER" },
495 { 36, "IFLA_BR_NF_CALL_IPTABLES" },
496 { 37, "IFLA_BR_NF_CALL_IP6TABLES" },
497 { 38, "IFLA_BR_NF_CALL_ARPTABLES" },
498 { 41, "IFLA_BR_VLAN_STATS_ENABLED" },
499 { 42, "IFLA_BR_MCAST_STATS_ENABLED" },
500 { 43, "IFLA_BR_MCAST_IGMP_VERSION" },
501 { 44, "IFLA_BR_MCAST_MLD_VERSION" },
502 };
503
504 for (size_t k = 0; k < ARRAY_SIZE(u8_br_attrs); k++) {
505 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "bridge",
506 u8_br_attrs[k].val, u8_br_attrs[k].name,
507 u8_val, pattern,
508 { 0, NULL },
509 { 1, "161" },
510 { 2, "161" });
511 }
512
513 unsigned short eth_p = htons(0x88C7);
514 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "bridge",
515 8, "IFLA_BR_VLAN_PROTOCOL",
516 eth_p, pattern,
517 { 1, "\"\\x88\"" },
518 { 2, "htons(ETH_P_PREAUTH)" },
519 { 2, "htons(ETH_P_PREAUTH)" });
520
521 static const uint8_t bridge_id[]
522 = { 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xc0, 0xde, 0xad };
523 static const struct val_name br_id_attrs[] = {
524 { 10, "IFLA_BR_ROOT_ID" },
525 { 11, "IFLA_BR_BRIDGE_ID" },
526 };
527
528 for (size_t k = 0; k < ARRAY_SIZE(br_id_attrs); k++) {
529 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "bridge",
530 br_id_attrs[k].val, br_id_attrs[k].name,
531 bridge_id, pattern,
532 { 7, "\"\\xbe\\xef\\xfa\\xce"
533 "\\xde\\xc0\\xde\"" },
534 { 8, "{prio=[190, 239]"
535 ", addr=fa:ce:de:c0:de:ad}" },
536 { 9, "{prio=[190, 239]"
537 ", addr=fa:ce:de:c0:de:ad}" });
538 }
539
540 /* tun attrs */
541 static const struct val_name u8_tun_attrs[] = {
542 { 4, "IFLA_TUN_PI" },
543 { 5, "IFLA_TUN_VNET_HDR" },
544 { 6, "IFLA_TUN_PERSIST" },
545 { 7, "IFLA_TUN_MULTI_QUEUE" },
546 };
547
548 for (size_t k = 0; k < ARRAY_SIZE(u8_tun_attrs); k++) {
549 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "tun",
550 u8_tun_attrs[k].val, u8_tun_attrs[k].name,
551 u8_val, pattern,
552 { 0, NULL },
553 { 1, "161" },
554 { 2, "161" });
555 }
556
557 static const struct val_name u32_tun_attrs[] = {
558 { 8, "IFLA_TUN_NUM_QUEUES" },
559 { 9, "IFLA_TUN_NUM_DISABLED_QUEUES" },
560 };
561
562 for (size_t k = 0; k < ARRAY_SIZE(u32_tun_attrs); k++) {
563 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "tun",
564 u32_tun_attrs[k].val,
565 u32_tun_attrs[k].name,
566 u32_val, pattern,
567 { 3, "\""
568 #if WORDS_BIGENDIAN
569 "\\xba\\xdc\\x0d"
570 #else
571 "\\xed\\x0d\\xdc"
572 #endif
573 "\"" },
574 { 4, "3134983661" },
575 { 5, "3134983661" });
576 }
577
578 static const struct val_name und_tun_attrs[] = {
579 { 0, "IFLA_TUN_UNSPEC" },
580 { 10, "0xa /* IFLA_TUN_??? */" },
581 };
582
583 for (size_t k = 0; k < ARRAY_SIZE(und_tun_attrs); k++) {
584 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "tun",
585 und_tun_attrs[k].val,
586 und_tun_attrs[k].name,
587 unknown_msg, pattern,
588 { 2, "\"\\xab\\xac\"" },
589 { 4, "\"\\xab\\xac\\xdb\\xcd\"" },
590 { 6,
591 "\"\\xab\\xac\\xdb\\xcd\\x61\\x62\"" },
592 { 8, "\"\\xab\\xac\\xdb\\xcd\\x61\\x62"
593 "\\x63\\x64\"" },
594 { 10, "\"\\xab\\xac\\xdb\\xcd\\x61\\x62"
595 "\\x63\\x64\\x65\\x66\"" });
596 }
597
598 static const uint32_t minus_one = 0xffffffffU;
599 static const struct val_name uid_tun_attrs[] = {
600 { 1, "IFLA_TUN_OWNER" },
601 { 2, "IFLA_TUN_GROUP" },
602 };
603
604 for (size_t k = 0; k < ARRAY_SIZE(uid_tun_attrs); k++) {
605 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "tun",
606 uid_tun_attrs[k].val,
607 uid_tun_attrs[k].name,
608 u32_val, pattern,
609 { 3, "\""
610 #if WORDS_BIGENDIAN
611 "\\xba\\xdc\\x0d"
612 #else
613 "\\xed\\x0d\\xdc"
614 #endif
615 "\"" },
616 { 4, "3134983661" },
617 { 5, "3134983661" });
618
619 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "tun",
620 uid_tun_attrs[k].val,
621 uid_tun_attrs[k].name,
622 minus_one, pattern,
623 { 3, "\"\\xff\\xff\\xff\"" },
624 { 4, "-1" },
625 { 5, "-1" });
626 }
627
628 static const struct {
629 uint8_t val;
630 const char *str;
631 } tun_types[] = {
632 { 0, "0 /* IFF_??? */"},
633 { 1, "IFF_TUN"},
634 { 2, "IFF_TAP"},
635 { 3, "0x3 /* IFF_??? */"},
636 { 0xda, "0xda /* IFF_??? */"},
637 };
638
639 for (size_t k = 0; k < ARRAY_SIZE(tun_types); k++) {
640 TEST_NESTED_LINKINFO(fd, nlh0, 2, "IFLA_INFO_DATA", "tun",
641 3, "IFLA_TUN_TYPE",
642 tun_types[k].val, pattern,
643 { 0, NULL },
644 { 1, tun_types[k].str },
645 { 2, tun_types[k].str });
646 }
647
648
649 /* IFLA_INFO_KIND + IFLA_INFO_XSTATS */
650 TEST_UNKNOWN_TUNNELS(fd, nlh0, IFLA_INFO_XSTATS, "IFLA_INFO_XSTATS",
651 unknown_msg, sizeof(unknown_msg),
652 {unsupported_tunnel_types COMMA
653 /*
654 * can decoder decodes its data only if it's big
655 * enough.
656 */
657 unsupported_xstats_types COMMA
658 unsupported_data_types COMMA
659 NULL},
660 printf("\"\\xab\\xac\\xdb\\xcd\""));
661
662 uint32_t can_stats_data[] = {
663 0xbadc0de0, 0xbadc0de1, 0xbadc0de2, 0xbadc0de3,
664 0xbadc0de4, 0xbadc0de5,
665 };
666
667 TEST_LINKINFO(fd, nlh0, IFLA_INFO_XSTATS, "can",
668 can_stats_data, pattern, print_quoted_hex,
669 printf("{bus_error=3134983648"
670 ", error_warning=3134983649"
671 ", error_passive=3134983650"
672 ", bus_off=3134983651"
673 ", arbitration_lost=3134983652"
674 ", restarts=3134983653}"));
675
676
677 /* IFLA_INFO_KIND + IFLA_INFO_SLVAE_KIND */
678 TEST_UNKNOWN_TUNNELS(fd, nlh0,
679 IFLA_INFO_SLAVE_KIND, "IFLA_INFO_SLAVE_KIND",
680 unknown_msg, sizeof(unknown_msg),
681 {unsupported_tunnel_types COMMA
682 unsupported_xstats_types COMMA
683 unsupported_data_types COMMA
684 NULL},
685 printf("\"\\253\\254\\333\\315\"..."));
686
687
688 /* IFLA_INFO_KIND + IFLA_INFO_SLAVE_DATA */
689 TEST_UNKNOWN_TUNNELS(fd, nlh0,
690 IFLA_INFO_SLAVE_DATA, "IFLA_INFO_SLAVE_DATA",
691 unknown_msg, sizeof(unknown_msg),
692 {unsupported_tunnel_types COMMA
693 unsupported_xstats_types COMMA
694 unsupported_data_types COMMA
695 NULL},
696 printf("\"\\xab\\xac\\xdb\\xcd\""));
697
698
699 /* IFLA_INFO_KIND + unknown type */
700 TEST_UNKNOWN_TUNNELS(fd, nlh0, 6, "0x6 /* IFLA_INFO_??? */",
701 unknown_msg, sizeof(unknown_msg),
702 {unsupported_tunnel_types COMMA
703 unsupported_xstats_types COMMA
704 unsupported_data_types COMMA
705 NULL},
706 printf("\"\\xab\\xac\\xdb\\xcd\""));
707
708
709 puts("+++ exited with 0 +++");
710 return 0;
711 }
712