17 #include <arpa/inet.h>
19 #include <libmnl/libmnl.h>
20 #include <linux/netfilter/nf_tables.h>
21 #include <libnftnl/expr.h>
22 #include <libnftnl/rule.h>
25 enum nft_registers sreg;
26 enum nft_registers dreg;
27 enum nft_byteorder_ops op;
33 nftnl_expr_byteorder_set(
struct nftnl_expr *e, uint16_t type,
34 const void *data, uint32_t data_len)
39 case NFTNL_EXPR_BYTEORDER_SREG:
40 byteorder->sreg = *((uint32_t *)data);
42 case NFTNL_EXPR_BYTEORDER_DREG:
43 byteorder->dreg = *((uint32_t *)data);
45 case NFTNL_EXPR_BYTEORDER_OP:
46 byteorder->op = *((uint32_t *)data);
48 case NFTNL_EXPR_BYTEORDER_LEN:
49 byteorder->len = *((
unsigned int *)data);
51 case NFTNL_EXPR_BYTEORDER_SIZE:
52 byteorder->size = *((
unsigned int *)data);
61 nftnl_expr_byteorder_get(
const struct nftnl_expr *e, uint16_t type,
67 case NFTNL_EXPR_BYTEORDER_SREG:
68 *data_len =
sizeof(byteorder->sreg);
69 return &byteorder->sreg;
70 case NFTNL_EXPR_BYTEORDER_DREG:
71 *data_len =
sizeof(byteorder->dreg);
72 return &byteorder->dreg;
73 case NFTNL_EXPR_BYTEORDER_OP:
74 *data_len =
sizeof(byteorder->op);
75 return &byteorder->op;
76 case NFTNL_EXPR_BYTEORDER_LEN:
77 *data_len =
sizeof(byteorder->len);
78 return &byteorder->len;
79 case NFTNL_EXPR_BYTEORDER_SIZE:
80 *data_len =
sizeof(byteorder->size);
81 return &byteorder->size;
86 static int nftnl_expr_byteorder_cb(
const struct nlattr *attr,
void *data)
88 const struct nlattr **tb = data;
89 int type = mnl_attr_get_type(attr);
91 if (mnl_attr_type_valid(attr, NFTA_BYTEORDER_MAX) < 0)
95 case NFTA_BYTEORDER_SREG:
96 case NFTA_BYTEORDER_DREG:
97 case NFTA_BYTEORDER_OP:
98 case NFTA_BYTEORDER_LEN:
99 case NFTA_BYTEORDER_SIZE:
100 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
110 nftnl_expr_byteorder_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
114 if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_SREG)) {
115 mnl_attr_put_u32(nlh, NFTA_BYTEORDER_SREG,
116 htonl(byteorder->sreg));
118 if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_DREG)) {
119 mnl_attr_put_u32(nlh, NFTA_BYTEORDER_DREG,
120 htonl(byteorder->dreg));
122 if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_OP)) {
123 mnl_attr_put_u32(nlh, NFTA_BYTEORDER_OP,
124 htonl(byteorder->op));
126 if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_LEN)) {
127 mnl_attr_put_u32(nlh, NFTA_BYTEORDER_LEN,
128 htonl(byteorder->len));
130 if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_SIZE)) {
131 mnl_attr_put_u32(nlh, NFTA_BYTEORDER_SIZE,
132 htonl(byteorder->size));
137 nftnl_expr_byteorder_parse(
struct nftnl_expr *e,
struct nlattr *attr)
140 struct nlattr *tb[NFTA_BYTEORDER_MAX+1] = {};
143 if (mnl_attr_parse_nested(attr, nftnl_expr_byteorder_cb, tb) < 0)
146 if (tb[NFTA_BYTEORDER_SREG]) {
148 ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_SREG]));
149 e->flags |= (1 << NFTNL_EXPR_BYTEORDER_SREG);
151 if (tb[NFTA_BYTEORDER_DREG]) {
153 ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_DREG]));
154 e->flags |= (1 << NFTNL_EXPR_BYTEORDER_DREG);
156 if (tb[NFTA_BYTEORDER_OP]) {
158 ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_OP]));
159 e->flags |= (1 << NFTNL_EXPR_BYTEORDER_OP);
161 if (tb[NFTA_BYTEORDER_LEN]) {
163 ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_LEN]));
164 e->flags |= (1 << NFTNL_EXPR_BYTEORDER_LEN);
166 if (tb[NFTA_BYTEORDER_SIZE]) {
168 ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_SIZE]));
169 e->flags |= (1 << NFTNL_EXPR_BYTEORDER_SIZE);
175 static const char *expr_byteorder_str[] = {
176 [NFT_BYTEORDER_HTON] =
"hton",
177 [NFT_BYTEORDER_NTOH] =
"ntoh",
180 static const char *bo2str(uint32_t type)
182 if (type > NFT_BYTEORDER_HTON)
185 return expr_byteorder_str[type];
188 static inline int nftnl_str2ntoh(
const char *op)
190 if (strcmp(op,
"ntoh") == 0)
191 return NFT_BYTEORDER_NTOH;
192 else if (strcmp(op,
"hton") == 0)
193 return NFT_BYTEORDER_HTON;
201 nftnl_expr_byteorder_json_parse(
struct nftnl_expr *e, json_t *root,
202 struct nftnl_parse_err *err)
206 uint32_t sreg, dreg, len, size;
209 if (nftnl_jansson_parse_reg(root,
"sreg", NFTNL_TYPE_U32, &sreg, err) == 0)
210 nftnl_expr_set_u32(e, NFTNL_EXPR_BYTEORDER_SREG, sreg);
212 if (nftnl_jansson_parse_reg(root,
"dreg", NFTNL_TYPE_U32, &dreg, err) == 0)
213 nftnl_expr_set_u32(e, NFTNL_EXPR_BYTEORDER_DREG, dreg);
215 op = nftnl_jansson_parse_str(root,
"op", err);
217 ntoh = nftnl_str2ntoh(op);
221 nftnl_expr_set_u32(e, NFTNL_EXPR_BYTEORDER_OP, ntoh);
224 if (nftnl_jansson_parse_val(root,
"len", NFTNL_TYPE_U32, &len, err) == 0)
225 nftnl_expr_set_u32(e, NFTNL_EXPR_BYTEORDER_LEN, len);
227 if (nftnl_jansson_parse_val(root,
"size", NFTNL_TYPE_U32, &size, err) == 0)
228 nftnl_expr_set_u32(e, NFTNL_EXPR_BYTEORDER_SIZE, size);
237 static int nftnl_expr_byteorder_export(
char *buf,
size_t size,
238 const struct nftnl_expr *e,
int type)
241 NFTNL_BUF_INIT(b, buf, size);
243 if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_SREG))
244 nftnl_buf_u32(&b, type, byteorder->sreg, SREG);
245 if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_DREG))
246 nftnl_buf_u32(&b, type, byteorder->dreg, DREG);
247 if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_OP))
248 nftnl_buf_str(&b, type, bo2str(byteorder->op), OP);
249 if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_LEN))
250 nftnl_buf_u32(&b, type, byteorder->len, LEN);
251 if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_SIZE))
252 nftnl_buf_u32(&b, type, byteorder->size, SIZE);
254 return nftnl_buf_done(&b);
257 static int nftnl_expr_byteorder_snprintf_default(
char *buf,
size_t size,
258 const struct nftnl_expr *e)
261 int remain = size, offset = 0, ret;
263 ret = snprintf(buf, remain,
"reg %u = %s(reg %u, %u, %u) ",
264 byteorder->dreg, bo2str(byteorder->op),
265 byteorder->sreg, byteorder->size, byteorder->len);
266 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
272 nftnl_expr_byteorder_snprintf(
char *buf,
size_t size, uint32_t type,
273 uint32_t flags,
const struct nftnl_expr *e)
276 case NFTNL_OUTPUT_DEFAULT:
277 return nftnl_expr_byteorder_snprintf_default(buf, size, e);
278 case NFTNL_OUTPUT_XML:
279 case NFTNL_OUTPUT_JSON:
280 return nftnl_expr_byteorder_export(buf, size, e, type);
287 static bool nftnl_expr_byteorder_cmp(
const struct nftnl_expr *e1,
288 const struct nftnl_expr *e2)
294 if (e1->flags & (1 << NFTNL_EXPR_BYTEORDER_SREG))
295 eq &= (b1->sreg == b2->sreg);
296 if (e1->flags & (1 << NFTNL_EXPR_BYTEORDER_DREG))
297 eq &= (b1->dreg == b2->dreg);
298 if (e1->flags & (1 << NFTNL_EXPR_BYTEORDER_OP))
299 eq &= (b1->op == b2->op);
300 if (e1->flags & (1 << NFTNL_EXPR_BYTEORDER_LEN))
301 eq &= (b1->len == b2->len);
302 if (e1->flags & (1 << NFTNL_EXPR_BYTEORDER_SIZE))
303 eq &= (b1->size == b2->size);
308 struct expr_ops expr_ops_byteorder = {
311 .max_attr = NFTA_BYTEORDER_MAX,
312 .cmp = nftnl_expr_byteorder_cmp,
313 .set = nftnl_expr_byteorder_set,
314 .get = nftnl_expr_byteorder_get,
315 .parse = nftnl_expr_byteorder_parse,
316 .build = nftnl_expr_byteorder_build,
317 .snprintf = nftnl_expr_byteorder_snprintf,
318 .json_parse = nftnl_expr_byteorder_json_parse,