diff options
Diffstat (limited to 'src/utils.c')
| -rw-r--r-- | src/utils.c | 275 |
1 files changed, 76 insertions, 199 deletions
diff --git a/src/utils.c b/src/utils.c index 3617837..bbe44b4 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,11 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org> * (C) 2013 by Arturo Borrero Gonzalez <arturo@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <internal.h> @@ -17,8 +13,11 @@ #include <errno.h> #include <inttypes.h> +#include <libmnl/libmnl.h> + #include <libnftnl/common.h> +#include <linux/if.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> @@ -39,146 +38,6 @@ const char *nftnl_family2str(uint32_t family) return nftnl_family_str[family]; } -int nftnl_str2family(const char *family) -{ - int i; - - for (i = 0; i < NFPROTO_NUMPROTO; i++) { - if (nftnl_family_str[i] == NULL) - continue; - - if (strcmp(nftnl_family_str[i], family) == 0) - return i; - } - - errno = EAFNOSUPPORT; - return -1; -} - -static struct { - int len; - int64_t min; - uint64_t max; -} basetype[] = { - [NFTNL_TYPE_U8] = { .len = sizeof(uint8_t), .max = UINT8_MAX }, - [NFTNL_TYPE_U16] = { .len = sizeof(uint16_t), .max = UINT16_MAX }, - [NFTNL_TYPE_U32] = { .len = sizeof(uint32_t), .max = UINT32_MAX }, - [NFTNL_TYPE_U64] = { .len = sizeof(uint64_t), .max = UINT64_MAX }, - [NFTNL_TYPE_S8] = { .len = sizeof(int8_t), .min = INT8_MIN, .max = INT8_MAX }, - [NFTNL_TYPE_S16] = { .len = sizeof(int16_t), .min = INT16_MIN, .max = INT16_MAX }, - [NFTNL_TYPE_S32] = { .len = sizeof(int32_t), .min = INT32_MIN, .max = INT32_MAX }, - [NFTNL_TYPE_S64] = { .len = sizeof(int64_t), .min = INT64_MIN, .max = INT64_MAX }, -}; - -int nftnl_get_value(enum nftnl_type type, void *val, void *out) -{ - union { - uint8_t u8; - uint16_t u16; - uint32_t u32; - int8_t s8; - int16_t s16; - int32_t s32; - } values; - void *valuep = NULL; - int64_t sval; - uint64_t uval; - - switch (type) { - case NFTNL_TYPE_U8: - case NFTNL_TYPE_U16: - case NFTNL_TYPE_U32: - case NFTNL_TYPE_U64: - memcpy(&uval, val, sizeof(uval)); - if (uval > basetype[type].max) { - errno = ERANGE; - return -1; - } - break; - case NFTNL_TYPE_S8: - case NFTNL_TYPE_S16: - case NFTNL_TYPE_S32: - case NFTNL_TYPE_S64: - memcpy(&sval, val, sizeof(sval)); - if (sval < basetype[type].min || - sval > (int64_t)basetype[type].max) { - errno = ERANGE; - return -1; - } - break; - } - - switch (type) { - case NFTNL_TYPE_U8: - values.u8 = uval; - valuep = &values.u8; - break; - case NFTNL_TYPE_U16: - values.u16 = uval; - valuep = &values.u16; - break; - case NFTNL_TYPE_U32: - values.u32 = uval; - valuep = &values.u32; - break; - case NFTNL_TYPE_U64: - valuep = &uval; - break; - case NFTNL_TYPE_S8: - values.s8 = sval; - valuep = &values.s8; - break; - case NFTNL_TYPE_S16: - values.s16 = sval; - valuep = &values.s16; - break; - case NFTNL_TYPE_S32: - values.s32 = sval; - valuep = &values.s32; - break; - case NFTNL_TYPE_S64: - valuep = &sval; - break; - } - memcpy(out, valuep, basetype[type].len); - return 0; -} - -int nftnl_strtoi(const char *string, int base, void *out, enum nftnl_type type) -{ - int ret; - int64_t sval = 0; - uint64_t uval = -1; - char *endptr; - - switch (type) { - case NFTNL_TYPE_U8: - case NFTNL_TYPE_U16: - case NFTNL_TYPE_U32: - case NFTNL_TYPE_U64: - uval = strtoll(string, &endptr, base); - ret = nftnl_get_value(type, &uval, out); - break; - case NFTNL_TYPE_S8: - case NFTNL_TYPE_S16: - case NFTNL_TYPE_S32: - case NFTNL_TYPE_S64: - sval = strtoull(string, &endptr, base); - ret = nftnl_get_value(type, &sval, out); - break; - default: - errno = EINVAL; - return -1; - } - - if (*endptr) { - errno = EINVAL; - return -1; - } - - return ret; -} - const char *nftnl_verdict2str(uint32_t verdict) { switch (verdict) { @@ -209,28 +68,6 @@ const char *nftnl_verdict2str(uint32_t verdict) } } -int nftnl_str2verdict(const char *verdict, int *verdict_num) -{ - if (strcmp(verdict, "accept") == 0) { - *verdict_num = NF_ACCEPT; - return 0; - } else if (strcmp(verdict, "drop") == 0) { - *verdict_num = NF_DROP; - return 0; - } else if (strcmp(verdict, "return") == 0) { - *verdict_num = NFT_RETURN; - return 0; - } else if (strcmp(verdict, "jump") == 0) { - *verdict_num = NFT_JUMP; - return 0; - } else if (strcmp(verdict, "goto") == 0) { - *verdict_num = NFT_GOTO; - return 0; - } - - return -1; -} - enum nftnl_cmd_type nftnl_flag2cmd(uint32_t flags) { if (flags & NFTNL_OF_EVENT_NEW) @@ -241,38 +78,6 @@ enum nftnl_cmd_type nftnl_flag2cmd(uint32_t flags) return NFTNL_CMD_UNSPEC; } -static const char *cmd2tag[NFTNL_CMD_MAX] = { - [NFTNL_CMD_ADD] = "add", - [NFTNL_CMD_INSERT] = "insert", - [NFTNL_CMD_DELETE] = "delete", - [NFTNL_CMD_REPLACE] = "replace", - [NFTNL_CMD_FLUSH] = "flush", -}; - -const char *nftnl_cmd2tag(enum nftnl_cmd_type cmd) -{ - if (cmd >= NFTNL_CMD_MAX) - return "unknown"; - - return cmd2tag[cmd]; -} - -uint32_t nftnl_str2cmd(const char *cmd) -{ - if (strcmp(cmd, "add") == 0) - return NFTNL_CMD_ADD; - else if (strcmp(cmd, "insert") == 0) - return NFTNL_CMD_INSERT; - else if (strcmp(cmd, "delete") == 0) - return NFTNL_CMD_DELETE; - else if (strcmp(cmd, "replace") == 0) - return NFTNL_CMD_REPLACE; - else if (strcmp(cmd, "flush") == 0) - return NFTNL_CMD_FLUSH; - - return NFTNL_CMD_UNSPEC; -} - int nftnl_fprintf(FILE *fp, const void *obj, uint32_t cmd, uint32_t type, uint32_t flags, int (*snprintf_cb)(char *buf, size_t bufsiz, const void *obj, @@ -330,3 +135,75 @@ void __noreturn __abi_breakage(const char *file, int line, const char *reason) "%s:%d reason: %s\n", file, line, reason); exit(EXIT_FAILURE); } + +int nftnl_set_str_attr(const char **dptr, uint32_t *flags, + uint16_t attr, const void *data, uint32_t data_len) +{ + if (*flags & (1 << attr)) + xfree(*dptr); + + *dptr = strndup(data, data_len); + if (!*dptr) + return -1; + + *flags |= (1 << attr); + return 0; +} + +static bool is_wildcard_str(const char *str) +{ + size_t len = strlen(str); + + if (len < 1 || str[len - 1] != '*') + return false; + if (len < 2 || str[len - 2] != '\\') + return true; + /* XXX: ignore backslash escaping for now */ + return false; +} + +void nftnl_attr_put_ifname(struct nlmsghdr *nlh, const char *ifname) +{ + uint16_t attr = NFTA_DEVICE_NAME; + char pfx[IFNAMSIZ]; + + if (is_wildcard_str(ifname)) { + snprintf(pfx, IFNAMSIZ, "%s", ifname); + pfx[strlen(pfx) - 1] = '\0'; + + attr = NFTA_DEVICE_PREFIX; + ifname = pfx; + } + mnl_attr_put_strz(nlh, attr, ifname); +} + +char *nftnl_attr_get_ifname(const struct nlattr *attr) +{ + const char *dev = mnl_attr_get_str(attr); + char buf[IFNAMSIZ]; + + switch (mnl_attr_get_type(attr)) { + case NFTA_DEVICE_NAME: + return strdup(dev); + case NFTA_DEVICE_PREFIX: + snprintf(buf, IFNAMSIZ, "%s*", dev); + return strdup(buf); + default: + return NULL; + } +} + +int nftnl_parse_str_attr(const struct nlattr *tb, int attr, + const char **field, uint32_t *flags) +{ + if (!tb) + return 0; + + if (*flags & (1 << attr)) + xfree(*field); + *field = strdup(mnl_attr_get_str(tb)); + if (!*field) + return -1; + *flags |= (1 << attr); + return 0; +} |
