iptables-save.c revision f643eb37e49a212d40eb060bcdfafbc366c0d616
1/* Code to save the iptables state, in human readable-form. */
2/* (C) 1999 by Paul 'Rusty' Russell <rusty@rustcorp.com.au> and
3 * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
4 *
5 * This code is distributed under the terms of GNU GPL v2
6 *
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 "libiptc/libiptc.h"
17#include "iptables.h"
18#include "iptables-multi.h"
19
20#ifndef NO_SHARED_LIBS
21#include <dlfcn.h>
22#endif
23
24static int show_binary = 0, show_counters = 0;
25
26static const struct option options[] = {
27	{.name = "binary",   .has_arg = false, .val = 'b'},
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/* Debugging prototype. */
36static int for_each_table(int (*func)(const char *tablename))
37{
38	int ret = 1;
39	FILE *procfile = NULL;
40	char tablename[IPT_TABLE_MAXNAMELEN+1];
41
42	procfile = fopen("/proc/net/ip_tables_names", "re");
43	if (!procfile)
44		return ret;
45
46	while (fgets(tablename, sizeof(tablename), procfile)) {
47		if (tablename[strlen(tablename) - 1] != '\n')
48			xtables_error(OTHER_PROBLEM,
49				   "Badly formed tablename `%s'\n",
50				   tablename);
51		tablename[strlen(tablename) - 1] = '\0';
52		ret &= func(tablename);
53	}
54
55	fclose(procfile);
56	return ret;
57}
58
59
60static int do_output(const char *tablename)
61{
62	struct iptc_handle *h;
63	const char *chain = NULL;
64
65	if (!tablename)
66		return for_each_table(&do_output);
67
68	h = iptc_init(tablename);
69	if (h == NULL) {
70		xtables_load_ko(xtables_modprobe_program, false);
71		h = iptc_init(tablename);
72	}
73	if (!h)
74		xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n",
75			   iptc_strerror(errno));
76
77	if (!show_binary) {
78		time_t now = time(NULL);
79
80		printf("# Generated by iptables-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 = iptc_first_chain(h);
87		     chain;
88		     chain = iptc_next_chain(h)) {
89
90			printf(":%s ", chain);
91			if (iptc_builtin(chain, h)) {
92				struct ipt_counters count;
93				printf("%s ",
94				       iptc_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
102		for (chain = iptc_first_chain(h);
103		     chain;
104		     chain = iptc_next_chain(h)) {
105			const struct ipt_entry *e;
106
107			/* Dump out rules */
108			e = iptc_first_rule(chain, h);
109			while(e) {
110				print_rule4(e, h, chain, show_counters);
111				e = iptc_next_rule(e, h);
112			}
113		}
114
115		now = time(NULL);
116		printf("COMMIT\n");
117		printf("# Completed on %s", ctime(&now));
118	} else {
119		/* Binary, huh?  OK. */
120		xtables_error(OTHER_PROBLEM, "Binary NYI\n");
121	}
122
123	iptc_free(h);
124
125	return 1;
126}
127
128/* Format:
129 * :Chain name POLICY packets bytes
130 * rule
131 */
132int
133iptables_save_main(int argc, char *argv[])
134{
135	const char *tablename = NULL;
136	int c;
137
138	iptables_globals.program_name = "iptables-save";
139	c = xtables_init_all(&iptables_globals, NFPROTO_IPV4);
140	if (c < 0) {
141		fprintf(stderr, "%s/%s Failed to initialize xtables\n",
142				iptables_globals.program_name,
143				iptables_globals.program_version);
144		exit(1);
145	}
146#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
147	init_extensions();
148	init_extensions4();
149#endif
150
151	while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) {
152		switch (c) {
153		case 'b':
154			show_binary = 1;
155			break;
156
157		case 'c':
158			show_counters = 1;
159			break;
160
161		case 't':
162			/* Select specific table. */
163			tablename = optarg;
164			break;
165		case 'M':
166			xtables_modprobe_program = optarg;
167			break;
168		case 'd':
169			do_output(tablename);
170			exit(0);
171		}
172	}
173
174	if (optind < argc) {
175		fprintf(stderr, "Unknown arguments found on commandline\n");
176		exit(1);
177	}
178
179	return !do_output(tablename);
180}
181