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