xref: /dpdk/app/test/test_cmdline_ipaddr.c (revision dbb860e03eb12ad621cbb68a0f3f1752bf188ab0)
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 }
708