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