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 #define IPPROTO_MH 135
32 enum nft_registers dreg;
39 nftnl_expr_exthdr_set(
struct nftnl_expr *e, uint16_t type,
40 const void *data, uint32_t data_len)
45 case NFTNL_EXPR_EXTHDR_DREG:
46 exthdr->dreg = *((uint32_t *)data);
48 case NFTNL_EXPR_EXTHDR_TYPE:
49 exthdr->type = *((uint8_t *)data);
51 case NFTNL_EXPR_EXTHDR_OFFSET:
52 exthdr->offset = *((uint32_t *)data);
54 case NFTNL_EXPR_EXTHDR_LEN:
55 exthdr->len = *((uint32_t *)data);
64 nftnl_expr_exthdr_get(
const struct nftnl_expr *e, uint16_t type,
70 case NFTNL_EXPR_EXTHDR_DREG:
71 *data_len =
sizeof(exthdr->dreg);
73 case NFTNL_EXPR_EXTHDR_TYPE:
74 *data_len =
sizeof(exthdr->type);
76 case NFTNL_EXPR_EXTHDR_OFFSET:
77 *data_len =
sizeof(exthdr->offset);
78 return &exthdr->offset;
79 case NFTNL_EXPR_EXTHDR_LEN:
80 *data_len =
sizeof(exthdr->len);
86 static int nftnl_expr_exthdr_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_EXTHDR_MAX) < 0)
95 case NFTA_EXTHDR_TYPE:
96 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
99 case NFTA_EXTHDR_DREG:
100 case NFTA_EXTHDR_OFFSET:
101 case NFTA_EXTHDR_LEN:
102 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
112 nftnl_expr_exthdr_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
116 if (e->flags & (1 << NFTNL_EXPR_EXTHDR_DREG))
117 mnl_attr_put_u32(nlh, NFTA_EXTHDR_DREG, htonl(exthdr->dreg));
118 if (e->flags & (1 << NFTNL_EXPR_EXTHDR_TYPE))
119 mnl_attr_put_u8(nlh, NFTA_EXTHDR_TYPE, exthdr->type);
120 if (e->flags & (1 << NFTNL_EXPR_EXTHDR_OFFSET))
121 mnl_attr_put_u32(nlh, NFTA_EXTHDR_OFFSET, htonl(exthdr->offset));
122 if (e->flags & (1 << NFTNL_EXPR_EXTHDR_LEN))
123 mnl_attr_put_u32(nlh, NFTA_EXTHDR_LEN, htonl(exthdr->len));
127 nftnl_expr_exthdr_parse(
struct nftnl_expr *e,
struct nlattr *attr)
130 struct nlattr *tb[NFTA_EXTHDR_MAX+1] = {};
132 if (mnl_attr_parse_nested(attr, nftnl_expr_exthdr_cb, tb) < 0)
135 if (tb[NFTA_EXTHDR_DREG]) {
136 exthdr->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_EXTHDR_DREG]));
137 e->flags |= (1 << NFTNL_EXPR_EXTHDR_DREG);
139 if (tb[NFTA_EXTHDR_TYPE]) {
140 exthdr->type = mnl_attr_get_u8(tb[NFTA_EXTHDR_TYPE]);
141 e->flags |= (1 << NFTNL_EXPR_EXTHDR_TYPE);
143 if (tb[NFTA_EXTHDR_OFFSET]) {
144 exthdr->offset = ntohl(mnl_attr_get_u32(tb[NFTA_EXTHDR_OFFSET]));
145 e->flags |= (1 << NFTNL_EXPR_EXTHDR_OFFSET);
147 if (tb[NFTA_EXTHDR_LEN]) {
148 exthdr->len = ntohl(mnl_attr_get_u32(tb[NFTA_EXTHDR_LEN]));
149 e->flags |= (1 << NFTNL_EXPR_EXTHDR_LEN);
155 static const char *type2str(uint32_t type)
158 case IPPROTO_HOPOPTS:
160 case IPPROTO_ROUTING:
162 case IPPROTO_FRAGMENT:
164 case IPPROTO_DSTOPTS:
173 static inline int str2exthdr_type(
const char *str)
175 if (strcmp(str,
"hopopts") == 0)
176 return IPPROTO_HOPOPTS;
177 else if (strcmp(str,
"routing") == 0)
178 return IPPROTO_ROUTING;
179 else if (strcmp(str,
"fragment") == 0)
180 return IPPROTO_FRAGMENT;
181 else if (strcmp(str,
"dstopts") == 0)
182 return IPPROTO_DSTOPTS;
183 else if (strcmp(str,
"mh") == 0)
190 nftnl_expr_exthdr_json_parse(
struct nftnl_expr *e, json_t *root,
191 struct nftnl_parse_err *err)
194 const char *exthdr_type;
198 if (nftnl_jansson_parse_reg(root,
"dreg", NFTNL_TYPE_U32, &uval32,
200 nftnl_expr_set_u32(e, NFTNL_EXPR_EXTHDR_DREG, uval32);
202 exthdr_type = nftnl_jansson_parse_str(root,
"exthdr_type", err);
203 if (exthdr_type != NULL) {
204 type = str2exthdr_type(exthdr_type);
207 nftnl_expr_set_u32(e, NFTNL_EXPR_EXTHDR_TYPE, type);
210 if (nftnl_jansson_parse_val(root,
"offset", NFTNL_TYPE_U32, &uval32,
212 nftnl_expr_set_u32(e, NFTNL_EXPR_EXTHDR_OFFSET, uval32);
214 if (nftnl_jansson_parse_val(root,
"len", NFTNL_TYPE_U32, &uval32, err) == 0)
215 nftnl_expr_set_u32(e, NFTNL_EXPR_EXTHDR_LEN, uval32);
225 nftnl_expr_exthdr_xml_parse(
struct nftnl_expr *e, mxml_node_t *tree,
226 struct nftnl_parse_err *err)
229 const char *exthdr_type;
231 uint32_t dreg, len, offset;
233 if (nftnl_mxml_reg_parse(tree,
"dreg", &dreg, MXML_DESCEND_FIRST,
234 NFTNL_XML_MAND, err) == 0)
235 nftnl_expr_set_u32(e, NFTNL_EXPR_EXTHDR_DREG, dreg);
237 exthdr_type = nftnl_mxml_str_parse(tree,
"exthdr_type",
238 MXML_DESCEND_FIRST, NFTNL_XML_MAND, err);
239 if (exthdr_type != NULL) {
240 type = str2exthdr_type(exthdr_type);
243 nftnl_expr_set_u8(e, NFTNL_EXPR_EXTHDR_TYPE, type);
247 if (nftnl_mxml_num_parse(tree,
"offset", MXML_DESCEND_FIRST, BASE_DEC,
248 &offset, NFTNL_TYPE_U32, NFTNL_XML_MAND, err) == 0)
249 nftnl_expr_set_u32(e, NFTNL_EXPR_EXTHDR_OFFSET, offset);
252 if (nftnl_mxml_num_parse(tree,
"len", MXML_DESCEND_FIRST, BASE_DEC,
253 &len, NFTNL_TYPE_U32, NFTNL_XML_MAND, err) == 0)
254 nftnl_expr_set_u32(e, NFTNL_EXPR_EXTHDR_LEN, len);
263 static int nftnl_expr_exthdr_export(
char *buf,
size_t len,
264 const struct nftnl_expr *e,
int type)
267 NFTNL_BUF_INIT(b, buf, len);
269 if (e->flags & (1 << NFTNL_EXPR_EXTHDR_DREG))
270 nftnl_buf_u32(&b, type, exthdr->dreg, DREG);
271 if (e->flags & (1 << NFTNL_EXPR_EXTHDR_TYPE))
272 nftnl_buf_str(&b, type, type2str(exthdr->type), EXTHDR_TYPE);
273 if (e->flags & (1 << NFTNL_EXPR_EXTHDR_OFFSET))
274 nftnl_buf_u32(&b, type, exthdr->offset, OFFSET);
275 if (e->flags & (1 << NFTNL_EXPR_EXTHDR_LEN))
276 nftnl_buf_u32(&b, type, exthdr->len, LEN);
278 return nftnl_buf_done(&b);
281 static int nftnl_expr_exthdr_snprintf_default(
char *buf,
size_t len,
282 const struct nftnl_expr *e)
286 return snprintf(buf, len,
"load %ub @ %u + %u => reg %u ",
287 exthdr->len, exthdr->type, exthdr->offset,
292 nftnl_expr_exthdr_snprintf(
char *buf,
size_t len, uint32_t type,
293 uint32_t flags,
const struct nftnl_expr *e)
296 case NFTNL_OUTPUT_DEFAULT:
297 return nftnl_expr_exthdr_snprintf_default(buf, len, e);
298 case NFTNL_OUTPUT_XML:
299 case NFTNL_OUTPUT_JSON:
300 return nftnl_expr_exthdr_export(buf, len, e, type);
307 struct expr_ops expr_ops_exthdr = {
310 .max_attr = NFTA_EXTHDR_MAX,
311 .set = nftnl_expr_exthdr_set,
312 .get = nftnl_expr_exthdr_get,
313 .parse = nftnl_expr_exthdr_parse,
314 .build = nftnl_expr_exthdr_build,
315 .snprintf = nftnl_expr_exthdr_snprintf,
316 .xml_parse = nftnl_expr_exthdr_xml_parse,
317 .json_parse = nftnl_expr_exthdr_json_parse,