blob: f9a95952d0e273176f9640a9a035a6792c74e0b4 [file] [log] [blame]
Marc Bouchere6869a82000-03-20 06:03:29 +00001/* Code to restore the iptables state, from file by iptables-save. */
2#include <getopt.h>
3#include <sys/errno.h>
4#include <string.h>
5#include <stdio.h>
6#include "packet-filter/userspace/iptables.h"
7#include "packet-filter/userspace/libiptc/libiptc.h"
8
9/* Keeping track of external matches and targets. */
10static struct option options[] = {
11 { "binary", 1, 0, 'b' },
12 { "counters", 1, 0, 'c' },
13 { "verbose", 1, 0, 'v' },
14 { "help", 1, 0, 'h' },
15 { 0 }
16};
17
18static void print_usage(const char *name, const char *version) __attribute__((noreturn));
19
20static void print_usage(const char *name, const char *version)
21{
22 fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-h]\n", name);
23 exit(1);
24}
25
26static int clean_slate(iptc_handle_t *handle)
27{
28 /* Skip over builtins. */
29 const char *i, *last = IPTC_LABEL_OUTPUT;
30
31 /* Be careful iterating: it isn't safe during delete. */
32 /* Re-iterate after each delete successful */
33 while ((i = iptc_next_chain(last, handle)) != NULL) {
34 if (!iptc_flush_entries(i, handle)
35 || !iptc_delete_chain(i, handle))
36 return 0;
37 }
38 return 1;
39}
40
41int main(int argc, char *argv[])
42{
43 iptc_handle_t handle;
44 char buffer[10240];
45 int counters = 0, binary = 0, verbose = 0;
46 unsigned int line = 0;
47 int c;
48 const char *chain;
49 FILE *in;
50
51 program_name = "iptables-restore";
52 program_version = NETFILTER_VERSION;
53
54 /* Don't use getopt here; it would interfere 8-(. */
55 if (optind == argc - 1) {
56 in = fopen(argv[optind], "r");
57 if (!in) {
58 fprintf(stderr, "Can't open %s: %s", argv[optind],
59 strerror(errno));
60 exit(1);
61 }
62 }
63 else if (optind < argc) {
64 fprintf(stderr, "Unknown arguments found on commandline");
65 exit(1);
66 }
67 else in = stdin;
68
69 handle = iptc_init();
70 if (!handle)
71 exit_error(VERSION_PROBLEM,
72 "can't initialize iptables-restore: %s",
73 iptc_strerror(errno));
74
75 if (!clean_slate(&handle))
76 exit_error(OTHER_PROBLEM, "Deleting old chains: %s",
77 iptc_strerror(errno));
78
79 /* Grab standard input. */
80 while (fgets(buffer, sizeof(buffer), in)) {
81 int ret;
82
83 line++;
84 if (buffer[0] == '\n') continue;
85 else if (buffer[0] == '#') {
86 if (verbose) fputs(buffer, stdout);
87 continue;
88 } else if (strcmp(buffer, "COMMIT\n") == 0)
89 ret = iptc_commit(&handle);
90 else if (buffer[0] == ':') {
91 /* New chain. */
92 char *chain, *policy;
93
94 /* FIXME: Don't ignore counters. */
95 chain = strtok(buffer+1, " \t\n");
96 if (!chain) {
97 exit_error(PARAMETER_PROBLEM,
98 "%s: line %u chain name invalid\n",
99 program_name, line);
100 exit(1);
101 }
102 policy = strtok(NULL, " \t\n");
103 if (!policy) {
104 exit_error(PARAMETER_PROBLEM,
105 "%s: line %u policy invalid\n",
106 program_name, line);
107 exit(1);
108 }
109 if (strcmp(policy, "-") != 0
110 && !iptc_set_policy(chain, policy, &handle))
111 exit_error(OTHER_PROBLEM,
112 "Can't set policy `%s'"
113 " on `%s' line %u: %s\n",
114 chain, policy, line,
115 iptc_strerror(errno));
116 } else {
117 char *newargv[1024];
118 int i;
119 char *ptr = buffer;
120
121 /* FIXME: Don't ignore counters. */
122 if (buffer[0] == '[') {
123 ptr = strchr(buffer, ']');
124 if (!ptr)
125 exit_error(PARAMETER_PROBLEM,
126 "Bad line %u: need ]\n",
127 line);
128 }
Rusty Russell7e53bf92000-03-20 07:03:28 +0000129
Marc Bouchere6869a82000-03-20 06:03:29 +0000130 /* strtok: a function only a coder could love */
131 newargv[0] = argv[0];
132 for (i = 1; i < sizeof(newargv)/sizeof(char *); i++) {
133 if (!(newargv[i] = strtok(ptr, " \t\n")))
134 break;
135 ptr = NULL;
136 }
137 if (i == sizeof(newargv)/sizeof(char *)) {
138 fprintf(stderr,
139 "%s: line %u too many arguments\n",
140 program_name, line);
141 exit(1);
142 }
143
144 ret = do_command(i, newargv, &handle);
145 }
146 if (!ret) {
147 fprintf(stderr, "%s: line %u failed\n",
148 program_name, line);
149 exit(1);
150 }
151 }
152
153 return 0;
154}