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