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 <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 static int show_counters = 0;
22
23 static const struct option options[] = {
24 {.name = "counters", .has_arg = false, .val = 'c'},
25 {.name = "dump", .has_arg = false, .val = 'd'},
26 {.name = "table", .has_arg = true, .val = 't'},
27 {.name = "modprobe", .has_arg = true, .val = 'M'},
28 {NULL},
29 };
30
31
32 /* Debugging prototype. */
for_each_table(int (* func)(const char * tablename))33 static int for_each_table(int (*func)(const char *tablename))
34 {
35 int ret = 1;
36 FILE *procfile = NULL;
37 char tablename[XT_TABLE_MAXNAMELEN+1];
38
39 procfile = fopen("/proc/net/ip6_tables_names", "re");
40 if (!procfile)
41 return ret;
42
43 while (fgets(tablename, sizeof(tablename), procfile)) {
44 if (tablename[strlen(tablename) - 1] != '\n')
45 xtables_error(OTHER_PROBLEM,
46 "Badly formed tablename `%s'\n",
47 tablename);
48 tablename[strlen(tablename) - 1] = '\0';
49 ret &= func(tablename);
50 }
51
52 fclose(procfile);
53 return ret;
54 }
55
56
do_output(const char * tablename)57 static int do_output(const char *tablename)
58 {
59 struct xtc_handle *h;
60 const char *chain = NULL;
61
62 if (!tablename)
63 return for_each_table(&do_output);
64
65 h = ip6tc_init(tablename);
66 if (h == NULL) {
67 xtables_load_ko(xtables_modprobe_program, false);
68 h = ip6tc_init(tablename);
69 }
70 if (!h)
71 xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n",
72 ip6tc_strerror(errno));
73
74 time_t now = time(NULL);
75
76 printf("# Generated by ip6tables-save v%s on %s",
77 IPTABLES_VERSION, ctime(&now));
78 printf("*%s\n", tablename);
79
80 /* Dump out chain names first,
81 * thereby preventing dependency conflicts */
82 for (chain = ip6tc_first_chain(h);
83 chain;
84 chain = ip6tc_next_chain(h)) {
85
86 printf(":%s ", chain);
87 if (ip6tc_builtin(chain, h)) {
88 struct xt_counters count;
89 printf("%s ",
90 ip6tc_get_policy(chain, &count, h));
91 printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt);
92 } else {
93 printf("- [0:0]\n");
94 }
95 }
96
97 for (chain = ip6tc_first_chain(h);
98 chain;
99 chain = ip6tc_next_chain(h)) {
100 const struct ip6t_entry *e;
101
102 /* Dump out rules */
103 e = ip6tc_first_rule(chain, h);
104 while(e) {
105 print_rule6(e, h, chain, show_counters);
106 e = ip6tc_next_rule(e, h);
107 }
108 }
109
110 now = time(NULL);
111 printf("COMMIT\n");
112 printf("# Completed on %s", ctime(&now));
113 ip6tc_free(h);
114
115 return 1;
116 }
117
118 /* Format:
119 * :Chain name POLICY packets bytes
120 * rule
121 */
ip6tables_save_main(int argc,char * argv[])122 int ip6tables_save_main(int argc, char *argv[])
123 {
124 const char *tablename = NULL;
125 int c;
126
127 ip6tables_globals.program_name = "ip6tables-save";
128 c = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6);
129 if (c < 0) {
130 fprintf(stderr, "%s/%s Failed to initialize xtables\n",
131 ip6tables_globals.program_name,
132 ip6tables_globals.program_version);
133 exit(1);
134 }
135 #if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
136 init_extensions();
137 init_extensions6();
138 #endif
139
140 while ((c = getopt_long(argc, argv, "bcdt:M:", options, NULL)) != -1) {
141 switch (c) {
142 case 'b':
143 fprintf(stderr, "-b/--binary option is not implemented\n");
144 break;
145 case 'c':
146 show_counters = 1;
147 break;
148
149 case 't':
150 /* Select specific table. */
151 tablename = optarg;
152 break;
153 case 'M':
154 xtables_modprobe_program = optarg;
155 break;
156 case 'd':
157 do_output(tablename);
158 exit(0);
159 }
160 }
161
162 if (optind < argc) {
163 fprintf(stderr, "Unknown arguments found on commandline\n");
164 exit(1);
165 }
166
167 return !do_output(tablename);
168 }
169