17 #include <netinet/in.h>
20 #include <linux/netfilter.h>
21 #include <linux/netfilter/nf_tables.h>
23 #include <libmnl/libmnl.h>
24 #include <libnftnl/common.h>
25 #include <libnftnl/ruleset.h>
26 #include <libnftnl/table.h>
27 #include <libnftnl/chain.h>
28 #include <libnftnl/set.h>
29 #include <libnftnl/rule.h>
33 static void memory_allocation_error(
void)
40 mnl_talk(
struct mnl_socket *nf_sock,
const void *data,
unsigned int len,
41 int (*cb)(
const struct nlmsghdr *nlh,
void *data),
void *cb_data)
43 char buf[MNL_SOCKET_BUFFER_SIZE];
44 uint32_t portid = mnl_socket_get_portid(nf_sock);
47 if (mnl_socket_sendto(nf_sock, data, len) < 0)
50 ret = mnl_socket_recvfrom(nf_sock, buf,
sizeof(buf));
52 ret = mnl_cb_run(buf, ret, seq, portid, cb, cb_data);
56 ret = mnl_socket_recvfrom(nf_sock, buf,
sizeof(buf));
59 if (ret < 0 && errno == EAGAIN)
68 static int rule_cb(
const struct nlmsghdr *nlh,
void *data)
75 memory_allocation_error();
77 if (nft_rule_nlmsg_parse(nlh, r) < 0)
80 nft_rule_list_add_tail(r, nlr_list);
88 static struct nft_rule_list *mnl_rule_dump(
struct mnl_socket *nf_sock,
91 char buf[MNL_SOCKET_BUFFER_SIZE];
96 nlr_list = nft_rule_list_alloc();
98 memory_allocation_error();
100 nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family,
103 ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, rule_cb, nlr_list);
109 nft_rule_list_free(nlr_list);
116 static int chain_cb(
const struct nlmsghdr *nlh,
void *data)
121 c = nft_chain_alloc();
123 memory_allocation_error();
125 if (nft_chain_nlmsg_parse(nlh, c) < 0)
128 nft_chain_list_add_tail(c, nlc_list);
136 static struct nft_chain_list *mnl_chain_dump(
struct mnl_socket *nf_sock,
139 char buf[MNL_SOCKET_BUFFER_SIZE];
140 struct nlmsghdr *nlh;
144 nlc_list = nft_chain_list_alloc();
145 if (nlc_list == NULL)
146 memory_allocation_error();
148 nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family,
151 ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, chain_cb, nlc_list);
157 nft_chain_list_free(nlc_list);
164 static int table_cb(
const struct nlmsghdr *nlh,
void *data)
169 t = nft_table_alloc();
171 memory_allocation_error();
173 if (nft_table_nlmsg_parse(nlh, t) < 0)
176 nft_table_list_add_tail(t, nlt_list);
184 static struct nft_table_list *mnl_table_dump(
struct mnl_socket *nf_sock,
187 char buf[MNL_SOCKET_BUFFER_SIZE];
188 struct nlmsghdr *nlh;
192 nlt_list = nft_table_list_alloc();
193 if (nlt_list == NULL)
194 memory_allocation_error();
196 nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family,
199 ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, table_cb, nlt_list);
205 nft_table_list_free(nlt_list);
212 static int set_elem_cb(
const struct nlmsghdr *nlh,
void *data)
214 nft_set_elems_nlmsg_parse(nlh, data);
218 static int mnl_setelem_get(
struct mnl_socket *nf_sock,
struct nft_set *nls)
220 char buf[MNL_SOCKET_BUFFER_SIZE];
221 struct nlmsghdr *nlh;
222 uint32_t family = nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY);
224 nlh = nft_set_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM, family,
225 NLM_F_DUMP|NLM_F_ACK, seq);
226 nft_set_nlmsg_build_payload(nlh, nls);
228 return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_elem_cb, nls);
234 static int set_cb(
const struct nlmsghdr *nlh,
void *data)
241 memory_allocation_error();
243 if (nft_set_nlmsg_parse(nlh, s) < 0)
246 nft_set_list_add_tail(s, nls_list);
255 mnl_set_dump(
struct mnl_socket *nf_sock,
int family)
257 char buf[MNL_SOCKET_BUFFER_SIZE];
258 struct nlmsghdr *nlh;
267 memory_allocation_error();
269 nlh = nft_set_nlmsg_build_hdr(buf, NFT_MSG_GETSET, family,
270 NLM_F_DUMP|NLM_F_ACK, seq);
271 nft_set_nlmsg_build_payload(nlh, s);
274 nls_list = nft_set_list_alloc();
275 if (nls_list == NULL)
276 memory_allocation_error();
278 ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_cb, nls_list);
282 i = nft_set_list_iter_create(nls_list);
284 memory_allocation_error();
286 si = nft_set_list_iter_next(i);
288 if (mnl_setelem_get(nf_sock, si) != 0) {
289 perror(
"E: Unable to get set elements");
290 nft_set_list_iter_destroy(i);
293 si = nft_set_list_iter_next(i);
296 nft_set_list_iter_destroy(i);
300 nft_set_list_free(nls_list);
308 static struct nft_ruleset *mnl_ruleset_dump(
struct mnl_socket *nf_sock)
316 rs = nft_ruleset_alloc();
318 memory_allocation_error();
320 t = mnl_table_dump(nf_sock, NFPROTO_UNSPEC);
322 nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_TABLELIST, t);
324 c = mnl_chain_dump(nf_sock, NFPROTO_UNSPEC);
326 nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_CHAINLIST, c);
328 s = mnl_set_dump(nf_sock, NFPROTO_UNSPEC);
330 nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_SETLIST, s);
332 r = mnl_rule_dump(nf_sock, NFPROTO_UNSPEC);
334 nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_RULELIST, r);
339 int main(
int argc,
char *argv[])
341 struct mnl_socket *nl;
342 uint32_t type = NFT_OUTPUT_DEFAULT;
347 fprintf(stderr,
"%s {xml|json}\n",
353 if (strcmp(argv[1],
"xml") == 0)
354 type = NFT_OUTPUT_XML;
355 else if (strcmp(argv[1],
"json") == 0)
356 type = NFT_OUTPUT_JSON;
358 fprintf(stderr,
"Unknown type: {xml|json}\n");
363 nl = mnl_socket_open(NETLINK_NETFILTER);
365 perror(
"mnl_socket_open");
369 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
370 perror(
"mnl_socket_bind");
376 rs = mnl_ruleset_dump(nl);
378 perror(
"ruleset_dump");
382 ret = nft_ruleset_fprintf(stdout, rs, type, 0);
383 fprintf(stdout,
"\n");
386 perror(
"E: Error during fprintf operations");