summaryrefslogtreecommitdiffstats
path: root/src/expr/data_reg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/expr/data_reg.c')
-rw-r--r--src/expr/data_reg.c121
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 *)&reg->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;
}