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;
38 nftnl_expr_hash_set(
struct nftnl_expr *e, uint16_t type,
39 const void *data, uint32_t data_len)
43 case NFTNL_EXPR_HASH_SREG:
44 memcpy(&hash->sreg, data,
sizeof(hash->sreg));
46 case NFTNL_EXPR_HASH_DREG:
47 memcpy(&hash->dreg, data,
sizeof(hash->dreg));
49 case NFTNL_EXPR_HASH_LEN:
50 memcpy(&hash->len, data,
sizeof(hash->len));
52 case NFTNL_EXPR_HASH_MODULUS:
53 memcpy(&hash->modulus, data,
sizeof(hash->modulus));
55 case NFTNL_EXPR_HASH_SEED:
56 memcpy(&hash->seed, data,
sizeof(hash->seed));
58 case NFTNL_EXPR_HASH_OFFSET:
59 memcpy(&hash->offset, data,
sizeof(hash->offset));
61 case NFTNL_EXPR_HASH_TYPE:
62 memcpy(&hash->type, data,
sizeof(hash->type));
64 case NFTNL_EXPR_HASH_SET_NAME:
65 hash->map.name = strdup(data);
69 case NFTNL_EXPR_HASH_SET_ID:
70 memcpy(&hash->map.id, data,
sizeof(hash->map.id));
79 nftnl_expr_hash_get(
const struct nftnl_expr *e, uint16_t type,
85 case NFTNL_EXPR_HASH_SREG:
86 *data_len =
sizeof(hash->sreg);
88 case NFTNL_EXPR_HASH_DREG:
89 *data_len =
sizeof(hash->dreg);
91 case NFTNL_EXPR_HASH_LEN:
92 *data_len =
sizeof(hash->len);
94 case NFTNL_EXPR_HASH_MODULUS:
95 *data_len =
sizeof(hash->modulus);
96 return &hash->modulus;
97 case NFTNL_EXPR_HASH_SEED:
98 *data_len =
sizeof(hash->seed);
100 case NFTNL_EXPR_HASH_OFFSET:
101 *data_len =
sizeof(hash->offset);
102 return &hash->offset;
103 case NFTNL_EXPR_HASH_TYPE:
104 *data_len =
sizeof(hash->type);
106 case NFTNL_EXPR_HASH_SET_NAME:
107 *data_len = strlen(hash->map.name) + 1;
108 return hash->map.name;
109 case NFTNL_EXPR_HASH_SET_ID:
110 *data_len =
sizeof(hash->map.id);
111 return &hash->map.id;
116 static int nftnl_expr_hash_cb(
const struct nlattr *attr,
void *data)
118 const struct nlattr **tb = data;
119 int type = mnl_attr_get_type(attr);
121 if (mnl_attr_type_valid(attr, NFTA_HASH_MAX) < 0)
128 case NFTA_HASH_MODULUS:
130 case NFTA_HASH_OFFSET:
132 case NFTA_HASH_SET_ID:
133 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
136 case NFTA_HASH_SET_NAME:
137 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
147 nftnl_expr_hash_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
151 if (e->flags & (1 << NFTNL_EXPR_HASH_SREG))
152 mnl_attr_put_u32(nlh, NFTA_HASH_SREG, htonl(hash->sreg));
153 if (e->flags & (1 << NFTNL_EXPR_HASH_DREG))
154 mnl_attr_put_u32(nlh, NFTA_HASH_DREG, htonl(hash->dreg));
155 if (e->flags & (1 << NFTNL_EXPR_HASH_LEN))
156 mnl_attr_put_u32(nlh, NFTA_HASH_LEN, htonl(hash->len));
157 if (e->flags & (1 << NFTNL_EXPR_HASH_MODULUS))
158 mnl_attr_put_u32(nlh, NFTA_HASH_MODULUS, htonl(hash->modulus));
159 if (e->flags & (1 << NFTNL_EXPR_HASH_SEED))
160 mnl_attr_put_u32(nlh, NFTA_HASH_SEED, htonl(hash->seed));
161 if (e->flags & (1 << NFTNL_EXPR_HASH_OFFSET))
162 mnl_attr_put_u32(nlh, NFTA_HASH_OFFSET, htonl(hash->offset));
163 if (e->flags & (1 << NFTNL_EXPR_HASH_TYPE))
164 mnl_attr_put_u32(nlh, NFTA_HASH_TYPE, htonl(hash->type));
165 if (e->flags & (1 << NFTNL_EXPR_HASH_SET_NAME))
166 mnl_attr_put_str(nlh, NFTA_HASH_SET_NAME, hash->map.name);
167 if (e->flags & (1 << NFTNL_EXPR_HASH_SET_ID))
168 mnl_attr_put_u32(nlh, NFTA_HASH_SET_ID, htonl(hash->map.id));
172 nftnl_expr_hash_parse(
struct nftnl_expr *e,
struct nlattr *attr)
175 struct nlattr *tb[NFTA_HASH_MAX+1] = {};
178 if (mnl_attr_parse_nested(attr, nftnl_expr_hash_cb, tb) < 0)
181 if (tb[NFTA_HASH_SREG]) {
182 hash->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_SREG]));
183 e->flags |= (1 << NFTNL_EXPR_HASH_SREG);
185 if (tb[NFTA_HASH_DREG]) {
186 hash->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_DREG]));
187 e->flags |= (1 << NFTNL_EXPR_HASH_DREG);
189 if (tb[NFTA_HASH_LEN]) {
190 hash->len = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_LEN]));
191 e->flags |= (1 << NFTNL_EXPR_HASH_LEN);
193 if (tb[NFTA_HASH_MODULUS]) {
194 hash->modulus = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_MODULUS]));
195 e->flags |= (1 << NFTNL_EXPR_HASH_MODULUS);
197 if (tb[NFTA_HASH_SEED]) {
198 hash->seed = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_SEED]));
199 e->flags |= (1 << NFTNL_EXPR_HASH_SEED);
201 if (tb[NFTA_HASH_OFFSET]) {
202 hash->offset = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_OFFSET]));
203 e->flags |= (1 << NFTNL_EXPR_HASH_OFFSET);
205 if (tb[NFTA_HASH_TYPE]) {
206 hash->type = ntohl(mnl_attr_get_u32(tb[NFTA_HASH_TYPE]));
207 e->flags |= (1 << NFTNL_EXPR_HASH_TYPE);
209 if (tb[NFTA_HASH_SET_NAME]) {
211 strdup(mnl_attr_get_str(tb[NFTA_HASH_SET_NAME]));
212 e->flags |= (1 << NFTNL_EXPR_HASH_SET_NAME);
214 if (tb[NFTA_HASH_SET_ID]) {
216 ntohl(mnl_attr_get_u32(tb[NFTA_HASH_SET_ID]));
217 e->flags |= (1 << NFTNL_EXPR_HASH_SET_ID);
224 nftnl_expr_hash_snprintf_default(
char *buf,
size_t size,
225 const struct nftnl_expr *e)
228 int remain = size, offset = 0, ret;
230 switch (hash->type) {
233 snprintf(buf, remain,
"reg %u = symhash() %% mod %u ",
236 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
238 case NFT_HASH_JENKINS:
241 snprintf(buf, remain,
242 "reg %u = jhash(reg %u, %u, 0x%x) %% mod %u ",
243 hash->dreg, hash->sreg, hash->len, hash->seed,
245 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
250 ret = snprintf(buf + offset, remain,
"offset %u ",
252 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
256 ret = snprintf(buf + offset, remain,
"set %s id %u ",
257 hash->map.name, hash->map.id);
258 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
265 nftnl_expr_hash_snprintf(
char *buf,
size_t len, uint32_t type,
266 uint32_t flags,
const struct nftnl_expr *e)
269 case NFTNL_OUTPUT_DEFAULT:
270 return nftnl_expr_hash_snprintf_default(buf, len, e);
271 case NFTNL_OUTPUT_XML:
272 case NFTNL_OUTPUT_JSON:
279 struct expr_ops expr_ops_hash = {
282 .max_attr = NFTA_HASH_MAX,
283 .set = nftnl_expr_hash_set,
284 .get = nftnl_expr_hash_get,
285 .parse = nftnl_expr_hash_parse,
286 .build = nftnl_expr_hash_build,
287 .snprintf = nftnl_expr_hash_snprintf,