1 : #define VSTR_PARSE_C
2 : /*
3 : * Copyright (C) 2002, 2003, 2004 James Antill
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Lesser General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Lesser General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public
16 : * License along with this library; if not, write to the Free Software
17 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 : *
19 : * email: james@and.org
20 : */
21 : /* functions for parsing data out of the Vstr */
22 : #include "main.h"
23 :
24 : #ifdef HAVE_ASCII_ALPHA
25 : # define VSTR__PARSE_NUM_USE_LOCAL 0
26 : #else
27 : # define VSTR__PARSE_NUM_USE_LOCAL 1
28 : #endif
29 :
30 :
31 : /* basically uses: [ ]*[-+](0x|0X|0)[0-9a-z_]+ */
32 : static int vstr__parse_num_beg(const Vstr_base *base,
33 : size_t *passed_pos, size_t *passed_len,
34 : unsigned int flags, int *is_neg, int *is_zeroed,
35 : unsigned int *err)
36 45813 : {
37 45813 : size_t pos = *passed_pos;
38 45813 : size_t len = *passed_len;
39 45813 : unsigned int num_base = flags & VSTR__MASK_PARSE_NUM_BASE;
40 45813 : int auto_base = FALSE;
41 45813 : char num_0 = '0';
42 45813 : char let_x_low = 'x';
43 45813 : char let_X_high = 'X';
44 45813 : char let_b_low = 'b';
45 45813 : char let_B_high = 'B';
46 45813 : char sym_minus = '-';
47 45813 : char sym_plus = '+';
48 45813 : char sym_space = ' ';
49 45813 : size_t tmp = 0;
50 :
51 45813 : if (!num_base)
52 639 : auto_base = TRUE;
53 45174 : else if (num_base > 36)
54 5 : num_base = 36;
55 45169 : else if (num_base == 1)
56 5 : ++num_base;
57 :
58 45813 : assert(!(auto_base && (flags & VSTR_FLAG_PARSE_NUM_NO_BEG_ZERO)));
59 :
60 45813 : if (!(flags & VSTR_FLAG_PARSE_NUM_LOCAL))
61 : {
62 45588 : num_0 = 0x30;
63 45588 : let_x_low = 0x78;
64 45588 : let_X_high = 0x58;
65 45588 : let_b_low = 0x62;
66 45588 : let_B_high = 0x42;
67 45588 : sym_minus = 0x2D;
68 45588 : sym_plus = 0x2B;
69 45588 : sym_space = 0x20;
70 : }
71 :
72 45813 : if (flags & VSTR_FLAG_PARSE_NUM_SPACE)
73 : {
74 519 : tmp = vstr_spn_chrs_fwd(base, pos, len, &sym_space, 1);
75 519 : if (tmp >= len)
76 : {
77 5 : *err = VSTR_TYPE_PARSE_NUM_ERR_ONLY_S;
78 5 : return (0);
79 : }
80 :
81 514 : pos += tmp;
82 514 : len -= tmp;
83 : }
84 :
85 45808 : if (!(flags & VSTR_FLAG_PARSE_NUM_NO_BEG_PM))
86 : {
87 7527 : tmp = vstr_spn_chrs_fwd(base, pos, len, &sym_minus, 1);
88 7527 : if (tmp > 1)
89 : {
90 5 : *err = VSTR_TYPE_PARSE_NUM_ERR_OOB;
91 5 : return (0);
92 : }
93 7522 : else if (!tmp)
94 : {
95 7442 : tmp = vstr_spn_chrs_fwd(base, pos, len, &sym_plus, 1);
96 7442 : if (tmp > 1)
97 : {
98 5 : *err = VSTR_TYPE_PARSE_NUM_ERR_OOB;
99 5 : return (0);
100 : }
101 : }
102 : else
103 80 : *is_neg = TRUE;
104 :
105 7517 : pos += tmp;
106 7517 : len -= tmp;
107 : }
108 :
109 45798 : if (!len)
110 : {
111 74 : *err = VSTR_TYPE_PARSE_NUM_ERR_ONLY_SPM;
112 74 : return (0);
113 : }
114 :
115 45724 : tmp = vstr_spn_chrs_fwd(base, pos, len, &num_0, 1);
116 45724 : *is_zeroed = !!tmp;
117 45724 : if ((tmp == 1) && (auto_base || (num_base == 16) || (num_base == 2)))
118 : {
119 714 : char xX[2];
120 :
121 714 : if (tmp == len)
122 : {
123 335 : *passed_len = 0;
124 335 : return (1);
125 : }
126 :
127 379 : pos += tmp;
128 379 : len -= tmp;
129 :
130 379 : xX[0] = let_x_low;
131 379 : xX[1] = let_X_high;
132 379 : tmp = vstr_spn_chrs_fwd(base, pos, len, xX, 2);
133 :
134 379 : if (tmp > 1)
135 : { /* It's a 0 */
136 5 : *err = VSTR_TYPE_PARSE_NUM_ERR_OOB;
137 5 : *passed_len = len;
138 5 : return (1);
139 : }
140 374 : if (tmp == 1)
141 : {
142 195 : if (auto_base)
143 185 : num_base = 16;
144 :
145 195 : pos += tmp;
146 195 : len -= tmp;
147 :
148 195 : if (!len)
149 : {
150 5 : *passed_pos = pos + len;
151 5 : *passed_len = 0;
152 5 : *err = VSTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX;
153 5 : return (0);
154 : }
155 :
156 190 : tmp = vstr_spn_chrs_fwd(base, pos, len, &num_0, 1);
157 : }
158 : else
159 : {
160 179 : xX[0] = let_b_low;
161 179 : xX[1] = let_B_high;
162 179 : tmp = vstr_spn_chrs_fwd(base, pos, len, xX, 2);
163 :
164 179 : if (tmp > 1)
165 : { /* It's a 0 */
166 5 : *err = VSTR_TYPE_PARSE_NUM_ERR_OOB;
167 5 : *passed_len = len;
168 5 : return (1);
169 : }
170 174 : if (tmp == 1)
171 : {
172 45 : if (auto_base)
173 40 : num_base = 2;
174 :
175 45 : pos += tmp;
176 45 : len -= tmp;
177 :
178 45 : if (!len)
179 : {
180 5 : *passed_pos = pos + len;
181 5 : *passed_len = 0;
182 5 : *err = VSTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX;
183 5 : return (0);
184 : }
185 :
186 40 : tmp = vstr_spn_chrs_fwd(base, pos, len, &num_0, 1);
187 : }
188 129 : else if (auto_base)
189 35 : num_base = 8;
190 : }
191 : }
192 45010 : else if (tmp && auto_base)
193 : {
194 20 : num_base = 8;
195 20 : --tmp;
196 : }
197 44990 : else if (auto_base)
198 334 : num_base = 10;
199 :
200 45369 : if (tmp && (flags & VSTR_FLAG_PARSE_NUM_NO_BEG_ZERO))
201 : {
202 441 : *passed_len = len - 1;
203 441 : if ((tmp != 1) || (len != 1))
204 411 : *err = VSTR_TYPE_PARSE_NUM_ERR_BEG_ZERO;
205 :
206 441 : return (1);
207 : }
208 :
209 44928 : if (tmp == len)
210 : { /* It's a 0 */
211 1778 : *passed_len = 0;
212 1778 : return (1);
213 : }
214 :
215 43150 : pos += tmp;
216 43150 : len -= tmp;
217 :
218 43150 : *passed_pos = pos;
219 43150 : *passed_len = len;
220 :
221 43150 : return (num_base);
222 : }
223 :
224 : #define VSTR__PARSE_NUM_BEG_A(num_type) \
225 : unsigned int dummy_err; \
226 : num_type ret = 0; \
227 : unsigned int num_base = 0; \
228 : int is_neg = FALSE; \
229 : int is_zeroed = FALSE; \
230 : size_t orig_len = len; \
231 : char sym_sep = '_'; \
232 : char ascii_num_end = 0x39; \
233 : char ascii_let_low_end = 0x7A; \
234 : char ascii_let_high_end = 0x5A; \
235 : char local_num_end = '9'; \
236 : static const char local_let_low[] = "abcdefghijklmnopqrstuvwxyz"; \
237 : static const char local_let_high[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; \
238 : \
239 : if (ret_len) *ret_len = 0; \
240 : if (!err) err = &dummy_err; \
241 : *err = VSTR_TYPE_PARSE_NUM_ERR_NONE; \
242 : \
243 : if (!(num_base = vstr__parse_num_beg(base, &pos, &len, flags, \
244 : &is_neg, &is_zeroed, err))) \
245 : return (0); \
246 : else if (num_base == 1) goto ret_num_len
247 :
248 : #define VSTR__PARSE_NUM_BEG_S(num_type) \
249 : VSTR__PARSE_NUM_BEG_A(num_type); \
250 : \
251 : if (is_neg && (flags & VSTR_FLAG_PARSE_NUM_NO_NEGATIVE)) \
252 : { \
253 : *err = VSTR_TYPE_PARSE_NUM_ERR_NEGATIVE; \
254 : return (0); \
255 : }
256 :
257 : #define VSTR__PARSE_NUM_BEG_U(num_type) \
258 : VSTR__PARSE_NUM_BEG_A(num_type); \
259 : \
260 : if (is_neg) \
261 : { \
262 : *err = VSTR_TYPE_PARSE_NUM_ERR_NEGATIVE; \
263 : return (0); \
264 : }
265 :
266 : #define VSTR__PARSE_NUM_ASCII() do { \
267 : if (!(flags & VSTR_FLAG_PARSE_NUM_LOCAL)) \
268 : { \
269 : sym_sep = 0x5F; \
270 : \
271 : if (num_base <= 10) \
272 : ascii_num_end = 0x30 + num_base - 1; \
273 : else if (num_base > 10) \
274 : { \
275 : ascii_let_low_end = 0x61 + (num_base - 11); \
276 : ascii_let_high_end = 0x41 + (num_base - 11); \
277 : } \
278 : } \
279 : else if (num_base <= 10) \
280 : local_num_end = '0' + num_base - 1; \
281 : } while (FALSE)
282 :
283 : #define VSTR__PARSE_NUM_BIN_CALC_NUM(num_type) do { \
284 : num_type old_ret = ret; \
285 : \
286 : ret = (ret * num_base) + add_num; \
287 : if ((flags & VSTR_FLAG_PARSE_NUM_OVERFLOW) && \
288 : (((ret - add_num) / num_base) != old_ret)) \
289 : { \
290 : *err = VSTR_TYPE_PARSE_NUM_ERR_OVERFLOW; \
291 : break; \
292 : } \
293 : } while (FALSE) \
294 :
295 : #define VSTR__PARSE_NUM_LOOP_BEG() do { \
296 : int done_once = is_zeroed; \
297 : Vstr_iter iter[1]; \
298 : int iter_ret = vstr_iter_fwd_beg(base, pos, len, iter); \
299 : \
300 : ASSERT(iter_ret); \
301 : while (len) \
302 : { \
303 : char scan = vstr_iter_fwd_chr(iter, NULL); \
304 : const char *end = NULL; \
305 : unsigned int add_num = 0; \
306 : \
307 : if (done_once && (scan == sym_sep)) \
308 : { \
309 : if (!(flags & VSTR_FLAG_PARSE_NUM_SEP)) break; \
310 : --len; \
311 : continue; \
312 : } \
313 : else if (VSTR__PARSE_NUM_USE_LOCAL && \
314 : (flags & VSTR_FLAG_PARSE_NUM_LOCAL)) \
315 : { \
316 : if ((scan >= '0') && (scan <= local_num_end)) \
317 : add_num = (scan - '0'); \
318 : else if (num_base <= 10) \
319 : break; \
320 : else if ((end = vstr_wrap_memchr(local_let_low, scan, \
321 : num_base - 10))) \
322 : add_num = 10 + (end - local_let_low); \
323 : else if ((end = vstr_wrap_memchr(local_let_high, scan, \
324 : num_base - 10))) \
325 : add_num = 10 + (end - local_let_high); \
326 : else \
327 : break; \
328 : } \
329 : else \
330 : { \
331 : if (scan < (char)0x30) break; \
332 : \
333 : if (scan <= ascii_num_end) \
334 : add_num = (scan - (char)0x30); \
335 : else if (num_base <= 10) \
336 : break; \
337 : else if ((scan >= (char)0x41) && (scan <= ascii_let_high_end)) \
338 : add_num = 10 + (scan - (char)0x41); \
339 : else if ((scan >= 0x61) && (scan <= ascii_let_low_end)) \
340 : add_num = 10 + (scan - (char)0x61); \
341 : else \
342 : break; \
343 : } \
344 :
345 : #define VSTR__PARSE_NUM_LOOP_END() \
346 : --len; \
347 : done_once = TRUE; \
348 : } \
349 : } while (FALSE)
350 :
351 : /* assume negative numbers can be one bigger than signed positive numbers */
352 : #define VSTR__PARSE_NUM_END_S(num_max) do { \
353 : if ((flags & VSTR_FLAG_PARSE_NUM_OVERFLOW) && \
354 : ((ret - is_neg) > num_max)) \
355 : { \
356 : *err = VSTR_TYPE_PARSE_NUM_ERR_OVERFLOW; \
357 : ret = num_max + is_neg; \
358 : } \
359 : if (len && !*err) *err = VSTR_TYPE_PARSE_NUM_ERR_OOB; \
360 : \
361 : ret_num_len: \
362 : if (ret_len) \
363 : *ret_len = (orig_len - len); \
364 : \
365 : if (is_neg) \
366 : return (-ret); \
367 : \
368 : return (ret); \
369 : } while (FALSE)
370 :
371 : #define VSTR__PARSE_NUM_END_U() do { \
372 : if (len && !*err) *err = VSTR_TYPE_PARSE_NUM_ERR_OOB; \
373 : \
374 : ret_num_len: \
375 : if (ret_len) \
376 : *ret_len = (orig_len - len); \
377 : \
378 : return (ret); \
379 : } while (FALSE)
380 :
381 : #define VSTR__PARSE_NUM_SFUNC(num_type, num_max) do { \
382 : VSTR__PARSE_NUM_BEG_S(num_type); \
383 : VSTR__PARSE_NUM_ASCII(); \
384 : VSTR__PARSE_NUM_LOOP_BEG(); \
385 : VSTR__PARSE_NUM_BIN_CALC_NUM(num_type); \
386 : VSTR__PARSE_NUM_LOOP_END(); \
387 : VSTR__PARSE_NUM_END_S(num_max); \
388 : } while (FALSE)
389 :
390 : #define VSTR__PARSE_NUM_UFUNC(num_type) do { \
391 : VSTR__PARSE_NUM_BEG_U(num_type); \
392 : VSTR__PARSE_NUM_ASCII(); \
393 : VSTR__PARSE_NUM_LOOP_BEG(); \
394 : VSTR__PARSE_NUM_BIN_CALC_NUM(num_type); \
395 : VSTR__PARSE_NUM_LOOP_END(); \
396 : VSTR__PARSE_NUM_END_U(); \
397 : } while (FALSE)
398 :
399 : void *vstr_parse_num(const Vstr_base *base, size_t pos, size_t len,
400 : unsigned int flags, size_t *ret_len,
401 : unsigned int *err,
402 : void *(*func)(unsigned int, int, unsigned int *, void *),
403 : void *data)
404 130 : {
405 130 : VSTR__PARSE_NUM_BEG_S(void *);
406 130 : ret = data;
407 130 : VSTR__PARSE_NUM_ASCII();
408 130 : VSTR__PARSE_NUM_LOOP_BEG();
409 :
410 620 : if (is_neg) add_num = -add_num;
411 :
412 620 : if (!(ret = func(num_base, add_num, err, ret)) && !*err)
413 10 : return (NULL); /* mem error */
414 :
415 610 : VSTR__PARSE_NUM_LOOP_END();
416 120 : VSTR__PARSE_NUM_END_U();
417 : }
418 :
419 : short vstr_parse_short(const Vstr_base *base, size_t pos, size_t len,
420 : unsigned int flags, size_t *ret_len,
421 : unsigned int *err)
422 100 : { VSTR__PARSE_NUM_SFUNC(unsigned short, SHRT_MAX); }
423 :
424 : unsigned short vstr_parse_ushort(const Vstr_base *base,
425 : size_t pos, size_t len,
426 : unsigned int flags, size_t *ret_len,
427 : unsigned int *err)
428 536 : { VSTR__PARSE_NUM_UFUNC(unsigned short); }
429 :
430 : int vstr_parse_int(const Vstr_base *base, size_t pos, size_t len,
431 : unsigned int flags, size_t *ret_len, unsigned int *err)
432 90 : { VSTR__PARSE_NUM_SFUNC(unsigned int, INT_MAX); }
433 :
434 : unsigned int vstr_parse_uint(const Vstr_base *base, size_t pos, size_t len,
435 : unsigned int flags, size_t *ret_len,
436 : unsigned int *err)
437 33213 : { VSTR__PARSE_NUM_UFUNC(unsigned int); }
438 :
439 : long vstr_parse_long(const Vstr_base *base, size_t pos, size_t len,
440 : unsigned int flags, size_t *ret_len,
441 : unsigned int *err)
442 10 : { VSTR__PARSE_NUM_SFUNC(unsigned long, LONG_MAX); }
443 :
444 : unsigned long vstr_parse_ulong(const Vstr_base *base, size_t pos, size_t len,
445 : unsigned int flags, size_t *ret_len,
446 : unsigned int *err)
447 6397 : { VSTR__PARSE_NUM_UFUNC(unsigned long); }
448 :
449 : intmax_t vstr_parse_intmax(const struct Vstr_base *base,
450 : size_t pos, size_t len,
451 : unsigned int flags, size_t *ret_len,
452 : unsigned int *err)
453 25 : { VSTR__PARSE_NUM_SFUNC(uintmax_t, INTMAX_MAX); }
454 :
455 : uintmax_t vstr_parse_uintmax(const struct Vstr_base *base,
456 : size_t pos, size_t len,
457 : unsigned int flags, size_t *ret_len,
458 : unsigned int *err)
459 5362 : { VSTR__PARSE_NUM_UFUNC(uintmax_t); }
460 :
461 : static int vstr__parse_ipv4_netmask(const struct Vstr_base *base,
462 : size_t pos, size_t *passed_len,
463 : unsigned int flags,
464 : unsigned int num_flags,
465 : char sym_dot,
466 : unsigned int *cidr, unsigned int *err)
467 : {
468 105 : int zero_rest = FALSE;
469 105 : size_t len = *passed_len;
470 105 : unsigned int scan = 0;
471 :
472 380 : while (len)
473 : {
474 360 : unsigned int tmp = 0;
475 360 : size_t num_len = 3;
476 :
477 360 : if (num_len > len)
478 30 : num_len = len;
479 :
480 360 : tmp = vstr_parse_uint(base, pos, num_len, 10 | num_flags,
481 : &num_len, NULL);
482 360 : if (!num_len)
483 5 : break;
484 :
485 355 : pos += num_len;
486 355 : len -= num_len;
487 :
488 355 : if (zero_rest && tmp)
489 : {
490 5 : *err = VSTR_TYPE_PARSE_IPV4_ERR_NETMASK_OOB;
491 5 : return (FALSE);
492 : }
493 350 : else if (!zero_rest)
494 : {
495 335 : if (tmp > 255)
496 : {
497 5 : *err = VSTR_TYPE_PARSE_IPV4_ERR_NETMASK_OOB;
498 5 : return (FALSE);
499 : }
500 :
501 330 : if (tmp != 255)
502 : {
503 75 : *cidr = scan * 8;
504 75 : switch (tmp)
505 : {
506 : default:
507 5 : *err = VSTR_TYPE_PARSE_IPV4_ERR_NETMASK_OOB;
508 5 : return (FALSE);
509 :
510 5 : case 254: *cidr += 7; break;
511 5 : case 252: *cidr += 6; break;
512 5 : case 248: *cidr += 5; break;
513 5 : case 240: *cidr += 4; break;
514 5 : case 224: *cidr += 3; break;
515 20 : case 192: *cidr += 2; break;
516 25 : case 128: *cidr += 1; break;
517 70 : case 0: break;
518 : }
519 70 : zero_rest = TRUE;
520 : }
521 : }
522 :
523 340 : ++scan;
524 :
525 340 : if (scan == 4)
526 60 : break;
527 :
528 280 : if (len && (vstr_export_chr(base, pos) != sym_dot))
529 5 : break;
530 :
531 275 : if (len)
532 : { /* skip the dot */
533 265 : ++pos;
534 265 : --len;
535 : }
536 : }
537 90 : if (!zero_rest)
538 25 : *cidr = scan * 8;
539 :
540 90 : if ((flags & VSTR_FLAG_PARSE_IPV4_NETMASK_FULL) && (scan != 4))
541 : {
542 10 : *err = VSTR_TYPE_PARSE_IPV4_ERR_NETMASK_FULL;
543 10 : return (FALSE);
544 : }
545 :
546 80 : *passed_len = len;
547 :
548 80 : return (TRUE);
549 : }
550 :
551 : static int vstr__parse_ipv4_cidr(const struct Vstr_base *base,
552 : size_t pos, size_t *passed_len,
553 : unsigned int flags,
554 : unsigned int num_flags,
555 : char sym_dot,
556 : unsigned int *cidr, unsigned int *err)
557 105 : {
558 105 : size_t len = *passed_len;
559 105 : size_t num_len = 0;
560 :
561 105 : if (len)
562 95 : *cidr = vstr_parse_uint(base, pos, len, 10 | num_flags,
563 : &num_len, NULL);
564 105 : if (num_len)
565 : {
566 95 : if ((flags & VSTR_FLAG_PARSE_IPV4_NETMASK) &&
567 : (*cidr > 32) && (len > num_len) &&
568 : (vstr_export_chr(base, pos + num_len) == sym_dot))
569 : {
570 70 : if (!vstr__parse_ipv4_netmask(base, pos, &len, flags, num_flags,
571 : sym_dot, cidr, err))
572 10 : return (FALSE);
573 : }
574 25 : else if (*cidr <= 32)
575 : {
576 20 : pos += num_len;
577 20 : len -= num_len;
578 : }
579 : else
580 : {
581 5 : *err = VSTR_TYPE_PARSE_IPV4_ERR_CIDR_OOB;
582 5 : return (FALSE);
583 : }
584 : }
585 10 : else if (flags & VSTR_FLAG_PARSE_IPV4_CIDR_FULL)
586 : {
587 5 : *err = VSTR_TYPE_PARSE_IPV4_ERR_CIDR_FULL;
588 5 : return (FALSE);
589 : }
590 : else
591 5 : *cidr = 32;
592 :
593 85 : *passed_len = len;
594 :
595 85 : return (TRUE);
596 : }
597 :
598 : int vstr_parse_ipv4(const struct Vstr_base *base,
599 : size_t pos, size_t len,
600 : unsigned char *ips, unsigned int *cidr,
601 : unsigned int flags, size_t *ret_len, unsigned int *err)
602 270 : {
603 270 : size_t orig_len = len;
604 270 : char sym_slash = 0x2F;
605 270 : char sym_dot = 0x2E;
606 270 : unsigned int num_flags = VSTR_FLAG_PARSE_NUM_NO_BEG_PM;
607 270 : unsigned int scan = 0;
608 270 : unsigned int dummy_err = 0;
609 :
610 270 : assert(ips);
611 :
612 270 : if (ret_len) *ret_len = 0;
613 270 : if (!err)
614 70 : err = &dummy_err;
615 :
616 270 : *err = 0;
617 :
618 270 : if (flags & VSTR_FLAG_PARSE_IPV4_LOCAL)
619 : {
620 20 : num_flags |= VSTR_FLAG_PARSE_NUM_LOCAL;
621 20 : sym_slash = '/';
622 20 : sym_dot = '.';
623 : }
624 :
625 270 : if (!(flags & VSTR_FLAG_PARSE_IPV4_ZEROS))
626 265 : num_flags |= VSTR_FLAG_PARSE_NUM_NO_BEG_ZERO;
627 :
628 995 : while (len)
629 : {
630 990 : unsigned int tmp = 0;
631 990 : size_t num_len = 3;
632 :
633 990 : if (num_len > len)
634 85 : num_len = len;
635 :
636 990 : tmp = vstr_parse_uint(base, pos, num_len, 10 | num_flags,
637 : &num_len, NULL);
638 990 : if (!num_len)
639 15 : break;
640 :
641 975 : if (tmp > 255)
642 : {
643 5 : *err = VSTR_TYPE_PARSE_IPV4_ERR_IPV4_OOB;
644 5 : return (FALSE);
645 : }
646 :
647 970 : pos += num_len;
648 970 : len -= num_len;
649 :
650 970 : ips[scan++] = tmp;
651 :
652 970 : if (scan == 4)
653 225 : break;
654 :
655 745 : if (len && (vstr_export_chr(base, pos) == sym_slash))
656 10 : break;
657 :
658 735 : if (len && (vstr_export_chr(base, pos) != sym_dot))
659 10 : break;
660 :
661 725 : if (len)
662 : { /* skip the dot */
663 720 : ++pos;
664 720 : --len;
665 : }
666 :
667 725 : if (len && (vstr_export_chr(base, pos) == sym_slash))
668 265 : break;
669 : }
670 :
671 265 : if ((scan != 4) && (flags & VSTR_FLAG_PARSE_IPV4_FULL))
672 : {
673 20 : *err = VSTR_TYPE_PARSE_IPV4_ERR_IPV4_FULL;
674 20 : return (FALSE);
675 : }
676 :
677 285 : while (scan < 4)
678 40 : ips[scan++] = 0;
679 :
680 245 : if (cidr)
681 185 : *cidr = 32;
682 :
683 245 : if (len && (vstr_export_chr(base, pos) == sym_slash))
684 : {
685 160 : if (flags & VSTR_FLAG_PARSE_IPV4_CIDR)
686 : {
687 105 : ++pos;
688 105 : --len;
689 :
690 105 : if (!vstr__parse_ipv4_cidr(base, pos, &len, flags, num_flags, sym_dot,
691 : cidr, err))
692 20 : return (FALSE);
693 : }
694 55 : else if (flags & VSTR_FLAG_PARSE_IPV4_NETMASK)
695 : {
696 35 : ++pos;
697 35 : --len;
698 :
699 35 : if (!vstr__parse_ipv4_netmask(base, pos, &len, flags, num_flags, sym_dot,
700 : cidr, err))
701 15 : return (FALSE);
702 : }
703 : }
704 :
705 210 : if (len && (flags & VSTR_FLAG_PARSE_IPV4_ONLY))
706 20 : *err = VSTR_TYPE_PARSE_IPV4_ERR_ONLY;
707 :
708 210 : if (ret_len)
709 210 : *ret_len = orig_len - len;
710 :
711 210 : return (TRUE);
712 : }
713 :
714 : static int vstr__parse_ipv6_cidr(const struct Vstr_base *base,
715 : size_t pos, size_t *passed_len,
716 : unsigned int flags,
717 : unsigned int num_flags,
718 : unsigned int *cidr, unsigned int *err)
719 110 : {
720 110 : size_t len = *passed_len;
721 110 : size_t num_len = 0;
722 :
723 110 : if (len)
724 90 : *cidr = vstr_parse_uint(base, pos, len, 10 | num_flags,
725 : &num_len, NULL);
726 110 : if (num_len)
727 : {
728 90 : if (*cidr <= 128)
729 : {
730 80 : pos += num_len;
731 80 : len -= num_len;
732 : }
733 : else
734 : {
735 10 : *err = VSTR_TYPE_PARSE_IPV6_ERR_CIDR_OOB;
736 10 : return (FALSE);
737 : }
738 : }
739 20 : else if (flags & VSTR_FLAG_PARSE_IPV6_CIDR_FULL)
740 : {
741 10 : *err = VSTR_TYPE_PARSE_IPV6_ERR_CIDR_FULL;
742 10 : return (FALSE);
743 : }
744 : else
745 10 : *cidr = 128;
746 :
747 90 : *passed_len = len;
748 :
749 90 : return (TRUE);
750 : }
751 :
752 : /* see rfc 2373 */
753 : /*
754 : * 1. 1 to 4 hexdigits in 8 groups: hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh
755 : * h:h:h:h:h:h:h:h
756 : * 2. Any number of 0000 may be abbreviated as "::", but only once
757 : * 3. Note this means that "::" is a valid ipv6 address (all zeros)
758 : * 4. The last two words may be written as an IPv4 address ::1234:127.0.0.1
759 : */
760 : int vstr_parse_ipv6(const struct Vstr_base *base,
761 : size_t pos, size_t len,
762 : unsigned int *ips, unsigned int *cidr,
763 : unsigned int flags, size_t *ret_len, unsigned int *err)
764 310 : {
765 310 : size_t orig_len = len;
766 310 : char sym_slash = 0x2F;
767 310 : char sym_colon = 0x3a;
768 310 : unsigned int num_flags = VSTR_FLAG_PARSE_NUM_NO_BEG_PM;
769 310 : unsigned int scan = 0;
770 310 : unsigned int dummy_err = 0;
771 310 : unsigned int off_null = 0;
772 310 : VSTR_SECTS_DECL(sects, 8);
773 310 : size_t num_len = 0;
774 :
775 310 : VSTR_SECTS_DECL_INIT(sects);
776 :
777 310 : assert(ips);
778 310 : vstr_wrap_memset(ips, 0, sizeof(int) * 8);
779 :
780 310 : if (ret_len) *ret_len = 0;
781 310 : if (!err)
782 155 : err = &dummy_err;
783 :
784 310 : *err = 0;
785 :
786 310 : if (len < 2)
787 : {
788 10 : *err = VSTR_TYPE_PARSE_IPV6_ERR_IPV6_FULL;
789 10 : return (FALSE);
790 : }
791 :
792 300 : if (flags & VSTR_FLAG_PARSE_IPV6_LOCAL)
793 : {
794 20 : num_flags |= VSTR_FLAG_PARSE_NUM_LOCAL;
795 20 : sym_slash = '/';
796 20 : sym_colon = ':';
797 : }
798 :
799 : {
800 300 : const int split_flags = (VSTR_FLAG_SPLIT_MID_NULL | VSTR_FLAG_SPLIT_NO_RET);
801 300 : char buf[2]; buf[0] = sym_colon; buf[1] = sym_colon;
802 :
803 300 : if (VSTR_CMP_BUF_EQ(base, pos, 2, buf, 2))
804 70 : vstr_sects_add(sects, pos, 0);
805 :
806 300 : vstr_split_buf(base, pos, len, buf, 1, sects, sects->sz, split_flags);
807 : }
808 :
809 1570 : while (scan < sects->num)
810 : {
811 1340 : unsigned int tmp = 0;
812 :
813 1340 : ++scan;
814 1340 : if (!VSTR_SECTS_NUM(sects, scan)->len)
815 : {
816 220 : if (off_null)
817 : {
818 10 : *err = VSTR_TYPE_PARSE_IPV6_ERR_IPV6_NULL;
819 10 : return (FALSE);
820 : }
821 :
822 210 : off_null = scan;
823 210 : ips[scan - 1] = 0;
824 210 : continue;
825 : }
826 :
827 1120 : tmp = vstr_parse_uint(base,
828 : VSTR_SECTS_NUM(sects, scan)->pos,
829 : VSTR_SECTS_NUM(sects, scan)->len, 16 | num_flags,
830 : &num_len, NULL);
831 1120 : if (!num_len && off_null && (off_null == (scan - 1)) &&
832 : (scan == sects->num))
833 50 : break;
834 :
835 1070 : if ((num_len > 4) || !num_len || (tmp > 0xFFFF))
836 : {
837 10 : *err = VSTR_TYPE_PARSE_IPV6_ERR_IPV6_OOB;
838 10 : return (FALSE);
839 : }
840 :
841 1060 : ips[scan - 1] = tmp;
842 : }
843 :
844 280 : len -= VSTR_SECTS_NUM(sects, scan)->pos - pos;
845 280 : pos = VSTR_SECTS_NUM(sects, scan)->pos;
846 280 : if (scan != 8)
847 : {
848 230 : ASSERT(scan < 8);
849 :
850 230 : if ((VSTR_SECTS_NUM(sects, scan)->len > 4) && (off_null || (scan == 7)))
851 : { /* try an ipv4 address at the end... */
852 70 : unsigned char ipv4_ips[4];
853 70 : unsigned int ipv4_flags = VSTR_FLAG_PARSE_IPV4_FULL;
854 70 : size_t tmp_num_len = 0;
855 :
856 70 : if (flags & VSTR_FLAG_PARSE_IPV6_LOCAL)
857 10 : ipv4_flags |= VSTR_FLAG_PARSE_IPV4_LOCAL;
858 :
859 70 : ASSERT(off_null != scan);
860 :
861 70 : if (vstr_parse_ipv4(base,
862 : VSTR_SECTS_NUM(sects, scan)->pos,
863 : VSTR_SECTS_NUM(sects, scan)->len,
864 : ipv4_ips, NULL, ipv4_flags, &tmp_num_len, NULL))
865 : {
866 60 : num_len = tmp_num_len;
867 60 : ips[scan - 1] = ipv4_ips[1] + (((unsigned int)ipv4_ips[0]) << 8);
868 60 : ips[scan++] = ipv4_ips[3] + (((unsigned int)ipv4_ips[2]) << 8);
869 : }
870 : }
871 230 : if (scan != 8 && !off_null)
872 : {
873 10 : *err = VSTR_TYPE_PARSE_IPV6_ERR_IPV6_FULL;
874 10 : return (FALSE);
875 : }
876 :
877 220 : if (off_null != scan) /* don't have to do anything for ends with :: */
878 : {
879 220 : unsigned int *beg = ips + off_null;
880 220 : unsigned int off_end = (8 - scan);
881 220 : unsigned int num = (scan - off_null);
882 :
883 220 : vstr_wrap_memmove(beg + off_end, beg, num * sizeof(unsigned int));
884 220 : vstr_wrap_memset(beg, 0, off_end * sizeof(unsigned int));
885 : }
886 : }
887 :
888 270 : ASSERT(len >= num_len);
889 270 : pos += num_len;
890 270 : len -= num_len;
891 270 : if (cidr)
892 270 : *cidr = 128;
893 :
894 270 : if (len && (vstr_export_chr(base, pos) == sym_slash))
895 : {
896 160 : if (flags & VSTR_FLAG_PARSE_IPV6_CIDR)
897 : {
898 110 : ++pos;
899 110 : --len;
900 :
901 110 : if (!vstr__parse_ipv6_cidr(base, pos, &len, flags, num_flags, cidr, err))
902 20 : return (FALSE);
903 : }
904 : }
905 :
906 250 : if (len && (flags & VSTR_FLAG_PARSE_IPV6_ONLY))
907 10 : *err = VSTR_TYPE_PARSE_IPV6_ERR_ONLY;
908 :
909 250 : if (ret_len)
910 250 : *ret_len = orig_len - len;
911 :
912 250 : return (TRUE);
913 : }
|