20 #include <arpa/inet.h>
21 #include <libmnl/libmnl.h>
22 #include <linux/netfilter/nf_tables.h>
23 #include <libnftnl/expr.h>
24 #include <libnftnl/rule.h>
28 enum nft_registers sreg_addr_min;
29 enum nft_registers sreg_addr_max;
30 enum nft_registers sreg_proto_min;
31 enum nft_registers sreg_proto_max;
33 enum nft_nat_types type;
37 nft_rule_expr_nat_set(
struct nft_rule_expr *e, uint16_t type,
38 const void *data, uint32_t data_len)
43 case NFT_EXPR_NAT_TYPE:
44 nat->type = *((uint32_t *)data);
46 case NFT_EXPR_NAT_FAMILY:
47 nat->family = *((uint32_t *)data);
49 case NFT_EXPR_NAT_REG_ADDR_MIN:
50 nat->sreg_addr_min = *((uint32_t *)data);
52 case NFT_EXPR_NAT_REG_ADDR_MAX:
53 nat->sreg_addr_max = *((uint32_t *)data);
55 case NFT_EXPR_NAT_REG_PROTO_MIN:
56 nat->sreg_proto_min = *((uint32_t *)data);
58 case NFT_EXPR_NAT_REG_PROTO_MAX:
59 nat->sreg_proto_max = *((uint32_t *)data);
69 nft_rule_expr_nat_get(
const struct nft_rule_expr *e, uint16_t type,
75 case NFT_EXPR_NAT_TYPE:
76 *data_len =
sizeof(nat->type);
78 case NFT_EXPR_NAT_FAMILY:
79 *data_len =
sizeof(nat->family);
81 case NFT_EXPR_NAT_REG_ADDR_MIN:
82 *data_len =
sizeof(nat->sreg_addr_min);
83 return &nat->sreg_addr_min;
84 case NFT_EXPR_NAT_REG_ADDR_MAX:
85 *data_len =
sizeof(nat->sreg_addr_max);
86 return &nat->sreg_addr_max;
87 case NFT_EXPR_NAT_REG_PROTO_MIN:
88 *data_len =
sizeof(nat->sreg_proto_min);
89 return &nat->sreg_proto_min;
90 case NFT_EXPR_NAT_REG_PROTO_MAX:
91 *data_len =
sizeof(nat->sreg_proto_max);
92 return &nat->sreg_proto_max;
97 static int nft_rule_expr_nat_cb(
const struct nlattr *attr,
void *data)
99 const struct nlattr **tb = data;
100 int type = mnl_attr_get_type(attr);
102 if (mnl_attr_type_valid(attr, NFTA_NAT_MAX) < 0)
107 case NFTA_NAT_FAMILY:
108 case NFTA_NAT_REG_ADDR_MIN:
109 case NFTA_NAT_REG_ADDR_MAX:
110 case NFTA_NAT_REG_PROTO_MIN:
111 case NFTA_NAT_REG_PROTO_MAX:
112 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
113 perror(
"mnl_attr_validate");
124 nft_rule_expr_nat_parse(
struct nft_rule_expr *e,
struct nlattr *attr)
127 struct nlattr *tb[NFTA_NAT_MAX+1] = {};
129 if (mnl_attr_parse_nested(attr, nft_rule_expr_nat_cb, tb) < 0)
132 if (tb[NFTA_NAT_TYPE]) {
133 nat->type = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_TYPE]));
134 e->flags |= (1 << NFT_EXPR_NAT_TYPE);
136 if (tb[NFTA_NAT_FAMILY]) {
137 nat->family = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_FAMILY]));
138 e->flags |= (1 << NFT_EXPR_NAT_FAMILY);
140 if (tb[NFTA_NAT_REG_ADDR_MIN]) {
142 ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_ADDR_MIN]));
143 e->flags |= (1 << NFT_EXPR_NAT_REG_ADDR_MIN);
145 if (tb[NFTA_NAT_REG_ADDR_MAX]) {
147 ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_ADDR_MAX]));
148 e->flags |= (1 << NFT_EXPR_NAT_REG_ADDR_MAX);
150 if (tb[NFTA_NAT_REG_PROTO_MIN]) {
151 nat->sreg_proto_min =
152 ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_PROTO_MIN]));
153 e->flags |= (1 << NFT_EXPR_NAT_REG_PROTO_MIN);
155 if (tb[NFTA_NAT_REG_PROTO_MAX]) {
156 nat->sreg_proto_max =
157 ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_PROTO_MAX]));
158 e->flags |= (1 << NFT_EXPR_NAT_REG_PROTO_MAX);
165 nft_rule_expr_nat_build(
struct nlmsghdr *nlh,
struct nft_rule_expr *e)
169 if (e->flags & (1 << NFT_EXPR_NAT_TYPE))
170 mnl_attr_put_u32(nlh, NFTA_NAT_TYPE, htonl(nat->type));
171 if (e->flags & (1 << NFT_EXPR_NAT_FAMILY))
172 mnl_attr_put_u32(nlh, NFTA_NAT_FAMILY, htonl(nat->family));
173 if (e->flags & (1 << NFT_EXPR_NAT_REG_ADDR_MIN))
174 mnl_attr_put_u32(nlh, NFTA_NAT_REG_ADDR_MIN,
175 htonl(nat->sreg_addr_min));
176 if (e->flags & (1 << NFT_EXPR_NAT_REG_ADDR_MAX))
177 mnl_attr_put_u32(nlh, NFTA_NAT_REG_ADDR_MAX,
178 htonl(nat->sreg_addr_max));
179 if (e->flags & (1 << NFT_EXPR_NAT_REG_PROTO_MIN))
180 mnl_attr_put_u32(nlh, NFTA_NAT_REG_PROTO_MIN,
181 htonl(nat->sreg_proto_min));
182 if (e->flags & (1 << NFT_EXPR_NAT_REG_PROTO_MAX))
183 mnl_attr_put_u32(nlh, NFTA_NAT_REG_PROTO_MAX,
184 htonl(nat->sreg_proto_max));
187 static inline const char *nft_nat2str(uint16_t nat)
199 static inline int nft_str2nat(
const char *nat)
201 if (strcmp(nat,
"snat") == 0)
203 else if (strcmp(nat,
"dnat") == 0)
211 static int nft_rule_expr_nat_json_parse(
struct nft_rule_expr *e, json_t *root,
212 struct nft_parse_err *err)
215 const char *nat_type, *family_str;
219 nat_type = nft_jansson_parse_str(root,
"nat_type", err);
220 if (nat_type == NULL)
223 val32 = nft_str2nat(nat_type);
227 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_TYPE, val32);
229 family_str = nft_jansson_parse_str(root,
"family", err);
230 if (family_str == NULL)
233 val32 = nft_str2family(family_str);
237 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_FAMILY, val32);
239 if (nft_jansson_parse_reg(root,
"sreg_addr_min", NFT_TYPE_U32,
241 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_ADDR_MIN, reg);
243 if (nft_jansson_parse_reg(root,
"sreg_addr_max", NFT_TYPE_U32,
245 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_ADDR_MAX, reg);
247 if (nft_jansson_parse_reg(root,
"sreg_proto_min", NFT_TYPE_U32,
249 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_PROTO_MIN, reg);
251 if (nft_jansson_parse_reg(root,
"sreg_proto_max", NFT_TYPE_U32,
253 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_PROTO_MAX, reg);
262 static int nft_rule_expr_nat_xml_parse(
struct nft_rule_expr *e, mxml_node_t *tree,
263 struct nft_parse_err *err)
266 const char *nat_type;
267 uint32_t family, nat_type_value;
268 uint32_t reg_addr_min, reg_addr_max;
269 uint32_t reg_proto_min, reg_proto_max;
271 nat_type = nft_mxml_str_parse(tree,
"type", MXML_DESCEND_FIRST,
273 if (nat_type == NULL)
276 nat_type_value = nft_str2nat(nat_type);
277 if (nat_type_value < 0)
279 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_TYPE, nat_type_value);
281 family = nft_mxml_family_parse(tree,
"family", MXML_DESCEND_FIRST,
287 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_FAMILY, family);
289 if (nft_mxml_reg_parse(tree,
"sreg_addr_min", ®_addr_min,
290 MXML_DESCEND, NFT_XML_MAND, err) == 0)
291 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_ADDR_MIN, reg_addr_min);
293 if (nft_mxml_reg_parse(tree,
"sreg_addr_max", ®_addr_max,
294 MXML_DESCEND, NFT_XML_MAND, err) == 0)
295 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_ADDR_MAX, reg_addr_max);
297 if (nft_mxml_reg_parse(tree,
"sreg_proto_min", ®_proto_min,
298 MXML_DESCEND, NFT_XML_MAND, err) == 0)
299 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_PROTO_MIN, reg_proto_min);
301 if (nft_mxml_reg_parse(tree,
"sreg_proto_max", ®_proto_max,
302 MXML_DESCEND, NFT_XML_MAND, err) == 0)
303 nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_PROTO_MAX, reg_proto_max);
313 nft_rule_expr_nat_snprintf_json(
char *buf,
size_t size,
314 struct nft_rule_expr *e)
317 int len = size, offset = 0, ret = 0;
319 ret = snprintf(buf, len,
"\"nat_type\":\"%s\",",
320 nft_nat2str(nat->type));
321 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
323 ret = snprintf(buf+offset, len,
"\"family\":\"%s\",",
324 nft_family2str(nat->family));
325 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
327 if (e->flags & (1 << NFT_EXPR_NAT_REG_ADDR_MIN)) {
328 ret = snprintf(buf+offset, len,
"\"sreg_addr_min\":%u,"
329 "\"sreg_addr_max\":%u,",
330 nat->sreg_addr_min, nat->sreg_addr_max);
331 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
334 if (e->flags & (1 << NFT_EXPR_NAT_REG_PROTO_MIN)) {
335 ret = snprintf(buf+offset, len,
"\"sreg_proto_min\":%u,"
336 "\"sreg_proto_max\":%u",
337 nat->sreg_proto_min, nat->sreg_proto_max);
338 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
346 nft_rule_expr_nat_snprintf_xml(
char *buf,
size_t size,
347 struct nft_rule_expr *e)
350 int len = size, offset = 0, ret = 0;
352 ret = snprintf(buf, len,
"<type>%s</type>", nft_nat2str(nat->type));
353 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
355 ret = snprintf(buf+offset, len,
"<family>%s</family>",
356 nft_family2str(nat->family));
357 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
359 if (e->flags & (1 << NFT_EXPR_NAT_REG_ADDR_MIN)) {
360 ret = snprintf(buf+offset, len,
361 "<sreg_addr_min>%u</sreg_addr_min>"
362 "<sreg_addr_max>%u</sreg_addr_max>",
363 nat->sreg_addr_min, nat->sreg_addr_max);
364 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
367 if (e->flags & (1 << NFT_EXPR_NAT_REG_PROTO_MIN)) {
368 ret = snprintf(buf+offset, len,
369 "<sreg_proto_min>%u</sreg_proto_min>"
370 "<sreg_proto_max>%u</sreg_proto_max>",
371 nat->sreg_proto_min, nat->sreg_proto_max);
372 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
379 nft_rule_expr_nat_snprintf_default(
char *buf,
size_t size,
380 struct nft_rule_expr *e)
383 int len = size, offset = 0, ret = 0;
385 ret = snprintf(buf, len,
"%s ", nft_nat2str(nat->type));
386 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
388 ret = snprintf(buf+offset, len,
"%s ", nft_family2str(nat->family));
389 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
391 if (e->flags & (1 << NFT_EXPR_NAT_REG_ADDR_MIN)) {
392 ret = snprintf(buf+offset, len,
393 "addr_min reg %u addr_max reg %u ",
394 nat->sreg_addr_min, nat->sreg_addr_max);
395 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
398 if (e->flags & (1 << NFT_EXPR_NAT_REG_PROTO_MIN)) {
399 ret = snprintf(buf+offset, len,
400 "proto_min reg %u proto_max reg %u ",
401 nat->sreg_proto_min, nat->sreg_proto_max);
402 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
409 nft_rule_expr_nat_snprintf(
char *buf,
size_t size, uint32_t type,
410 uint32_t flags,
struct nft_rule_expr *e)
413 case NFT_OUTPUT_DEFAULT:
414 return nft_rule_expr_nat_snprintf_default(buf, size, e);
416 return nft_rule_expr_nat_snprintf_xml(buf, size, e);
417 case NFT_OUTPUT_JSON:
418 return nft_rule_expr_nat_snprintf_json(buf, size, e);
425 struct expr_ops expr_ops_nat = {
428 .max_attr = NFTA_NAT_MAX,
429 .set = nft_rule_expr_nat_set,
430 .get = nft_rule_expr_nat_get,
431 .parse = nft_rule_expr_nat_parse,
432 .build = nft_rule_expr_nat_build,
433 .snprintf = nft_rule_expr_nat_snprintf,
434 .xml_parse = nft_rule_expr_nat_xml_parse,
435 .json_parse = nft_rule_expr_nat_json_parse,
438 static void __init expr_nat_init(
void)
440 nft_expr_ops_register(&expr_ops_nat);