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 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