14 #include <netinet/in.h>
15 #include <netinet/ip.h>
16 #include <netinet/tcp.h>
17 #include <arpa/inet.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
22 #include <linux/netfilter.h>
23 #include <linux/netfilter/nfnetlink.h>
24 #include <linux/netfilter/nf_tables.h>
26 #include <libmnl/libmnl.h>
27 #include <libnftnl/ruleset.h>
28 #include <libnftnl/table.h>
29 #include <libnftnl/chain.h>
30 #include <libnftnl/rule.h>
31 #include <libnftnl/set.h>
33 struct mnl_nlmsg_batch *batch;
39 uint16_t nl_type, nl_flags;
42 struct nftnl_set *set;
44 cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);
46 set = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET);
52 nl_type = NFT_MSG_NEWSETELEM;
53 nl_flags = NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
55 case NFTNL_CMD_DELETE:
56 nl_type = NFT_MSG_DELSETELEM;
67 iter_elems = nftnl_set_elems_iter_create(set);
68 if (iter_elems == NULL)
71 nlh = nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), nl_type,
72 nftnl_set_get_u32(set,
76 nftnl_set_elems_nlmsg_build_payload_iter(nlh, iter_elems);
77 mnl_nlmsg_batch_next(batch);
79 nftnl_set_elems_iter_destroy(iter_elems);
89 uint16_t nl_type, nl_flags;
90 struct nftnl_set *set;
94 cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);
96 set = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET);
102 nl_type = NFT_MSG_NEWSET;
103 nl_flags = NLM_F_CREATE|NLM_F_ACK;
105 case NFTNL_CMD_DELETE:
106 nl_type = NFT_MSG_DELSET;
107 nl_flags = NLM_F_ACK;
113 nlh = nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
115 nftnl_set_get_u32(set,
120 nftnl_set_nlmsg_build_payload(nlh, set);
121 mnl_nlmsg_batch_next(batch);
123 ret = nftnl_ruleset_set_elems(ctx);
129 static int nftnl_ruleset_rule_build_msg(
const struct nftnl_parse_ctx *ctx,
132 struct nlmsghdr *nlh;
133 uint16_t nl_type, nl_flags;
137 nl_type = NFT_MSG_NEWRULE;
138 nl_flags = NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK;
139 nftnl_rule_unset(rule, NFTNL_RULE_HANDLE);
141 case NFTNL_CMD_DELETE:
142 nl_type = NFT_MSG_DELRULE;
143 nl_flags = NLM_F_ACK;
145 case NFTNL_CMD_REPLACE:
146 nl_type = NFT_MSG_NEWRULE;
147 nl_flags = NLM_F_REPLACE|NLM_F_ACK;
149 case NFTNL_CMD_INSERT:
150 nl_type = NFT_MSG_NEWRULE;
151 nl_flags = NLM_F_CREATE|NLM_F_ACK;
152 nftnl_rule_unset(rule, NFTNL_RULE_HANDLE);
158 nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
160 nftnl_rule_get_u32(rule,
165 nftnl_rule_nlmsg_build_payload(nlh, rule);
166 mnl_nlmsg_batch_next(batch);
177 cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);
179 rule = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_RULE);
183 ret = nftnl_ruleset_rule_build_msg(ctx, cmd, rule);
188 static int nftnl_ruleset_flush_rules(
const struct nftnl_parse_ctx *ctx)
196 nlr = nftnl_rule_alloc();
200 type = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE);
202 case NFTNL_RULESET_TABLE:
203 nlt = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE);
204 nftnl_rule_set(nlr, NFTNL_RULE_TABLE,
205 nftnl_table_get(nlt, NFTNL_TABLE_NAME));
206 nftnl_rule_set(nlr, NFTNL_RULE_FAMILY,
207 nftnl_table_get(nlt, NFTNL_TABLE_FAMILY));
209 case NFTNL_RULESET_CHAIN:
210 nlc = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN);
211 nftnl_rule_set(nlr, NFTNL_RULE_TABLE,
214 nftnl_rule_set(nlr, NFTNL_RULE_CHAIN,
217 nftnl_rule_set(nlr, NFTNL_RULE_FAMILY,
218 nftnl_chain_get(nlc, NFTNL_TABLE_FAMILY));
224 ret = nftnl_ruleset_rule_build_msg(ctx, NFTNL_CMD_DELETE, nlr);
225 nftnl_rule_free(nlr);
229 nftnl_rule_free(nlr);
235 struct nlmsghdr *nlh;
236 uint16_t nl_type, nl_flags;
240 cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);
242 chain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN);
248 nl_type = NFT_MSG_NEWCHAIN;
249 nl_flags = NLM_F_CREATE|NLM_F_ACK;
251 case NFTNL_CMD_DELETE:
252 nl_type = NFT_MSG_DELCHAIN;
253 nl_flags = NLM_F_ACK;
255 case NFTNL_CMD_FLUSH:
256 return nftnl_ruleset_flush_rules(ctx);
261 nftnl_chain_unset(chain, NFTNL_CHAIN_HANDLE);
262 nlh = nftnl_chain_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
264 nftnl_chain_get_u32(chain,
269 nftnl_chain_nlmsg_build_payload(nlh, chain);
270 mnl_nlmsg_batch_next(batch);
277 static int nftnl_ruleset_table_build_msg(
const struct nftnl_parse_ctx *ctx,
280 struct nlmsghdr *nlh;
281 uint16_t nl_type, nl_flags;
285 nl_type = NFT_MSG_NEWTABLE;
286 nl_flags = NLM_F_CREATE|NLM_F_ACK;
288 case NFTNL_CMD_DELETE:
289 nl_type = NFT_MSG_DELTABLE;
290 nl_flags = NLM_F_ACK;
292 case NFTNL_CMD_FLUSH:
293 return nftnl_ruleset_flush_rules(ctx);
298 nlh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
300 nftnl_table_get_u32(table,
305 nftnl_table_nlmsg_build_payload(nlh, table);
306 mnl_nlmsg_batch_next(batch);
317 cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);
319 table = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE);
323 ret = nftnl_ruleset_table_build_msg(ctx, cmd, table);
328 static int nftnl_ruleset_flush_ruleset(
const struct nftnl_parse_ctx *ctx)
333 table = nftnl_table_alloc();
337 ret = nftnl_ruleset_table_build_msg(ctx, NFTNL_CMD_DELETE, table);
338 nftnl_table_free(table);
348 type = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE);
351 case NFTNL_RULESET_TABLE:
352 ret = nftnl_ruleset_table(ctx);
354 case NFTNL_RULESET_CHAIN:
355 ret = nftnl_ruleset_chain(ctx);
357 case NFTNL_RULESET_RULE:
358 ret = nftnl_ruleset_rule(ctx);
360 case NFTNL_RULESET_SET:
361 ret = nftnl_ruleset_parse_set(ctx);
363 case NFTNL_RULESET_SET_ELEMS:
364 ret = nftnl_ruleset_set_elems(ctx);
366 case NFTNL_RULESET_RULESET:
367 ret = nftnl_ruleset_flush_ruleset(ctx);
373 nftnl_ruleset_ctx_free(ctx);
377 int main(
int argc,
char *argv[])
379 struct nftnl_parse_err *err;
380 const char *filename;
382 int ret = -1, len, batching, portid;
383 uint32_t ruleset_seq;
384 char buf[MNL_SOCKET_BUFFER_SIZE];
385 struct mnl_socket *nl;
388 printf(
"Usage: %s <file>\n", argv[0]);
392 fp = fopen(argv[1],
"r");
394 printf(
"unable to open file %s: %s\n", argv[1],
399 err = nftnl_parse_err_alloc();
405 batching = nftnl_batch_is_supported();
407 perror(
"Cannot talk to nfnetlink");
412 batch = mnl_nlmsg_batch_start(buf,
sizeof(buf));
415 nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++);
416 mnl_nlmsg_batch_next(batch);
421 len = strlen(filename);
422 if (len >= 5 && strcmp(&filename[len - 5],
".json") == 0)
423 ret = nftnl_ruleset_parse_file_cb(NFTNL_PARSE_JSON, fp, err, NULL,
425 else if (len >= 4 && strcmp(&filename[len - 4],
".xml") == 0)
426 ret = nftnl_ruleset_parse_file_cb(NFTNL_PARSE_XML, fp, err, NULL,
429 printf(
"the filename %s must to end in .xml or .json\n",
435 nftnl_parse_perror(
"fail", err);
442 nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++);
443 mnl_nlmsg_batch_next(batch);
446 nl = mnl_socket_open(NETLINK_NETFILTER);
448 perror(
"mnl_socket_open");
452 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
453 perror(
"mnl_socket_bind");
456 portid = mnl_socket_get_portid(nl);
458 if (mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch),
459 mnl_nlmsg_batch_size(batch)) < 0) {
460 perror(
"mnl_socket_send");
464 mnl_nlmsg_batch_stop(batch);
466 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
468 ret = mnl_cb_run(buf, ret, ruleset_seq, portid, NULL, NULL);
471 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
478 mnl_socket_close(nl);