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 430 /* if should have passed, or should have failed */ 431 if ((ret < 0) == 432 (can_parse_addr(ipaddr_valid_strs[i].flags, flags))) { 433 printf("Error: unexpected behavior when parsing %s as %s!\n", 434 ipaddr_valid_strs[i].str, buf); 435 printf("Parsed result: "); 436 dump_addr(result); 437 printf("Expected result: "); 438 dump_addr(ipaddr_valid_strs[i].addr); 439 return -1; 440 } 441 if (ret != -1 && 442 is_addr_different(result, ipaddr_valid_strs[i].addr)) { 443 printf("Error: result mismatch when parsing %s as %s!\n", 444 ipaddr_valid_strs[i].str, buf); 445 printf("Parsed result: "); 446 dump_addr(result); 447 printf("Expected result: "); 448 dump_addr(ipaddr_valid_strs[i].addr); 449 return -1; 450 } 451 } 452 } 453 454 /* test garbage ipv4 address strings */ 455 for (i = 0; i < IPADDR_GARBAGE_ADDR4_STRS_SIZE; i++) { 456 457 struct in_addr tmp = IPv4_GARBAGE_ADDR; 458 459 /* test each valid string against different flags */ 460 for (flags = 1; flags < 0x8; flags++) { 461 462 /* skip bad flag */ 463 if (flags == CMDLINE_IPADDR_NETWORK) 464 continue; 465 466 /* clear out everything */ 467 memset(buf, 0, sizeof(buf)); 468 memset(&result, 0, sizeof(result)); 469 memset(&token, 0, sizeof(token)); 470 471 token.ipaddr_data.flags = flags; 472 473 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 474 buf, sizeof(buf)); 475 476 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 477 ipaddr_garbage_addr4_strs[i], (void*)&result); 478 479 /* if should have passed, or should have failed */ 480 if ((ret < 0) == 481 (can_parse_addr(CMDLINE_IPADDR_V4, flags))) { 482 printf("Error: unexpected behavior when parsing %s as %s!\n", 483 ipaddr_garbage_addr4_strs[i], buf); 484 return -1; 485 } 486 if (ret != -1 && 487 memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) { 488 printf("Error: result mismatch when parsing %s as %s!\n", 489 ipaddr_garbage_addr4_strs[i], buf); 490 return -1; 491 } 492 } 493 } 494 495 /* test garbage ipv6 address strings */ 496 for (i = 0; i < IPADDR_GARBAGE_ADDR6_STRS_SIZE; i++) { 497 498 cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR}; 499 500 /* test each valid string against different flags */ 501 for (flags = 1; flags < 0x8; flags++) { 502 503 /* skip bad flag */ 504 if (flags == CMDLINE_IPADDR_NETWORK) 505 continue; 506 507 /* clear out everything */ 508 memset(buf, 0, sizeof(buf)); 509 memset(&result, 0, sizeof(result)); 510 memset(&token, 0, sizeof(token)); 511 512 token.ipaddr_data.flags = flags; 513 514 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 515 buf, sizeof(buf)); 516 517 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 518 ipaddr_garbage_addr6_strs[i], (void*)&result); 519 520 /* if should have passed, or should have failed */ 521 if ((ret < 0) == 522 (can_parse_addr(CMDLINE_IPADDR_V6, flags))) { 523 printf("Error: unexpected behavior when parsing %s as %s!\n", 524 ipaddr_garbage_addr6_strs[i], buf); 525 return -1; 526 } 527 if (ret != -1 && 528 memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) { 529 printf("Error: result mismatch when parsing %s as %s!\n", 530 ipaddr_garbage_addr6_strs[i], buf); 531 return -1; 532 } 533 } 534 } 535 536 537 /* test garbage ipv4 network strings */ 538 for (i = 0; i < IPADDR_GARBAGE_NETWORK4_STRS_SIZE; i++) { 539 540 struct in_addr tmp = IPv4_GARBAGE_ADDR; 541 542 /* test each valid string against different flags */ 543 for (flags = 1; flags < 0x8; flags++) { 544 545 /* skip bad flag */ 546 if (flags == CMDLINE_IPADDR_NETWORK) 547 continue; 548 549 /* clear out everything */ 550 memset(buf, 0, sizeof(buf)); 551 memset(&result, 0, sizeof(result)); 552 memset(&token, 0, sizeof(token)); 553 554 token.ipaddr_data.flags = flags; 555 556 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 557 buf, sizeof(buf)); 558 559 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 560 ipaddr_garbage_network4_strs[i], (void*)&result); 561 562 /* if should have passed, or should have failed */ 563 if ((ret < 0) == 564 (can_parse_addr(CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK, flags))) { 565 printf("Error: unexpected behavior when parsing %s as %s!\n", 566 ipaddr_garbage_network4_strs[i], buf); 567 return -1; 568 } 569 if (ret != -1 && 570 memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) { 571 printf("Error: result mismatch when parsing %s as %s!\n", 572 ipaddr_garbage_network4_strs[i], buf); 573 return -1; 574 } 575 } 576 } 577 578 /* test garbage ipv6 address strings */ 579 for (i = 0; i < IPADDR_GARBAGE_NETWORK6_STRS_SIZE; i++) { 580 581 cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR}; 582 583 /* test each valid string against different flags */ 584 for (flags = 1; flags < 0x8; flags++) { 585 586 /* skip bad flag */ 587 if (flags == CMDLINE_IPADDR_NETWORK) 588 continue; 589 590 /* clear out everything */ 591 memset(buf, 0, sizeof(buf)); 592 memset(&result, 0, sizeof(result)); 593 memset(&token, 0, sizeof(token)); 594 595 token.ipaddr_data.flags = flags; 596 597 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 598 buf, sizeof(buf)); 599 600 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 601 ipaddr_garbage_network6_strs[i], (void*)&result); 602 603 /* if should have passed, or should have failed */ 604 if ((ret < 0) == 605 (can_parse_addr(CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK, flags))) { 606 printf("Error: unexpected behavior when parsing %s as %s!\n", 607 ipaddr_garbage_network6_strs[i], buf); 608 return -1; 609 } 610 if (ret != -1 && 611 memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) { 612 printf("Error: result mismatch when parsing %s as %s!\n", 613 ipaddr_garbage_network6_strs[i], buf); 614 return -1; 615 } 616 } 617 } 618 619 return 0; 620 } 621 622 int 623 test_parse_ipaddr_invalid_data(void) 624 { 625 cmdline_parse_token_ipaddr_t token; 626 char buf[CMDLINE_TEST_BUFSIZE]; 627 cmdline_ipaddr_t result; 628 unsigned i; 629 uint8_t flags; 630 int ret; 631 632 memset(&result, 0, sizeof(result)); 633 634 /* test invalid strings */ 635 for (i = 0; i < IPADDR_INVALID_STRS_SIZE; i++) { 636 637 /* test each valid string against different flags */ 638 for (flags = 1; flags < 0x8; flags++) { 639 640 /* skip bad flag */ 641 if (flags == CMDLINE_IPADDR_NETWORK) 642 continue; 643 644 /* clear out everything */ 645 memset(buf, 0, sizeof(buf)); 646 memset(&token, 0, sizeof(token)); 647 648 token.ipaddr_data.flags = flags; 649 650 cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 651 buf, sizeof(buf)); 652 653 ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 654 ipaddr_invalid_strs[i], (void*)&result); 655 656 if (ret != -1) { 657 printf("Error: parsing %s as %s succeeded!\n", 658 ipaddr_invalid_strs[i], buf); 659 printf("Parsed result: "); 660 dump_addr(result); 661 return -1; 662 } 663 } 664 } 665 666 return 0; 667 } 668 669 int 670 test_parse_ipaddr_invalid_param(void) 671 { 672 cmdline_parse_token_ipaddr_t token; 673 char buf[CMDLINE_TEST_BUFSIZE]; 674 cmdline_ipaddr_t result; 675 676 snprintf(buf, sizeof(buf), "1.2.3.4"); 677 token.ipaddr_data.flags = CMDLINE_IPADDR_V4; 678 679 /* null token */ 680 if (cmdline_parse_ipaddr(NULL, buf, (void*)&result) != -1) { 681 printf("Error: parser accepted invalid parameters!\n"); 682 return -1; 683 } 684 /* null buffer */ 685 if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 686 NULL, (void*)&result) != -1) { 687 printf("Error: parser accepted invalid parameters!\n"); 688 return -1; 689 } 690 /* empty buffer */ 691 if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 692 "", (void*)&result) != -1) { 693 printf("Error: parser accepted invalid parameters!\n"); 694 return -1; 695 } 696 /* null result */ 697 if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, 698 buf, NULL) == -1) { 699 printf("Error: parser rejected null result!\n"); 700 return -1; 701 } 702 703 /* null token */ 704 if (cmdline_get_help_ipaddr(NULL, buf, 0) != -1) { 705 printf("Error: help accepted invalid parameters!\n"); 706 return -1; 707 } 708 /* null buffer */ 709 if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, 710 NULL, 0) != -1) { 711 printf("Error: help accepted invalid parameters!\n"); 712 return -1; 713 } 714 return 0; 715 } 716