~csurbhi/ubuntu/maverick/iptables/iptable-fix.600195

« back to all changes in this revision

Viewing changes to iptables-restore.c.orig

  • Committer: Bazaar Package Importer
  • Author(s): Soren Hansen
  • Date: 2008-06-24 15:06:04 UTC
  • mfrom: (5.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080624150604-5t7r1o1kxq0ycz81
Tags: 1.4.0-4ubuntu1
* Merge from debian unstable, remaining changes:
  - Took references to 2.4 kernel out of doc-base control files (Jordan
    Mantha, Malone #25972) (patches/all/091-fix-2.4-references.patch)
  - Use linux-libc-dev instead of local copy of kernel-headers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Code to restore the iptables state, from file by iptables-save. 
 
2
 * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
 
3
 * based on previous code from Rusty Russell <rusty@linuxcare.com.au>
 
4
 *
 
5
 * This code is distributed under the terms of GNU GPL v2
 
6
 *
 
7
 * $Id: iptables-restore.c 6706 2006-12-09 13:06:04Z /C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=yasuyuki/emailAddress=yasuyuki@netfilter.org $
 
8
 */
 
9
 
 
10
#include <getopt.h>
 
11
#include <sys/errno.h>
 
12
#include <string.h>
 
13
#include <stdio.h>
 
14
#include <stdlib.h>
 
15
#include "iptables.h"
 
16
#include "libiptc/libiptc.h"
 
17
 
 
18
#ifdef DEBUG
 
19
#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
 
20
#else
 
21
#define DEBUGP(x, args...) 
 
22
#endif
 
23
 
 
24
static int binary = 0, counters = 0, verbose = 0, noflush = 0;
 
25
 
 
26
/* Keeping track of external matches and targets.  */
 
27
static struct option options[] = {
 
28
        { "binary", 0, 0, 'b' },
 
29
        { "counters", 0, 0, 'c' },
 
30
        { "verbose", 0, 0, 'v' },
 
31
        { "test", 0, 0, 't' },
 
32
        { "help", 0, 0, 'h' },
 
33
        { "noflush", 0, 0, 'n'},
 
34
        { "modprobe", 1, 0, 'M'},
 
35
        { 0 }
 
36
};
 
37
 
 
38
static void print_usage(const char *name, const char *version) __attribute__((noreturn));
 
39
 
 
40
static void print_usage(const char *name, const char *version)
 
41
{
 
42
        fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-t] [-h]\n"
 
43
                        "          [ --binary ]\n"
 
44
                        "          [ --counters ]\n"
 
45
                        "          [ --verbose ]\n"
 
46
                        "          [ --test ]\n"
 
47
                        "          [ --help ]\n"
 
48
                        "          [ --noflush ]\n"
 
49
                        "          [ --modprobe=<command>]\n", name);
 
50
                
 
51
        exit(1);
 
52
}
 
53
 
 
54
iptc_handle_t create_handle(const char *tablename, const char* modprobe )
 
55
{
 
56
        iptc_handle_t handle;
 
57
 
 
58
        handle = iptc_init(tablename);
 
59
 
 
60
        if (!handle) {
 
61
                /* try to insmod the module if iptc_init failed */
 
62
                iptables_insmod("ip_tables", modprobe);
 
63
                handle = iptc_init(tablename);
 
64
        }
 
65
 
 
66
        if (!handle) {
 
67
                exit_error(PARAMETER_PROBLEM, "%s: unable to initialize"
 
68
                        "table '%s'\n", program_name, tablename);
 
69
                exit(1);
 
70
        }
 
71
        return handle;
 
72
}
 
73
 
 
74
static int parse_counters(char *string, struct ipt_counters *ctr)
 
75
{
 
76
        return (sscanf(string, "[%llu:%llu]", (unsigned long long *)&ctr->pcnt, (unsigned long long *)&ctr->bcnt) == 2);
 
77
}
 
78
 
 
79
/* global new argv and argc */
 
80
static char *newargv[255];
 
81
static int newargc;
 
82
 
 
83
/* function adding one argument to newargv, updating newargc 
 
84
 * returns true if argument added, false otherwise */
 
85
static int add_argv(char *what) {
 
86
        DEBUGP("add_argv: %s\n", what);
 
87
        if (what && ((newargc + 1) < sizeof(newargv)/sizeof(char *))) {
 
88
                newargv[newargc] = strdup(what);
 
89
                newargc++;
 
90
                return 1;
 
91
        } else 
 
92
                return 0;
 
93
}
 
94
 
 
95
static void free_argv(void) {
 
96
        int i;
 
97
 
 
98
        for (i = 0; i < newargc; i++)
 
99
                free(newargv[i]);
 
100
}
 
101
 
 
102
#ifdef IPTABLES_MULTI
 
103
int
 
104
iptables_restore_main(int argc, char *argv[])
 
105
#else
 
106
int
 
107
main(int argc, char *argv[])
 
108
#endif
 
109
{
 
110
        iptc_handle_t handle = NULL;
 
111
        char buffer[10240];
 
112
        int c;
 
113
        char curtable[IPT_TABLE_MAXNAMELEN + 1];
 
114
        FILE *in;
 
115
        const char *modprobe = 0;
 
116
        int in_table = 0, testing = 0;
 
117
 
 
118
        program_name = "iptables-restore";
 
119
        program_version = IPTABLES_VERSION;
 
120
        line = 0;
 
121
 
 
122
        lib_dir = getenv("IPTABLES_LIB_DIR");
 
123
        if (!lib_dir)
 
124
                lib_dir = IPT_LIB_DIR;
 
125
 
 
126
#ifdef NO_SHARED_LIBS
 
127
        init_extensions();
 
128
#endif
 
129
 
 
130
        while ((c = getopt_long(argc, argv, "bcvthnM:", options, NULL)) != -1) {
 
131
                switch (c) {
 
132
                        case 'b':
 
133
                                binary = 1;
 
134
                                break;
 
135
                        case 'c':
 
136
                                counters = 1;
 
137
                                break;
 
138
                        case 'v':
 
139
                                verbose = 1;
 
140
                                break;
 
141
                        case 't':
 
142
                                testing = 1;
 
143
                                break;
 
144
                        case 'h':
 
145
                                print_usage("iptables-restore",
 
146
                                            IPTABLES_VERSION);
 
147
                                break;
 
148
                        case 'n':
 
149
                                noflush = 1;
 
150
                                break;
 
151
                        case 'M':
 
152
                                modprobe = optarg;
 
153
                                break;
 
154
                }
 
155
        }
 
156
        
 
157
        if (optind == argc - 1) {
 
158
                in = fopen(argv[optind], "r");
 
159
                if (!in) {
 
160
                        fprintf(stderr, "Can't open %s: %s", argv[optind],
 
161
                                strerror(errno));
 
162
                        exit(1);
 
163
                }
 
164
        }
 
165
        else if (optind < argc) {
 
166
                fprintf(stderr, "Unknown arguments found on commandline");
 
167
                exit(1);
 
168
        }
 
169
        else in = stdin;
 
170
        
 
171
        /* Grab standard input. */
 
172
        while (fgets(buffer, sizeof(buffer), in)) {
 
173
                int ret = 0;
 
174
 
 
175
                line++;
 
176
                if (buffer[0] == '\n')
 
177
                        continue;
 
178
                else if (buffer[0] == '#') {
 
179
                        if (verbose)
 
180
                                fputs(buffer, stdout);
 
181
                        continue;
 
182
                } else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
 
183
                        if (!testing) {
 
184
                                DEBUGP("Calling commit\n");
 
185
                                ret = iptc_commit(&handle);
 
186
                        } else {
 
187
                                DEBUGP("Not calling commit, testing\n");
 
188
                                ret = 1;
 
189
                        }
 
190
                        in_table = 0;
 
191
                } else if ((buffer[0] == '*') && (!in_table)) {
 
192
                        /* New table */
 
193
                        char *table;
 
194
 
 
195
                        table = strtok(buffer+1, " \t\n");
 
196
                        DEBUGP("line %u, table '%s'\n", line, table);
 
197
                        if (!table) {
 
198
                                exit_error(PARAMETER_PROBLEM, 
 
199
                                        "%s: line %u table name invalid\n",
 
200
                                        program_name, line);
 
201
                                exit(1);
 
202
                        }
 
203
                        strncpy(curtable, table, IPT_TABLE_MAXNAMELEN);
 
204
                        curtable[IPT_TABLE_MAXNAMELEN] = '\0';
 
205
 
 
206
                        if (handle)
 
207
                                iptc_free(&handle);
 
208
 
 
209
                        handle = create_handle(table, modprobe);
 
210
                        if (noflush == 0) {
 
211
                                DEBUGP("Cleaning all chains of table '%s'\n",
 
212
                                        table);
 
213
                                for_each_chain(flush_entries, verbose, 1, 
 
214
                                                &handle);
 
215
        
 
216
                                DEBUGP("Deleting all user-defined chains "
 
217
                                       "of table '%s'\n", table);
 
218
                                for_each_chain(delete_chain, verbose, 0, 
 
219
                                                &handle) ;
 
220
                        }
 
221
 
 
222
                        ret = 1;
 
223
                        in_table = 1;
 
224
 
 
225
                } else if ((buffer[0] == ':') && (in_table)) {
 
226
                        /* New chain. */
 
227
                        char *policy, *chain;
 
228
 
 
229
                        chain = strtok(buffer+1, " \t\n");
 
230
                        DEBUGP("line %u, chain '%s'\n", line, chain);
 
231
                        if (!chain) {
 
232
                                exit_error(PARAMETER_PROBLEM,
 
233
                                           "%s: line %u chain name invalid\n",
 
234
                                           program_name, line);
 
235
                                exit(1);
 
236
                        }
 
237
 
 
238
                        if (iptc_builtin(chain, handle) <= 0) {
 
239
                                if (noflush && iptc_is_chain(chain, handle)) {
 
240
                                        DEBUGP("Flushing existing user defined chain '%s'\n", chain);
 
241
                                        if (!iptc_flush_entries(chain, &handle))
 
242
                                                exit_error(PARAMETER_PROBLEM,
 
243
                                                           "error flushing chain "
 
244
                                                           "'%s':%s\n", chain,
 
245
                                                           strerror(errno));
 
246
                                } else {
 
247
                                        DEBUGP("Creating new chain '%s'\n", chain);
 
248
                                        if (!iptc_create_chain(chain, &handle))
 
249
                                                exit_error(PARAMETER_PROBLEM,
 
250
                                                           "error creating chain "
 
251
                                                           "'%s':%s\n", chain,
 
252
                                                           strerror(errno));
 
253
                                }
 
254
                        }
 
255
 
 
256
                        policy = strtok(NULL, " \t\n");
 
257
                        DEBUGP("line %u, policy '%s'\n", line, policy);
 
258
                        if (!policy) {
 
259
                                exit_error(PARAMETER_PROBLEM,
 
260
                                           "%s: line %u policy invalid\n",
 
261
                                           program_name, line);
 
262
                                exit(1);
 
263
                        }
 
264
 
 
265
                        if (strcmp(policy, "-") != 0) {
 
266
                                struct ipt_counters count;
 
267
 
 
268
                                if (counters) {
 
269
                                        char *ctrs;
 
270
                                        ctrs = strtok(NULL, " \t\n");
 
271
 
 
272
                                        if (!ctrs || !parse_counters(ctrs, &count))
 
273
                                                exit_error(PARAMETER_PROBLEM,
 
274
                                                           "invalid policy counters "
 
275
                                                           "for chain '%s'\n", chain);
 
276
 
 
277
                                } else {
 
278
                                        memset(&count, 0, 
 
279
                                               sizeof(struct ipt_counters));
 
280
                                }
 
281
 
 
282
                                DEBUGP("Setting policy of chain %s to %s\n",
 
283
                                        chain, policy);
 
284
 
 
285
                                if (!iptc_set_policy(chain, policy, &count,
 
286
                                                     &handle))
 
287
                                        exit_error(OTHER_PROBLEM,
 
288
                                                "Can't set policy `%s'"
 
289
                                                " on `%s' line %u: %s\n",
 
290
                                                chain, policy, line,
 
291
                                                iptc_strerror(errno));
 
292
                        }
 
293
 
 
294
                        ret = 1;
 
295
 
 
296
                } else if (in_table) {
 
297
                        int a;
 
298
                        char *ptr = buffer;
 
299
                        char *pcnt = NULL;
 
300
                        char *bcnt = NULL;
 
301
                        char *parsestart;
 
302
 
 
303
                        /* the parser */
 
304
                        char *param_start, *curchar;
 
305
                        int quote_open;
 
306
 
 
307
                        /* reset the newargv */
 
308
                        newargc = 0;
 
309
 
 
310
                        if (buffer[0] == '[') {
 
311
                                /* we have counters in our input */
 
312
                                ptr = strchr(buffer, ']');
 
313
                                if (!ptr)
 
314
                                        exit_error(PARAMETER_PROBLEM,
 
315
                                                   "Bad line %u: need ]\n",
 
316
                                                   line);
 
317
 
 
318
                                pcnt = strtok(buffer+1, ":");
 
319
                                if (!pcnt)
 
320
                                        exit_error(PARAMETER_PROBLEM,
 
321
                                                   "Bad line %u: need :\n",
 
322
                                                   line);
 
323
 
 
324
                                bcnt = strtok(NULL, "]");
 
325
                                if (!bcnt)
 
326
                                        exit_error(PARAMETER_PROBLEM,
 
327
                                                   "Bad line %u: need ]\n",
 
328
                                                   line);
 
329
 
 
330
                                /* start command parsing after counter */
 
331
                                parsestart = ptr + 1;
 
332
                        } else {
 
333
                                /* start command parsing at start of line */
 
334
                                parsestart = buffer;
 
335
                        }
 
336
 
 
337
                        add_argv(argv[0]);
 
338
                        add_argv("-t");
 
339
                        add_argv((char *) &curtable);
 
340
                        
 
341
                        if (counters && pcnt && bcnt) {
 
342
                                add_argv("--set-counters");
 
343
                                add_argv((char *) pcnt);
 
344
                                add_argv((char *) bcnt);
 
345
                        }
 
346
 
 
347
                        /* After fighting with strtok enough, here's now
 
348
                         * a 'real' parser. According to Rusty I'm now no
 
349
                         * longer a real hacker, but I can live with that */
 
350
 
 
351
                        quote_open = 0;
 
352
                        param_start = parsestart;
 
353
                        
 
354
                        for (curchar = parsestart; *curchar; curchar++) {
 
355
                                if (*curchar == '"') {
 
356
                                        /* quote_open cannot be true if there
 
357
                                         * was no previous character.  Thus, 
 
358
                                         * curchar-1 has to be within bounds */
 
359
                                        if (quote_open && 
 
360
                                            *(curchar-1) != '\\') {
 
361
                                                quote_open = 0;
 
362
                                                *curchar = ' ';
 
363
                                        } else {
 
364
                                                quote_open = 1;
 
365
                                                param_start++;
 
366
                                        }
 
367
                                } 
 
368
                                if (*curchar == ' '
 
369
                                    || *curchar == '\t'
 
370
                                    || * curchar == '\n') {
 
371
                                        char param_buffer[1024];
 
372
                                        int param_len = curchar-param_start;
 
373
 
 
374
                                        if (quote_open)
 
375
                                                continue;
 
376
 
 
377
                                        if (!param_len) {
 
378
                                                /* two spaces? */
 
379
                                                param_start++;
 
380
                                                continue;
 
381
                                        }
 
382
                                        
 
383
                                        /* end of one parameter */
 
384
                                        strncpy(param_buffer, param_start,
 
385
                                                param_len);
 
386
                                        *(param_buffer+param_len) = '\0';
 
387
 
 
388
                                        /* check if table name specified */
 
389
                                        if (!strncmp(param_buffer, "-t", 3)
 
390
                                            || !strncmp(param_buffer, "--table", 8)) {
 
391
                                                exit_error(PARAMETER_PROBLEM, 
 
392
                                                   "Line %u seems to have a "
 
393
                                                   "-t table option.\n", line);
 
394
                                                exit(1);
 
395
                                        }
 
396
 
 
397
                                        add_argv(param_buffer);
 
398
                                        param_start += param_len + 1;
 
399
                                } else {
 
400
                                        /* regular character, skip */
 
401
                                }
 
402
                        }
 
403
 
 
404
                        DEBUGP("calling do_command(%u, argv, &%s, handle):\n",
 
405
                                newargc, curtable);
 
406
 
 
407
                        for (a = 0; a < newargc; a++)
 
408
                                DEBUGP("argv[%u]: %s\n", a, newargv[a]);
 
409
 
 
410
                        ret = do_command(newargc, newargv, 
 
411
                                         &newargv[2], &handle);
 
412
 
 
413
                        free_argv();
 
414
                }
 
415
                if (!ret) {
 
416
                        fprintf(stderr, "%s: line %u failed\n",
 
417
                                        program_name, line);
 
418
                        exit(1);
 
419
                }
 
420
        }
 
421
        if (in_table) {
 
422
                fprintf(stderr, "%s: COMMIT expected at line %u\n",
 
423
                                program_name, line + 1);
 
424
                exit(1);
 
425
        }
 
426
 
 
427
        return 0;
 
428
}