ip6tables-save.c revision 296dca39be1166c4b7c6367c1b97ee95aebddfc3
1/* Code to save the ip6tables state, in human readable-form. */
2/* Author:  Andras Kis-Szabo <kisza@sch.bme.hu>
3 * Original code: iptables-save
4 * Authors: Paul 'Rusty' Russel <rusty@linuxcare.com.au> and
5 *          Harald Welte <laforge@gnumonks.org>
6 * This code is distributed under the terms of GNU GPL v2
7 */
8#include <getopt.h>
9#include <sys/errno.h>
10#include <stdio.h>
11#include <fcntl.h>
12#include <stdlib.h>
13#include <string.h>
14#include <time.h>
15#include <netdb.h>
16#include <arpa/inet.h>
17#include "libiptc/libip6tc.h"
18#include "ip6tables.h"
19#include "ip6tables-multi.h"
20
21#ifndef NO_SHARED_LIBS
22#include <dlfcn.h>
23#endif
24
25static int show_counters = 0;
26
27static const struct option options[] = {
28	{.name = "counters", .has_arg = false, .val = 'c'},
29	{.name = "dump",     .has_arg = false, .val = 'd'},
30	{.name = "table",    .has_arg = true,  .val = 't'},
31	{.name = "modprobe", .has_arg = true,  .val = 'M'},
32	{NULL},
33};
34
35
36/* Debugging prototype. */
37static int for_each_table(int (*func)(const char *tablename))
38{
39	int ret = 1;
40	FILE *procfile = NULL;
41	char tablename[IP6T_TABLE_MAXNAMELEN+1];
42
43	procfile = fopen("/proc/net/ip6_tables_names", "re");
44	if (!procfile)
45		return ret;
46
47	while (fgets(tablename, sizeof(tablename), procfile)) {
48		if (tablename[strlen(tablename) - 1] != '\n')
49			xtables_error(OTHER_PROBLEM,
50				   "Badly formed tablename `%s'\n",
51				   tablename);
52		tablename[strlen(tablename) - 1] = '\0';
53		ret &= func(tablename);
54	}
55
56	fclose(procfile);
57	return ret;
58}
59
60
61static int do_output(const char *tablename)
62{
63	struct ip6tc_handle *h;
64	const char *chain = NULL;
65
66	if (!tablename)
67		return for_each_table(&do_output);
68
69	h = ip6tc_init(tablename);
70	if (h == NULL) {
71		xtables_load_ko(xtables_modprobe_program, false);
72		h = ip6tc_init(tablename);
73	}
74	if (!h)
75		xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n",
76			   ip6tc_strerror(errno));
77
78	time_t now = time(NULL);
79
80	printf("# Generated by ip6tables-save v%s on %s",
81	       IPTABLES_VERSION, ctime(&now));
82	printf("*%s\n", tablename);
83
84	/* Dump out chain names first,
85	 * thereby preventing dependency conflicts */
86	for (chain = ip6tc_first_chain(h);
87	     chain;
88	     chain = ip6tc_next_chain(h)) {
89
90		printf(":%s ", chain);
91		if (ip6tc_builtin(chain, h)) {
92			struct ip6t_counters count;
93			printf("%s ",
94			       ip6tc_get_policy(chain, &count, h));
95			printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt);
96		} else {
97			printf("- [0:0]\n");
98		}
99	}
100
101	for (chain = ip6tc_first_chain(h);
102	     chain;
103	     chain = ip6tc_next_chain(h)) {
104		const struct ip6t_entry *e;
105
106		/* Dump out rules */
107		e = ip6tc_first_rule(chain, h);
108		while(e) {
109			print_rule6(e, h, chain, show_counters);
110			e = ip6tc_next_rule(e, h);
111		}
112	}
113
114	now = time(NULL);
115	printf("COMMIT\n");
116	printf("# Completed on %s", ctime(&now));
117	ip6tc_free(h);
118
119	return 1;
120}
121
122/* Format:
123 * :Chain name POLICY packets bytes
124 * rule
125 */
126int ip6tables_save_main(int argc, char *argv[])
127{
128	const char *tablename = NULL;
129	int c;
130
131	ip6tables_globals.program_name = "ip6tables-save";
132	c = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6);
133	if (c < 0) {
134		fprintf(stderr, "%s/%s Failed to initialize xtables\n",
135				ip6tables_globals.program_name,
136				ip6tables_globals.program_version);
137		exit(1);
138	}
139#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
140	init_extensions();
141	init_extensions6();
142#endif
143
144	while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) {
145		switch (c) {
146		case 'c':
147			show_counters = 1;
148			break;
149
150		case 't':
151			/* Select specific table. */
152			tablename = optarg;
153			break;
154		case 'M':
155			xtables_modprobe_program = optarg;
156			break;
157		case 'd':
158			do_output(tablename);
159			exit(0);
160		}
161	}
162
163	if (optind < argc) {
164		fprintf(stderr, "Unknown arguments found on commandline\n");
165		exit(1);
166	}
167
168	return !do_output(tablename);
169}
170