Add a helper function to handle the XML validations. The functions works this way: * input string (which contains the number) * base the number has (e.g. base 10 or 16) * pointer to where you want to store the conversed number. * datatype, to make additional validations like overflows. Thus, to get a base 10 uint32_t number from a string: if (nft_strtol(string, 10, &number, NFT_STRTOL_U32) != 0) return -1 Also, I already have a patch that implements this functions all around the XML parsing code. Of course, other approach are possibles. Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@xxxxxxxxx> --- 0 files changed diff --git a/src/Makefile.am b/src/Makefile.am index 8a61ce8..bfbcaf7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,7 +4,8 @@ lib_LTLIBRARIES = libnftables.la libnftables_la_LIBADD = ${LIBMNL_LIBS} libnftables_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnftables.map \ -version-info $(LIBVERSION) -libnftables_la_SOURCES = table.c \ +libnftables_la_SOURCES = utils.c \ + table.c \ chain.c \ rule.c \ set.c \ diff --git a/src/internal.h b/src/internal.h index 0c5de21..094b198 100644 --- a/src/internal.h +++ b/src/internal.h @@ -58,6 +58,22 @@ struct nft_set_elem { uint32_t flags; }; +/* utils */ +enum nft_strtol_type { + NFT_STRTOL_U8 = 0, + NFT_STRTOL_S8, + NFT_STRTOL_U16, + NFT_STRTOL_S16, + NFT_STRTOL_U32, + NFT_STRTOL_S32, + NFT_STRTOL_U64, + NFT_STRTOL_S64, + NFT_STRTOL_INT, + NFT_STRTOL_UINT, +}; + +int nft_strtol(const char *string, int base, void *number, enum nft_strtol_type type); + #define SNPRINTF_BUFFER_SIZE(ret, size, len, offset) \ size += ret; \ if (ret > len) \ diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..9037eec --- /dev/null +++ b/src/utils.c @@ -0,0 +1,115 @@ +#include <internal.h> +#include <stdlib.h> +#include <limits.h> +#include <stdint.h> + +int nft_strtol(const char *string, int base, void *number, + enum nft_strtol_type type) +{ + int64_t stmp = 0; + uint64_t utmp = -1; + char *endptr; + int is_signed; + + switch (type) { + case NFT_STRTOL_U8: + case NFT_STRTOL_U16: + case NFT_STRTOL_U32: + case NFT_STRTOL_U64: + case NFT_STRTOL_UINT: + is_signed = 0; + break; + case NFT_STRTOL_S8: + case NFT_STRTOL_S16: + case NFT_STRTOL_S32: + case NFT_STRTOL_S64: + case NFT_STRTOL_INT: + is_signed = 1; + break; + default: + return -1; + } + + if (is_signed == 1) { + stmp = strtoll(string, &endptr, base); + } else { + utmp = strtoull(string, &endptr, base); + if (utmp < 0) + return -1; + } + + if (*endptr) + return -1; + + + + /* check for each dest type overflow and send back the number*/ + switch (type) { + case NFT_STRTOL_U8: + if (utmp > UINT8_MAX) + return -1; + uint8_t *retv_u8 = (uint8_t *)number; + *retv_u8 = (uint8_t)utmp; + break; + case NFT_STRTOL_S8: + if (stmp > INT8_MAX || stmp < INT8_MIN) + return -1; + int8_t *retv_s8 = (int8_t *)number; + *retv_s8 = (int8_t)stmp; + break; + case NFT_STRTOL_U16: + if (utmp > UINT16_MAX) + return -1; + uint16_t *retv_u16 = (uint16_t *)number; + *retv_u16 = (uint16_t)utmp; + break; + case NFT_STRTOL_S16: + if (stmp > INT16_MAX || stmp < INT16_MIN) + return -1; + int16_t *retv_s16 = (int16_t *)number; + *retv_s16 = (int16_t)stmp; + break; + case NFT_STRTOL_U32: + if (utmp > UINT32_MAX) + return -1; + uint32_t *retv_u32 = (uint32_t *)number; + *retv_u32 = (uint32_t)utmp; + break; + case NFT_STRTOL_S32: + if (stmp > INT32_MAX || stmp < INT32_MIN) + return -1; + int32_t *retv_s32 = (int32_t *)number; + *retv_s32 = (int32_t)stmp; + break; + case NFT_STRTOL_U64: + /* note: UINT64_MAX > ULLONG_MAX */ + if (utmp == ULLONG_MAX) + return -1; + uint64_t *retv_u64 = (uint64_t *)number; + *retv_u64 = (uint64_t)utmp; + break; + case NFT_STRTOL_S64: + /* note: INT64_MAX > LLONG_MAX */ + if (stmp == LLONG_MAX || stmp == LLONG_MIN) + return -1; + int64_t *retv_s64 = (int64_t *)number; + *retv_s64 = (int64_t)stmp; + break; + case NFT_STRTOL_UINT: + if (utmp > UINT_MAX) + return -1; + unsigned int *retv_ui = (unsigned int *)number; + *retv_ui = (unsigned int)utmp; + break; + case NFT_STRTOL_INT: + if (stmp > INT_MAX || stmp < INT_MIN) + return -1; + int *retv_si = (int *)number; + *retv_si = (int)stmp; + break; + default: + return -1; + } + + return 0; +} -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html