14 #include <arpa/inet.h>
16 #include <linux/netfilter/nf_tables.h>
19 #include <libmnl/libmnl.h>
20 #include <libnftnl/expr.h>
21 #include <libnftnl/rule.h>
24 enum nft_hash_types type;
25 enum nft_registers sreg;
26 enum nft_registers dreg;
34 nftnl_expr_hash_set(
struct nftnl_expr *e, uint16_t type,
35 const void *data, uint32_t data_len)
39 case NFTNL_EXPR_HASH_SREG:
40 hash->sreg = *((uint32_t *)data);
42 case NFTNL_EXPR_HASH_DREG:
43 hash->dreg = *((uint32_t *)data);
45 case NFTNL_EXPR_HASH_LEN:
46 hash->len = *((uint32_t *)data);
48 case NFTNL_EXPR_HASH_MODULUS:
49 hash->modulus = *((uint32_t *)data);
51 case NFTNL_EXPR_HASH_SEED:
52 hash->seed = *((uint32_t *)data);
54 case NFTNL_EXPR_HASH_OFFSET:
55 hash->offset = *((uint32_t *)data);
57 case NFTNL_EXPR_HASH_TYPE:
58 hash->type = *((uint32_t *)data);
67 nftnl_expr_hash_get(
const struct nftnl_expr *e, uint16_t type,
73 case NFTNL_EXPR_HASH_SREG:
74 *data_len =
sizeof(hash->sreg);
76 case NFTNL_EXPR_HASH_DREG:
77 *data_len =
sizeof(hash->dreg);
79 case NFTNL_EXPR_HASH_LEN:
80 *data_len =
sizeof(hash->len);
82 case NFTNL_EXPR_HASH_MODULUS:
83 *data_len =
sizeof(hash->modulus);
84 return &hash->modulus;
85 case NFTNL_EXPR_HASH_SEED:
86 *data_len =
sizeof(hash->seed);
88 case NFTNL_EXPR_HASH_OFFSET:
89 *data_len =
sizeof(hash->offset);
91 case NFTNL_EXPR_HASH_TYPE:
92 *data_len =
sizeof(hash->type);
98 static int nftnl_expr_hash_cb(
const struct nlattr *attr,
void *data)
100 const struct nlattr **tb = data;
101 int type = mnl_attr_get_type(attr);
103 if (mnl_attr_type_valid(attr, NFTA_HASH_MAX) < 0)
110 case NFTA_HASH_MODULUS:
112 case NFTA_HASH_OFFSET:
114 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
124 nftnl_expr_hash_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
128 if (e->flags & (1 << NFTNL_EXPR_HASH_SREG))
129 mnl_attr_put_u32(nlh, NFTA_HASH_SREG, htonl(hash->sreg));
130 if (e->flags & (1 << NFTNL_EXPR_HASH_DREG))
131 mnl_attr_put_u32(nlh, NFTA_HASH_DREG, htonl(hash->dreg));
132 if (e->flags & (1 << NFTNL_EXPR_HASH_LEN))
133 mnl_attr_put_u32(nlh, NFTA_HASH_LEN, htonl(hash->len));
134 if (e->flags & (1 << NFTNL_EXPR_HASH_MODULUS))
135 mnl_attr_put_u32(nlh, NFTA_HASH_MODULUS, htonl(hash->modulus));
136 if (e->flags & (1 << NFTNL_EXPR_HASH_SEED))
137 mnl_attr_put_u32(nlh, NFTA_HASH_SEED, htonl(hash->seed));
138 if (e->flags & (1 << NFTNL_EXPR_HASH_OFFSET))
139 mnl_attr_put_u32(nlh, NFTA_HASH_OFFSET, htonl(hash->offset));
140 if (e->flags & (1 << NFTNL_EXPR_HASH_TYPE))
141 mnl_attr_put_u32(nlh, NFTA_HASH_TYPE, htonl(hash->type));
145 nftnl_expr_hash_parse(
struct nftnl_expr *e,
struct nlattr *attr)
148 struct nlattr *tb[NFTA_HASH_MAX+1] = {};
151 if (mnl_attr_parse_nested(attr, nftnl_expr_hash_cb, tb) < 0)
154 if (tb[NFTA_HASH_SREG]) {
155 hash->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_SREG]));
156 e->flags |= (1 << NFTNL_EXPR_HASH_SREG);
158 if (tb[NFTA_HASH_DREG]) {
159 hash->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_DREG]));
160 e->flags |= (1 << NFTNL_EXPR_HASH_DREG);
162 if (tb[NFTA_HASH_LEN]) {
163 hash->len = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_LEN]));
164 e->flags |= (1 << NFTNL_EXPR_HASH_LEN);
166 if (tb[NFTA_HASH_MODULUS]) {
167 hash->modulus = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_MODULUS]));
168 e->flags |= (1 << NFTNL_EXPR_HASH_MODULUS);
170 if (tb[NFTA_HASH_SEED]) {
171 hash->seed = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_SEED]));
172 e->flags |= (1 << NFTNL_EXPR_HASH_SEED);
174 if (tb[NFTA_HASH_OFFSET]) {
175 hash->offset = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_OFFSET]));
176 e->flags |= (1 << NFTNL_EXPR_HASH_OFFSET);
178 if (tb[NFTA_HASH_TYPE]) {
179 hash->type = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_TYPE]));
180 e->flags |= (1 << NFTNL_EXPR_HASH_TYPE);
186 static int nftnl_expr_hash_json_parse(
struct nftnl_expr *e, json_t *root,
187 struct nftnl_parse_err *err)
190 uint32_t sreg, dreg, len, modulus, seed, offset, type;
192 if (nftnl_jansson_parse_reg(root,
"sreg", NFTNL_TYPE_U32,
194 nftnl_expr_set_u32(e, NFTNL_EXPR_HASH_SREG, sreg);
196 if (nftnl_jansson_parse_reg(root,
"dreg", NFTNL_TYPE_U32,
198 nftnl_expr_set_u32(e, NFTNL_EXPR_HASH_DREG, dreg);
200 if (nftnl_jansson_parse_val(root,
"len", NFTNL_TYPE_U32,
202 nftnl_expr_set_u32(e, NFTNL_EXPR_HASH_LEN, len);
204 if (nftnl_jansson_parse_val(root,
"modulus", NFTNL_TYPE_U32,
206 nftnl_expr_set_u32(e, NFTNL_EXPR_HASH_MODULUS, modulus);
208 if (nftnl_jansson_parse_val(root,
"seed", NFTNL_TYPE_U32,
210 nftnl_expr_set_u32(e, NFTNL_EXPR_HASH_SEED, seed);
212 if (nftnl_jansson_parse_val(root,
"offset", NFTNL_TYPE_U32,
214 nftnl_expr_set_u32(e, NFTNL_EXPR_HASH_OFFSET, offset);
216 if (nftnl_jansson_parse_val(root,
"type", NFTNL_TYPE_U32,
218 nftnl_expr_set_u32(e, NFTNL_EXPR_HASH_TYPE, type);
228 nftnl_expr_hash_snprintf_default(
char *buf,
size_t size,
229 const struct nftnl_expr *e)
232 int remain = size, offset = 0, ret;
234 switch (hash->type) {
237 snprintf(buf, remain,
"reg %u = symhash() %% mod %u ",
240 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
242 case NFT_HASH_JENKINS:
245 snprintf(buf, remain,
246 "reg %u = jhash(reg %u, %u, 0x%x) %% mod %u ",
247 hash->dreg, hash->sreg, hash->len, hash->seed,
249 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
254 ret = snprintf(buf + offset, remain,
"offset %u ",
256 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
262 static int nftnl_expr_hash_export(
char *buf,
size_t size,
263 const struct nftnl_expr *e,
int type)
267 NFTNL_BUF_INIT(b, buf, size);
269 if (e->flags & (1 << NFTNL_EXPR_HASH_SREG))
270 nftnl_buf_u32(&b, type, hash->sreg, SREG);
271 if (e->flags & (1 << NFTNL_EXPR_HASH_DREG))
272 nftnl_buf_u32(&b, type, hash->dreg, DREG);
273 if (e->flags & (1 << NFTNL_EXPR_HASH_LEN))
274 nftnl_buf_u32(&b, type, hash->len, LEN);
275 if (e->flags & (1 << NFTNL_EXPR_HASH_MODULUS))
276 nftnl_buf_u32(&b, type, hash->modulus, MODULUS);
277 if (e->flags & (1 << NFTNL_EXPR_HASH_SEED))
278 nftnl_buf_u32(&b, type, hash->seed, SEED);
279 if (e->flags & (1 << NFTNL_EXPR_HASH_OFFSET))
280 nftnl_buf_u32(&b, type, hash->offset, OFFSET);
281 if (e->flags & (1 << NFTNL_EXPR_HASH_TYPE))
282 nftnl_buf_u32(&b, type, hash->type, TYPE);
284 return nftnl_buf_done(&b);
288 nftnl_expr_hash_snprintf(
char *buf,
size_t len, uint32_t type,
289 uint32_t flags,
const struct nftnl_expr *e)
292 case NFTNL_OUTPUT_DEFAULT:
293 return nftnl_expr_hash_snprintf_default(buf, len, e);
294 case NFTNL_OUTPUT_XML:
295 case NFTNL_OUTPUT_JSON:
296 return nftnl_expr_hash_export(buf, len, e, type);
303 static bool nftnl_expr_hash_cmp(
const struct nftnl_expr *e1,
304 const struct nftnl_expr *e2)
310 if (e1->flags & (1 << NFTNL_EXPR_HASH_SREG))
311 eq &= (h1->sreg == h2->sreg);
312 if (e1->flags & (1 << NFTNL_EXPR_HASH_DREG))
313 eq &= (h1->dreg == h2->dreg);
314 if (e1->flags & (1 << NFTNL_EXPR_HASH_LEN))
315 eq &= (h1->len == h2->len);
316 if (e1->flags & (1 << NFTNL_EXPR_HASH_MODULUS))
317 eq &= (h1->modulus == h2->modulus);
318 if (e1->flags & (1 << NFTNL_EXPR_HASH_SEED))
319 eq &= (h1->seed == h2->seed);
320 if (e1->flags & (1 << NFTNL_EXPR_HASH_OFFSET))
321 eq &= (h1->offset == h2->offset);
322 if (e1->flags & (1 << NFTNL_EXPR_HASH_TYPE))
323 eq &= (h1->type == h2->type);
328 struct expr_ops expr_ops_hash = {
331 .max_attr = NFTA_HASH_MAX,
332 .cmp = nftnl_expr_hash_cmp,
333 .set = nftnl_expr_hash_set,
334 .get = nftnl_expr_hash_get,
335 .parse = nftnl_expr_hash_parse,
336 .build = nftnl_expr_hash_build,
337 .snprintf = nftnl_expr_hash_snprintf,
338 .json_parse = nftnl_expr_hash_json_parse,