diff options
Diffstat (limited to 'src/expr/data_reg.c')
| -rw-r--r-- | src/expr/data_reg.c | 121 |
1 files changed, 77 insertions, 44 deletions
diff --git a/src/expr/data_reg.c b/src/expr/data_reg.c index 4e35a79..d01e0f7 100644 --- a/src/expr/data_reg.c +++ b/src/expr/data_reg.c @@ -1,11 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.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. - * * This code has been sponsored by Sophos Astaro <http://www.sophos.com> */ @@ -24,16 +20,64 @@ #include <libnftnl/rule.h> #include "internal.h" +static bool big_endian_host(void) +{ + uint16_t v = 1; + + return v == htons(v); +} + +static int __reg_value_snprintf(char *buf, size_t remain, + uint8_t *data, size_t datalen, + bool reverse, const char *pfx) +{ + int offset = 0, ret, i, idx; + const char *sep = ""; + + for (i = 0; i < datalen; i++) { + if ((i % 4) == 0) { + ret = snprintf(buf + offset, remain, "%s%s", sep, pfx); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + sep = " "; + } + if (reverse) + idx = datalen - i - 1; + else + idx = i; + + ret = snprintf(buf + offset, remain, "%.2x", data[idx]); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + } + + return offset; +} + static int -nftnl_data_reg_value_snprintf_default(char *buf, size_t size, +nftnl_data_reg_value_snprintf_default(char *buf, size_t remain, const union nftnl_data_reg *reg, uint32_t flags) { - int remain = size, offset = 0, ret, i; + uint32_t byteorder = big_endian_host() ? 0 : reg->byteorder; + const char *pfx = flags & DATA_F_NOPFX ? "" : "0x"; + int offset = 0, ret, i, pos = 0; + + for (i = 0; i < array_size(reg->sizes); i++) { + int curlen = reg->sizes[i] ?: reg->len; + bool reverse = byteorder & (1 << i); - for (i = 0; i < div_round_up(reg->len, sizeof(uint32_t)); i++) { - ret = snprintf(buf + offset, remain, "0x%.8x ", reg->val[i]); + if (i > 0) { + ret = snprintf(buf + offset, remain, " . "); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + } + + ret = __reg_value_snprintf(buf + offset, remain, + (void *)®->val[pos], + curlen, reverse, pfx); SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + pos += div_round_up(curlen, sizeof(uint32_t)); + if (pos >= reg->len / sizeof(uint32_t)) + break; } return offset; @@ -46,11 +90,11 @@ nftnl_data_reg_verdict_snprintf_def(char *buf, size_t size, { int remain = size, offset = 0, ret = 0; - ret = snprintf(buf, size, "%s ", nftnl_verdict2str(reg->verdict)); + ret = snprintf(buf, size, "%s", nftnl_verdict2str(reg->verdict)); SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (reg->chain != NULL) { - ret = snprintf(buf + offset, remain, "-> %s ", reg->chain); + ret = snprintf(buf + offset, remain, " -> %s", reg->chain); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } @@ -59,38 +103,19 @@ nftnl_data_reg_verdict_snprintf_def(char *buf, size_t size, int nftnl_data_reg_snprintf(char *buf, size_t size, const union nftnl_data_reg *reg, - uint32_t output_format, uint32_t flags, - int reg_type) + uint32_t flags, int reg_type) { switch(reg_type) { case DATA_VALUE: - switch(output_format) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_data_reg_value_snprintf_default(buf, size, - reg, flags); - case NFTNL_OUTPUT_JSON: - case NFTNL_OUTPUT_XML: - default: - break; - } - break; + return nftnl_data_reg_value_snprintf_default(buf, size, + reg, flags); case DATA_VERDICT: case DATA_CHAIN: - switch(output_format) { - case NFTNL_OUTPUT_DEFAULT: - return nftnl_data_reg_verdict_snprintf_def(buf, size, - reg, flags); - case NFTNL_OUTPUT_JSON: - case NFTNL_OUTPUT_XML: - default: - break; - } - break; + return nftnl_data_reg_verdict_snprintf_def(buf, size, + reg, flags); default: - break; + return -1; } - - return -1; } static int nftnl_data_parse_cb(const struct nlattr *attr, void *data) @@ -221,14 +246,22 @@ int nftnl_parse_data(union nftnl_data_reg *data, struct nlattr *attr, int *type) return ret; } -void nftnl_free_verdict(const union nftnl_data_reg *data) +int nftnl_data_cpy(union nftnl_data_reg *dreg, const void *src, + uint32_t len, uint32_t byteorder, uint8_t *sizes) { - switch(data->verdict) { - case NFT_JUMP: - case NFT_GOTO: - xfree(data->chain); - break; - default: - break; + int ret = 0; + + if (len > sizeof(dreg->val)) { + len = sizeof(dreg->val); + ret = -1; } + + memcpy(dreg->val, src, len); + dreg->len = len; + dreg->byteorder = byteorder; + if (sizes) + memcpy(dreg->sizes, sizes, sizeof(dreg->sizes)); + else + memset(dreg->sizes, 0, sizeof(dreg->sizes)); + return ret; } |
