libnftnl 1.2.6
nft-ruleset-get.c
1/*
2 * Copyright (c) 2013 Arturo Borrero Gonzalez <arturo@debian.org>
3 *
4 * based on previous code from:
5 *
6 * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org>
7 *
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 */
13
14#include <stdlib.h>
15#include <time.h>
16#include <string.h>
17#include <netinet/in.h>
18#include <errno.h>
19
20#include <linux/netfilter.h>
21#include <linux/netfilter/nf_tables.h>
22
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>
30
31static int seq;
32
33static void memory_allocation_error(void)
34{
35 perror("OOM");
36 exit(EXIT_FAILURE);
37}
38
39static int
40mnl_talk(struct mnl_socket *nf_sock, const void *data, unsigned int len,
41 int (*cb)(const struct nlmsghdr *nlh, void *data), void *cb_data)
42{
43 char buf[MNL_SOCKET_BUFFER_SIZE];
44 uint32_t portid = mnl_socket_get_portid(nf_sock);
45 int ret;
46
47 if (mnl_socket_sendto(nf_sock, data, len) < 0)
48 return -1;
49
50 ret = mnl_socket_recvfrom(nf_sock, buf, sizeof(buf));
51 while (ret > 0) {
52 ret = mnl_cb_run(buf, ret, seq, portid, cb, cb_data);
53 if (ret <= 0)
54 goto out;
55
56 ret = mnl_socket_recvfrom(nf_sock, buf, sizeof(buf));
57 }
58out:
59 if (ret < 0 && errno == EAGAIN)
60 return 0;
61
62 return ret;
63}
64
65/*
66 * Rule
67 */
68static int rule_cb(const struct nlmsghdr *nlh, void *data)
69{
70 struct nftnl_rule_list *nlr_list = data;
71 struct nftnl_rule *r;
72
73 r = nftnl_rule_alloc();
74 if (r == NULL)
75 memory_allocation_error();
76
77 if (nftnl_rule_nlmsg_parse(nlh, r) < 0)
78 goto err_free;
79
80 nftnl_rule_list_add_tail(r, nlr_list);
81 return MNL_CB_OK;
82
83err_free:
84 nftnl_rule_free(r);
85 return MNL_CB_OK;
86}
87
88static struct nftnl_rule_list *mnl_rule_dump(struct mnl_socket *nf_sock,
89 int family)
90{
91 char buf[MNL_SOCKET_BUFFER_SIZE];
92 struct nlmsghdr *nlh;
93 struct nftnl_rule_list *nlr_list;
94 int ret;
95
96 nlr_list = nftnl_rule_list_alloc();
97 if (nlr_list == NULL)
98 memory_allocation_error();
99
100 nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family,
101 NLM_F_DUMP, seq);
102
103 ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, rule_cb, nlr_list);
104 if (ret < 0)
105 goto err;
106
107 return nlr_list;
108err:
109 nftnl_rule_list_free(nlr_list);
110 return NULL;
111}
112
113/*
114 * Chain
115 */
116static int chain_cb(const struct nlmsghdr *nlh, void *data)
117{
118 struct nftnl_chain_list *nlc_list = data;
119 struct nftnl_chain *c;
120
121 c = nftnl_chain_alloc();
122 if (c == NULL)
123 memory_allocation_error();
124
125 if (nftnl_chain_nlmsg_parse(nlh, c) < 0)
126 goto err_free;
127
128 nftnl_chain_list_add_tail(c, nlc_list);
129 return MNL_CB_OK;
130
131err_free:
132 nftnl_chain_free(c);
133 return MNL_CB_OK;
134}
135
136static struct nftnl_chain_list *mnl_chain_dump(struct mnl_socket *nf_sock,
137 int family)
138{
139 char buf[MNL_SOCKET_BUFFER_SIZE];
140 struct nlmsghdr *nlh;
141 struct nftnl_chain_list *nlc_list;
142 int ret;
143
144 nlc_list = nftnl_chain_list_alloc();
145 if (nlc_list == NULL)
146 memory_allocation_error();
147
148 nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family,
149 NLM_F_DUMP, seq);
150
151 ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, chain_cb, nlc_list);
152 if (ret < 0)
153 goto err;
154
155 return nlc_list;
156err:
157 nftnl_chain_list_free(nlc_list);
158 return NULL;
159}
160
161/*
162 * Table
163 */
164static int table_cb(const struct nlmsghdr *nlh, void *data)
165{
166 struct nftnl_table_list *nlt_list = data;
167 struct nftnl_table *t;
168
169 t = nftnl_table_alloc();
170 if (t == NULL)
171 memory_allocation_error();
172
173 if (nftnl_table_nlmsg_parse(nlh, t) < 0)
174 goto err_free;
175
176 nftnl_table_list_add_tail(t, nlt_list);
177 return MNL_CB_OK;
178
179err_free:
180 nftnl_table_free(t);
181 return MNL_CB_OK;
182}
183
184static struct nftnl_table_list *mnl_table_dump(struct mnl_socket *nf_sock,
185 int family)
186{
187 char buf[MNL_SOCKET_BUFFER_SIZE];
188 struct nlmsghdr *nlh;
189 struct nftnl_table_list *nlt_list;
190 int ret;
191
192 nlt_list = nftnl_table_list_alloc();
193 if (nlt_list == NULL)
194 memory_allocation_error();
195
196 nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family,
197 NLM_F_DUMP, seq);
198
199 ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, table_cb, nlt_list);
200 if (ret < 0)
201 goto err;
202
203 return nlt_list;
204err:
205 nftnl_table_list_free(nlt_list);
206 return NULL;
207}
208
209/*
210 * Set elements
211 */
212static int set_elem_cb(const struct nlmsghdr *nlh, void *data)
213{
214 nftnl_set_elems_nlmsg_parse(nlh, data);
215 return MNL_CB_OK;
216}
217
218static int mnl_setelem_get(struct mnl_socket *nf_sock, struct nftnl_set *nls)
219{
220 char buf[MNL_SOCKET_BUFFER_SIZE];
221 struct nlmsghdr *nlh;
222 uint32_t family = nftnl_set_get_u32(nls, NFTNL_SET_FAMILY);
223
224 nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM, family,
225 NLM_F_DUMP | NLM_F_ACK, seq);
226 nftnl_set_nlmsg_build_payload(nlh, nls);
227
228 return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_elem_cb, nls);
229}
230
231/*
232 * Set
233 */
234static int set_cb(const struct nlmsghdr *nlh, void *data)
235{
236 struct nftnl_set_list *nls_list = data;
237 struct nftnl_set *s;
238
239 s = nftnl_set_alloc();
240 if (s == NULL)
241 memory_allocation_error();
242
243 if (nftnl_set_nlmsg_parse(nlh, s) < 0)
244 goto err_free;
245
246 nftnl_set_list_add_tail(s, nls_list);
247 return MNL_CB_OK;
248
249err_free:
250 nftnl_set_free(s);
251 return MNL_CB_OK;
252}
253
254static struct nftnl_set_list *
255mnl_set_dump(struct mnl_socket *nf_sock, int family)
256{
257 char buf[MNL_SOCKET_BUFFER_SIZE];
258 struct nlmsghdr *nlh;
259 struct nftnl_set *s;
260 struct nftnl_set_list *nls_list;
261 struct nftnl_set *si;
262 struct nftnl_set_list_iter *i;
263 int ret;
264
265 s = nftnl_set_alloc();
266 if (s == NULL)
267 memory_allocation_error();
268
269 nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSET, family,
270 NLM_F_DUMP | NLM_F_ACK, seq);
271 nftnl_set_nlmsg_build_payload(nlh, s);
272 nftnl_set_free(s);
273
274 nls_list = nftnl_set_list_alloc();
275 if (nls_list == NULL)
276 memory_allocation_error();
277
278 ret = mnl_talk(nf_sock, nlh, nlh->nlmsg_len, set_cb, nls_list);
279 if (ret < 0)
280 goto err;
281
282 i = nftnl_set_list_iter_create(nls_list);
283 if (i == NULL)
284 memory_allocation_error();
285
286 si = nftnl_set_list_iter_next(i);
287 while (si != NULL) {
288 if (mnl_setelem_get(nf_sock, si) != 0) {
289 perror("E: Unable to get set elements");
290 nftnl_set_list_iter_destroy(i);
291 goto err;
292 }
293 si = nftnl_set_list_iter_next(i);
294 }
295
296 nftnl_set_list_iter_destroy(i);
297
298 return nls_list;
299err:
300 nftnl_set_list_free(nls_list);
301 return NULL;
302}
303
304/*
305 * ruleset
306 */
307
308static struct nftnl_ruleset *mnl_ruleset_dump(struct mnl_socket *nf_sock)
309{
310 struct nftnl_ruleset *rs;
311 struct nftnl_table_list *t;
312 struct nftnl_chain_list *c;
313 struct nftnl_set_list *s;
314 struct nftnl_rule_list *r;
315
316 rs = nftnl_ruleset_alloc();
317 if (rs == NULL)
318 memory_allocation_error();
319
320 t = mnl_table_dump(nf_sock, NFPROTO_UNSPEC);
321 if (t != NULL)
322 nftnl_ruleset_set(rs, NFTNL_RULESET_TABLELIST, t);
323
324 c = mnl_chain_dump(nf_sock, NFPROTO_UNSPEC);
325 if (c != NULL)
326 nftnl_ruleset_set(rs, NFTNL_RULESET_CHAINLIST, c);
327
328 s = mnl_set_dump(nf_sock, NFPROTO_UNSPEC);
329 if (s != NULL)
330 nftnl_ruleset_set(rs, NFTNL_RULESET_SETLIST, s);
331
332 r = mnl_rule_dump(nf_sock, NFPROTO_UNSPEC);
333 if (r != NULL)
334 nftnl_ruleset_set(rs, NFTNL_RULESET_RULELIST, r);
335
336 return rs;
337}
338
339int main(int argc, char *argv[])
340{
341 struct mnl_socket *nl;
342 uint32_t type = NFTNL_OUTPUT_DEFAULT;
343 struct nftnl_ruleset *rs;
344 int ret;
345
346 if (argc > 2) {
347 fprintf(stderr, "%s\n", argv[0]);
348 exit(EXIT_FAILURE);
349 }
350
351 nl = mnl_socket_open(NETLINK_NETFILTER);
352 if (nl == NULL) {
353 perror("mnl_socket_open");
354 exit(EXIT_FAILURE);
355 }
356
357 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
358 perror("mnl_socket_bind");
359 exit(EXIT_FAILURE);
360 }
361
362 seq = time(NULL);
363
364 rs = mnl_ruleset_dump(nl);
365 if (rs == NULL) {
366 perror("ruleset_dump");
367 exit(EXIT_FAILURE);
368 }
369
370 ret = nftnl_ruleset_fprintf(stdout, rs, type, 0);
371 fprintf(stdout, "\n");
372
373 if (ret == -1)
374 perror("E: Error during fprintf operations");
375
376 return 0;
377}