]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/parse-util.c
networkd: tunnel ignore wrong conf rather than assert
[thirdparty/systemd.git] / src / basic / parse-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6 ***/
7
8 #include <errno.h>
9 #include <inttypes.h>
10 #include <locale.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/socket.h>
15
16 #include "alloc-util.h"
17 #include "errno-list.h"
18 #include "extract-word.h"
19 #include "locale-util.h"
20 #include "macro.h"
21 #include "missing.h"
22 #include "parse-util.h"
23 #include "process-util.h"
24 #include "string-util.h"
25
26 int parse_boolean(const char *v) {
27 assert(v);
28
29 if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
30 return 1;
31 else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
32 return 0;
33
34 return -EINVAL;
35 }
36
37 int parse_pid(const char *s, pid_t* ret_pid) {
38 unsigned long ul = 0;
39 pid_t pid;
40 int r;
41
42 assert(s);
43 assert(ret_pid);
44
45 r = safe_atolu(s, &ul);
46 if (r < 0)
47 return r;
48
49 pid = (pid_t) ul;
50
51 if ((unsigned long) pid != ul)
52 return -ERANGE;
53
54 if (!pid_is_valid(pid))
55 return -ERANGE;
56
57 *ret_pid = pid;
58 return 0;
59 }
60
61 int parse_mode(const char *s, mode_t *ret) {
62 char *x;
63 long l;
64
65 assert(s);
66 assert(ret);
67
68 s += strspn(s, WHITESPACE);
69 if (s[0] == '-')
70 return -ERANGE;
71
72 errno = 0;
73 l = strtol(s, &x, 8);
74 if (errno > 0)
75 return -errno;
76 if (!x || x == s || *x != 0)
77 return -EINVAL;
78 if (l < 0 || l > 07777)
79 return -ERANGE;
80
81 *ret = (mode_t) l;
82 return 0;
83 }
84
85 int parse_ifindex(const char *s, int *ret) {
86 int ifi, r;
87
88 r = safe_atoi(s, &ifi);
89 if (r < 0)
90 return r;
91 if (ifi <= 0)
92 return -EINVAL;
93
94 *ret = ifi;
95 return 0;
96 }
97
98 int parse_mtu(int family, const char *s, uint32_t *ret) {
99 uint64_t u;
100 size_t m;
101 int r;
102
103 r = parse_size(s, 1024, &u);
104 if (r < 0)
105 return r;
106
107 if (u > UINT32_MAX)
108 return -ERANGE;
109
110 if (family == AF_INET6)
111 m = IPV6_MIN_MTU; /* This is 1280 */
112 else
113 m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */
114
115 if (u < m)
116 return -ERANGE;
117
118 *ret = (uint32_t) u;
119 return 0;
120 }
121
122 int parse_size(const char *t, uint64_t base, uint64_t *size) {
123
124 /* Soo, sometimes we want to parse IEC binary suffixes, and
125 * sometimes SI decimal suffixes. This function can parse
126 * both. Which one is the right way depends on the
127 * context. Wikipedia suggests that SI is customary for
128 * hardware metrics and network speeds, while IEC is
129 * customary for most data sizes used by software and volatile
130 * (RAM) memory. Hence be careful which one you pick!
131 *
132 * In either case we use just K, M, G as suffix, and not Ki,
133 * Mi, Gi or so (as IEC would suggest). That's because that's
134 * frickin' ugly. But this means you really need to make sure
135 * to document which base you are parsing when you use this
136 * call. */
137
138 struct table {
139 const char *suffix;
140 unsigned long long factor;
141 };
142
143 static const struct table iec[] = {
144 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
145 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
146 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
147 { "G", 1024ULL*1024ULL*1024ULL },
148 { "M", 1024ULL*1024ULL },
149 { "K", 1024ULL },
150 { "B", 1ULL },
151 { "", 1ULL },
152 };
153
154 static const struct table si[] = {
155 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
156 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
157 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
158 { "G", 1000ULL*1000ULL*1000ULL },
159 { "M", 1000ULL*1000ULL },
160 { "K", 1000ULL },
161 { "B", 1ULL },
162 { "", 1ULL },
163 };
164
165 const struct table *table;
166 const char *p;
167 unsigned long long r = 0;
168 unsigned n_entries, start_pos = 0;
169
170 assert(t);
171 assert(IN_SET(base, 1000, 1024));
172 assert(size);
173
174 if (base == 1000) {
175 table = si;
176 n_entries = ELEMENTSOF(si);
177 } else {
178 table = iec;
179 n_entries = ELEMENTSOF(iec);
180 }
181
182 p = t;
183 do {
184 unsigned long long l, tmp;
185 double frac = 0;
186 char *e;
187 unsigned i;
188
189 p += strspn(p, WHITESPACE);
190
191 errno = 0;
192 l = strtoull(p, &e, 10);
193 if (errno > 0)
194 return -errno;
195 if (e == p)
196 return -EINVAL;
197 if (*p == '-')
198 return -ERANGE;
199
200 if (*e == '.') {
201 e++;
202
203 /* strtoull() itself would accept space/+/- */
204 if (*e >= '0' && *e <= '9') {
205 unsigned long long l2;
206 char *e2;
207
208 l2 = strtoull(e, &e2, 10);
209 if (errno > 0)
210 return -errno;
211
212 /* Ignore failure. E.g. 10.M is valid */
213 frac = l2;
214 for (; e < e2; e++)
215 frac /= 10;
216 }
217 }
218
219 e += strspn(e, WHITESPACE);
220
221 for (i = start_pos; i < n_entries; i++)
222 if (startswith(e, table[i].suffix))
223 break;
224
225 if (i >= n_entries)
226 return -EINVAL;
227
228 if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
229 return -ERANGE;
230
231 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
232 if (tmp > ULLONG_MAX - r)
233 return -ERANGE;
234
235 r += tmp;
236 if ((unsigned long long) (uint64_t) r != r)
237 return -ERANGE;
238
239 p = e + strlen(table[i].suffix);
240
241 start_pos = i + 1;
242
243 } while (*p);
244
245 *size = r;
246
247 return 0;
248 }
249
250 int parse_range(const char *t, unsigned *lower, unsigned *upper) {
251 _cleanup_free_ char *word = NULL;
252 unsigned l, u;
253 int r;
254
255 assert(lower);
256 assert(upper);
257
258 /* Extract the lower bound. */
259 r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
260 if (r < 0)
261 return r;
262 if (r == 0)
263 return -EINVAL;
264
265 r = safe_atou(word, &l);
266 if (r < 0)
267 return r;
268
269 /* Check for the upper bound and extract it if needed */
270 if (!t)
271 /* Single number with no dashes. */
272 u = l;
273 else if (!*t)
274 /* Trailing dash is an error. */
275 return -EINVAL;
276 else {
277 r = safe_atou(t, &u);
278 if (r < 0)
279 return r;
280 }
281
282 *lower = l;
283 *upper = u;
284 return 0;
285 }
286
287 int parse_errno(const char *t) {
288 int r, e;
289
290 assert(t);
291
292 r = errno_from_name(t);
293 if (r > 0)
294 return r;
295
296 r = safe_atoi(t, &e);
297 if (r < 0)
298 return r;
299
300 /* 0 is also allowed here */
301 if (!errno_is_valid(e) && e != 0)
302 return -ERANGE;
303
304 return e;
305 }
306
307 int parse_syscall_and_errno(const char *in, char **name, int *error) {
308 _cleanup_free_ char *n = NULL;
309 char *p;
310 int e = -1;
311
312 assert(in);
313 assert(name);
314 assert(error);
315
316 /*
317 * This parse "syscall:errno" like "uname:EILSEQ", "@sync:255".
318 * If errno is omitted, then error is set to -1.
319 * Empty syscall name is not allowed.
320 * Here, we do not check that the syscall name is valid or not.
321 */
322
323 p = strchr(in, ':');
324 if (p) {
325 e = parse_errno(p + 1);
326 if (e < 0)
327 return e;
328
329 n = strndup(in, p - in);
330 } else
331 n = strdup(in);
332
333 if (!n)
334 return -ENOMEM;
335
336 if (isempty(n))
337 return -EINVAL;
338
339 *error = e;
340 *name = TAKE_PTR(n);
341
342 return 0;
343 }
344
345 char *format_bytes(char *buf, size_t l, uint64_t t) {
346 unsigned i;
347
348 /* This only does IEC units so far */
349
350 static const struct {
351 const char *suffix;
352 uint64_t factor;
353 } table[] = {
354 { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
355 { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
356 { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
357 { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
358 { "M", UINT64_C(1024)*UINT64_C(1024) },
359 { "K", UINT64_C(1024) },
360 };
361
362 if (t == (uint64_t) -1)
363 return NULL;
364
365 for (i = 0; i < ELEMENTSOF(table); i++) {
366
367 if (t >= table[i].factor) {
368 snprintf(buf, l,
369 "%" PRIu64 ".%" PRIu64 "%s",
370 t / table[i].factor,
371 ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
372 table[i].suffix);
373
374 goto finish;
375 }
376 }
377
378 snprintf(buf, l, "%" PRIu64 "B", t);
379
380 finish:
381 buf[l-1] = 0;
382 return buf;
383
384 }
385
386 int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
387 char *x = NULL;
388 unsigned long l;
389
390 assert(s);
391 assert(ret_u);
392 assert(base <= 16);
393
394 /* strtoul() is happy to parse negative values, and silently
395 * converts them to unsigned values without generating an
396 * error. We want a clean error, hence let's look for the "-"
397 * prefix on our own, and generate an error. But let's do so
398 * only after strtoul() validated that the string is clean
399 * otherwise, so that we return EINVAL preferably over
400 * ERANGE. */
401
402 s += strspn(s, WHITESPACE);
403
404 errno = 0;
405 l = strtoul(s, &x, base);
406 if (errno > 0)
407 return -errno;
408 if (!x || x == s || *x != 0)
409 return -EINVAL;
410 if (s[0] == '-')
411 return -ERANGE;
412 if ((unsigned long) (unsigned) l != l)
413 return -ERANGE;
414
415 *ret_u = (unsigned) l;
416 return 0;
417 }
418
419 int safe_atoi(const char *s, int *ret_i) {
420 char *x = NULL;
421 long l;
422
423 assert(s);
424 assert(ret_i);
425
426 errno = 0;
427 l = strtol(s, &x, 0);
428 if (errno > 0)
429 return -errno;
430 if (!x || x == s || *x != 0)
431 return -EINVAL;
432 if ((long) (int) l != l)
433 return -ERANGE;
434
435 *ret_i = (int) l;
436 return 0;
437 }
438
439 int safe_atollu(const char *s, long long unsigned *ret_llu) {
440 char *x = NULL;
441 unsigned long long l;
442
443 assert(s);
444 assert(ret_llu);
445
446 s += strspn(s, WHITESPACE);
447
448 errno = 0;
449 l = strtoull(s, &x, 0);
450 if (errno > 0)
451 return -errno;
452 if (!x || x == s || *x != 0)
453 return -EINVAL;
454 if (*s == '-')
455 return -ERANGE;
456
457 *ret_llu = l;
458 return 0;
459 }
460
461 int safe_atolli(const char *s, long long int *ret_lli) {
462 char *x = NULL;
463 long long l;
464
465 assert(s);
466 assert(ret_lli);
467
468 errno = 0;
469 l = strtoll(s, &x, 0);
470 if (errno > 0)
471 return -errno;
472 if (!x || x == s || *x != 0)
473 return -EINVAL;
474
475 *ret_lli = l;
476 return 0;
477 }
478
479 int safe_atou8(const char *s, uint8_t *ret) {
480 char *x = NULL;
481 unsigned long l;
482
483 assert(s);
484 assert(ret);
485
486 s += strspn(s, WHITESPACE);
487
488 errno = 0;
489 l = strtoul(s, &x, 0);
490 if (errno > 0)
491 return -errno;
492 if (!x || x == s || *x != 0)
493 return -EINVAL;
494 if (s[0] == '-')
495 return -ERANGE;
496 if ((unsigned long) (uint8_t) l != l)
497 return -ERANGE;
498
499 *ret = (uint8_t) l;
500 return 0;
501 }
502
503 int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
504 char *x = NULL;
505 unsigned long l;
506
507 assert(s);
508 assert(ret);
509 assert(base <= 16);
510
511 s += strspn(s, WHITESPACE);
512
513 errno = 0;
514 l = strtoul(s, &x, base);
515 if (errno > 0)
516 return -errno;
517 if (!x || x == s || *x != 0)
518 return -EINVAL;
519 if (s[0] == '-')
520 return -ERANGE;
521 if ((unsigned long) (uint16_t) l != l)
522 return -ERANGE;
523
524 *ret = (uint16_t) l;
525 return 0;
526 }
527
528 int safe_atoi16(const char *s, int16_t *ret) {
529 char *x = NULL;
530 long l;
531
532 assert(s);
533 assert(ret);
534
535 errno = 0;
536 l = strtol(s, &x, 0);
537 if (errno > 0)
538 return -errno;
539 if (!x || x == s || *x != 0)
540 return -EINVAL;
541 if ((long) (int16_t) l != l)
542 return -ERANGE;
543
544 *ret = (int16_t) l;
545 return 0;
546 }
547
548 int safe_atod(const char *s, double *ret_d) {
549 _cleanup_(freelocalep) locale_t loc = (locale_t) 0;
550 char *x = NULL;
551 double d = 0;
552
553 assert(s);
554 assert(ret_d);
555
556 loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
557 if (loc == (locale_t) 0)
558 return -errno;
559
560 errno = 0;
561 d = strtod_l(s, &x, loc);
562 if (errno > 0)
563 return -errno;
564 if (!x || x == s || *x != 0)
565 return -EINVAL;
566
567 *ret_d = (double) d;
568 return 0;
569 }
570
571 int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
572 size_t i;
573 unsigned val = 0;
574 const char *s;
575
576 s = *p;
577
578 /* accept any number of digits, strtoull is limted to 19 */
579 for (i=0; i < digits; i++,s++) {
580 if (*s < '0' || *s > '9') {
581 if (i == 0)
582 return -EINVAL;
583
584 /* too few digits, pad with 0 */
585 for (; i < digits; i++)
586 val *= 10;
587
588 break;
589 }
590
591 val *= 10;
592 val += *s - '0';
593 }
594
595 /* maybe round up */
596 if (*s >= '5' && *s <= '9')
597 val++;
598
599 s += strspn(s, DIGITS);
600
601 *p = s;
602 *res = val;
603
604 return 0;
605 }
606
607 int parse_percent_unbounded(const char *p) {
608 const char *pc, *n;
609 int r, v;
610
611 pc = endswith(p, "%");
612 if (!pc)
613 return -EINVAL;
614
615 n = strndupa(p, pc - p);
616 r = safe_atoi(n, &v);
617 if (r < 0)
618 return r;
619 if (v < 0)
620 return -ERANGE;
621
622 return v;
623 }
624
625 int parse_percent(const char *p) {
626 int v;
627
628 v = parse_percent_unbounded(p);
629 if (v > 100)
630 return -ERANGE;
631
632 return v;
633 }
634
635 int parse_nice(const char *p, int *ret) {
636 int n, r;
637
638 r = safe_atoi(p, &n);
639 if (r < 0)
640 return r;
641
642 if (!nice_is_valid(n))
643 return -ERANGE;
644
645 *ret = n;
646 return 0;
647 }
648
649 int parse_ip_port(const char *s, uint16_t *ret) {
650 uint16_t l;
651 int r;
652
653 r = safe_atou16(s, &l);
654 if (r < 0)
655 return r;
656
657 if (l == 0)
658 return -EINVAL;
659
660 *ret = (uint16_t) l;
661
662 return 0;
663 }
664
665 int parse_dev(const char *s, dev_t *ret) {
666 unsigned x, y;
667 dev_t d;
668
669 if (sscanf(s, "%u:%u", &x, &y) != 2)
670 return -EINVAL;
671
672 d = makedev(x, y);
673 if ((unsigned) major(d) != x || (unsigned) minor(d) != y)
674 return -EINVAL;
675
676 *ret = d;
677 return 0;
678 }
679
680 int parse_oom_score_adjust(const char *s, int *ret) {
681 int r, v;
682
683 assert(s);
684 assert(ret);
685
686 r = safe_atoi(s, &v);
687 if (r < 0)
688 return r;
689
690 if (v < OOM_SCORE_ADJ_MIN || v > OOM_SCORE_ADJ_MAX)
691 return -ERANGE;
692
693 *ret = v;
694 return 0;
695 }