xref: /dpdk/app/test/test_cmdline_ipaddr.c (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
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 static void
266 dump_addr(cmdline_ipaddr_t addr)
267 {
268 	switch (addr.family) {
269 	case AF_INET:
270 	{
271 		printf(NIPQUAD_FMT " prefixlen=%u\n",
272 				NIPQUAD(addr.addr.ipv4.s_addr), addr.prefixlen);
273 		break;
274 	}
275 	case AF_INET6:
276 	{
277 		printf(NIP6_FMT " prefixlen=%u\n",
278 				NIP6(addr.addr.ipv6), addr.prefixlen);
279 		break;
280 	}
281 	default:
282 		printf("Can't dump: unknown address family.\n");
283 		return;
284 	}
285 }
286 
287 
288 static int
289 is_addr_different(cmdline_ipaddr_t addr1, cmdline_ipaddr_t addr2)
290 {
291 	if (addr1.family != addr2.family)
292 		return 1;
293 
294 	if (addr1.prefixlen != addr2.prefixlen)
295 		return 1;
296 
297 	switch (addr1.family) {
298 	/* IPv4 */
299 	case AF_INET:
300 		if (memcmp(&addr1.addr.ipv4, &addr2.addr.ipv4,
301 				sizeof(struct in_addr)) != 0)
302 			return 1;
303 		break;
304 	/* IPv6 */
305 	case AF_INET6:
306 	{
307 		if (memcmp(&addr1.addr.ipv6, &addr2.addr.ipv6,
308 				sizeof(struct in6_addr)) != 0)
309 			return 1;
310 		break;
311 	}
312 	/* thing that should not be */
313 	default:
314 		return -1;
315 	}
316 	return 0;
317 }
318 
319 static int
320 can_parse_addr(unsigned addr_flags, unsigned test_flags)
321 {
322 	if ((test_flags & addr_flags) == addr_flags) {
323 		/* if we are not trying to parse network addresses */
324 		if (test_flags < CMDLINE_IPADDR_NETWORK)
325 			return 1;
326 		/* if this is a network address */
327 		else if (addr_flags & CMDLINE_IPADDR_NETWORK)
328 			return 1;
329 	}
330 	return 0;
331 }
332 
333 int
334 test_parse_ipaddr_valid(void)
335 {
336 	cmdline_parse_token_ipaddr_t token;
337 	char buf[CMDLINE_TEST_BUFSIZE];
338 	cmdline_ipaddr_t result;
339 	unsigned i;
340 	uint8_t flags;
341 	int ret;
342 
343 	/* cover all cases in help */
344 	for (flags = 0x1; flags < 0x8; flags++) {
345 		token.ipaddr_data.flags = flags;
346 
347 		memset(buf, 0, sizeof(buf));
348 
349 		if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
350 				buf, sizeof(buf)) == -1) {
351 			printf("Error: help rejected valid parameters!\n");
352 			return -1;
353 		}
354 	}
355 
356 	/* test valid strings */
357 	for (i = 0; i < RTE_DIM(ipaddr_valid_strs); i++) {
358 
359 		/* test each valid string against different flags */
360 		for (flags = 1; flags < 0x8; flags++) {
361 
362 			/* skip bad flag */
363 			if (flags == CMDLINE_IPADDR_NETWORK)
364 				continue;
365 
366 			/* clear out everything */
367 			memset(buf, 0, sizeof(buf));
368 			memset(&result, 0, sizeof(result));
369 			memset(&token, 0, sizeof(token));
370 
371 			token.ipaddr_data.flags = flags;
372 
373 			cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
374 							buf, sizeof(buf));
375 
376 			ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
377 				ipaddr_valid_strs[i].str, (void*)&result,
378 				sizeof(result));
379 
380 			/* if should have passed, or should have failed */
381 			if ((ret < 0) ==
382 					(can_parse_addr(ipaddr_valid_strs[i].flags, flags))) {
383 				printf("Error: unexpected behavior when parsing %s as %s!\n",
384 						ipaddr_valid_strs[i].str, buf);
385 				printf("Parsed result: ");
386 				dump_addr(result);
387 				printf("Expected result: ");
388 				dump_addr(ipaddr_valid_strs[i].addr);
389 				return -1;
390 			}
391 			if (ret != -1 &&
392 					is_addr_different(result, ipaddr_valid_strs[i].addr)) {
393 				printf("Error: result mismatch when parsing %s as %s!\n",
394 						ipaddr_valid_strs[i].str, buf);
395 				printf("Parsed result: ");
396 				dump_addr(result);
397 				printf("Expected result: ");
398 				dump_addr(ipaddr_valid_strs[i].addr);
399 				return -1;
400 			}
401 		}
402 	}
403 
404 	/* test garbage ipv4 address strings */
405 	for (i = 0; i < RTE_DIM(ipaddr_garbage_addr4_strs); i++) {
406 
407 		struct in_addr tmp = IPv4_GARBAGE_ADDR;
408 
409 		/* test each valid string against different flags */
410 		for (flags = 1; flags < 0x8; flags++) {
411 
412 			/* skip bad flag */
413 			if (flags == CMDLINE_IPADDR_NETWORK)
414 				continue;
415 
416 			/* clear out everything */
417 			memset(buf, 0, sizeof(buf));
418 			memset(&result, 0, sizeof(result));
419 			memset(&token, 0, sizeof(token));
420 
421 			token.ipaddr_data.flags = flags;
422 
423 			cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
424 							buf, sizeof(buf));
425 
426 			ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
427 				ipaddr_garbage_addr4_strs[i], (void*)&result,
428 				sizeof(result));
429 
430 			/* if should have passed, or should have failed */
431 			if ((ret < 0) ==
432 					(can_parse_addr(CMDLINE_IPADDR_V4, flags))) {
433 				printf("Error: unexpected behavior when parsing %s as %s!\n",
434 						ipaddr_garbage_addr4_strs[i], buf);
435 				return -1;
436 			}
437 			if (ret != -1 &&
438 					memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) {
439 				printf("Error: result mismatch when parsing %s as %s!\n",
440 						ipaddr_garbage_addr4_strs[i], buf);
441 				return -1;
442 			}
443 		}
444 	}
445 
446 	/* test garbage ipv6 address strings */
447 	for (i = 0; i < RTE_DIM(ipaddr_garbage_addr6_strs); i++) {
448 
449 		cmdline_ipaddr_t tmp = {.addr = IPv6_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_addr6_strs[i], (void*)&result,
470 				sizeof(result));
471 
472 			/* if should have passed, or should have failed */
473 			if ((ret < 0) ==
474 					(can_parse_addr(CMDLINE_IPADDR_V6, flags))) {
475 				printf("Error: unexpected behavior when parsing %s as %s!\n",
476 						ipaddr_garbage_addr6_strs[i], buf);
477 				return -1;
478 			}
479 			if (ret != -1 &&
480 					memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) {
481 				printf("Error: result mismatch when parsing %s as %s!\n",
482 						ipaddr_garbage_addr6_strs[i], buf);
483 				return -1;
484 			}
485 		}
486 	}
487 
488 
489 	/* test garbage ipv4 network strings */
490 	for (i = 0; i < RTE_DIM(ipaddr_garbage_network4_strs); i++) {
491 
492 		struct in_addr tmp = IPv4_GARBAGE_ADDR;
493 
494 		/* test each valid string against different flags */
495 		for (flags = 1; flags < 0x8; flags++) {
496 
497 			/* skip bad flag */
498 			if (flags == CMDLINE_IPADDR_NETWORK)
499 				continue;
500 
501 			/* clear out everything */
502 			memset(buf, 0, sizeof(buf));
503 			memset(&result, 0, sizeof(result));
504 			memset(&token, 0, sizeof(token));
505 
506 			token.ipaddr_data.flags = flags;
507 
508 			cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
509 							buf, sizeof(buf));
510 
511 			ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
512 				ipaddr_garbage_network4_strs[i], (void*)&result,
513 				sizeof(result));
514 
515 			/* if should have passed, or should have failed */
516 			if ((ret < 0) ==
517 					(can_parse_addr(CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK, flags))) {
518 				printf("Error: unexpected behavior when parsing %s as %s!\n",
519 						ipaddr_garbage_network4_strs[i], buf);
520 				return -1;
521 			}
522 			if (ret != -1 &&
523 					memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) {
524 				printf("Error: result mismatch when parsing %s as %s!\n",
525 						ipaddr_garbage_network4_strs[i], buf);
526 				return -1;
527 			}
528 		}
529 	}
530 
531 	/* test garbage ipv6 address strings */
532 	for (i = 0; i < RTE_DIM(ipaddr_garbage_network6_strs); i++) {
533 
534 		cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR};
535 
536 		/* test each valid string against different flags */
537 		for (flags = 1; flags < 0x8; flags++) {
538 
539 			/* skip bad flag */
540 			if (flags == CMDLINE_IPADDR_NETWORK)
541 				continue;
542 
543 			/* clear out everything */
544 			memset(buf, 0, sizeof(buf));
545 			memset(&result, 0, sizeof(result));
546 			memset(&token, 0, sizeof(token));
547 
548 			token.ipaddr_data.flags = flags;
549 
550 			cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
551 							buf, sizeof(buf));
552 
553 			ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
554 				ipaddr_garbage_network6_strs[i], (void*)&result,
555 				sizeof(result));
556 
557 			/* if should have passed, or should have failed */
558 			if ((ret < 0) ==
559 					(can_parse_addr(CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK, flags))) {
560 				printf("Error: unexpected behavior when parsing %s as %s!\n",
561 						ipaddr_garbage_network6_strs[i], buf);
562 				return -1;
563 			}
564 			if (ret != -1 &&
565 					memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) {
566 				printf("Error: result mismatch when parsing %s as %s!\n",
567 						ipaddr_garbage_network6_strs[i], buf);
568 				return -1;
569 			}
570 		}
571 	}
572 
573 	return 0;
574 }
575 
576 int
577 test_parse_ipaddr_invalid_data(void)
578 {
579 	cmdline_parse_token_ipaddr_t token;
580 	char buf[CMDLINE_TEST_BUFSIZE];
581 	cmdline_ipaddr_t result;
582 	unsigned i;
583 	uint8_t flags;
584 	int ret;
585 
586 	memset(&result, 0, sizeof(result));
587 
588 	/* test invalid strings */
589 	for (i = 0; i < RTE_DIM(ipaddr_invalid_strs); i++) {
590 
591 		/* test each valid string against different flags */
592 		for (flags = 1; flags < 0x8; flags++) {
593 
594 			/* skip bad flag */
595 			if (flags == CMDLINE_IPADDR_NETWORK)
596 				continue;
597 
598 			/* clear out everything */
599 			memset(buf, 0, sizeof(buf));
600 			memset(&token, 0, sizeof(token));
601 
602 			token.ipaddr_data.flags = flags;
603 
604 			cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
605 					buf, sizeof(buf));
606 
607 			ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
608 				ipaddr_invalid_strs[i], (void*)&result,
609 				sizeof(result));
610 
611 			if (ret != -1) {
612 				printf("Error: parsing %s as %s succeeded!\n",
613 						ipaddr_invalid_strs[i], buf);
614 				printf("Parsed result: ");
615 				dump_addr(result);
616 				return -1;
617 			}
618 		}
619 	}
620 
621 	return 0;
622 }
623 
624 int
625 test_parse_ipaddr_invalid_param(void)
626 {
627 	cmdline_parse_token_ipaddr_t token;
628 	char buf[CMDLINE_TEST_BUFSIZE];
629 	cmdline_ipaddr_t result;
630 
631 	snprintf(buf, sizeof(buf), "1.2.3.4");
632 	token.ipaddr_data.flags = CMDLINE_IPADDR_V4;
633 
634 	/* null token */
635 	if (cmdline_parse_ipaddr(NULL, buf, (void*)&result,
636 			sizeof(result)) != -1) {
637 		printf("Error: parser accepted invalid parameters!\n");
638 		return -1;
639 	}
640 	/* null buffer */
641 	if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
642 			NULL, (void*)&result, sizeof(result)) != -1) {
643 		printf("Error: parser accepted invalid parameters!\n");
644 		return -1;
645 	}
646 	/* empty buffer */
647 	if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
648 			"", (void*)&result, sizeof(result)) != -1) {
649 		printf("Error: parser accepted invalid parameters!\n");
650 		return -1;
651 	}
652 	/* null result */
653 	if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
654 			buf, NULL, 0) == -1) {
655 		printf("Error: parser rejected null result!\n");
656 		return -1;
657 	}
658 
659 	/* null token */
660 	if (cmdline_get_help_ipaddr(NULL, buf, 0) != -1) {
661 		printf("Error: help accepted invalid parameters!\n");
662 		return -1;
663 	}
664 	/* null buffer */
665 	if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
666 			NULL, 0) != -1) {
667 		printf("Error: help accepted invalid parameters!\n");
668 		return -1;
669 	}
670 	return 0;
671 }
672