18 #include <arpa/inet.h>
20 #include <libmnl/libmnl.h>
22 #include <linux/netfilter/nf_tables.h>
24 #include <libnftnl/expr.h>
25 #include <libnftnl/rule.h>
28 enum nft_registers sreg;
29 enum nft_registers dreg;
30 enum nft_payload_bases base;
38 nftnl_expr_payload_set(
struct nftnl_expr *e, uint16_t type,
39 const void *data, uint32_t data_len)
44 case NFTNL_EXPR_PAYLOAD_SREG:
45 payload->sreg = *((uint32_t *)data);
47 case NFTNL_EXPR_PAYLOAD_DREG:
48 payload->dreg = *((uint32_t *)data);
50 case NFTNL_EXPR_PAYLOAD_BASE:
51 payload->base = *((uint32_t *)data);
53 case NFTNL_EXPR_PAYLOAD_OFFSET:
54 payload->offset = *((
unsigned int *)data);
56 case NFTNL_EXPR_PAYLOAD_LEN:
57 payload->len = *((
unsigned int *)data);
59 case NFTNL_EXPR_PAYLOAD_CSUM_TYPE:
60 payload->csum_type = *((uint32_t *)data);
62 case NFTNL_EXPR_PAYLOAD_CSUM_OFFSET:
63 payload->csum_offset = *((uint32_t *)data);
72 nftnl_expr_payload_get(
const struct nftnl_expr *e, uint16_t type,
78 case NFTNL_EXPR_PAYLOAD_SREG:
79 *data_len =
sizeof(payload->sreg);
80 return &payload->sreg;
81 case NFTNL_EXPR_PAYLOAD_DREG:
82 *data_len =
sizeof(payload->dreg);
83 return &payload->dreg;
84 case NFTNL_EXPR_PAYLOAD_BASE:
85 *data_len =
sizeof(payload->base);
86 return &payload->base;
87 case NFTNL_EXPR_PAYLOAD_OFFSET:
88 *data_len =
sizeof(payload->offset);
89 return &payload->offset;
90 case NFTNL_EXPR_PAYLOAD_LEN:
91 *data_len =
sizeof(payload->len);
93 case NFTNL_EXPR_PAYLOAD_CSUM_TYPE:
94 *data_len =
sizeof(payload->csum_type);
95 return &payload->csum_type;
96 case NFTNL_EXPR_PAYLOAD_CSUM_OFFSET:
97 *data_len =
sizeof(payload->csum_offset);
98 return &payload->csum_offset;
103 static int nftnl_expr_payload_cb(
const struct nlattr *attr,
void *data)
105 const struct nlattr **tb = data;
106 int type = mnl_attr_get_type(attr);
108 if (mnl_attr_type_valid(attr, NFTA_PAYLOAD_MAX) < 0)
112 case NFTA_PAYLOAD_SREG:
113 case NFTA_PAYLOAD_DREG:
114 case NFTA_PAYLOAD_BASE:
115 case NFTA_PAYLOAD_OFFSET:
116 case NFTA_PAYLOAD_LEN:
117 case NFTA_PAYLOAD_CSUM_TYPE:
118 case NFTA_PAYLOAD_CSUM_OFFSET:
119 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
129 nftnl_expr_payload_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
133 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_SREG))
134 mnl_attr_put_u32(nlh, NFTA_PAYLOAD_SREG, htonl(payload->sreg));
135 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_DREG))
136 mnl_attr_put_u32(nlh, NFTA_PAYLOAD_DREG, htonl(payload->dreg));
137 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_BASE))
138 mnl_attr_put_u32(nlh, NFTA_PAYLOAD_BASE, htonl(payload->base));
139 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_OFFSET))
140 mnl_attr_put_u32(nlh, NFTA_PAYLOAD_OFFSET, htonl(payload->offset));
141 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_LEN))
142 mnl_attr_put_u32(nlh, NFTA_PAYLOAD_LEN, htonl(payload->len));
143 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_CSUM_TYPE))
144 mnl_attr_put_u32(nlh, NFTA_PAYLOAD_CSUM_TYPE,
145 htonl(payload->csum_type));
146 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_CSUM_OFFSET))
147 mnl_attr_put_u32(nlh, NFTA_PAYLOAD_CSUM_OFFSET,
148 htonl(payload->csum_offset));
152 nftnl_expr_payload_parse(
struct nftnl_expr *e,
struct nlattr *attr)
155 struct nlattr *tb[NFTA_PAYLOAD_MAX+1] = {};
157 if (mnl_attr_parse_nested(attr, nftnl_expr_payload_cb, tb) < 0)
160 if (tb[NFTA_PAYLOAD_SREG]) {
161 payload->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_SREG]));
162 e->flags |= (1 << NFT_EXPR_PAYLOAD_SREG);
164 if (tb[NFTA_PAYLOAD_DREG]) {
165 payload->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_DREG]));
166 e->flags |= (1 << NFTNL_EXPR_PAYLOAD_DREG);
168 if (tb[NFTA_PAYLOAD_BASE]) {
169 payload->base = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_BASE]));
170 e->flags |= (1 << NFTNL_EXPR_PAYLOAD_BASE);
172 if (tb[NFTA_PAYLOAD_OFFSET]) {
173 payload->offset = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_OFFSET]));
174 e->flags |= (1 << NFTNL_EXPR_PAYLOAD_OFFSET);
176 if (tb[NFTA_PAYLOAD_LEN]) {
177 payload->len = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_LEN]));
178 e->flags |= (1 << NFTNL_EXPR_PAYLOAD_LEN);
180 if (tb[NFTA_PAYLOAD_CSUM_TYPE]) {
181 payload->csum_type = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_CSUM_TYPE]));
182 e->flags |= (1 << NFTNL_EXPR_PAYLOAD_CSUM_TYPE);
184 if (tb[NFTA_PAYLOAD_CSUM_OFFSET]) {
185 payload->csum_offset = ntohl(mnl_attr_get_u32(tb[NFTA_PAYLOAD_CSUM_OFFSET]));
186 e->flags |= (1 << NFTNL_EXPR_PAYLOAD_CSUM_OFFSET);
191 static char *base2str_array[NFT_PAYLOAD_TRANSPORT_HEADER+1] = {
192 [NFT_PAYLOAD_LL_HEADER] =
"link",
193 [NFT_PAYLOAD_NETWORK_HEADER] =
"network",
194 [NFT_PAYLOAD_TRANSPORT_HEADER] =
"transport",
197 static const char *base2str(
enum nft_payload_bases base)
199 if (base > NFT_PAYLOAD_TRANSPORT_HEADER)
202 return base2str_array[base];
205 static inline int nftnl_str2base(
const char *base)
207 if (strcmp(base,
"link") == 0)
208 return NFT_PAYLOAD_LL_HEADER;
209 else if (strcmp(base,
"network") == 0)
210 return NFT_PAYLOAD_NETWORK_HEADER;
211 else if (strcmp(base,
"transport") == 0)
212 return NFT_PAYLOAD_TRANSPORT_HEADER;
220 nftnl_expr_payload_json_parse(
struct nftnl_expr *e, json_t *root,
221 struct nftnl_parse_err *err)
224 const char *base_str;
225 uint32_t reg, uval32;
228 if (nftnl_jansson_parse_reg(root,
"dreg", NFTNL_TYPE_U32, ®, err) == 0)
229 nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_DREG, reg);
231 base_str = nftnl_jansson_parse_str(root,
"base", err);
232 if (base_str != NULL) {
233 base = nftnl_str2base(base_str);
237 nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_BASE, base);
240 if (nftnl_jansson_parse_val(root,
"offset", NFTNL_TYPE_U32, &uval32,
242 nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_OFFSET, uval32);
244 if (nftnl_jansson_parse_val(root,
"len", NFTNL_TYPE_U32, &uval32, err) == 0)
245 nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_LEN, uval32);
255 nftnl_expr_payload_xml_parse(
struct nftnl_expr *e, mxml_node_t *tree,
256 struct nftnl_parse_err *err)
259 const char *base_str;
261 uint32_t dreg, offset, len;
263 if (nftnl_mxml_reg_parse(tree,
"dreg", &dreg, MXML_DESCEND_FIRST,
264 NFTNL_XML_MAND, err) == 0)
265 nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_DREG, dreg);
267 base_str = nftnl_mxml_str_parse(tree,
"base", MXML_DESCEND_FIRST,
268 NFTNL_XML_MAND, err);
269 if (base_str != NULL) {
270 base = nftnl_str2base(base_str);
274 nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_BASE, base);
277 if (nftnl_mxml_num_parse(tree,
"offset", MXML_DESCEND_FIRST, BASE_DEC,
278 &offset, NFTNL_TYPE_U32, NFTNL_XML_MAND, err) == 0)
279 nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_OFFSET, offset);
282 if (nftnl_mxml_num_parse(tree,
"len", MXML_DESCEND_FIRST, BASE_DEC,
283 &len, NFTNL_TYPE_U32, NFTNL_XML_MAND, err) == 0)
284 nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_LEN, len);
293 static int nftnl_expr_payload_export(
char *buf,
size_t size, uint32_t flags,
294 const struct nftnl_expr *e,
int type)
297 NFTNL_BUF_INIT(b, buf, size);
299 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_DREG))
300 nftnl_buf_u32(&b, type, payload->dreg, DREG);
301 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_OFFSET))
302 nftnl_buf_u32(&b, type, payload->offset, OFFSET);
303 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_LEN))
304 nftnl_buf_u32(&b, type, payload->len, LEN);
305 if (e->flags & (1 << NFTNL_EXPR_PAYLOAD_BASE))
306 nftnl_buf_str(&b, type, base2str(payload->base), BASE);
308 return nftnl_buf_done(&b);
312 nftnl_expr_payload_snprintf(
char *buf,
size_t len, uint32_t type,
313 uint32_t flags,
const struct nftnl_expr *e)
318 case NFTNL_OUTPUT_DEFAULT:
320 return snprintf(buf, len,
"write reg %u => %ub @ %s header + %u csum_type %u csum_off %u ",
322 payload->len, base2str(payload->base),
323 payload->offset, payload->csum_type,
324 payload->csum_offset);
326 return snprintf(buf, len,
"load %ub @ %s header + %u => reg %u ",
327 payload->len, base2str(payload->base),
328 payload->offset, payload->dreg);
329 case NFTNL_OUTPUT_XML:
330 case NFTNL_OUTPUT_JSON:
331 return nftnl_expr_payload_export(buf, len, flags, e, type);
338 struct expr_ops expr_ops_payload = {
341 .max_attr = NFTA_PAYLOAD_MAX,
342 .set = nftnl_expr_payload_set,
343 .get = nftnl_expr_payload_get,
344 .parse = nftnl_expr_payload_parse,
345 .build = nftnl_expr_payload_build,
346 .snprintf = nftnl_expr_payload_snprintf,
347 .xml_parse = nftnl_expr_payload_xml_parse,
348 .json_parse = nftnl_expr_payload_json_parse,