return -EINVAL;
}
+int parse_tristate_full(const char *v, const char *third, int *ret) {
+ int r;
+
+ if (isempty(v) || streq_ptr(v, third)) { /* Empty string is always taken as the third/invalid/auto state */
+ if (ret)
+ *ret = -1;
+ } else {
+ r = parse_boolean(v);
+ if (r < 0)
+ return r;
+
+ if (ret)
+ *ret = r;
+ }
+
+ return 0;
+}
+
int parse_pid(const char *s, pid_t* ret_pid) {
unsigned long ul = 0;
pid_t pid;
int r;
assert(s);
- assert(ret_pid);
r = safe_atolu(s, &ul);
if (r < 0)
if (!pid_is_valid(pid))
return -ERANGE;
- *ret_pid = pid;
+ if (ret_pid)
+ *ret_pid = pid;
return 0;
}
}
int parse_mtu(int family, const char *s, uint32_t *ret) {
- uint64_t u;
- size_t m;
+ uint64_t u, m;
int r;
r = parse_size(s, 1024, &u);
if (u > UINT32_MAX)
return -ERANGE;
- if (family == AF_INET6)
+ switch (family) {
+ case AF_INET:
+ m = IPV4_MIN_MTU; /* This is 68 */
+ break;
+ case AF_INET6:
m = IPV6_MIN_MTU; /* This is 1280 */
- else
- m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */
+ break;
+ default:
+ m = 0;
+ }
if (u < m)
return -ERANGE;
e++;
/* strtoull() itself would accept space/+/- */
- if (*e >= '0' && *e <= '9') {
+ if (ascii_isdigit(*e)) {
unsigned long long l2;
char *e2;
return 0;
}
+int parse_sector_size(const char *t, uint64_t *ret) {
+ int r;
+
+ assert(t);
+ assert(ret);
+
+ uint64_t ss;
+
+ r = safe_atou64(t, &ss);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse sector size parameter %s", t);
+ if (ss < 512 || ss > 4096) /* Allow up to 4K due to dm-crypt support and 4K alignment by the homed LUKS backend */
+ return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Sector size not between 512 and 4096: %s", t);
+ if (!ISPOWEROF2(ss))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Sector size not power of 2: %s", t);
+
+ *ret = ss;
+ return 0;
+}
+
int parse_range(const char *t, unsigned *lower, unsigned *upper) {
_cleanup_free_ char *word = NULL;
unsigned l, u;
return e;
}
+int parse_fd(const char *t) {
+ int r, fd;
+
+ assert(t);
+
+ r = safe_atoi(t, &fd);
+ if (r < 0)
+ return r;
+
+ if (fd < 0)
+ return -EBADF;
+
+ return fd;
+}
+
static const char *mangle_base(const char *s, unsigned *base) {
const char *k;
return 0;
}
+int safe_atou_bounded(const char *s, unsigned min, unsigned max, unsigned *ret) {
+ unsigned v;
+ int r;
+
+ r = safe_atou(s, &v);
+ if (r < 0)
+ return r;
+
+ if (v < min || v > max)
+ return -ERANGE;
+
+ *ret = v;
+ return 0;
+}
+
int safe_atoi(const char *s, int *ret_i) {
unsigned base = 0;
char *x = NULL;
return 0;
}
-int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu) {
+int safe_atollu_full(const char *s, unsigned base, unsigned long long *ret_llu) {
char *x = NULL;
unsigned long long l;
return 0;
}
-int safe_atou8(const char *s, uint8_t *ret) {
- unsigned base = 0;
- unsigned long l;
- char *x = NULL;
-
- assert(s);
-
- s += strspn(s, WHITESPACE);
- s = mangle_base(s, &base);
+int safe_atou8_full(const char *s, unsigned base, uint8_t *ret) {
+ unsigned u;
+ int r;
- errno = 0;
- l = strtoul(s, &x, base);
- if (errno > 0)
- return -errno;
- if (!x || x == s || *x != 0)
- return -EINVAL;
- if (l != 0 && s[0] == '-')
- return -ERANGE;
- if ((unsigned long) (uint8_t) l != l)
+ r = safe_atou_full(s, base, &u);
+ if (r < 0)
+ return r;
+ if (u > UINT8_MAX)
return -ERANGE;
- if (ret)
- *ret = (uint8_t) l;
+ *ret = (uint8_t) u;
return 0;
}
int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
- char *x = NULL;
- unsigned long l;
-
- assert(s);
- assert(SAFE_ATO_MASK_FLAGS(base) <= 16);
-
- if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_WHITESPACE) &&
- strchr(WHITESPACE, s[0]))
- return -EINVAL;
-
- s += strspn(s, WHITESPACE);
-
- if (FLAGS_SET(base, SAFE_ATO_REFUSE_PLUS_MINUS) &&
- IN_SET(s[0], '+', '-'))
- return -EINVAL;
-
- if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_ZERO) &&
- s[0] == '0' && s[1] != 0)
- return -EINVAL;
-
- s = mangle_base(s, &base);
+ unsigned u;
+ int r;
- errno = 0;
- l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base));
- if (errno > 0)
- return -errno;
- if (!x || x == s || *x != 0)
- return -EINVAL;
- if (l != 0 && s[0] == '-')
- return -ERANGE;
- if ((unsigned long) (uint16_t) l != l)
+ r = safe_atou_full(s, base, &u);
+ if (r < 0)
+ return r;
+ if (u > UINT16_MAX)
return -ERANGE;
- if (ret)
- *ret = (uint16_t) l;
-
+ *ret = (uint16_t) u;
return 0;
}
/* accept any number of digits, strtoull is limited to 19 */
for (size_t i = 0; i < digits; i++,s++) {
- if (*s < '0' || *s > '9') {
+ if (!ascii_isdigit(*s)) {
if (i == 0)
return -EINVAL;
uint16_t l;
int r;
- r = safe_atou16(s, &l);
+ r = safe_atou16_full(s, SAFE_ATO_REFUSE_LEADING_WHITESPACE, &l);
if (r < 0)
return r;
return 0;
}
-int parse_dev(const char *s, dev_t *ret) {
- const char *major;
- unsigned x, y;
- size_t n;
- int r;
-
- n = strspn(s, DIGITS);
- if (n == 0)
- return -EINVAL;
- if (s[n] != ':')
- return -EINVAL;
-
- major = strndupa(s, n);
- r = safe_atou(major, &x);
- if (r < 0)
- return r;
-
- r = safe_atou(s + n + 1, &y);
- if (r < 0)
- return r;
-
- if (!DEVICE_MAJOR_VALID(x) || !DEVICE_MINOR_VALID(y))
- return -ERANGE;
-
- *ret = makedev(x, y);
- return 0;
-}
-
int parse_oom_score_adjust(const char *s, int *ret) {
int r, v;
if (!d)
return -EINVAL;
- i_str = strndupa(s, d - s);
+ i_str = strndupa_safe(s, d - s);
f_str = d + 1;
r = safe_atolu_full(i_str, 10, &i);
return store_loadavg_fixed_point(i, f, ret);
}
+
+/* Limitations are described in https://www.netfilter.org/projects/nftables/manpage.html and
+ * https://bugzilla.netfilter.org/show_bug.cgi?id=1175 */
+bool nft_identifier_valid(const char *id) {
+ if (!id)
+ return false;
+
+ size_t len = strlen(id);
+ if (len == 0 || len > 31)
+ return false;
+
+ if (!ascii_isalpha(id[0]))
+ return false;
+
+ for (size_t i = 1; i < len; i++)
+ if (!ascii_isalpha(id[i]) && !ascii_isdigit(id[i]) && !IN_SET(id[i], '/', '\\', '_', '.'))
+ return false;
+ return true;
+}