]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/parse-util.c
dfe311b043533b8ef950c6b1b35aa10623327aed
[thirdparty/systemd.git] / src / basic / parse-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <linux/ipv6.h>
4 #include <linux/netfilter/nf_tables.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <sys/socket.h>
8
9 #include "alloc-util.h"
10 #include "errno-list.h"
11 #include "extract-word.h"
12 #include "locale-util.h"
13 #include "log.h"
14 #include "missing_network.h"
15 #include "parse-util.h"
16 #include "process-util.h"
17 #include "string-util.h"
18 #include "strv.h"
19
20 int parse_boolean(const char *v) {
21 if (!v)
22 return -EINVAL;
23
24 if (STRCASE_IN_SET(v,
25 "1",
26 "yes",
27 "y",
28 "true",
29 "t",
30 "on"))
31 return 1;
32
33 if (STRCASE_IN_SET(v,
34 "0",
35 "no",
36 "n",
37 "false",
38 "f",
39 "off"))
40 return 0;
41
42 return -EINVAL;
43 }
44
45 int parse_tristate_full(const char *v, const char *third, int *ret) {
46 int r;
47
48 if (isempty(v) || streq_ptr(v, third)) { /* Empty string is always taken as the third/invalid/auto state */
49 if (ret)
50 *ret = -1;
51 } else {
52 r = parse_boolean(v);
53 if (r < 0)
54 return r;
55
56 if (ret)
57 *ret = r;
58 }
59
60 return 0;
61 }
62
63 int parse_pid(const char *s, pid_t* ret_pid) {
64 unsigned long ul = 0;
65 pid_t pid;
66 int r;
67
68 assert(s);
69
70 r = safe_atolu(s, &ul);
71 if (r < 0)
72 return r;
73
74 pid = (pid_t) ul;
75
76 if ((unsigned long) pid != ul)
77 return -ERANGE;
78
79 if (!pid_is_valid(pid))
80 return -ERANGE;
81
82 if (ret_pid)
83 *ret_pid = pid;
84 return 0;
85 }
86
87 int parse_mode(const char *s, mode_t *ret) {
88 unsigned m;
89 int r;
90
91 assert(s);
92
93 r = safe_atou_full(s, 8 |
94 SAFE_ATO_REFUSE_PLUS_MINUS, /* Leading '+' or even '-' char? that's just weird,
95 * refuse. User might have wanted to add mode flags or
96 * so, but this parser doesn't allow that, so let's
97 * better be safe. */
98 &m);
99 if (r < 0)
100 return r;
101 if (m > 07777)
102 return -ERANGE;
103
104 if (ret)
105 *ret = m;
106 return 0;
107 }
108
109 int parse_ifindex(const char *s) {
110 int ifi, r;
111
112 assert(s);
113
114 r = safe_atoi(s, &ifi);
115 if (r < 0)
116 return r;
117 if (ifi <= 0)
118 return -EINVAL;
119
120 return ifi;
121 }
122
123 int parse_mtu(int family, const char *s, uint32_t *ret) {
124 uint64_t u, m;
125 int r;
126
127 r = parse_size(s, 1024, &u);
128 if (r < 0)
129 return r;
130
131 if (u > UINT32_MAX)
132 return -ERANGE;
133
134 switch (family) {
135 case AF_INET:
136 m = IPV4_MIN_MTU; /* This is 68 */
137 break;
138 case AF_INET6:
139 m = IPV6_MIN_MTU; /* This is 1280 */
140 break;
141 default:
142 m = 0;
143 }
144
145 if (u < m)
146 return -ERANGE;
147
148 *ret = (uint32_t) u;
149 return 0;
150 }
151
152 int parse_size(const char *t, uint64_t base, uint64_t *size) {
153
154 /* Soo, sometimes we want to parse IEC binary suffixes, and
155 * sometimes SI decimal suffixes. This function can parse
156 * both. Which one is the right way depends on the
157 * context. Wikipedia suggests that SI is customary for
158 * hardware metrics and network speeds, while IEC is
159 * customary for most data sizes used by software and volatile
160 * (RAM) memory. Hence be careful which one you pick!
161 *
162 * In either case we use just K, M, G as suffix, and not Ki,
163 * Mi, Gi or so (as IEC would suggest). That's because that's
164 * frickin' ugly. But this means you really need to make sure
165 * to document which base you are parsing when you use this
166 * call. */
167
168 struct table {
169 const char *suffix;
170 unsigned long long factor;
171 };
172
173 static const struct table iec[] = {
174 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
175 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
176 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
177 { "G", 1024ULL*1024ULL*1024ULL },
178 { "M", 1024ULL*1024ULL },
179 { "K", 1024ULL },
180 { "B", 1ULL },
181 { "", 1ULL },
182 };
183
184 static const struct table si[] = {
185 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
186 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
187 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
188 { "G", 1000ULL*1000ULL*1000ULL },
189 { "M", 1000ULL*1000ULL },
190 { "K", 1000ULL },
191 { "B", 1ULL },
192 { "", 1ULL },
193 };
194
195 const struct table *table;
196 const char *p;
197 unsigned long long r = 0;
198 unsigned n_entries, start_pos = 0;
199
200 assert(t);
201 assert(IN_SET(base, 1000, 1024));
202 assert(size);
203
204 if (base == 1000) {
205 table = si;
206 n_entries = ELEMENTSOF(si);
207 } else {
208 table = iec;
209 n_entries = ELEMENTSOF(iec);
210 }
211
212 p = t;
213 do {
214 unsigned long long l, tmp;
215 double frac = 0;
216 char *e;
217 unsigned i;
218
219 p += strspn(p, WHITESPACE);
220
221 errno = 0;
222 l = strtoull(p, &e, 10);
223 if (errno > 0)
224 return -errno;
225 if (e == p)
226 return -EINVAL;
227 if (*p == '-')
228 return -ERANGE;
229
230 if (*e == '.') {
231 e++;
232
233 /* strtoull() itself would accept space/+/- */
234 if (ascii_isdigit(*e)) {
235 unsigned long long l2;
236 char *e2;
237
238 l2 = strtoull(e, &e2, 10);
239 if (errno > 0)
240 return -errno;
241
242 /* Ignore failure. E.g. 10.M is valid */
243 frac = l2;
244 for (; e < e2; e++)
245 frac /= 10;
246 }
247 }
248
249 e += strspn(e, WHITESPACE);
250
251 for (i = start_pos; i < n_entries; i++)
252 if (startswith(e, table[i].suffix))
253 break;
254
255 if (i >= n_entries)
256 return -EINVAL;
257
258 if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
259 return -ERANGE;
260
261 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
262 if (tmp > ULLONG_MAX - r)
263 return -ERANGE;
264
265 r += tmp;
266 if ((unsigned long long) (uint64_t) r != r)
267 return -ERANGE;
268
269 p = e + strlen(table[i].suffix);
270
271 start_pos = i + 1;
272
273 } while (*p);
274
275 *size = r;
276
277 return 0;
278 }
279
280 int parse_sector_size(const char *t, uint64_t *ret) {
281 int r;
282
283 assert(t);
284 assert(ret);
285
286 uint64_t ss;
287
288 r = safe_atou64(t, &ss);
289 if (r < 0)
290 return log_error_errno(r, "Failed to parse sector size parameter %s", t);
291 if (ss < 512 || ss > 4096) /* Allow up to 4K due to dm-crypt support and 4K alignment by the homed LUKS backend */
292 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Sector size not between 512 and 4096: %s", t);
293 if (!ISPOWEROF2(ss))
294 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Sector size not power of 2: %s", t);
295
296 *ret = ss;
297 return 0;
298 }
299
300 int parse_range(const char *t, unsigned *lower, unsigned *upper) {
301 _cleanup_free_ char *word = NULL;
302 unsigned l, u;
303 int r;
304
305 assert(lower);
306 assert(upper);
307
308 /* Extract the lower bound. */
309 r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
310 if (r < 0)
311 return r;
312 if (r == 0)
313 return -EINVAL;
314
315 r = safe_atou(word, &l);
316 if (r < 0)
317 return r;
318
319 /* Check for the upper bound and extract it if needed */
320 if (!t)
321 /* Single number with no dashes. */
322 u = l;
323 else if (!*t)
324 /* Trailing dash is an error. */
325 return -EINVAL;
326 else {
327 r = safe_atou(t, &u);
328 if (r < 0)
329 return r;
330 }
331
332 *lower = l;
333 *upper = u;
334 return 0;
335 }
336
337 int parse_errno(const char *t) {
338 int r, e;
339
340 assert(t);
341
342 r = errno_from_name(t);
343 if (r > 0)
344 return r;
345
346 r = safe_atoi(t, &e);
347 if (r < 0)
348 return r;
349
350 /* 0 is also allowed here */
351 if (!errno_is_valid(e) && e != 0)
352 return -ERANGE;
353
354 return e;
355 }
356
357 int parse_fd(const char *t) {
358 int r, fd;
359
360 assert(t);
361
362 r = safe_atoi(t, &fd);
363 if (r < 0)
364 return r;
365
366 if (fd < 0)
367 return -EBADF;
368
369 return fd;
370 }
371
372 static const char *mangle_base(const char *s, unsigned *base) {
373 const char *k;
374
375 assert(s);
376 assert(base);
377
378 /* Base already explicitly specified, then don't do anything. */
379 if (SAFE_ATO_MASK_FLAGS(*base) != 0)
380 return s;
381
382 /* Support Python 3 style "0b" and 0x" prefixes, because they truly make sense, much more than C's "0" prefix for octal. */
383 k = STARTSWITH_SET(s, "0b", "0B");
384 if (k) {
385 *base = 2 | (*base & SAFE_ATO_ALL_FLAGS);
386 return k;
387 }
388
389 k = STARTSWITH_SET(s, "0o", "0O");
390 if (k) {
391 *base = 8 | (*base & SAFE_ATO_ALL_FLAGS);
392 return k;
393 }
394
395 return s;
396 }
397
398 int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
399 char *x = NULL;
400 unsigned long l;
401
402 assert(s);
403 assert(SAFE_ATO_MASK_FLAGS(base) <= 16);
404
405 /* strtoul() is happy to parse negative values, and silently converts them to unsigned values without
406 * generating an error. We want a clean error, hence let's look for the "-" prefix on our own, and
407 * generate an error. But let's do so only after strtoul() validated that the string is clean
408 * otherwise, so that we return EINVAL preferably over ERANGE. */
409
410 if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_WHITESPACE) &&
411 strchr(WHITESPACE, s[0]))
412 return -EINVAL;
413
414 s += strspn(s, WHITESPACE);
415
416 if (FLAGS_SET(base, SAFE_ATO_REFUSE_PLUS_MINUS) &&
417 IN_SET(s[0], '+', '-'))
418 return -EINVAL; /* Note that we check the "-" prefix again a second time below, but return a
419 * different error. I.e. if the SAFE_ATO_REFUSE_PLUS_MINUS flag is set we
420 * blanket refuse +/- prefixed integers, while if it is missing we'll just
421 * return ERANGE, because the string actually parses correctly, but doesn't
422 * fit in the return type. */
423
424 if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_ZERO) &&
425 s[0] == '0' && !streq(s, "0"))
426 return -EINVAL; /* This is particularly useful to avoid ambiguities between C's octal
427 * notation and assumed-to-be-decimal integers with a leading zero. */
428
429 s = mangle_base(s, &base);
430
431 errno = 0;
432 l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base) /* Let's mask off the flags bits so that only the actual
433 * base is left */);
434 if (errno > 0)
435 return -errno;
436 if (!x || x == s || *x != 0)
437 return -EINVAL;
438 if (l != 0 && s[0] == '-')
439 return -ERANGE;
440 if ((unsigned long) (unsigned) l != l)
441 return -ERANGE;
442
443 if (ret_u)
444 *ret_u = (unsigned) l;
445
446 return 0;
447 }
448
449 int safe_atou_bounded(const char *s, unsigned min, unsigned max, unsigned *ret) {
450 unsigned v;
451 int r;
452
453 r = safe_atou(s, &v);
454 if (r < 0)
455 return r;
456
457 if (v < min || v > max)
458 return -ERANGE;
459
460 *ret = v;
461 return 0;
462 }
463
464 int safe_atoi(const char *s, int *ret_i) {
465 unsigned base = 0;
466 char *x = NULL;
467 long l;
468
469 assert(s);
470
471 s += strspn(s, WHITESPACE);
472 s = mangle_base(s, &base);
473
474 errno = 0;
475 l = strtol(s, &x, base);
476 if (errno > 0)
477 return -errno;
478 if (!x || x == s || *x != 0)
479 return -EINVAL;
480 if ((long) (int) l != l)
481 return -ERANGE;
482
483 if (ret_i)
484 *ret_i = (int) l;
485
486 return 0;
487 }
488
489 int safe_atollu_full(const char *s, unsigned base, unsigned long long *ret_llu) {
490 char *x = NULL;
491 unsigned long long l;
492
493 assert(s);
494 assert(SAFE_ATO_MASK_FLAGS(base) <= 16);
495
496 if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_WHITESPACE) &&
497 strchr(WHITESPACE, s[0]))
498 return -EINVAL;
499
500 s += strspn(s, WHITESPACE);
501
502 if (FLAGS_SET(base, SAFE_ATO_REFUSE_PLUS_MINUS) &&
503 IN_SET(s[0], '+', '-'))
504 return -EINVAL;
505
506 if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_ZERO) &&
507 s[0] == '0' && s[1] != 0)
508 return -EINVAL;
509
510 s = mangle_base(s, &base);
511
512 errno = 0;
513 l = strtoull(s, &x, SAFE_ATO_MASK_FLAGS(base));
514 if (errno > 0)
515 return -errno;
516 if (!x || x == s || *x != 0)
517 return -EINVAL;
518 if (l != 0 && s[0] == '-')
519 return -ERANGE;
520
521 if (ret_llu)
522 *ret_llu = l;
523
524 return 0;
525 }
526
527 int safe_atolli(const char *s, long long *ret_lli) {
528 unsigned base = 0;
529 char *x = NULL;
530 long long l;
531
532 assert(s);
533
534 s += strspn(s, WHITESPACE);
535 s = mangle_base(s, &base);
536
537 errno = 0;
538 l = strtoll(s, &x, base);
539 if (errno > 0)
540 return -errno;
541 if (!x || x == s || *x != 0)
542 return -EINVAL;
543
544 if (ret_lli)
545 *ret_lli = l;
546
547 return 0;
548 }
549
550 int safe_atou8_full(const char *s, unsigned base, uint8_t *ret) {
551 unsigned u;
552 int r;
553
554 r = safe_atou_full(s, base, &u);
555 if (r < 0)
556 return r;
557 if (u > UINT8_MAX)
558 return -ERANGE;
559
560 *ret = (uint8_t) u;
561 return 0;
562 }
563
564 int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
565 unsigned u;
566 int r;
567
568 r = safe_atou_full(s, base, &u);
569 if (r < 0)
570 return r;
571 if (u > UINT16_MAX)
572 return -ERANGE;
573
574 *ret = (uint16_t) u;
575 return 0;
576 }
577
578 int safe_atoi16(const char *s, int16_t *ret) {
579 unsigned base = 0;
580 char *x = NULL;
581 long l;
582
583 assert(s);
584
585 s += strspn(s, WHITESPACE);
586 s = mangle_base(s, &base);
587
588 errno = 0;
589 l = strtol(s, &x, base);
590 if (errno > 0)
591 return -errno;
592 if (!x || x == s || *x != 0)
593 return -EINVAL;
594 if ((long) (int16_t) l != l)
595 return -ERANGE;
596
597 if (ret)
598 *ret = (int16_t) l;
599
600 return 0;
601 }
602
603 int safe_atod(const char *s, double *ret_d) {
604 _cleanup_(freelocalep) locale_t loc = (locale_t) 0;
605 char *x = NULL;
606 double d = 0;
607
608 assert(s);
609
610 loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
611 if (loc == (locale_t) 0)
612 return -errno;
613
614 errno = 0;
615 d = strtod_l(s, &x, loc);
616 if (errno > 0)
617 return -errno;
618 if (!x || x == s || *x != 0)
619 return -EINVAL;
620
621 if (ret_d)
622 *ret_d = (double) d;
623
624 return 0;
625 }
626
627 int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
628 unsigned val = 0;
629 const char *s;
630
631 s = *p;
632
633 /* accept any number of digits, strtoull is limited to 19 */
634 for (size_t i = 0; i < digits; i++, s++) {
635 if (!ascii_isdigit(*s)) {
636 if (i == 0)
637 return -EINVAL;
638
639 /* too few digits, pad with 0 */
640 for (; i < digits; i++)
641 val *= 10;
642
643 break;
644 }
645
646 val *= 10;
647 val += *s - '0';
648 }
649
650 /* maybe round up */
651 if (*s >= '5' && *s <= '9')
652 val++;
653
654 s += strspn(s, DIGITS);
655
656 *p = s;
657 *res = val;
658
659 return 0;
660 }
661
662 int parse_nice(const char *p, int *ret) {
663 int n, r;
664
665 r = safe_atoi(p, &n);
666 if (r < 0)
667 return r;
668
669 if (!nice_is_valid(n))
670 return -ERANGE;
671
672 *ret = n;
673 return 0;
674 }
675
676 int parse_ip_port(const char *s, uint16_t *ret) {
677 uint16_t l;
678 int r;
679
680 r = safe_atou16_full(s, SAFE_ATO_REFUSE_LEADING_WHITESPACE, &l);
681 if (r < 0)
682 return r;
683
684 if (l == 0)
685 return -EINVAL;
686
687 *ret = (uint16_t) l;
688
689 return 0;
690 }
691
692 int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high, bool allow_zero) {
693 unsigned l, h;
694 int r;
695
696 r = parse_range(s, &l, &h);
697 if (r < 0)
698 return r;
699
700 if (l > 65535 || h > 65535)
701 return -EINVAL;
702
703 if (!allow_zero && (l == 0 || h == 0))
704 return -EINVAL;
705
706 if (h < l)
707 return -EINVAL;
708
709 *low = l;
710 *high = h;
711
712 return 0;
713 }
714
715 int parse_oom_score_adjust(const char *s, int *ret) {
716 int r, v;
717
718 assert(s);
719 assert(ret);
720
721 r = safe_atoi(s, &v);
722 if (r < 0)
723 return r;
724
725 if (!oom_score_adjust_is_valid(v))
726 return -ERANGE;
727
728 *ret = v;
729 return 0;
730 }
731
732 int store_loadavg_fixed_point(unsigned long i, unsigned long f, loadavg_t *ret) {
733 assert(ret);
734
735 if (i >= (~0UL << LOADAVG_PRECISION_BITS))
736 return -ERANGE;
737
738 i = i << LOADAVG_PRECISION_BITS;
739 f = DIV_ROUND_UP((f << LOADAVG_PRECISION_BITS), 100);
740
741 if (f >= LOADAVG_FIXED_POINT_1_0)
742 return -ERANGE;
743
744 *ret = i | f;
745 return 0;
746 }
747
748 int parse_loadavg_fixed_point(const char *s, loadavg_t *ret) {
749 const char *d, *f_str, *i_str;
750 unsigned long i, f;
751 int r;
752
753 assert(s);
754 assert(ret);
755
756 d = strchr(s, '.');
757 if (!d)
758 return -EINVAL;
759
760 i_str = strndupa_safe(s, d - s);
761 f_str = d + 1;
762
763 r = safe_atolu_full(i_str, 10, &i);
764 if (r < 0)
765 return r;
766
767 r = safe_atolu_full(f_str, 10, &f);
768 if (r < 0)
769 return r;
770
771 return store_loadavg_fixed_point(i, f, ret);
772 }
773
774 /* Limitations are described in https://www.netfilter.org/projects/nftables/manpage.html and
775 * https://bugzilla.netfilter.org/show_bug.cgi?id=1175 */
776 bool nft_identifier_valid(const char *id) {
777 if (isempty(id))
778 return false;
779
780 if (strlen(id) >= NFT_NAME_MAXLEN)
781 return false;
782
783 if (!ascii_isalpha(id[0]))
784 return false;
785
786 return in_charset(id + 1, ALPHANUMERICAL "/\\_.");
787 }