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