14#include <netinet/in.h>
16#include <libmnl/libmnl.h>
17#include <linux/netfilter.h>
18#include <linux/netfilter/nf_tables.h>
19#include <libnftnl/expr.h>
20#include <libnftnl/rule.h>
23static bool big_endian_host(
void)
30static int __reg_value_snprintf(
char *buf,
size_t remain,
31 uint8_t *data,
size_t datalen,
32 bool reverse,
const char *pfx)
34 int offset = 0, ret, i, idx;
37 for (i = 0; i < datalen; i++) {
39 ret = snprintf(buf + offset, remain,
"%s%s", sep, pfx);
40 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
44 idx = datalen - i - 1;
48 ret = snprintf(buf + offset, remain,
"%.2x", data[idx]);
49 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
56nftnl_data_reg_value_snprintf_default(
char *buf,
size_t remain,
57 const union nftnl_data_reg *reg,
60 uint32_t byteorder = big_endian_host() ? 0 : reg->byteorder;
61 const char *pfx = flags & DATA_F_NOPFX ?
"" :
"0x";
62 int offset = 0, ret, i, pos = 0;
64 for (i = 0; i < array_size(reg->sizes); i++) {
65 int curlen = reg->sizes[i] ?: reg->len;
66 bool reverse = byteorder & (1 << i);
69 ret = snprintf(buf + offset, remain,
" . ");
70 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
73 ret = __reg_value_snprintf(buf + offset, remain,
74 (
void *)®->val[pos],
75 curlen, reverse, pfx);
76 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
78 pos += div_round_up(curlen,
sizeof(uint32_t));
79 if (pos >= reg->len /
sizeof(uint32_t))
87nftnl_data_reg_verdict_snprintf_def(
char *buf,
size_t size,
88 const union nftnl_data_reg *reg,
91 int remain = size, offset = 0, ret = 0;
93 ret = snprintf(buf, size,
"%s", nftnl_verdict2str(reg->verdict));
94 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
96 if (reg->chain != NULL) {
97 ret = snprintf(buf + offset, remain,
" -> %s", reg->chain);
98 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
104int nftnl_data_reg_snprintf(
char *buf,
size_t size,
105 const union nftnl_data_reg *reg,
106 uint32_t flags,
int reg_type)
110 return nftnl_data_reg_value_snprintf_default(buf, size,
114 return nftnl_data_reg_verdict_snprintf_def(buf, size,
121static int nftnl_data_parse_cb(
const struct nlattr *attr,
void *data)
123 const struct nlattr **tb = data;
124 int type = mnl_attr_get_type(attr);
126 if (mnl_attr_type_valid(attr, NFTA_DATA_MAX) < 0)
130 case NFTA_DATA_VALUE:
131 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
134 case NFTA_DATA_VERDICT:
135 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
143static int nftnl_verdict_parse_cb(
const struct nlattr *attr,
void *data)
145 const struct nlattr **tb = data;
146 int type = mnl_attr_get_type(attr);
148 if (mnl_attr_type_valid(attr, NFTA_VERDICT_MAX) < 0)
152 case NFTA_VERDICT_CODE:
153 case NFTA_VERDICT_CHAIN_ID:
154 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
157 case NFTA_VERDICT_CHAIN:
158 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
167nftnl_parse_verdict(
union nftnl_data_reg *data,
const struct nlattr *attr,
int *type)
169 struct nlattr *tb[NFTA_VERDICT_MAX+1];
171 if (mnl_attr_parse_nested(attr, nftnl_verdict_parse_cb, tb) < 0)
174 if (!tb[NFTA_VERDICT_CODE])
177 data->verdict = ntohl(mnl_attr_get_u32(tb[NFTA_VERDICT_CODE]));
179 switch(data->verdict) {
187 *type = DATA_VERDICT;
188 data->len =
sizeof(data->verdict);
192 if (!tb[NFTA_VERDICT_CHAIN])
195 data->chain = strdup(mnl_attr_get_str(tb[NFTA_VERDICT_CHAIN]));
210__nftnl_parse_data(
union nftnl_data_reg *data,
const struct nlattr *attr)
212 void *orig = mnl_attr_get_payload(attr);
213 uint32_t data_len = mnl_attr_get_payload_len(attr);
218 if (data_len >
sizeof(data->val))
221 memcpy(data->val, orig, data_len);
222 data->len = data_len;
227int nftnl_parse_data(
union nftnl_data_reg *data,
struct nlattr *attr,
int *type)
229 struct nlattr *tb[NFTA_DATA_MAX+1] = {};
232 if (mnl_attr_parse_nested(attr, nftnl_data_parse_cb, tb) < 0)
235 if (tb[NFTA_DATA_VALUE]) {
239 ret = __nftnl_parse_data(data, tb[NFTA_DATA_VALUE]);
243 if (tb[NFTA_DATA_VERDICT])
244 ret = nftnl_parse_verdict(data, tb[NFTA_DATA_VERDICT], type);
249int nftnl_data_cpy(
union nftnl_data_reg *dreg,
const void *src,
250 uint32_t len, uint32_t byteorder, uint8_t *sizes)
254 if (len >
sizeof(dreg->val)) {
255 len =
sizeof(dreg->val);
259 memcpy(dreg->val, src, len);
261 dreg->byteorder = byteorder;
263 memcpy(dreg->sizes, sizes,
sizeof(dreg->sizes));
265 memset(dreg->sizes, 0,
sizeof(dreg->sizes));