14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang * Copyright(c) 2010-2014 Intel Corporation
34418919fSjohnjiang */
44418919fSjohnjiang
54418919fSjohnjiang #include <stdio.h>
64418919fSjohnjiang #include <string.h>
74418919fSjohnjiang #include <inttypes.h>
84418919fSjohnjiang #include <netinet/in.h>
94418919fSjohnjiang #include <sys/socket.h>
104418919fSjohnjiang
114418919fSjohnjiang #include <rte_string_fns.h>
124418919fSjohnjiang
134418919fSjohnjiang #include <cmdline_parse.h>
144418919fSjohnjiang #include <cmdline_parse_ipaddr.h>
154418919fSjohnjiang
164418919fSjohnjiang #include "test_cmdline.h"
174418919fSjohnjiang
184418919fSjohnjiang #define IP4(a,b,c,d) {((uint32_t)(((a) & 0xff)) | \
194418919fSjohnjiang (((b) & 0xff) << 8) | \
204418919fSjohnjiang (((c) & 0xff) << 16) | \
214418919fSjohnjiang ((d) & 0xff) << 24)}
224418919fSjohnjiang
234418919fSjohnjiang #define U16_SWAP(x) \
244418919fSjohnjiang (((x & 0xFF) << 8) | ((x & 0xFF00) >> 8))
254418919fSjohnjiang
264418919fSjohnjiang /* create IPv6 address, swapping bytes where needed */
274418919fSjohnjiang #ifndef s6_addr16
284418919fSjohnjiang # define s6_addr16 __u6_addr.__u6_addr16
294418919fSjohnjiang #endif
304418919fSjohnjiang #define IP6(a,b,c,d,e,f,g,h) .ipv6 = \
314418919fSjohnjiang {.s6_addr16 = \
324418919fSjohnjiang {U16_SWAP(a),U16_SWAP(b),U16_SWAP(c),U16_SWAP(d),\
334418919fSjohnjiang U16_SWAP(e),U16_SWAP(f),U16_SWAP(g),U16_SWAP(h)}}
344418919fSjohnjiang
354418919fSjohnjiang /** these are defined in netinet/in.h but not present in linux headers */
364418919fSjohnjiang #ifndef NIPQUAD
374418919fSjohnjiang
384418919fSjohnjiang #define NIPQUAD_FMT "%u.%u.%u.%u"
394418919fSjohnjiang #define NIPQUAD(addr) \
404418919fSjohnjiang (unsigned)((unsigned char *)&addr)[0], \
414418919fSjohnjiang (unsigned)((unsigned char *)&addr)[1], \
424418919fSjohnjiang (unsigned)((unsigned char *)&addr)[2], \
434418919fSjohnjiang (unsigned)((unsigned char *)&addr)[3]
444418919fSjohnjiang
454418919fSjohnjiang #define NIP6_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
464418919fSjohnjiang #define NIP6(addr) \
474418919fSjohnjiang (unsigned)((addr).s6_addr[0]), \
484418919fSjohnjiang (unsigned)((addr).s6_addr[1]), \
494418919fSjohnjiang (unsigned)((addr).s6_addr[2]), \
504418919fSjohnjiang (unsigned)((addr).s6_addr[3]), \
514418919fSjohnjiang (unsigned)((addr).s6_addr[4]), \
524418919fSjohnjiang (unsigned)((addr).s6_addr[5]), \
534418919fSjohnjiang (unsigned)((addr).s6_addr[6]), \
544418919fSjohnjiang (unsigned)((addr).s6_addr[7]), \
554418919fSjohnjiang (unsigned)((addr).s6_addr[8]), \
564418919fSjohnjiang (unsigned)((addr).s6_addr[9]), \
574418919fSjohnjiang (unsigned)((addr).s6_addr[10]), \
584418919fSjohnjiang (unsigned)((addr).s6_addr[11]), \
594418919fSjohnjiang (unsigned)((addr).s6_addr[12]), \
604418919fSjohnjiang (unsigned)((addr).s6_addr[13]), \
614418919fSjohnjiang (unsigned)((addr).s6_addr[14]), \
624418919fSjohnjiang (unsigned)((addr).s6_addr[15])
634418919fSjohnjiang
644418919fSjohnjiang #endif
654418919fSjohnjiang
664418919fSjohnjiang
674418919fSjohnjiang
684418919fSjohnjiang struct ipaddr_str {
694418919fSjohnjiang const char * str;
704418919fSjohnjiang cmdline_ipaddr_t addr;
714418919fSjohnjiang unsigned flags;
724418919fSjohnjiang };
734418919fSjohnjiang
744418919fSjohnjiang const struct ipaddr_str ipaddr_valid_strs[] = {
754418919fSjohnjiang {"0.0.0.0", {AF_INET, {IP4(0,0,0,0)}, 0},
764418919fSjohnjiang CMDLINE_IPADDR_V4},
774418919fSjohnjiang {"0.0.0.0/0", {AF_INET, {IP4(0,0,0,0)}, 0},
784418919fSjohnjiang CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
794418919fSjohnjiang {"0.0.0.0/24", {AF_INET, {IP4(0,0,0,0)}, 24},
804418919fSjohnjiang CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
814418919fSjohnjiang {"192.168.1.0/24", {AF_INET, {IP4(192,168,1,0)}, 24},
824418919fSjohnjiang CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
834418919fSjohnjiang {"34.56.78.90/1", {AF_INET, {IP4(34,56,78,90)}, 1},
844418919fSjohnjiang CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
854418919fSjohnjiang {"::", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 0},
864418919fSjohnjiang CMDLINE_IPADDR_V6},
874418919fSjohnjiang {"::1", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 0},
884418919fSjohnjiang CMDLINE_IPADDR_V6},
894418919fSjohnjiang {"::1/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 32},
904418919fSjohnjiang CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
914418919fSjohnjiang {"::/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 32},
924418919fSjohnjiang CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
934418919fSjohnjiang /* RFC5952 requests that only lowercase should be used */
944418919fSjohnjiang {"1234:5678:90ab:cdef:4321:8765:BA09:FEDC", {AF_INET6,
954418919fSjohnjiang {IP6(0x1234,0x5678,0x90AB,0xCDEF,0x4321,0x8765,0xBA09,0xFEDC)},
964418919fSjohnjiang 0},
974418919fSjohnjiang CMDLINE_IPADDR_V6},
984418919fSjohnjiang {"1234::1234/64", {AF_INET6,
994418919fSjohnjiang {IP6(0x1234,0,0,0,0,0,0,0x1234)},
1004418919fSjohnjiang 64},
1014418919fSjohnjiang CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
1024418919fSjohnjiang {"1234::/64", {AF_INET6,
1034418919fSjohnjiang {IP6(0x1234,0,0,0,0,0,0,0)},
1044418919fSjohnjiang 64},
1054418919fSjohnjiang CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
1064418919fSjohnjiang {"1:1::1/32", {AF_INET6,
1074418919fSjohnjiang {IP6(1,1,0,0,0,0,0,1)},
1084418919fSjohnjiang 32},
1094418919fSjohnjiang CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
1104418919fSjohnjiang {"1:2:3:4::/64", {AF_INET6,
1114418919fSjohnjiang {IP6(1,2,3,4,0,0,0,0)},
1124418919fSjohnjiang 64},
1134418919fSjohnjiang CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
1144418919fSjohnjiang {"::ffff:192.168.1.0/64", {AF_INET6,
1154418919fSjohnjiang {IP6(0,0,0,0,0,0xFFFF,0xC0A8,0x100)},
1164418919fSjohnjiang 64},
1174418919fSjohnjiang CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
1184418919fSjohnjiang /* RFC5952 requests not using :: to skip one block of zeros*/
1194418919fSjohnjiang {"1::2:3:4:5:6:7", {AF_INET6,
1204418919fSjohnjiang {IP6(1,0,2,3,4,5,6,7)},
1214418919fSjohnjiang 0},
1224418919fSjohnjiang CMDLINE_IPADDR_V6},
1234418919fSjohnjiang };
1244418919fSjohnjiang
1254418919fSjohnjiang const char * ipaddr_garbage_addr4_strs[] = {
1264418919fSjohnjiang /* IPv4 */
1274418919fSjohnjiang "192.168.1.0 garbage",
1284418919fSjohnjiang "192.168.1.0\0garbage",
1294418919fSjohnjiang "192.168.1.0#garbage",
1304418919fSjohnjiang "192.168.1.0\tgarbage",
1314418919fSjohnjiang "192.168.1.0\rgarbage",
1324418919fSjohnjiang "192.168.1.0\ngarbage",
1334418919fSjohnjiang };
1344418919fSjohnjiang #define IPv4_GARBAGE_ADDR IP4(192,168,1,0)
1354418919fSjohnjiang
1364418919fSjohnjiang const char * ipaddr_garbage_addr6_strs[] = {
1374418919fSjohnjiang /* IPv6 */
1384418919fSjohnjiang "1:2:3:4::8 garbage",
1394418919fSjohnjiang "1:2:3:4::8#garbage",
1404418919fSjohnjiang "1:2:3:4::8\0garbage",
1414418919fSjohnjiang "1:2:3:4::8\rgarbage",
1424418919fSjohnjiang "1:2:3:4::8\ngarbage",
1434418919fSjohnjiang "1:2:3:4::8\tgarbage",
1444418919fSjohnjiang };
1454418919fSjohnjiang #define IPv6_GARBAGE_ADDR {IP6(1,2,3,4,0,0,0,8)}
1464418919fSjohnjiang
1474418919fSjohnjiang const char * ipaddr_garbage_network4_strs[] = {
1484418919fSjohnjiang /* IPv4 */
1494418919fSjohnjiang "192.168.1.0/24 garbage",
1504418919fSjohnjiang "192.168.1.0/24\0garbage",
1514418919fSjohnjiang "192.168.1.0/24#garbage",
1524418919fSjohnjiang "192.168.1.0/24\tgarbage",
1534418919fSjohnjiang "192.168.1.0/24\rgarbage",
1544418919fSjohnjiang "192.168.1.0/24\ngarbage",
1554418919fSjohnjiang };
1564418919fSjohnjiang #define IPv4_GARBAGE_PREFIX 24
1574418919fSjohnjiang
1584418919fSjohnjiang const char * ipaddr_garbage_network6_strs[] = {
1594418919fSjohnjiang /* IPv6 */
1604418919fSjohnjiang "1:2:3:4::8/64 garbage",
1614418919fSjohnjiang "1:2:3:4::8/64#garbage",
1624418919fSjohnjiang "1:2:3:4::8/64\0garbage",
1634418919fSjohnjiang "1:2:3:4::8/64\rgarbage",
1644418919fSjohnjiang "1:2:3:4::8/64\ngarbage",
1654418919fSjohnjiang "1:2:3:4::8/64\tgarbage",
1664418919fSjohnjiang };
1674418919fSjohnjiang #define IPv6_GARBAGE_PREFIX 64
1684418919fSjohnjiang
1694418919fSjohnjiang
1704418919fSjohnjiang
1714418919fSjohnjiang const char * ipaddr_invalid_strs[] = {
1724418919fSjohnjiang /** IPv4 **/
1734418919fSjohnjiang
1744418919fSjohnjiang /* invalid numbers */
1754418919fSjohnjiang "0.0.0.-1",
1764418919fSjohnjiang "0.0.-1.0",
1774418919fSjohnjiang "0.-1.0.0",
1784418919fSjohnjiang "-1.0.0.0",
1794418919fSjohnjiang "0.0.0.-1/24",
1804418919fSjohnjiang "256.123.123.123",
1814418919fSjohnjiang "255.256.123.123",
1824418919fSjohnjiang "255.255.256.123",
1834418919fSjohnjiang "255.255.255.256",
1844418919fSjohnjiang "256.123.123.123/24",
1854418919fSjohnjiang "255.256.123.123/24",
1864418919fSjohnjiang "255.255.256.123/24",
1874418919fSjohnjiang "255.255.255.256/24",
1884418919fSjohnjiang /* invalid network mask */
1894418919fSjohnjiang "1.2.3.4/33",
1904418919fSjohnjiang "1.2.3.4/33231313",
1914418919fSjohnjiang "1.2.3.4/-1",
1924418919fSjohnjiang "1.2.3.4/24/33",
1934418919fSjohnjiang "1.2.3.4/24/-1",
1944418919fSjohnjiang "1.2.3.4/24/",
1954418919fSjohnjiang /* wrong format */
1964418919fSjohnjiang "1/24"
1974418919fSjohnjiang "/24"
1984418919fSjohnjiang "123.123.123",
1994418919fSjohnjiang "123.123.123.",
2004418919fSjohnjiang "123.123.123.123.",
2014418919fSjohnjiang "123.123.123..123",
2024418919fSjohnjiang "123.123.123.123.123",
2034418919fSjohnjiang ".123.123.123",
2044418919fSjohnjiang ".123.123.123.123",
2054418919fSjohnjiang "123.123.123/24",
2064418919fSjohnjiang "123.123.123./24",
2074418919fSjohnjiang "123.123.123.123./24",
2084418919fSjohnjiang "123.123.123..123/24",
2094418919fSjohnjiang "123.123.123.123.123/24",
2104418919fSjohnjiang ".123.123.123/24",
2114418919fSjohnjiang ".123.123.123.123/24",
2124418919fSjohnjiang /* invalid characters */
2134418919fSjohnjiang "123.123.123.12F",
2144418919fSjohnjiang "123.123.12F.123",
2154418919fSjohnjiang "123.12F.123.123",
2164418919fSjohnjiang "12F.123.123.123",
2174418919fSjohnjiang "12J.123.123.123",
2184418919fSjohnjiang "123,123,123,123",
2194418919fSjohnjiang "123!123!123!12F",
2204418919fSjohnjiang "123.123.123.123/4F",
2214418919fSjohnjiang
2224418919fSjohnjiang /** IPv6 **/
2234418919fSjohnjiang
2244418919fSjohnjiang /* wrong format */
2254418919fSjohnjiang "::fffff",
2264418919fSjohnjiang "ffff:",
2274418919fSjohnjiang "1:2:3:4:5:6:7:192.168.1.1",
2284418919fSjohnjiang "1234:192.168.1.1:ffff::",
2294418919fSjohnjiang "1:2:3:4:5:6:7:890ab",
2304418919fSjohnjiang "1:2:3:4:5:6:7890a:b",
2314418919fSjohnjiang "1:2:3:4:5:67890:a:b",
2324418919fSjohnjiang "1:2:3:4:56789:0:a:b",
2334418919fSjohnjiang "1:2:3:45678:9:0:a:b",
2344418919fSjohnjiang "1:2:34567:8:9:0:a:b",
2354418919fSjohnjiang "1:23456:7:8:9:0:a:b",
2364418919fSjohnjiang "12345:6:7:8:9:0:a:b",
2374418919fSjohnjiang "1:::2",
2384418919fSjohnjiang "1::::2",
2394418919fSjohnjiang "::fffff/64",
2404418919fSjohnjiang "1::2::3",
2414418919fSjohnjiang "1::2::3/64",
2424418919fSjohnjiang ":1:2",
2434418919fSjohnjiang ":1:2/64",
2444418919fSjohnjiang ":1::2",
2454418919fSjohnjiang ":1::2/64",
2464418919fSjohnjiang "1::2:3:4:5:6:7:8/64",
2474418919fSjohnjiang
2484418919fSjohnjiang /* invalid network mask */
2494418919fSjohnjiang "1:2:3:4:5:6:7:8/129",
2504418919fSjohnjiang "1:2:3:4:5:6:7:8/-1",
2514418919fSjohnjiang
2524418919fSjohnjiang /* invalid characters */
2534418919fSjohnjiang "a:b:c:d:e:f:g::",
2544418919fSjohnjiang
2554418919fSjohnjiang /** misc **/
2564418919fSjohnjiang
2574418919fSjohnjiang /* too long */
2584418919fSjohnjiang "1234:1234:1234:1234:1234:1234:1234:1234:1234:1234:1234"
2594418919fSjohnjiang "random invalid text",
2604418919fSjohnjiang "",
2614418919fSjohnjiang "\0",
2624418919fSjohnjiang " ",
2634418919fSjohnjiang };
2644418919fSjohnjiang
2654418919fSjohnjiang static void
dump_addr(cmdline_ipaddr_t addr)2664418919fSjohnjiang dump_addr(cmdline_ipaddr_t addr)
2674418919fSjohnjiang {
2684418919fSjohnjiang switch (addr.family) {
2694418919fSjohnjiang case AF_INET:
2704418919fSjohnjiang {
2714418919fSjohnjiang printf(NIPQUAD_FMT " prefixlen=%u\n",
2724418919fSjohnjiang NIPQUAD(addr.addr.ipv4.s_addr), addr.prefixlen);
2734418919fSjohnjiang break;
2744418919fSjohnjiang }
2754418919fSjohnjiang case AF_INET6:
2764418919fSjohnjiang {
2774418919fSjohnjiang printf(NIP6_FMT " prefixlen=%u\n",
2784418919fSjohnjiang NIP6(addr.addr.ipv6), addr.prefixlen);
2794418919fSjohnjiang break;
2804418919fSjohnjiang }
2814418919fSjohnjiang default:
2824418919fSjohnjiang printf("Can't dump: unknown address family.\n");
2834418919fSjohnjiang return;
2844418919fSjohnjiang }
2854418919fSjohnjiang }
2864418919fSjohnjiang
2874418919fSjohnjiang
2884418919fSjohnjiang static int
is_addr_different(cmdline_ipaddr_t addr1,cmdline_ipaddr_t addr2)2894418919fSjohnjiang is_addr_different(cmdline_ipaddr_t addr1, cmdline_ipaddr_t addr2)
2904418919fSjohnjiang {
2914418919fSjohnjiang if (addr1.family != addr2.family)
2924418919fSjohnjiang return 1;
2934418919fSjohnjiang
2944418919fSjohnjiang if (addr1.prefixlen != addr2.prefixlen)
2954418919fSjohnjiang return 1;
2964418919fSjohnjiang
2974418919fSjohnjiang switch (addr1.family) {
2984418919fSjohnjiang /* IPv4 */
2994418919fSjohnjiang case AF_INET:
3004418919fSjohnjiang if (memcmp(&addr1.addr.ipv4, &addr2.addr.ipv4,
3014418919fSjohnjiang sizeof(struct in_addr)) != 0)
3024418919fSjohnjiang return 1;
3034418919fSjohnjiang break;
3044418919fSjohnjiang /* IPv6 */
3054418919fSjohnjiang case AF_INET6:
3064418919fSjohnjiang {
3074418919fSjohnjiang if (memcmp(&addr1.addr.ipv6, &addr2.addr.ipv6,
3084418919fSjohnjiang sizeof(struct in6_addr)) != 0)
3094418919fSjohnjiang return 1;
3104418919fSjohnjiang break;
3114418919fSjohnjiang }
3124418919fSjohnjiang /* thing that should not be */
3134418919fSjohnjiang default:
3144418919fSjohnjiang return -1;
3154418919fSjohnjiang }
3164418919fSjohnjiang return 0;
3174418919fSjohnjiang }
3184418919fSjohnjiang
3194418919fSjohnjiang static int
can_parse_addr(unsigned addr_flags,unsigned test_flags)3204418919fSjohnjiang can_parse_addr(unsigned addr_flags, unsigned test_flags)
3214418919fSjohnjiang {
3224418919fSjohnjiang if ((test_flags & addr_flags) == addr_flags) {
3234418919fSjohnjiang /* if we are not trying to parse network addresses */
3244418919fSjohnjiang if (test_flags < CMDLINE_IPADDR_NETWORK)
3254418919fSjohnjiang return 1;
3264418919fSjohnjiang /* if this is a network address */
3274418919fSjohnjiang else if (addr_flags & CMDLINE_IPADDR_NETWORK)
3284418919fSjohnjiang return 1;
3294418919fSjohnjiang }
3304418919fSjohnjiang return 0;
3314418919fSjohnjiang }
3324418919fSjohnjiang
3334418919fSjohnjiang int
test_parse_ipaddr_valid(void)3344418919fSjohnjiang test_parse_ipaddr_valid(void)
3354418919fSjohnjiang {
3364418919fSjohnjiang cmdline_parse_token_ipaddr_t token;
3374418919fSjohnjiang char buf[CMDLINE_TEST_BUFSIZE];
3384418919fSjohnjiang cmdline_ipaddr_t result;
3394418919fSjohnjiang unsigned i;
3404418919fSjohnjiang uint8_t flags;
3414418919fSjohnjiang int ret;
3424418919fSjohnjiang
3434418919fSjohnjiang /* cover all cases in help */
3444418919fSjohnjiang for (flags = 0x1; flags < 0x8; flags++) {
3454418919fSjohnjiang token.ipaddr_data.flags = flags;
3464418919fSjohnjiang
3474418919fSjohnjiang memset(buf, 0, sizeof(buf));
3484418919fSjohnjiang
3494418919fSjohnjiang if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
3504418919fSjohnjiang buf, sizeof(buf)) == -1) {
3514418919fSjohnjiang printf("Error: help rejected valid parameters!\n");
3524418919fSjohnjiang return -1;
3534418919fSjohnjiang }
3544418919fSjohnjiang }
3554418919fSjohnjiang
3564418919fSjohnjiang /* test valid strings */
357*2d9fd380Sjfb8856606 for (i = 0; i < RTE_DIM(ipaddr_valid_strs); i++) {
3584418919fSjohnjiang
3594418919fSjohnjiang /* test each valid string against different flags */
3604418919fSjohnjiang for (flags = 1; flags < 0x8; flags++) {
3614418919fSjohnjiang
3624418919fSjohnjiang /* skip bad flag */
3634418919fSjohnjiang if (flags == CMDLINE_IPADDR_NETWORK)
3644418919fSjohnjiang continue;
3654418919fSjohnjiang
3664418919fSjohnjiang /* clear out everything */
3674418919fSjohnjiang memset(buf, 0, sizeof(buf));
3684418919fSjohnjiang memset(&result, 0, sizeof(result));
3694418919fSjohnjiang memset(&token, 0, sizeof(token));
3704418919fSjohnjiang
3714418919fSjohnjiang token.ipaddr_data.flags = flags;
3724418919fSjohnjiang
3734418919fSjohnjiang cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
3744418919fSjohnjiang buf, sizeof(buf));
3754418919fSjohnjiang
3764418919fSjohnjiang ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
3774418919fSjohnjiang ipaddr_valid_strs[i].str, (void*)&result,
3784418919fSjohnjiang sizeof(result));
3794418919fSjohnjiang
3804418919fSjohnjiang /* if should have passed, or should have failed */
3814418919fSjohnjiang if ((ret < 0) ==
3824418919fSjohnjiang (can_parse_addr(ipaddr_valid_strs[i].flags, flags))) {
3834418919fSjohnjiang printf("Error: unexpected behavior when parsing %s as %s!\n",
3844418919fSjohnjiang ipaddr_valid_strs[i].str, buf);
3854418919fSjohnjiang printf("Parsed result: ");
3864418919fSjohnjiang dump_addr(result);
3874418919fSjohnjiang printf("Expected result: ");
3884418919fSjohnjiang dump_addr(ipaddr_valid_strs[i].addr);
3894418919fSjohnjiang return -1;
3904418919fSjohnjiang }
3914418919fSjohnjiang if (ret != -1 &&
3924418919fSjohnjiang is_addr_different(result, ipaddr_valid_strs[i].addr)) {
3934418919fSjohnjiang printf("Error: result mismatch when parsing %s as %s!\n",
3944418919fSjohnjiang ipaddr_valid_strs[i].str, buf);
3954418919fSjohnjiang printf("Parsed result: ");
3964418919fSjohnjiang dump_addr(result);
3974418919fSjohnjiang printf("Expected result: ");
3984418919fSjohnjiang dump_addr(ipaddr_valid_strs[i].addr);
3994418919fSjohnjiang return -1;
4004418919fSjohnjiang }
4014418919fSjohnjiang }
4024418919fSjohnjiang }
4034418919fSjohnjiang
4044418919fSjohnjiang /* test garbage ipv4 address strings */
405*2d9fd380Sjfb8856606 for (i = 0; i < RTE_DIM(ipaddr_garbage_addr4_strs); i++) {
4064418919fSjohnjiang
4074418919fSjohnjiang struct in_addr tmp = IPv4_GARBAGE_ADDR;
4084418919fSjohnjiang
4094418919fSjohnjiang /* test each valid string against different flags */
4104418919fSjohnjiang for (flags = 1; flags < 0x8; flags++) {
4114418919fSjohnjiang
4124418919fSjohnjiang /* skip bad flag */
4134418919fSjohnjiang if (flags == CMDLINE_IPADDR_NETWORK)
4144418919fSjohnjiang continue;
4154418919fSjohnjiang
4164418919fSjohnjiang /* clear out everything */
4174418919fSjohnjiang memset(buf, 0, sizeof(buf));
4184418919fSjohnjiang memset(&result, 0, sizeof(result));
4194418919fSjohnjiang memset(&token, 0, sizeof(token));
4204418919fSjohnjiang
4214418919fSjohnjiang token.ipaddr_data.flags = flags;
4224418919fSjohnjiang
4234418919fSjohnjiang cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
4244418919fSjohnjiang buf, sizeof(buf));
4254418919fSjohnjiang
4264418919fSjohnjiang ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
4274418919fSjohnjiang ipaddr_garbage_addr4_strs[i], (void*)&result,
4284418919fSjohnjiang sizeof(result));
4294418919fSjohnjiang
4304418919fSjohnjiang /* if should have passed, or should have failed */
4314418919fSjohnjiang if ((ret < 0) ==
4324418919fSjohnjiang (can_parse_addr(CMDLINE_IPADDR_V4, flags))) {
4334418919fSjohnjiang printf("Error: unexpected behavior when parsing %s as %s!\n",
4344418919fSjohnjiang ipaddr_garbage_addr4_strs[i], buf);
4354418919fSjohnjiang return -1;
4364418919fSjohnjiang }
4374418919fSjohnjiang if (ret != -1 &&
4384418919fSjohnjiang memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) {
4394418919fSjohnjiang printf("Error: result mismatch when parsing %s as %s!\n",
4404418919fSjohnjiang ipaddr_garbage_addr4_strs[i], buf);
4414418919fSjohnjiang return -1;
4424418919fSjohnjiang }
4434418919fSjohnjiang }
4444418919fSjohnjiang }
4454418919fSjohnjiang
4464418919fSjohnjiang /* test garbage ipv6 address strings */
447*2d9fd380Sjfb8856606 for (i = 0; i < RTE_DIM(ipaddr_garbage_addr6_strs); i++) {
4484418919fSjohnjiang
4494418919fSjohnjiang cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR};
4504418919fSjohnjiang
4514418919fSjohnjiang /* test each valid string against different flags */
4524418919fSjohnjiang for (flags = 1; flags < 0x8; flags++) {
4534418919fSjohnjiang
4544418919fSjohnjiang /* skip bad flag */
4554418919fSjohnjiang if (flags == CMDLINE_IPADDR_NETWORK)
4564418919fSjohnjiang continue;
4574418919fSjohnjiang
4584418919fSjohnjiang /* clear out everything */
4594418919fSjohnjiang memset(buf, 0, sizeof(buf));
4604418919fSjohnjiang memset(&result, 0, sizeof(result));
4614418919fSjohnjiang memset(&token, 0, sizeof(token));
4624418919fSjohnjiang
4634418919fSjohnjiang token.ipaddr_data.flags = flags;
4644418919fSjohnjiang
4654418919fSjohnjiang cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
4664418919fSjohnjiang buf, sizeof(buf));
4674418919fSjohnjiang
4684418919fSjohnjiang ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
4694418919fSjohnjiang ipaddr_garbage_addr6_strs[i], (void*)&result,
4704418919fSjohnjiang sizeof(result));
4714418919fSjohnjiang
4724418919fSjohnjiang /* if should have passed, or should have failed */
4734418919fSjohnjiang if ((ret < 0) ==
4744418919fSjohnjiang (can_parse_addr(CMDLINE_IPADDR_V6, flags))) {
4754418919fSjohnjiang printf("Error: unexpected behavior when parsing %s as %s!\n",
4764418919fSjohnjiang ipaddr_garbage_addr6_strs[i], buf);
4774418919fSjohnjiang return -1;
4784418919fSjohnjiang }
4794418919fSjohnjiang if (ret != -1 &&
4804418919fSjohnjiang memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) {
4814418919fSjohnjiang printf("Error: result mismatch when parsing %s as %s!\n",
4824418919fSjohnjiang ipaddr_garbage_addr6_strs[i], buf);
4834418919fSjohnjiang return -1;
4844418919fSjohnjiang }
4854418919fSjohnjiang }
4864418919fSjohnjiang }
4874418919fSjohnjiang
4884418919fSjohnjiang
4894418919fSjohnjiang /* test garbage ipv4 network strings */
490*2d9fd380Sjfb8856606 for (i = 0; i < RTE_DIM(ipaddr_garbage_network4_strs); i++) {
4914418919fSjohnjiang
4924418919fSjohnjiang struct in_addr tmp = IPv4_GARBAGE_ADDR;
4934418919fSjohnjiang
4944418919fSjohnjiang /* test each valid string against different flags */
4954418919fSjohnjiang for (flags = 1; flags < 0x8; flags++) {
4964418919fSjohnjiang
4974418919fSjohnjiang /* skip bad flag */
4984418919fSjohnjiang if (flags == CMDLINE_IPADDR_NETWORK)
4994418919fSjohnjiang continue;
5004418919fSjohnjiang
5014418919fSjohnjiang /* clear out everything */
5024418919fSjohnjiang memset(buf, 0, sizeof(buf));
5034418919fSjohnjiang memset(&result, 0, sizeof(result));
5044418919fSjohnjiang memset(&token, 0, sizeof(token));
5054418919fSjohnjiang
5064418919fSjohnjiang token.ipaddr_data.flags = flags;
5074418919fSjohnjiang
5084418919fSjohnjiang cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
5094418919fSjohnjiang buf, sizeof(buf));
5104418919fSjohnjiang
5114418919fSjohnjiang ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
5124418919fSjohnjiang ipaddr_garbage_network4_strs[i], (void*)&result,
5134418919fSjohnjiang sizeof(result));
5144418919fSjohnjiang
5154418919fSjohnjiang /* if should have passed, or should have failed */
5164418919fSjohnjiang if ((ret < 0) ==
5174418919fSjohnjiang (can_parse_addr(CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK, flags))) {
5184418919fSjohnjiang printf("Error: unexpected behavior when parsing %s as %s!\n",
5194418919fSjohnjiang ipaddr_garbage_network4_strs[i], buf);
5204418919fSjohnjiang return -1;
5214418919fSjohnjiang }
5224418919fSjohnjiang if (ret != -1 &&
5234418919fSjohnjiang memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) {
5244418919fSjohnjiang printf("Error: result mismatch when parsing %s as %s!\n",
5254418919fSjohnjiang ipaddr_garbage_network4_strs[i], buf);
5264418919fSjohnjiang return -1;
5274418919fSjohnjiang }
5284418919fSjohnjiang }
5294418919fSjohnjiang }
5304418919fSjohnjiang
5314418919fSjohnjiang /* test garbage ipv6 address strings */
532*2d9fd380Sjfb8856606 for (i = 0; i < RTE_DIM(ipaddr_garbage_network6_strs); i++) {
5334418919fSjohnjiang
5344418919fSjohnjiang cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR};
5354418919fSjohnjiang
5364418919fSjohnjiang /* test each valid string against different flags */
5374418919fSjohnjiang for (flags = 1; flags < 0x8; flags++) {
5384418919fSjohnjiang
5394418919fSjohnjiang /* skip bad flag */
5404418919fSjohnjiang if (flags == CMDLINE_IPADDR_NETWORK)
5414418919fSjohnjiang continue;
5424418919fSjohnjiang
5434418919fSjohnjiang /* clear out everything */
5444418919fSjohnjiang memset(buf, 0, sizeof(buf));
5454418919fSjohnjiang memset(&result, 0, sizeof(result));
5464418919fSjohnjiang memset(&token, 0, sizeof(token));
5474418919fSjohnjiang
5484418919fSjohnjiang token.ipaddr_data.flags = flags;
5494418919fSjohnjiang
5504418919fSjohnjiang cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
5514418919fSjohnjiang buf, sizeof(buf));
5524418919fSjohnjiang
5534418919fSjohnjiang ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
5544418919fSjohnjiang ipaddr_garbage_network6_strs[i], (void*)&result,
5554418919fSjohnjiang sizeof(result));
5564418919fSjohnjiang
5574418919fSjohnjiang /* if should have passed, or should have failed */
5584418919fSjohnjiang if ((ret < 0) ==
5594418919fSjohnjiang (can_parse_addr(CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK, flags))) {
5604418919fSjohnjiang printf("Error: unexpected behavior when parsing %s as %s!\n",
5614418919fSjohnjiang ipaddr_garbage_network6_strs[i], buf);
5624418919fSjohnjiang return -1;
5634418919fSjohnjiang }
5644418919fSjohnjiang if (ret != -1 &&
5654418919fSjohnjiang memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) {
5664418919fSjohnjiang printf("Error: result mismatch when parsing %s as %s!\n",
5674418919fSjohnjiang ipaddr_garbage_network6_strs[i], buf);
5684418919fSjohnjiang return -1;
5694418919fSjohnjiang }
5704418919fSjohnjiang }
5714418919fSjohnjiang }
5724418919fSjohnjiang
5734418919fSjohnjiang return 0;
5744418919fSjohnjiang }
5754418919fSjohnjiang
5764418919fSjohnjiang int
test_parse_ipaddr_invalid_data(void)5774418919fSjohnjiang test_parse_ipaddr_invalid_data(void)
5784418919fSjohnjiang {
5794418919fSjohnjiang cmdline_parse_token_ipaddr_t token;
5804418919fSjohnjiang char buf[CMDLINE_TEST_BUFSIZE];
5814418919fSjohnjiang cmdline_ipaddr_t result;
5824418919fSjohnjiang unsigned i;
5834418919fSjohnjiang uint8_t flags;
5844418919fSjohnjiang int ret;
5854418919fSjohnjiang
5864418919fSjohnjiang memset(&result, 0, sizeof(result));
5874418919fSjohnjiang
5884418919fSjohnjiang /* test invalid strings */
589*2d9fd380Sjfb8856606 for (i = 0; i < RTE_DIM(ipaddr_invalid_strs); i++) {
5904418919fSjohnjiang
5914418919fSjohnjiang /* test each valid string against different flags */
5924418919fSjohnjiang for (flags = 1; flags < 0x8; flags++) {
5934418919fSjohnjiang
5944418919fSjohnjiang /* skip bad flag */
5954418919fSjohnjiang if (flags == CMDLINE_IPADDR_NETWORK)
5964418919fSjohnjiang continue;
5974418919fSjohnjiang
5984418919fSjohnjiang /* clear out everything */
5994418919fSjohnjiang memset(buf, 0, sizeof(buf));
6004418919fSjohnjiang memset(&token, 0, sizeof(token));
6014418919fSjohnjiang
6024418919fSjohnjiang token.ipaddr_data.flags = flags;
6034418919fSjohnjiang
6044418919fSjohnjiang cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
6054418919fSjohnjiang buf, sizeof(buf));
6064418919fSjohnjiang
6074418919fSjohnjiang ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
6084418919fSjohnjiang ipaddr_invalid_strs[i], (void*)&result,
6094418919fSjohnjiang sizeof(result));
6104418919fSjohnjiang
6114418919fSjohnjiang if (ret != -1) {
6124418919fSjohnjiang printf("Error: parsing %s as %s succeeded!\n",
6134418919fSjohnjiang ipaddr_invalid_strs[i], buf);
6144418919fSjohnjiang printf("Parsed result: ");
6154418919fSjohnjiang dump_addr(result);
6164418919fSjohnjiang return -1;
6174418919fSjohnjiang }
6184418919fSjohnjiang }
6194418919fSjohnjiang }
6204418919fSjohnjiang
6214418919fSjohnjiang return 0;
6224418919fSjohnjiang }
6234418919fSjohnjiang
6244418919fSjohnjiang int
test_parse_ipaddr_invalid_param(void)6254418919fSjohnjiang test_parse_ipaddr_invalid_param(void)
6264418919fSjohnjiang {
6274418919fSjohnjiang cmdline_parse_token_ipaddr_t token;
6284418919fSjohnjiang char buf[CMDLINE_TEST_BUFSIZE];
6294418919fSjohnjiang cmdline_ipaddr_t result;
6304418919fSjohnjiang
6314418919fSjohnjiang snprintf(buf, sizeof(buf), "1.2.3.4");
6324418919fSjohnjiang token.ipaddr_data.flags = CMDLINE_IPADDR_V4;
6334418919fSjohnjiang
6344418919fSjohnjiang /* null token */
6354418919fSjohnjiang if (cmdline_parse_ipaddr(NULL, buf, (void*)&result,
6364418919fSjohnjiang sizeof(result)) != -1) {
6374418919fSjohnjiang printf("Error: parser accepted invalid parameters!\n");
6384418919fSjohnjiang return -1;
6394418919fSjohnjiang }
6404418919fSjohnjiang /* null buffer */
6414418919fSjohnjiang if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
6424418919fSjohnjiang NULL, (void*)&result, sizeof(result)) != -1) {
6434418919fSjohnjiang printf("Error: parser accepted invalid parameters!\n");
6444418919fSjohnjiang return -1;
6454418919fSjohnjiang }
6464418919fSjohnjiang /* empty buffer */
6474418919fSjohnjiang if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
6484418919fSjohnjiang "", (void*)&result, sizeof(result)) != -1) {
6494418919fSjohnjiang printf("Error: parser accepted invalid parameters!\n");
6504418919fSjohnjiang return -1;
6514418919fSjohnjiang }
6524418919fSjohnjiang /* null result */
6534418919fSjohnjiang if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
6544418919fSjohnjiang buf, NULL, 0) == -1) {
6554418919fSjohnjiang printf("Error: parser rejected null result!\n");
6564418919fSjohnjiang return -1;
6574418919fSjohnjiang }
6584418919fSjohnjiang
6594418919fSjohnjiang /* null token */
6604418919fSjohnjiang if (cmdline_get_help_ipaddr(NULL, buf, 0) != -1) {
6614418919fSjohnjiang printf("Error: help accepted invalid parameters!\n");
6624418919fSjohnjiang return -1;
6634418919fSjohnjiang }
6644418919fSjohnjiang /* null buffer */
6654418919fSjohnjiang if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
6664418919fSjohnjiang NULL, 0) != -1) {
6674418919fSjohnjiang printf("Error: help accepted invalid parameters!\n");
6684418919fSjohnjiang return -1;
6694418919fSjohnjiang }
6704418919fSjohnjiang return 0;
6714418919fSjohnjiang }
672