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