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_export(
char *buf,
size_t size,
279 const struct nftnl_expr *e,
int type)
282 NFTNL_BUF_INIT(b, buf, size);
284 if (e->flags & (1 << NFTNL_EXPR_NAT_TYPE))
285 nftnl_buf_str(&b, type, nat2str(nat->type), NAT_TYPE);
286 if (e->flags & (1 << NFTNL_EXPR_NAT_FAMILY))
287 nftnl_buf_str(&b, type, nftnl_family2str(nat->family), FAMILY);
288 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN))
289 nftnl_buf_u32(&b, type, nat->sreg_addr_min, SREG_ADDR_MIN);
290 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX))
291 nftnl_buf_u32(&b, type, nat->sreg_addr_max, SREG_ADDR_MAX);
292 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN))
293 nftnl_buf_u32(&b, type, nat->sreg_proto_min, SREG_PROTO_MIN);
294 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX))
295 nftnl_buf_u32(&b, type, nat->sreg_proto_max, SREG_PROTO_MAX);
296 if (e->flags & (1 << NFTNL_EXPR_NAT_FLAGS))
297 nftnl_buf_u32(&b, type, nat->flags, FLAGS);
299 return nftnl_buf_done(&b);
303 nftnl_expr_nat_snprintf_default(
char *buf,
size_t size,
304 const struct nftnl_expr *e)
307 int remain = size, offset = 0, ret = 0;
309 ret = snprintf(buf, remain,
"%s ", nat2str(nat->type));
310 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
312 ret = snprintf(buf + offset, remain,
"%s ",
313 nftnl_family2str(nat->family));
314 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
316 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN)) {
317 ret = snprintf(buf + offset, remain,
318 "addr_min reg %u addr_max reg %u ",
319 nat->sreg_addr_min, nat->sreg_addr_max);
320 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
323 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN)) {
324 ret = snprintf(buf + offset, remain,
325 "proto_min reg %u proto_max reg %u ",
326 nat->sreg_proto_min, nat->sreg_proto_max);
327 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
330 if (e->flags & (1 << NFTNL_EXPR_NAT_FLAGS)) {
331 ret = snprintf(buf + offset, remain,
"flags %u", nat->flags);
332 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
339 nftnl_expr_nat_snprintf(
char *buf,
size_t size, uint32_t type,
340 uint32_t flags,
const struct nftnl_expr *e)
343 case NFTNL_OUTPUT_DEFAULT:
344 return nftnl_expr_nat_snprintf_default(buf, size, e);
345 case NFTNL_OUTPUT_XML:
346 case NFTNL_OUTPUT_JSON:
347 return nftnl_expr_nat_export(buf, size, e, type);
354 static bool nftnl_expr_nat_cmp(
const struct nftnl_expr *e1,
355 const struct nftnl_expr *e2)
360 if (e1->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN))
361 eq &= (n1->sreg_addr_min == n2->sreg_addr_min);
362 if (e1->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX))
363 eq &= (n1->sreg_addr_max == n2->sreg_addr_max);
364 if (e1->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN))
365 eq &= (n1->sreg_proto_min == n2->sreg_proto_min);
366 if (e1->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX))
367 eq &= (n1->sreg_proto_max == n2->sreg_proto_max);
368 if (e1->flags & (1 << NFTNL_EXPR_NAT_FAMILY))
369 eq &= (n1->family == n2->family);
370 if (e1->flags & (1 << NFTNL_EXPR_NAT_TYPE))
371 eq &= (n1->type == n2->type);
372 if (e1->flags & (1 << NFTNL_EXPR_NAT_FLAGS))
373 eq &= (n1->flags == n2->flags);
378 struct expr_ops expr_ops_nat = {
381 .max_attr = NFTA_NAT_MAX,
382 .cmp = nftnl_expr_nat_cmp,
383 .set = nftnl_expr_nat_set,
384 .get = nftnl_expr_nat_get,
385 .parse = nftnl_expr_nat_parse,
386 .build = nftnl_expr_nat_build,
387 .snprintf = nftnl_expr_nat_snprintf,
388 .json_parse = nftnl_expr_nat_json_parse,