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