blob: f7a94f2c888ef14affd353dd40047496b3213e57 [file] [log] [blame]
András Kis-Szabó2f523792001-02-27 09:59:48 +00001/* Code to restore the iptables state, from file by ip6tables-save.
2 * Author: Andras Kis-Szabo <kisza@sch.bme.hu>
3 *
4 * based on iptables-restore
5 * Authors:
6 * Harald Welte <laforge@gnumonks.org>
7 * Rusty Russell <rusty@linuxcare.com.au>
8 *
9 */
10
11#include <getopt.h>
12#include <sys/errno.h>
13#include <string.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include "ip6tables.h"
17#include "libiptc/libip6tc.h"
18
19#ifdef DEBUG
20#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
21#else
22#define DEBUGP(x, args...)
23#endif
24
25extern int for_each_chain(int (*fn)(const ip6t_chainlabel, int, ip6tc_handle_t *), int verbose, int builtinstoo, ip6tc_handle_t *handle);
26extern int flush_entries(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
27extern int delete_chain(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
28
29static int binary = 0, counters = 0, verbose = 0, noflush = 0;
30
31/* Keeping track of external matches and targets. */
32static struct option options[] = {
33 { "binary", 0, 0, 'b' },
34 { "counters", 0, 0, 'c' },
35/* { "verbose", 1, 0, 'v' }, */
36 { "help", 0, 0, 'h' },
37 { "noflush", 0, 0, 'n'},
Harald Welte58918652001-06-16 18:25:25 +000038 { "modprobe", 1, 0, 'M'},
András Kis-Szabó2f523792001-02-27 09:59:48 +000039 { 0 }
40};
41
42static void print_usage(const char *name, const char *version) __attribute__((noreturn));
43
44static void print_usage(const char *name, const char *version)
45{
46 fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-h]\n"
47 " [ --binary ]\n"
48 " [ --counters ]\n"
49 " [ --verbose ]\n"
50 " [ --help ]\n"
Harald Welte58918652001-06-16 18:25:25 +000051 " [ --noflush ]\n"
52 " [ --modprobe=<command>]\n", name);
András Kis-Szabó2f523792001-02-27 09:59:48 +000053
54 exit(1);
55}
56
Harald Welte58918652001-06-16 18:25:25 +000057ip6tc_handle_t create_handle(const char *tablename, const char* modprobe)
András Kis-Szabó2f523792001-02-27 09:59:48 +000058{
59 ip6tc_handle_t handle;
60
61 handle = ip6tc_init(tablename);
Harald Welte58918652001-06-16 18:25:25 +000062
63 if (!handle) {
64 /* try to insmod the module if iptc_init failed */
65 ip6tables_insmod("ip6_tables", modprobe);
66 handle = ip6tc_init(tablename);
67 }
68
András Kis-Szabó2f523792001-02-27 09:59:48 +000069 if (!handle) {
70 exit_error(PARAMETER_PROBLEM, "%s: unable to initialize"
71 "table '%s'\n", program_name, tablename);
72 exit(1);
73 }
74 return handle;
75}
76
77int parse_counters(char *string, struct ip6t_counters *ctr)
78{
79 return (sscanf(string, "[%llu:%llu]", &ctr->pcnt, &ctr->bcnt) == 2);
80}
81
82int main(int argc, char *argv[])
83{
84 ip6tc_handle_t handle;
85 char buffer[10240];
86 unsigned int line = 0;
87 int c;
88 char curtable[IP6T_TABLE_MAXNAMELEN + 1];
89 char curchain[IP6T_FUNCTION_MAXNAMELEN + 1];
90 FILE *in;
Harald Welte58918652001-06-16 18:25:25 +000091 const char *modprobe = 0;
András Kis-Szabó2f523792001-02-27 09:59:48 +000092
93 program_name = "ip6tables-restore";
94 program_version = NETFILTER_VERSION;
95
Harald Welte58918652001-06-16 18:25:25 +000096 while ((c = getopt_long(argc, argv, "bcvhnM:", options, NULL)) != -1) {
András Kis-Szabó2f523792001-02-27 09:59:48 +000097 switch (c) {
98 case 'b':
99 binary = 1;
100 break;
101 case 'c':
102 counters = 1;
103 break;
104 case 'h':
105 print_usage("ip6tables-restore",
106 NETFILTER_VERSION);
107 break;
108 case 'n':
109 noflush = 1;
110 break;
Harald Welte58918652001-06-16 18:25:25 +0000111 case 'M':
112 modprobe = optarg;
113 break;
András Kis-Szabó2f523792001-02-27 09:59:48 +0000114 }
115 }
116
117 if (optind == argc - 1) {
118 in = fopen(argv[optind], "r");
119 if (!in) {
120 fprintf(stderr, "Can't open %s: %s", argv[optind],
121 strerror(errno));
122 exit(1);
123 }
124 }
125 else if (optind < argc) {
126 fprintf(stderr, "Unknown arguments found on commandline");
127 exit(1);
128 }
129 else in = stdin;
130/*
131 handle = iptc_init("filter");
132 if (!handle)
133 exit_error(VERSION_PROBLEM,
134 "can't initialize iptables-restore: %s",
135 iptc_strerror(errno));
136
137 if (!clean_slate(&handle))
138 exit_error(OTHER_PROBLEM, "Deleting old chains: %s",
139 iptc_strerror(errno));
140*/
141 /* Grab standard input. */
142 while (fgets(buffer, sizeof(buffer), in)) {
143 int ret;
144
145 line++;
146 if (buffer[0] == '\n') continue;
147 else if (buffer[0] == '#') {
148 if (verbose) fputs(buffer, stdout);
149 continue;
150 } else if (strcmp(buffer, "COMMIT\n") == 0) {
151 DEBUGP("Calling commit\n");
152 ret = ip6tc_commit(&handle);
153 } else if (buffer[0] == '*') {
154 /* New table */
155 char *table;
156
157 table = strtok(buffer+1, " \t\n");
158 DEBUGP("line %u, table '%s'\n", line, table);
159 if (!table) {
160 exit_error(PARAMETER_PROBLEM,
161 "%s: line %u table name invalid\n",
162 program_name, line);
163 exit(1);
164 }
165 strncpy(curtable, table, IP6T_TABLE_MAXNAMELEN);
166
Harald Welte58918652001-06-16 18:25:25 +0000167 handle = create_handle(table, modprobe);
András Kis-Szabó2f523792001-02-27 09:59:48 +0000168 if (noflush == 0) {
169 DEBUGP("Cleaning all chains of table '%s'\n",
170 table);
171 for_each_chain(flush_entries, verbose, 1,
172 &handle);
173
174 DEBUGP("Deleting all user-defined chains "
175 "of table '%s'\n", table);
176 for_each_chain(delete_chain, verbose, 0,
177 &handle) ;
178 }
179
180 ret = 1;
181
182 } else if (buffer[0] == ':') {
183 /* New chain. */
184 char *policy, *chain;
185
186 chain = strtok(buffer+1, " \t\n");
187 DEBUGP("line %u, chain '%s'\n", line, chain);
188 if (!chain) {
189 exit_error(PARAMETER_PROBLEM,
190 "%s: line %u chain name invalid\n",
191 program_name, line);
192 exit(1);
193 }
194 strncpy(curchain, chain, IP6T_FUNCTION_MAXNAMELEN);
195
196 /* why the f... does iptc_builtin not work here ? */
197 /* FIXME: abort if chain creation fails --RR */
198// if (!iptc_builtin(curchain, &handle)) {
199 DEBUGP("Creating new chain '%s'\n", curchain);
200 if (!ip6tc_create_chain(curchain, &handle))
201 DEBUGP("unable to create chain '%s':%s\n", curchain,
202 strerror(errno));
203// }
204
205 policy = strtok(NULL, " \t\n");
206 DEBUGP("line %u, policy '%s'\n", line, policy);
207 if (!policy) {
208 exit_error(PARAMETER_PROBLEM,
209 "%s: line %u policy invalid\n",
210 program_name, line);
211 exit(1);
212 }
213
214 if (strcmp(policy, "-") != 0) {
215 struct ip6t_counters count;
216
217 if (counters) {
218 char *ctrs;
219 ctrs = strtok(NULL, " \t\n");
220
221 parse_counters(ctrs, &count);
222
223 } else {
224 memset(&count, 0,
225 sizeof(struct ip6t_counters));
226 }
227
228 DEBUGP("Setting policy of chain %s to %s\n",
229 chain, policy);
230
231 if (!ip6tc_set_policy(chain, policy, &count,
232 &handle))
233 exit_error(OTHER_PROBLEM,
234 "Can't set policy `%s'"
235 " on `%s' line %u: %s\n",
236 chain, policy, line,
237 ip6tc_strerror(errno));
238 }
239
240 ret = 1;
241
242 } else {
243 char *newargv[1024];
244 int i,a, argvsize;
245 char *ptr = buffer;
246 char *pcnt = NULL;
247 char *bcnt = NULL;
248
249 if (buffer[0] == '[') {
250 ptr = strchr(buffer, ']');
251 if (!ptr)
252 exit_error(PARAMETER_PROBLEM,
253 "Bad line %u: need ]\n",
254 line);
255 pcnt = strtok(buffer+1, ":");
256 bcnt = strtok(NULL, "]");
257 }
258
259 newargv[0] = argv[0];
260 newargv[1] = "-t";
261 newargv[2] = (char *) &curtable;
262 newargv[3] = "-A";
263 newargv[4] = (char *) &curchain;
264 argvsize = 5;
265
266 if (counters && pcnt && bcnt) {
267 newargv[5] = "--set-counters";
268 newargv[6] = (char *) pcnt;
269 newargv[7] = (char *) bcnt;
270 argvsize = 8;
271 }
272
273 // strtok initcialize!
274 if ( buffer[0]!='[' )
275 {
276 if (!(newargv[argvsize] = strtok(buffer, " \t\n")))
277 goto ImLaMeR;
278 //break;
279 argvsize++;
280 }
281
282 /* strtok: a function only a coder could love */
283 for (i = argvsize; i < sizeof(newargv)/sizeof(char *);
284 i++) {
285 if (!(newargv[i] = strtok(NULL, " \t\n")))
286 break;
287 ptr = NULL;
288 }
289ImLaMeR: if (i == sizeof(newargv)/sizeof(char *)) {
290 fprintf(stderr,
291 "%s: line %u too many arguments\n",
292 program_name, line);
293 exit(1);
294 }
295
296 DEBUGP("===>calling do_command6(%u, argv, &%s, handle):\n",
297 i, curtable);
298
299 for (a = 0; a <= i; a++)
300 DEBUGP("argv[%u]: %s\n", a, newargv[a]);
301
302 ret = do_command6(i, newargv, &newargv[2], &handle);
303 }
304 if (!ret) {
305 fprintf(stderr, "%s: line %u failed\n",
306 program_name, line);
307 exit(1);
308 }
309 }
310
311 return 0;
312}