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;
38nftnl_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 memcpy(&nat->type, data,
sizeof(nat->type));
47 case NFTNL_EXPR_NAT_FAMILY:
48 memcpy(&nat->family, data,
sizeof(nat->family));
50 case NFTNL_EXPR_NAT_REG_ADDR_MIN:
51 memcpy(&nat->sreg_addr_min, data,
sizeof(nat->sreg_addr_min));
53 case NFTNL_EXPR_NAT_REG_ADDR_MAX:
54 memcpy(&nat->sreg_addr_max, data,
sizeof(nat->sreg_addr_max));
56 case NFTNL_EXPR_NAT_REG_PROTO_MIN:
57 memcpy(&nat->sreg_proto_min, data,
sizeof(nat->sreg_proto_min));
59 case NFTNL_EXPR_NAT_REG_PROTO_MAX:
60 memcpy(&nat->sreg_proto_max, data,
sizeof(nat->sreg_proto_max));
62 case NFTNL_EXPR_NAT_FLAGS:
63 memcpy(&nat->flags, data,
sizeof(nat->flags));
73nftnl_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);
104static 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)
130nftnl_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);
175nftnl_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));
199static inline const char *nat2str(uint16_t nat)
211static inline int nftnl_str2nat(
const char *nat)
213 if (strcmp(nat,
"snat") == 0)
215 else if (strcmp(nat,
"dnat") == 0)
224nftnl_expr_nat_snprintf(
char *buf,
size_t remain,
225 uint32_t flags,
const struct nftnl_expr *e)
228 int offset = 0, ret = 0;
230 ret = snprintf(buf, remain,
"%s ", nat2str(nat->type));
231 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
233 ret = snprintf(buf + offset, remain,
"%s ",
234 nftnl_family2str(nat->family));
235 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
237 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN)) {
238 ret = snprintf(buf + offset, remain,
239 "addr_min reg %u ", nat->sreg_addr_min);
240 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
243 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX)) {
244 ret = snprintf(buf + offset, remain,
245 "addr_max reg %u ", nat->sreg_addr_max);
246 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
249 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN)) {
250 ret = snprintf(buf + offset, remain,
251 "proto_min reg %u ", nat->sreg_proto_min);
252 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
255 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX)) {
256 ret = snprintf(buf + offset, remain,
257 "proto_max reg %u ", nat->sreg_proto_max);
258 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
261 if (e->flags & (1 << NFTNL_EXPR_NAT_FLAGS)) {
262 ret = snprintf(buf + offset, remain,
"flags 0x%x ", nat->flags);
263 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
269struct expr_ops expr_ops_nat = {
272 .max_attr = NFTA_NAT_MAX,
273 .set = nftnl_expr_nat_set,
274 .get = nftnl_expr_nat_get,
275 .parse = nftnl_expr_nat_parse,
276 .build = nftnl_expr_nat_build,
277 .output = nftnl_expr_nat_snprintf,