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