1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <linux/ipv6.h>
4 #include <linux/netfilter/nf_tables.h>
7 #include <sys/socket.h>
9 #include "alloc-util.h"
10 #include "errno-list.h"
11 #include "extract-word.h"
12 #include "locale-util.h"
14 #include "missing_network.h"
15 #include "parse-util.h"
16 #include "process-util.h"
17 #include "string-util.h"
20 int parse_boolean(const char *v
) {
45 int parse_tristate_full(const char *v
, const char *third
, int *ret
) {
48 if (isempty(v
) || streq_ptr(v
, third
)) { /* Empty string is always taken as the third/invalid/auto state */
63 int parse_pid(const char *s
, pid_t
* ret_pid
) {
70 r
= safe_atolu(s
, &ul
);
76 if ((unsigned long) pid
!= ul
)
79 if (!pid_is_valid(pid
))
87 int parse_mode(const char *s
, mode_t
*ret
) {
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
109 int parse_ifindex(const char *s
) {
114 r
= safe_atoi(s
, &ifi
);
123 int parse_mtu(int family
, const char *s
, uint32_t *ret
) {
127 r
= parse_size(s
, 1024, &u
);
136 m
= IPV4_MIN_MTU
; /* This is 68 */
139 m
= IPV6_MIN_MTU
; /* This is 1280 */
152 int parse_size(const char *t
, uint64_t base
, uint64_t *size
) {
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!
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
170 unsigned long long factor
;
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 },
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 },
195 const struct table
*table
;
197 unsigned long long r
= 0;
198 unsigned n_entries
, start_pos
= 0;
201 assert(IN_SET(base
, 1000, 1024));
206 n_entries
= ELEMENTSOF(si
);
209 n_entries
= ELEMENTSOF(iec
);
214 unsigned long long l
, tmp
;
219 p
+= strspn(p
, WHITESPACE
);
222 l
= strtoull(p
, &e
, 10);
233 /* strtoull() itself would accept space/+/- */
234 if (ascii_isdigit(*e
)) {
235 unsigned long long l2
;
238 l2
= strtoull(e
, &e2
, 10);
242 /* Ignore failure. E.g. 10.M is valid */
249 e
+= strspn(e
, WHITESPACE
);
251 for (i
= start_pos
; i
< n_entries
; i
++)
252 if (startswith(e
, table
[i
].suffix
))
258 if (l
+ (frac
> 0) > ULLONG_MAX
/ table
[i
].factor
)
261 tmp
= l
* table
[i
].factor
+ (unsigned long long) (frac
* table
[i
].factor
);
262 if (tmp
> ULLONG_MAX
- r
)
266 if ((unsigned long long) (uint64_t) r
!= r
)
269 p
= e
+ strlen(table
[i
].suffix
);
280 int parse_sector_size(const char *t
, uint64_t *ret
) {
288 r
= safe_atou64(t
, &ss
);
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
);
294 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Sector size not power of 2: %s", t
);
300 int parse_range(const char *t
, unsigned *lower
, unsigned *upper
) {
301 _cleanup_free_
char *word
= NULL
;
308 /* Extract the lower bound. */
309 r
= extract_first_word(&t
, &word
, "-", EXTRACT_DONT_COALESCE_SEPARATORS
);
315 r
= safe_atou(word
, &l
);
319 /* Check for the upper bound and extract it if needed */
321 /* Single number with no dashes. */
324 /* Trailing dash is an error. */
327 r
= safe_atou(t
, &u
);
337 int parse_errno(const char *t
) {
342 r
= errno_from_name(t
);
346 r
= safe_atoi(t
, &e
);
350 /* 0 is also allowed here */
351 if (!errno_is_valid(e
) && e
!= 0)
357 int parse_fd(const char *t
) {
362 r
= safe_atoi(t
, &fd
);
372 static const char *mangle_base(const char *s
, unsigned *base
) {
378 /* Base already explicitly specified, then don't do anything. */
379 if (SAFE_ATO_MASK_FLAGS(*base
) != 0)
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");
385 *base
= 2 | (*base
& SAFE_ATO_ALL_FLAGS
);
389 k
= STARTSWITH_SET(s
, "0o", "0O");
391 *base
= 8 | (*base
& SAFE_ATO_ALL_FLAGS
);
398 int safe_atou_full(const char *s
, unsigned base
, unsigned *ret_u
) {
403 assert(SAFE_ATO_MASK_FLAGS(base
) <= 16);
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. */
410 if (FLAGS_SET(base
, SAFE_ATO_REFUSE_LEADING_WHITESPACE
) &&
411 strchr(WHITESPACE
, s
[0]))
414 s
+= strspn(s
, WHITESPACE
);
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. */
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. */
429 s
= mangle_base(s
, &base
);
432 l
= strtoul(s
, &x
, SAFE_ATO_MASK_FLAGS(base
) /* Let's mask off the flags bits so that only the actual
436 if (!x
|| x
== s
|| *x
!= 0)
438 if (l
!= 0 && s
[0] == '-')
440 if ((unsigned long) (unsigned) l
!= l
)
444 *ret_u
= (unsigned) l
;
449 int safe_atou_bounded(const char *s
, unsigned min
, unsigned max
, unsigned *ret
) {
453 r
= safe_atou(s
, &v
);
457 if (v
< min
|| v
> max
)
464 int safe_atoi(const char *s
, int *ret_i
) {
471 s
+= strspn(s
, WHITESPACE
);
472 s
= mangle_base(s
, &base
);
475 l
= strtol(s
, &x
, base
);
478 if (!x
|| x
== s
|| *x
!= 0)
480 if ((long) (int) l
!= l
)
489 int safe_atollu_full(const char *s
, unsigned base
, unsigned long long *ret_llu
) {
491 unsigned long long l
;
494 assert(SAFE_ATO_MASK_FLAGS(base
) <= 16);
496 if (FLAGS_SET(base
, SAFE_ATO_REFUSE_LEADING_WHITESPACE
) &&
497 strchr(WHITESPACE
, s
[0]))
500 s
+= strspn(s
, WHITESPACE
);
502 if (FLAGS_SET(base
, SAFE_ATO_REFUSE_PLUS_MINUS
) &&
503 IN_SET(s
[0], '+', '-'))
506 if (FLAGS_SET(base
, SAFE_ATO_REFUSE_LEADING_ZERO
) &&
507 s
[0] == '0' && s
[1] != 0)
510 s
= mangle_base(s
, &base
);
513 l
= strtoull(s
, &x
, SAFE_ATO_MASK_FLAGS(base
));
516 if (!x
|| x
== s
|| *x
!= 0)
518 if (l
!= 0 && s
[0] == '-')
527 int safe_atolli(const char *s
, long long *ret_lli
) {
534 s
+= strspn(s
, WHITESPACE
);
535 s
= mangle_base(s
, &base
);
538 l
= strtoll(s
, &x
, base
);
541 if (!x
|| x
== s
|| *x
!= 0)
550 int safe_atou8_full(const char *s
, unsigned base
, uint8_t *ret
) {
554 r
= safe_atou_full(s
, base
, &u
);
564 int safe_atou16_full(const char *s
, unsigned base
, uint16_t *ret
) {
568 r
= safe_atou_full(s
, base
, &u
);
578 int safe_atoi16(const char *s
, int16_t *ret
) {
585 s
+= strspn(s
, WHITESPACE
);
586 s
= mangle_base(s
, &base
);
589 l
= strtol(s
, &x
, base
);
592 if (!x
|| x
== s
|| *x
!= 0)
594 if ((long) (int16_t) l
!= l
)
603 int safe_atod(const char *s
, double *ret_d
) {
604 _cleanup_(freelocalep
) locale_t loc
= (locale_t
) 0;
610 loc
= newlocale(LC_NUMERIC_MASK
, "C", (locale_t
) 0);
611 if (loc
== (locale_t
) 0)
615 d
= strtod_l(s
, &x
, loc
);
618 if (!x
|| x
== s
|| *x
!= 0)
627 int parse_fractional_part_u(const char **p
, size_t digits
, unsigned *res
) {
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
)) {
639 /* too few digits, pad with 0 */
640 for (; i
< digits
; i
++)
651 if (*s
>= '5' && *s
<= '9')
654 s
+= strspn(s
, DIGITS
);
662 int parse_nice(const char *p
, int *ret
) {
665 r
= safe_atoi(p
, &n
);
669 if (!nice_is_valid(n
))
676 int parse_ip_port(const char *s
, uint16_t *ret
) {
680 r
= safe_atou16_full(s
, SAFE_ATO_REFUSE_LEADING_WHITESPACE
, &l
);
692 int parse_ip_port_range(const char *s
, uint16_t *low
, uint16_t *high
, bool allow_zero
) {
696 r
= parse_range(s
, &l
, &h
);
700 if (l
> 65535 || h
> 65535)
703 if (!allow_zero
&& (l
== 0 || h
== 0))
715 int parse_oom_score_adjust(const char *s
, int *ret
) {
721 r
= safe_atoi(s
, &v
);
725 if (!oom_score_adjust_is_valid(v
))
732 int store_loadavg_fixed_point(unsigned long i
, unsigned long f
, loadavg_t
*ret
) {
735 if (i
>= (~0UL << LOADAVG_PRECISION_BITS
))
738 i
= i
<< LOADAVG_PRECISION_BITS
;
739 f
= DIV_ROUND_UP((f
<< LOADAVG_PRECISION_BITS
), 100);
741 if (f
>= LOADAVG_FIXED_POINT_1_0
)
748 int parse_loadavg_fixed_point(const char *s
, loadavg_t
*ret
) {
749 const char *d
, *f_str
, *i_str
;
760 i_str
= strndupa_safe(s
, d
- s
);
763 r
= safe_atolu_full(i_str
, 10, &i
);
767 r
= safe_atolu_full(f_str
, 10, &f
);
771 return store_loadavg_fixed_point(i
, f
, ret
);
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
) {
780 if (strlen(id
) >= NFT_NAME_MAXLEN
)
783 if (!ascii_isalpha(id
[0]))
786 return in_charset(id
+ 1, ALPHANUMERICAL
"/\\_.");