21 #include <arpa/inet.h>
22 #include <libmnl/libmnl.h>
23 #include <linux/netfilter/nf_tables.h>
24 #include <libnftnl/expr.h>
25 #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;
38 nftnl_expr_nat_set(
struct nftnl_expr *e, uint16_t type,
39 const void *data, uint32_t data_len)
44 case NFTNL_EXPR_NAT_TYPE:
45 nat->type = *((uint32_t *)data);
47 case NFTNL_EXPR_NAT_FAMILY:
48 nat->family = *((uint32_t *)data);
50 case NFTNL_EXPR_NAT_REG_ADDR_MIN:
51 nat->sreg_addr_min = *((uint32_t *)data);
53 case NFTNL_EXPR_NAT_REG_ADDR_MAX:
54 nat->sreg_addr_max = *((uint32_t *)data);
56 case NFTNL_EXPR_NAT_REG_PROTO_MIN:
57 nat->sreg_proto_min = *((uint32_t *)data);
59 case NFTNL_EXPR_NAT_REG_PROTO_MAX:
60 nat->sreg_proto_max = *((uint32_t *)data);
62 case NFTNL_EXPR_NAT_FLAGS:
63 nat->flags = *((uint32_t *)data);
73 nftnl_expr_nat_get(
const struct nftnl_expr *e, uint16_t type,
79 case NFTNL_EXPR_NAT_TYPE:
80 *data_len =
sizeof(nat->type);
82 case NFTNL_EXPR_NAT_FAMILY:
83 *data_len =
sizeof(nat->family);
85 case NFTNL_EXPR_NAT_REG_ADDR_MIN:
86 *data_len =
sizeof(nat->sreg_addr_min);
87 return &nat->sreg_addr_min;
88 case NFTNL_EXPR_NAT_REG_ADDR_MAX:
89 *data_len =
sizeof(nat->sreg_addr_max);
90 return &nat->sreg_addr_max;
91 case NFTNL_EXPR_NAT_REG_PROTO_MIN:
92 *data_len =
sizeof(nat->sreg_proto_min);
93 return &nat->sreg_proto_min;
94 case NFTNL_EXPR_NAT_REG_PROTO_MAX:
95 *data_len =
sizeof(nat->sreg_proto_max);
96 return &nat->sreg_proto_max;
97 case NFTNL_EXPR_NAT_FLAGS:
98 *data_len =
sizeof(nat->flags);
104 static int nftnl_expr_nat_cb(
const struct nlattr *attr,
void *data)
106 const struct nlattr **tb = data;
107 int type = mnl_attr_get_type(attr);
109 if (mnl_attr_type_valid(attr, NFTA_NAT_MAX) < 0)
114 case NFTA_NAT_FAMILY:
115 case NFTA_NAT_REG_ADDR_MIN:
116 case NFTA_NAT_REG_ADDR_MAX:
117 case NFTA_NAT_REG_PROTO_MIN:
118 case NFTA_NAT_REG_PROTO_MAX:
120 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
130 nftnl_expr_nat_parse(
struct nftnl_expr *e,
struct nlattr *attr)
133 struct nlattr *tb[NFTA_NAT_MAX+1] = {};
135 if (mnl_attr_parse_nested(attr, nftnl_expr_nat_cb, tb) < 0)
138 if (tb[NFTA_NAT_TYPE]) {
139 nat->type = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_TYPE]));
140 e->flags |= (1 << NFTNL_EXPR_NAT_TYPE);
142 if (tb[NFTA_NAT_FAMILY]) {
143 nat->family = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_FAMILY]));
144 e->flags |= (1 << NFTNL_EXPR_NAT_FAMILY);
146 if (tb[NFTA_NAT_REG_ADDR_MIN]) {
148 ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_ADDR_MIN]));
149 e->flags |= (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN);
151 if (tb[NFTA_NAT_REG_ADDR_MAX]) {
153 ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_ADDR_MAX]));
154 e->flags |= (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX);
156 if (tb[NFTA_NAT_REG_PROTO_MIN]) {
157 nat->sreg_proto_min =
158 ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_PROTO_MIN]));
159 e->flags |= (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN);
161 if (tb[NFTA_NAT_REG_PROTO_MAX]) {
162 nat->sreg_proto_max =
163 ntohl(mnl_attr_get_u32(tb[NFTA_NAT_REG_PROTO_MAX]));
164 e->flags |= (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX);
166 if (tb[NFTA_NAT_FLAGS]) {
167 nat->flags = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_FLAGS]));
168 e->flags |= (1 << NFTNL_EXPR_NAT_FLAGS);
175 nftnl_expr_nat_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
179 if (e->flags & (1 << NFTNL_EXPR_NAT_TYPE))
180 mnl_attr_put_u32(nlh, NFTA_NAT_TYPE, htonl(nat->type));
181 if (e->flags & (1 << NFTNL_EXPR_NAT_FAMILY))
182 mnl_attr_put_u32(nlh, NFTA_NAT_FAMILY, htonl(nat->family));
183 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN))
184 mnl_attr_put_u32(nlh, NFTA_NAT_REG_ADDR_MIN,
185 htonl(nat->sreg_addr_min));
186 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX))
187 mnl_attr_put_u32(nlh, NFTA_NAT_REG_ADDR_MAX,
188 htonl(nat->sreg_addr_max));
189 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN))
190 mnl_attr_put_u32(nlh, NFTA_NAT_REG_PROTO_MIN,
191 htonl(nat->sreg_proto_min));
192 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX))
193 mnl_attr_put_u32(nlh, NFTA_NAT_REG_PROTO_MAX,
194 htonl(nat->sreg_proto_max));
195 if (e->flags & (1 << NFTNL_EXPR_NAT_FLAGS))
196 mnl_attr_put_u32(nlh, NFTA_NAT_FLAGS, htonl(nat->flags));
199 static inline const char *nat2str(uint16_t nat)
211 static inline int nftnl_str2nat(
const char *nat)
213 if (strcmp(nat,
"snat") == 0)
215 else if (strcmp(nat,
"dnat") == 0)
223 static int nftnl_expr_nat_json_parse(
struct nftnl_expr *e, json_t *root,
224 struct nftnl_parse_err *err)
227 const char *nat_type, *family_str;
231 nat_type = nftnl_jansson_parse_str(root,
"nat_type", err);
232 if (nat_type == NULL)
235 val32 = nftnl_str2nat(nat_type);
239 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_TYPE, val32);
241 family_str = nftnl_jansson_parse_str(root,
"family", err);
242 if (family_str == NULL)
245 val32 = nftnl_str2family(family_str);
249 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_FAMILY, val32);
251 if (nftnl_jansson_parse_reg(root,
"sreg_addr_min", NFTNL_TYPE_U32,
253 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_REG_ADDR_MIN, reg);
255 if (nftnl_jansson_parse_reg(root,
"sreg_addr_max", NFTNL_TYPE_U32,
257 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_REG_ADDR_MAX, reg);
259 if (nftnl_jansson_parse_reg(root,
"sreg_proto_min", NFTNL_TYPE_U32,
261 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_REG_PROTO_MIN, reg);
263 if (nftnl_jansson_parse_reg(root,
"sreg_proto_max", NFTNL_TYPE_U32,
265 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_REG_PROTO_MAX, reg);
267 if (nftnl_jansson_parse_val(root,
"flags", NFTNL_TYPE_U32,
269 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_FLAGS, flags);
278 static int nftnl_expr_nat_xml_parse(
struct nftnl_expr *e, mxml_node_t *tree,
279 struct nftnl_parse_err *err)
282 const char *nat_type;
283 uint32_t family, nat_type_value, flags;
284 uint32_t reg_addr_min, reg_addr_max;
285 uint32_t reg_proto_min, reg_proto_max;
287 nat_type = nftnl_mxml_str_parse(tree,
"nat_type", MXML_DESCEND_FIRST,
288 NFTNL_XML_MAND, err);
289 if (nat_type == NULL)
292 nat_type_value = nftnl_str2nat(nat_type);
293 if (nat_type_value < 0)
295 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_TYPE, nat_type_value);
297 family = nftnl_mxml_family_parse(tree,
"family", MXML_DESCEND_FIRST,
298 NFTNL_XML_MAND, err);
303 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_FAMILY, family);
305 if (nftnl_mxml_reg_parse(tree,
"sreg_addr_min", ®_addr_min,
306 MXML_DESCEND, NFTNL_XML_MAND, err) == 0)
307 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_REG_ADDR_MIN, reg_addr_min);
309 if (nftnl_mxml_reg_parse(tree,
"sreg_addr_max", ®_addr_max,
310 MXML_DESCEND, NFTNL_XML_MAND, err) == 0)
311 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_REG_ADDR_MAX, reg_addr_max);
313 if (nftnl_mxml_reg_parse(tree,
"sreg_proto_min", ®_proto_min,
314 MXML_DESCEND, NFTNL_XML_MAND, err) == 0)
315 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_REG_PROTO_MIN, reg_proto_min);
317 if (nftnl_mxml_reg_parse(tree,
"sreg_proto_max", ®_proto_max,
318 MXML_DESCEND, NFTNL_XML_MAND, err) == 0)
319 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_REG_PROTO_MAX, reg_proto_max);
321 if (nftnl_mxml_num_parse(tree,
"flags", MXML_DESCEND, BASE_DEC, &flags,
322 NFTNL_TYPE_U32, NFTNL_XML_MAND, err) == 0)
323 nftnl_expr_set_u32(e, NFTNL_EXPR_NAT_FLAGS, flags);
332 static int nftnl_expr_nat_export(
char *buf,
size_t size,
333 const struct nftnl_expr *e,
int type)
336 NFTNL_BUF_INIT(b, buf, size);
338 if (e->flags & (1 << NFTNL_EXPR_NAT_TYPE))
339 nftnl_buf_str(&b, type, nat2str(nat->type), NAT_TYPE);
340 if (e->flags & (1 << NFTNL_EXPR_NAT_FAMILY))
341 nftnl_buf_str(&b, type, nftnl_family2str(nat->family), FAMILY);
342 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN))
343 nftnl_buf_u32(&b, type, nat->sreg_addr_min, SREG_ADDR_MIN);
344 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX))
345 nftnl_buf_u32(&b, type, nat->sreg_addr_max, SREG_ADDR_MAX);
346 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN))
347 nftnl_buf_u32(&b, type, nat->sreg_proto_min, SREG_PROTO_MIN);
348 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX))
349 nftnl_buf_u32(&b, type, nat->sreg_proto_max, SREG_PROTO_MAX);
350 if (e->flags & (1 << NFTNL_EXPR_NAT_FLAGS))
351 nftnl_buf_u32(&b, type, nat->flags, FLAGS);
353 return nftnl_buf_done(&b);
357 nftnl_expr_nat_snprintf_default(
char *buf,
size_t size,
358 const struct nftnl_expr *e)
361 int len = size, offset = 0, ret = 0;
363 ret = snprintf(buf, len,
"%s ", nat2str(nat->type));
364 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
366 ret = snprintf(buf+offset, len,
"%s ", nftnl_family2str(nat->family));
367 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
369 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN)) {
370 ret = snprintf(buf+offset, len,
371 "addr_min reg %u addr_max reg %u ",
372 nat->sreg_addr_min, nat->sreg_addr_max);
373 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
376 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN)) {
377 ret = snprintf(buf+offset, len,
378 "proto_min reg %u proto_max reg %u ",
379 nat->sreg_proto_min, nat->sreg_proto_max);
380 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
383 if (e->flags & (1 << NFTNL_EXPR_NAT_FLAGS)) {
384 ret = snprintf(buf+offset, len,
"flags %u", nat->flags);
385 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
392 nftnl_expr_nat_snprintf(
char *buf,
size_t size, uint32_t type,
393 uint32_t flags,
const struct nftnl_expr *e)
396 case NFTNL_OUTPUT_DEFAULT:
397 return nftnl_expr_nat_snprintf_default(buf, size, e);
398 case NFTNL_OUTPUT_XML:
399 case NFTNL_OUTPUT_JSON:
400 return nftnl_expr_nat_export(buf, size, e, type);
407 struct expr_ops expr_ops_nat = {
410 .max_attr = NFTA_NAT_MAX,
411 .set = nftnl_expr_nat_set,
412 .get = nftnl_expr_nat_get,
413 .parse = nftnl_expr_nat_parse,
414 .build = nftnl_expr_nat_build,
415 .snprintf = nftnl_expr_nat_snprintf,
416 .xml_parse = nftnl_expr_nat_xml_parse,
417 .json_parse = nftnl_expr_nat_json_parse,