17 #include <arpa/inet.h>
18 #include <libmnl/libmnl.h>
19 #include <linux/netfilter/nf_tables.h>
20 #include <libnftnl/expr.h>
21 #include <libnftnl/rule.h>
24 enum nft_registers sreg_addr_min;
25 enum nft_registers sreg_addr_max;
26 enum nft_registers sreg_proto_min;
27 enum nft_registers sreg_proto_max;
29 enum nft_nat_types type;
34 nftnl_expr_nat_set(
struct nftnl_expr *e, uint16_t type,
35 const void *data, uint32_t data_len)
40 case NFTNL_EXPR_NAT_TYPE:
41 memcpy(&nat->type, data, data_len);
43 case NFTNL_EXPR_NAT_FAMILY:
44 memcpy(&nat->family, data, data_len);
46 case NFTNL_EXPR_NAT_REG_ADDR_MIN:
47 memcpy(&nat->sreg_addr_min, data, data_len);
49 case NFTNL_EXPR_NAT_REG_ADDR_MAX:
50 memcpy(&nat->sreg_addr_max, data, data_len);
52 case NFTNL_EXPR_NAT_REG_PROTO_MIN:
53 memcpy(&nat->sreg_proto_min, data, data_len);
55 case NFTNL_EXPR_NAT_REG_PROTO_MAX:
56 memcpy(&nat->sreg_proto_max, data, data_len);
58 case NFTNL_EXPR_NAT_FLAGS:
59 memcpy(&nat->flags, data, data_len);
67 nftnl_expr_nat_get(
const struct nftnl_expr *e, uint16_t type,
73 case NFTNL_EXPR_NAT_TYPE:
74 *data_len =
sizeof(nat->type);
76 case NFTNL_EXPR_NAT_FAMILY:
77 *data_len =
sizeof(nat->family);
79 case NFTNL_EXPR_NAT_REG_ADDR_MIN:
80 *data_len =
sizeof(nat->sreg_addr_min);
81 return &nat->sreg_addr_min;
82 case NFTNL_EXPR_NAT_REG_ADDR_MAX:
83 *data_len =
sizeof(nat->sreg_addr_max);
84 return &nat->sreg_addr_max;
85 case NFTNL_EXPR_NAT_REG_PROTO_MIN:
86 *data_len =
sizeof(nat->sreg_proto_min);
87 return &nat->sreg_proto_min;
88 case NFTNL_EXPR_NAT_REG_PROTO_MAX:
89 *data_len =
sizeof(nat->sreg_proto_max);
90 return &nat->sreg_proto_max;
91 case NFTNL_EXPR_NAT_FLAGS:
92 *data_len =
sizeof(nat->flags);
98 static int nftnl_expr_nat_cb(
const struct nlattr *attr,
void *data)
100 const struct nlattr **tb = data;
101 int type = mnl_attr_get_type(attr);
103 if (mnl_attr_type_valid(attr, NFTA_NAT_MAX) < 0)
108 case NFTA_NAT_FAMILY:
109 case NFTA_NAT_REG_ADDR_MIN:
110 case NFTA_NAT_REG_ADDR_MAX:
111 case NFTA_NAT_REG_PROTO_MIN:
112 case NFTA_NAT_REG_PROTO_MAX:
114 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
124 nftnl_expr_nat_parse(
struct nftnl_expr *e,
struct nlattr *attr)
127 struct nlattr *tb[NFTA_NAT_MAX+1] = {};
129 if (mnl_attr_parse_nested(attr, nftnl_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 << NFTNL_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 << NFTNL_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 << NFTNL_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 << NFTNL_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 << NFTNL_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 << NFTNL_EXPR_NAT_REG_PROTO_MAX);
160 if (tb[NFTA_NAT_FLAGS]) {
161 nat->flags = ntohl(mnl_attr_get_u32(tb[NFTA_NAT_FLAGS]));
162 e->flags |= (1 << NFTNL_EXPR_NAT_FLAGS);
169 nftnl_expr_nat_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
173 if (e->flags & (1 << NFTNL_EXPR_NAT_TYPE))
174 mnl_attr_put_u32(nlh, NFTA_NAT_TYPE, htonl(nat->type));
175 if (e->flags & (1 << NFTNL_EXPR_NAT_FAMILY))
176 mnl_attr_put_u32(nlh, NFTA_NAT_FAMILY, htonl(nat->family));
177 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN))
178 mnl_attr_put_u32(nlh, NFTA_NAT_REG_ADDR_MIN,
179 htonl(nat->sreg_addr_min));
180 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX))
181 mnl_attr_put_u32(nlh, NFTA_NAT_REG_ADDR_MAX,
182 htonl(nat->sreg_addr_max));
183 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN))
184 mnl_attr_put_u32(nlh, NFTA_NAT_REG_PROTO_MIN,
185 htonl(nat->sreg_proto_min));
186 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX))
187 mnl_attr_put_u32(nlh, NFTA_NAT_REG_PROTO_MAX,
188 htonl(nat->sreg_proto_max));
189 if (e->flags & (1 << NFTNL_EXPR_NAT_FLAGS))
190 mnl_attr_put_u32(nlh, NFTA_NAT_FLAGS, htonl(nat->flags));
193 static inline const char *nat2str(uint16_t nat)
206 nftnl_expr_nat_snprintf(
char *buf,
size_t remain,
207 uint32_t flags,
const struct nftnl_expr *e)
210 int offset = 0, ret = 0;
212 ret = snprintf(buf, remain,
"%s ", nat2str(nat->type));
213 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
215 ret = snprintf(buf + offset, remain,
"%s ",
216 nftnl_family2str(nat->family));
217 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
219 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN)) {
220 ret = snprintf(buf + offset, remain,
221 "addr_min reg %u ", nat->sreg_addr_min);
222 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
225 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX)) {
226 ret = snprintf(buf + offset, remain,
227 "addr_max reg %u ", nat->sreg_addr_max);
228 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
231 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN)) {
232 ret = snprintf(buf + offset, remain,
233 "proto_min reg %u ", nat->sreg_proto_min);
234 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
237 if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX)) {
238 ret = snprintf(buf + offset, remain,
239 "proto_max reg %u ", nat->sreg_proto_max);
240 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
243 if (e->flags & (1 << NFTNL_EXPR_NAT_FLAGS)) {
244 ret = snprintf(buf + offset, remain,
"flags 0x%x ", nat->flags);
245 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
251 static struct attr_policy nat_attr_policy[__NFTNL_EXPR_NAT_MAX] = {
252 [NFTNL_EXPR_NAT_TYPE] = { .maxlen =
sizeof(uint32_t) },
253 [NFTNL_EXPR_NAT_FAMILY] = { .maxlen =
sizeof(uint32_t) },
254 [NFTNL_EXPR_NAT_REG_ADDR_MIN] = { .maxlen =
sizeof(uint32_t) },
255 [NFTNL_EXPR_NAT_REG_ADDR_MAX] = { .maxlen =
sizeof(uint32_t) },
256 [NFTNL_EXPR_NAT_REG_PROTO_MIN] = { .maxlen =
sizeof(uint32_t) },
257 [NFTNL_EXPR_NAT_REG_PROTO_MAX] = { .maxlen =
sizeof(uint32_t) },
258 [NFTNL_EXPR_NAT_FLAGS] = { .maxlen =
sizeof(uint32_t) },
261 struct expr_ops expr_ops_nat = {
264 .nftnl_max_attr = __NFTNL_EXPR_NAT_MAX - 1,
265 .attr_policy = nat_attr_policy,
266 .set = nftnl_expr_nat_set,
267 .get = nftnl_expr_nat_get,
268 .parse = nftnl_expr_nat_parse,
269 .build = nftnl_expr_nat_build,
270 .output = nftnl_expr_nat_snprintf,