1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 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 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <inttypes.h> 37 #include <netinet/in.h> 38 39 #ifndef __linux__ 40 #include <net/socket.h> 41 #endif 42 43 #include <rte_string_fns.h> 44 45 #include <cmdline_parse.h> 46 #include <cmdline_parse_ipaddr.h> 47 48 #include "test_cmdline.h" 49 50 #define IP4(a,b,c,d) {((uint32_t)(((a) & 0xff)) | \ 51 (((b) & 0xff) << 8) | \ 52 (((c) & 0xff) << 16) | \ 53 ((d) & 0xff) << 24)} 54 55 #define U16_SWAP(x) \ 56 (((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)) 57 58 /* create IPv6 address, swapping bytes where needed */ 59 #define IP6(a,b,c,d,e,f,g,h) .ipv6 = \ 60 {.s6_addr16 = \ 61 {U16_SWAP(a),U16_SWAP(b),U16_SWAP(c),U16_SWAP(d),\ 62 U16_SWAP(e),U16_SWAP(f),U16_SWAP(g),U16_SWAP(h)}} 63 64 /** these are defined in netinet/in.h but not present in linux headers */ 65 #ifdef __linux__ 66 #define NIPQUAD_FMT "%u.%u.%u.%u" 67 #define NIPQUAD(addr) \ 68 (unsigned)((unsigned char *)&addr)[0], \ 69 (unsigned)((unsigned char *)&addr)[1], \ 70 (unsigned)((unsigned char *)&addr)[2], \ 71 (unsigned)((unsigned char *)&addr)[3] 72 73 #define NIP6_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x" 74 #define NIP6(addr) \ 75 (unsigned)((addr).s6_addr[0]), \ 76 (unsigned)((addr).s6_addr[1]), \ 77 (unsigned)((addr).s6_addr[2]), \ 78 (unsigned)((addr).s6_addr[3]), \ 79 (unsigned)((addr).s6_addr[4]), \ 80 (unsigned)((addr).s6_addr[5]), \ 81 (unsigned)((addr).s6_addr[6]), \ 82 (unsigned)((addr).s6_addr[7]), \ 83 (unsigned)((addr).s6_addr[8]), \ 84 (unsigned)((addr).s6_addr[9]), \ 85 (unsigned)((addr).s6_addr[10]), \ 86 (unsigned)((addr).s6_addr[11]), \ 87 (unsigned)((addr).s6_addr[12]), \ 88 (unsigned)((addr).s6_addr[13]), \ 89 (unsigned)((addr).s6_addr[14]), \ 90 (unsigned)((addr).s6_addr[15]) 91 #endif 92 93 94 95 struct ipaddr_str { 96 const char * str; 97 cmdline_ipaddr_t addr; 98 unsigned flags; 99 }; 100 101 const struct ipaddr_str ipaddr_valid_strs[] = { 102 {"0.0.0.0", {AF_INET, {IP4(0,0,0,0)}, 0}, 103 CMDLINE_IPADDR_V4}, 104 {"0.0.0.0/0", {AF_INET, {IP4(0,0,0,0)}, 0}, 105 CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK}, 106 {"0.0.0.0/24", {AF_INET, {IP4(0,0,0,0)}, 24}, 107 CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK}, 108 {"192.168.1.0/24", {AF_INET, {IP4(192,168,1,0)}, 24}, 109 CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK}, 110 {"012.34.56.78/24", {AF_INET, {IP4(12,34,56,78)}, 24}, 111 CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK}, 112 {"34.56.78.90/1", {AF_INET, {IP4(34,56,78,90)}, 1}, 113 CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK}, 114 {"::", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 0}, 115 CMDLINE_IPADDR_V6}, 116 {"::1", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 0}, 117 CMDLINE_IPADDR_V6}, 118 {"::1/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 32}, 119 CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, 120 {"::/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 32}, 121 CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, 122 /* RFC5952 requests that only lowercase should be used */ 123 {"1234:5678:90ab:cdef:4321:8765:BA09:FEDC", {AF_INET6, 124 {IP6(0x1234,0x5678,0x90AB,0xCDEF,0x4321,0x8765,0xBA09,0xFEDC)}, 125 0}, 126 CMDLINE_IPADDR_V6}, 127 {"1234::1234/64", {AF_INET6, 128 {IP6(0x1234,0,0,0,0,0,0,0x1234)}, 129 64}, 130 CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, 131 {"1234::/64", {AF_INET6, 132 {IP6(0x1234,0,0,0,0,0,0,0)}, 133 64}, 134 CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, 135 {"1:1::1/32", {AF_INET6, 136 {IP6(1,1,0,0,0,0,0,1)}, 137 32}, 138 CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, 139 {"1:2:3:4::/64", {AF_INET6, 140 {IP6(1,2,3,4,0,0,0,0)}, 141 64}, 142 CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, 143 {"::ffff:192.168.1.0/64", {AF_INET6, 144 {IP6(0,0,0,0,0,0xFFFF,0xC0A8,0x100)}, 145 64}, 146 CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, 147 /* RFC5952 requests not using :: to skip one block of zeros*/ 148 {"1::2:3:4:5:6:7", {AF_INET6, 149 {IP6(1,0,2,3,4,5,6,7)}, 150 0}, 151 CMDLINE_IPADDR_V6}, 152 }; 153 154 const char * ipaddr_garbage_addr4_strs[] = { 155 /* IPv4 */ 156 "192.168.1.0 garbage", 157 "192.168.1.0\0garbage", 158 "192.168.1.0#garbage", 159 "192.168.1.0\tgarbage", 160 "192.168.1.0\rgarbage", 161 "192.168.1.0\ngarbage", 162 }; 163 #define IPv4_GARBAGE_ADDR IP4(192,168,1,0) 164 165 const char * ipaddr_garbage_addr6_strs[] = { 166 /* IPv6 */ 167 "1:2:3:4::8 garbage", 168 "1:2:3:4::8#garbage", 169 "1:2:3:4::8\0garbage", 170 "1:2:3:4::8\rgarbage", 171 "1:2:3:4::8\ngarbage", 172 "1:2:3:4::8\tgarbage", 173 }; 174 #define IPv6_GARBAGE_ADDR {IP6(1,2,3,4,0,0,0,8)} 175 176 const char * ipaddr_garbage_network4_strs[] = { 177 /* IPv4 */ 178 "192.168.1.0/24 garbage", 179 "192.168.1.0/24\0garbage", 180 "192.168.1.0/24#garbage", 181 "192.168.1.0/24\tgarbage", 182 "192.168.1.0/24\rgarbage", 183 "192.168.1.0/24\ngarbage", 184 }; 185 #define IPv4_GARBAGE_PREFIX 24 186 187 const char * ipaddr_garbage_network6_strs[] = { 188 /* IPv6 */ 189 "1:2:3:4::8/64 garbage", 190 "1:2:3:4::8/64#garbage", 191 "1:2:3:4::8/64\0garbage", 192 "1:2:3:4::8/64\rgarbage", 193 "1:2:3:4::8/64\ngarbage", 194 "1:2:3:4::8/64\tgarbage", 195 }; 196 #define IPv6_GARBAGE_PREFIX 64 197 198 199 200 const char * ipaddr_invalid_strs[] = { 201 /** IPv4 **/ 202 203 /* invalid numbers */ 204 "0.0.0.-1", 205 "0.0.-1.0", 206 "0.-1.0.0", 207 "-1.0.0.0", 208 "0.0.0.-1/24", 209 "256.123.123.123", 210 "255.256.123.123", 211 "255.255.256.123", 212 "255.255.255.256", 213 "256.123.123.123/24", 214 "255.256.123.123/24", 215 "255.255.256.123/24", 216 "255.255.255.256/24", 217 /* invalid network mask */ 218 "1.2.3.4/33", 219 "1.2.3.4/33231313", 220 "1.2.3.4/-1", 221 "1.2.3.4/24/33", 222 "1.2.3.4/24/-1", 223 "1.2.3.4/24/", 224 /* wrong format */ 225 "1/24" 226 "/24" 227 "123.123.123", 228 "123.123.123.", 229 "123.123.123.123.", 230 "123.123.123..123", 231 "123.123.123.123.123", 232 ".123.123.123", 233 ".123.123.123.123", 234 "123.123.123/24", 235 "123.123.123./24", 236 "123.123.123.123./24", 237 "123.123.123..123/24", 238 "123.123.123.123.123/24", 239 ".123.123.123/24", 240 ".123.123.123.123/24", 241 /* invalid characters */ 242 "123.123.123.12F", 243 "123.123.12F.123", 244 "123.12F.123.123", 245 "12F.123.123.123", 246 "12J.123.123.123", 247 "123,123,123,123", 248 "123!123!123!12F", 249 "123.123.123.123/4F", 250 251 /** IPv6 **/ 252 253 /* wrong format */ 254 "::fffff", 255 "ffff:", 256 "1:2:3:4:5:6:7:192.168.1.1", 257 "1234:192.168.1.1:ffff::", 258 "1:2:3:4:5:6:7:890ab", 259 "1:2:3:4:5:6:7890a:b", 260 "1:2:3:4:5:67890:a:b", 261 "1:2:3:4:56789:0:a:b", 262 "1:2:3:45678:9:0:a:b", 263 "1:2:34567:8:9:0:a:b", 264 "1:23456:7:8:9:0:a:b", 265 "12345:6:7:8:9:0:a:b", 266 "1:::2", 267 "1::::2", 268 "::fffff/64", 269 "1::2::3", 270 "1::2::3/64", 271 ":1:2", 272 ":1:2/64", 273 ":1::2", 274 ":1::2/64", 275 "1::2:3:4:5:6:7:8/64", 276 277 /* invalid network mask */ 278 "1:2:3:4:5:6:7:8/129", 279 "1:2:3:4:5:6:7:8/-1", 280 281 /* invalid characters */ 282 "a:b:c:d:e:f:g::", 283 284 /** misc **/ 285 286 /* too long */ 287 "1234:1234:1234:1234:1234:1234:1234:1234:1234:1234:1234" 288 "random invalid text", 289 "", 290 "\0", 291 " ", 292 }; 293 294 #define IPADDR_VALID_STRS_SIZE \ 295 (sizeof(ipaddr_valid_strs) / sizeof(ipaddr_valid_strs[0])) 296 #define IPADDR_GARBAGE_ADDR4_STRS_SIZE \ 297 (sizeof(ipaddr_garbage_addr4_strs) / sizeof(ipaddr_garbage_addr4_strs[0])) 298 #define IPADDR_GARBAGE_ADDR6_STRS_SIZE \ 299 (sizeof(ipaddr_garbage_addr6_strs) / sizeof(ipaddr_garbage_addr6_strs[0])) 300 #define IPADDR_GARBAGE_NETWORK4_STRS_SIZE \ 301 (sizeof(ipaddr_garbage_network4_strs) / sizeof(ipaddr_garbage_network4_strs[0])) 302 #define IPADDR_GARBAGE_NETWORK6_STRS_SIZE \ 303 (sizeof(ipaddr_garbage_network6_strs) / sizeof(ipaddr_garbage_network6_strs[0])) 304 #define IPADDR_INVALID_STRS_SIZE \ 305 (sizeof(ipaddr_invalid_strs) / sizeof(ipaddr_invalid_strs[0])) 306 307 static void 308 dump_addr(cmdline_ipaddr_t addr) 309 { 310 switch (addr.family) { 311 case AF_INET: 312 { 313 printf(NIPQUAD_FMT " prefixlen=%u\n", 314 NIPQUAD(addr.addr.ipv4.s_addr), addr.prefixlen); 315 break; 316 } 317 case AF_INET6: 318 { 319 printf(NIP6_FMT " prefixlen=%u\n", 320 NIP6(addr.addr.ipv6), addr.prefixlen); 321 break; 322 } 323 default: 324 printf("Can't dump: unknown address family.\n"); 325 return; 326 } 327 } 328 329 330 static int 331 is_addr_different(cmdline_ipaddr_t addr1, cmdline_ipaddr_t addr2) 332 { 333 if (addr1.family != addr2.family) 334 return 1; 335 336 if (addr1.prefixlen != addr2.prefixlen) 337 return 1; 338 339 switch (addr1.family) { 340 /* IPv4 */ 341 case AF_INET: 342 if (memcmp(&addr1.addr.ipv4, &addr2.addr.ipv4, 343 sizeof(struct in_addr)) != 0) 344 return 1; 345 break; 346 /* IPv6 */ 347 case AF_INET6: 348 { 349 if (memcmp(&addr1.addr.ipv6, &addr2.addr.ipv6, 350 sizeof(struct in6_addr)) != 0) 351 return 1; 352 break; 353 } 354 /* thing that should not be */ 355 default: 356 return -1; 357 } 358 return 0; 359 } 360 361 static int 362 can_parse_addr(unsigned addr_flags, unsigned test_flags) 363 { 364 if ((test_flags & addr_flags) == addr_flags) { 365 /* if we are not trying to parse network addresses */ 366 if (test_flags < CMDLINE_IPADDR_NETWORK) 367 return 1; 368 /* if this is a network address */ 369 else if (addr_flags & CMDLINE_IPADDR_NETWORK) 370 return 1; 371 } 372 return 0; 373 } 374 375 int 376 test_parse_ipaddr_valid(void) 377 { 378 cmdline_parse_token_ipaddr_t token; 379 char buf[CMDLINE_TEST_BUFSIZE]; 380 cmdline_ipaddr_t result; 381 unsigned i; 382 uint8_t flags; 383 int ret; 384 385 /* cover all cases in help */ 386 for (flags = 0x1; flags < 0x8; flags++) { 387 token.ipaddr_data.flags = flags; 388 389 memset(buf, 0, sizeof(buf)); 390 391 if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 392 buf, sizeof(buf)) == -1) { 393 printf("Error: help rejected valid parameters!\n"); 394 return -1; 395 } 396 } 397 398 /* test valid strings */ 399 for (i = 0; i < IPADDR_VALID_STRS_SIZE; i++) { 400 401 /* test each valid string against different flags */ 402 for (flags = 1; flags < 0x8; flags++) { 403 404 /* skip bad flag */ 405 if (flags == CMDLINE_IPADDR_NETWORK) 406 continue; 407 408 /* clear out everything */ 409 memset(buf, 0, sizeof(buf)); 410 memset(&result, 0, sizeof(result)); 411 memset(&token, 0, sizeof(token)); 412 413 token.ipaddr_data.flags = flags; 414 415 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 416 buf, sizeof(buf)); 417 418 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 419 ipaddr_valid_strs[i].str, (void*)&result); 420 421 /* if should have passed, or should have failed */ 422 if ((ret < 0) == 423 (can_parse_addr(ipaddr_valid_strs[i].flags, flags))) { 424 printf("Error: unexpected behavior when parsing %s as %s!\n", 425 ipaddr_valid_strs[i].str, buf); 426 printf("Parsed result: "); 427 dump_addr(result); 428 printf("Expected result: "); 429 dump_addr(ipaddr_valid_strs[i].addr); 430 return -1; 431 } 432 if (ret != -1 && 433 is_addr_different(result, ipaddr_valid_strs[i].addr)) { 434 printf("Error: result mismatch when parsing %s as %s!\n", 435 ipaddr_valid_strs[i].str, buf); 436 printf("Parsed result: "); 437 dump_addr(result); 438 printf("Expected result: "); 439 dump_addr(ipaddr_valid_strs[i].addr); 440 return -1; 441 } 442 } 443 } 444 445 /* test garbage ipv4 address strings */ 446 for (i = 0; i < IPADDR_GARBAGE_ADDR4_STRS_SIZE; i++) { 447 448 struct in_addr tmp = IPv4_GARBAGE_ADDR; 449 450 /* test each valid string against different flags */ 451 for (flags = 1; flags < 0x8; flags++) { 452 453 /* skip bad flag */ 454 if (flags == CMDLINE_IPADDR_NETWORK) 455 continue; 456 457 /* clear out everything */ 458 memset(buf, 0, sizeof(buf)); 459 memset(&result, 0, sizeof(result)); 460 memset(&token, 0, sizeof(token)); 461 462 token.ipaddr_data.flags = flags; 463 464 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 465 buf, sizeof(buf)); 466 467 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 468 ipaddr_garbage_addr4_strs[i], (void*)&result); 469 470 /* if should have passed, or should have failed */ 471 if ((ret < 0) == 472 (can_parse_addr(CMDLINE_IPADDR_V4, flags))) { 473 printf("Error: unexpected behavior when parsing %s as %s!\n", 474 ipaddr_garbage_addr4_strs[i], buf); 475 return -1; 476 } 477 if (ret != -1 && 478 memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) { 479 printf("Error: result mismatch when parsing %s as %s!\n", 480 ipaddr_garbage_addr4_strs[i], buf); 481 return -1; 482 } 483 } 484 } 485 486 /* test garbage ipv6 address strings */ 487 for (i = 0; i < IPADDR_GARBAGE_ADDR6_STRS_SIZE; i++) { 488 489 cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR}; 490 491 /* test each valid string against different flags */ 492 for (flags = 1; flags < 0x8; flags++) { 493 494 /* skip bad flag */ 495 if (flags == CMDLINE_IPADDR_NETWORK) 496 continue; 497 498 /* clear out everything */ 499 memset(buf, 0, sizeof(buf)); 500 memset(&result, 0, sizeof(result)); 501 memset(&token, 0, sizeof(token)); 502 503 token.ipaddr_data.flags = flags; 504 505 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 506 buf, sizeof(buf)); 507 508 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 509 ipaddr_garbage_addr6_strs[i], (void*)&result); 510 511 /* if should have passed, or should have failed */ 512 if ((ret < 0) == 513 (can_parse_addr(CMDLINE_IPADDR_V6, flags))) { 514 printf("Error: unexpected behavior when parsing %s as %s!\n", 515 ipaddr_garbage_addr6_strs[i], buf); 516 return -1; 517 } 518 if (ret != -1 && 519 memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) { 520 printf("Error: result mismatch when parsing %s as %s!\n", 521 ipaddr_garbage_addr6_strs[i], buf); 522 return -1; 523 } 524 } 525 } 526 527 528 /* test garbage ipv4 network strings */ 529 for (i = 0; i < IPADDR_GARBAGE_NETWORK4_STRS_SIZE; i++) { 530 531 struct in_addr tmp = IPv4_GARBAGE_ADDR; 532 533 /* test each valid string against different flags */ 534 for (flags = 1; flags < 0x8; flags++) { 535 536 /* skip bad flag */ 537 if (flags == CMDLINE_IPADDR_NETWORK) 538 continue; 539 540 /* clear out everything */ 541 memset(buf, 0, sizeof(buf)); 542 memset(&result, 0, sizeof(result)); 543 memset(&token, 0, sizeof(token)); 544 545 token.ipaddr_data.flags = flags; 546 547 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 548 buf, sizeof(buf)); 549 550 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 551 ipaddr_garbage_network4_strs[i], (void*)&result); 552 553 /* if should have passed, or should have failed */ 554 if ((ret < 0) == 555 (can_parse_addr(CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK, flags))) { 556 printf("Error: unexpected behavior when parsing %s as %s!\n", 557 ipaddr_garbage_network4_strs[i], buf); 558 return -1; 559 } 560 if (ret != -1 && 561 memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) { 562 printf("Error: result mismatch when parsing %s as %s!\n", 563 ipaddr_garbage_network4_strs[i], buf); 564 return -1; 565 } 566 } 567 } 568 569 /* test garbage ipv6 address strings */ 570 for (i = 0; i < IPADDR_GARBAGE_NETWORK6_STRS_SIZE; i++) { 571 572 cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR}; 573 574 /* test each valid string against different flags */ 575 for (flags = 1; flags < 0x8; flags++) { 576 577 /* skip bad flag */ 578 if (flags == CMDLINE_IPADDR_NETWORK) 579 continue; 580 581 /* clear out everything */ 582 memset(buf, 0, sizeof(buf)); 583 memset(&result, 0, sizeof(result)); 584 memset(&token, 0, sizeof(token)); 585 586 token.ipaddr_data.flags = flags; 587 588 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 589 buf, sizeof(buf)); 590 591 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 592 ipaddr_garbage_network6_strs[i], (void*)&result); 593 594 /* if should have passed, or should have failed */ 595 if ((ret < 0) == 596 (can_parse_addr(CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK, flags))) { 597 printf("Error: unexpected behavior when parsing %s as %s!\n", 598 ipaddr_garbage_network6_strs[i], buf); 599 return -1; 600 } 601 if (ret != -1 && 602 memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) { 603 printf("Error: result mismatch when parsing %s as %s!\n", 604 ipaddr_garbage_network6_strs[i], buf); 605 return -1; 606 } 607 } 608 } 609 610 return 0; 611 } 612 613 int 614 test_parse_ipaddr_invalid_data(void) 615 { 616 cmdline_parse_token_ipaddr_t token; 617 char buf[CMDLINE_TEST_BUFSIZE]; 618 cmdline_ipaddr_t result; 619 unsigned i; 620 uint8_t flags; 621 int ret; 622 623 memset(&result, 0, sizeof(result)); 624 625 /* test invalid strings */ 626 for (i = 0; i < IPADDR_INVALID_STRS_SIZE; i++) { 627 628 /* test each valid string against different flags */ 629 for (flags = 1; flags < 0x8; flags++) { 630 631 /* skip bad flag */ 632 if (flags == CMDLINE_IPADDR_NETWORK) 633 continue; 634 635 /* clear out everything */ 636 memset(buf, 0, sizeof(buf)); 637 memset(&token, 0, sizeof(token)); 638 639 token.ipaddr_data.flags = flags; 640 641 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 642 buf, sizeof(buf)); 643 644 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 645 ipaddr_invalid_strs[i], (void*)&result); 646 647 if (ret != -1) { 648 printf("Error: parsing %s as %s succeeded!\n", 649 ipaddr_invalid_strs[i], buf); 650 printf("Parsed result: "); 651 dump_addr(result); 652 return -1; 653 } 654 } 655 } 656 657 return 0; 658 } 659 660 int 661 test_parse_ipaddr_invalid_param(void) 662 { 663 cmdline_parse_token_ipaddr_t token; 664 char buf[CMDLINE_TEST_BUFSIZE]; 665 cmdline_ipaddr_t result; 666 667 rte_snprintf(buf, sizeof(buf), "1.2.3.4"); 668 token.ipaddr_data.flags = CMDLINE_IPADDR_V4; 669 670 /* null token */ 671 if (cmdline_parse_ipaddr(NULL, buf, (void*)&result) != -1) { 672 printf("Error: parser accepted invalid parameters!\n"); 673 return -1; 674 } 675 /* null buffer */ 676 if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 677 NULL, (void*)&result) != -1) { 678 printf("Error: parser accepted invalid parameters!\n"); 679 return -1; 680 } 681 /* empty buffer */ 682 if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 683 "", (void*)&result) != -1) { 684 printf("Error: parser accepted invalid parameters!\n"); 685 return -1; 686 } 687 /* null result */ 688 if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 689 buf, NULL) == -1) { 690 printf("Error: parser rejected null result!\n"); 691 return -1; 692 } 693 694 /* null token */ 695 if (cmdline_get_help_ipaddr(NULL, buf, 0) != -1) { 696 printf("Error: help accepted invalid parameters!\n"); 697 return -1; 698 } 699 /* null buffer */ 700 if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 701 NULL, 0) != -1) { 702 printf("Error: help accepted invalid parameters!\n"); 703 return -1; 704 } 705 return 0; 706 } 707