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