diff options
author | Arturo Borrero <arturo.borrero.glez@gmail.com> | 2013-07-25 18:46:35 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-07-25 20:03:21 +0200 |
commit | e13819c5f5b6138c4c7e01156d0fd9f58b11702d (patch) | |
tree | c4bbc0256f537099a8233915597419843359793b /src/utils.c | |
parent | 3ebc57b84c227fcfc55545af85e246ab4cad2041 (diff) |
src: xml: consolidate common XML code via nft_mxml_num_parse
This patch moves common XML parsing code to nft_mxml_num_parse().
To handle this, the nft_strtoi() helper fuction is included.
I've changed some MXML_DESCEND[_FIRST] flags to avoid match a nested node under
some circumstances, ie, matching two nodes with the same name that are descendant.
Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/utils.c b/src/utils.c index be1b5d8..4a0bb9c 100644 --- a/src/utils.c +++ b/src/utils.c @@ -14,6 +14,8 @@ #include <limits.h> #include <stdint.h> #include <arpa/inet.h> +#include <errno.h> +#include <inttypes.h> const char *nft_family2str(uint32_t family) { @@ -44,3 +46,74 @@ int nft_str2family(const char *family) return -1; } + +static struct { + int len; + int64_t min; + uint64_t max; +} basetype[] = { + [NFT_TYPE_U8] = { .len = sizeof(uint8_t), .max = UINT8_MAX }, + [NFT_TYPE_U16] = { .len = sizeof(uint16_t), .max = UINT16_MAX }, + [NFT_TYPE_U32] = { .len = sizeof(uint32_t), .max = UINT32_MAX }, + [NFT_TYPE_U64] = { .len = sizeof(uint64_t), .max = UINT64_MAX }, + [NFT_TYPE_S8] = { .len = sizeof(int8_t), .min = INT8_MIN, .max = INT8_MAX }, + [NFT_TYPE_S16] = { .len = sizeof(int16_t), .min = INT16_MIN, .max = INT16_MAX }, + [NFT_TYPE_S32] = { .len = sizeof(int32_t), .min = INT32_MIN, .max = INT32_MAX }, + [NFT_TYPE_S64] = { .len = sizeof(int64_t), .min = INT64_MIN, .max = INT64_MAX }, +}; + +int nft_strtoi(const char *string, int base, void *out, enum nft_type type) +{ + int64_t sval = 0; + uint64_t uval = -1; + char *endptr; + + switch (type) { + case NFT_TYPE_U8: + case NFT_TYPE_U16: + case NFT_TYPE_U32: + case NFT_TYPE_U64: + uval = strtoll(string, &endptr, base); + break; + case NFT_TYPE_S8: + case NFT_TYPE_S16: + case NFT_TYPE_S32: + case NFT_TYPE_S64: + sval = strtoull(string, &endptr, base); + break; + default: + errno = EINVAL; + return -1; + } + + if (*endptr) { + errno = EINVAL; + return -1; + } + + switch (type) { + case NFT_TYPE_U8: + case NFT_TYPE_U16: + case NFT_TYPE_U32: + case NFT_TYPE_U64: + if (uval > basetype[type].max) { + errno = ERANGE; + return -1; + } + memcpy(out, &uval, basetype[type].len); + break; + case NFT_TYPE_S8: + case NFT_TYPE_S16: + case NFT_TYPE_S32: + case NFT_TYPE_S64: + if (sval < basetype[type].min || + sval > (int64_t)basetype[type].max) { + errno = ERANGE; + return -1; + } + memcpy(out, &sval, basetype[type].len); + break; + } + + return 0; +} |