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