bug fix
[iptables.git] / iptables-save.c
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
24 static int show_binary = 0, show_counters = 0;
25
26 static 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         {NULL},
32 };
33
34 /* Debugging prototype. */
35 static int for_each_table(int (*func)(const char *tablename))
36 {
37         int ret = 1;
38         FILE *procfile = NULL;
39         char tablename[IPT_TABLE_MAXNAMELEN+1];
40
41         procfile = fopen("/proc/net/ip_tables_names", "r");
42         if (!procfile)
43                 exit_error(OTHER_PROBLEM,
44                            "Unable to open /proc/net/ip_tables_names: %s\n",
45                            strerror(errno));
46
47         while (fgets(tablename, sizeof(tablename), procfile)) {
48                 if (tablename[strlen(tablename) - 1] != '\n')
49                         exit_error(OTHER_PROBLEM, 
50                                    "Badly formed tablename `%s'\n",
51                                    tablename);
52                 tablename[strlen(tablename) - 1] = '\0';
53                 ret &= func(tablename);
54         }
55
56         return ret;
57 }
58
59
60 static int do_output(const char *tablename)
61 {
62         iptc_handle_t 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)
70                 exit_error(OTHER_PROBLEM, "Can't initialize: %s\n",
71                            iptc_strerror(errno));
72
73         if (!show_binary) {
74                 time_t now = time(NULL);
75
76                 printf("# Generated by iptables-save v%s on %s",
77                        XTABLES_VERSION, ctime(&now));
78                 printf("*%s\n", tablename);
79
80                 /* Dump out chain names first,
81                  * thereby preventing dependency conflicts */
82                 for (chain = iptc_first_chain(&h);
83                      chain;
84                      chain = iptc_next_chain(&h)) {
85
86                         printf(":%s ", chain);
87                         if (iptc_builtin(chain, h)) {
88                                 struct ipt_counters count;
89                                 printf("%s ",
90                                        iptc_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
98                 for (chain = iptc_first_chain(&h);
99                      chain;
100                      chain = iptc_next_chain(&h)) {
101                         const struct ipt_entry *e;
102
103                         /* Dump out rules */
104                         e = iptc_first_rule(chain, &h);
105                         while(e) {
106                                 print_rule(e, &h, chain, show_counters);
107                                 e = iptc_next_rule(e, &h);
108                         }
109                 }
110
111                 now = time(NULL);
112                 printf("COMMIT\n");
113                 printf("# Completed on %s", ctime(&now));
114         } else {
115                 /* Binary, huh?  OK. */
116                 exit_error(OTHER_PROBLEM, "Binary NYI\n");
117         }
118
119         iptc_free(&h);
120
121         return 1;
122 }
123
124 /* Format:
125  * :Chain name POLICY packets bytes
126  * rule
127  */
128 #ifdef IPTABLES_MULTI
129 int
130 iptables_save_main(int argc, char *argv[])
131 #else
132 int
133 main(int argc, char *argv[])
134 #endif
135 {
136         const char *tablename = NULL;
137         int c;
138
139         program_name = "iptables-save";
140         program_version = XTABLES_VERSION;
141
142         lib_dir = getenv("XTABLES_LIBDIR");
143         if (lib_dir == NULL) {
144                 lib_dir = getenv("IPTABLES_LIB_DIR");
145                 if (lib_dir != NULL)
146                         fprintf(stderr, "IPTABLES_LIB_DIR is deprecated\n");
147         }
148         if (lib_dir == NULL)
149                 lib_dir = XTABLES_LIBDIR;
150
151 #ifdef NO_SHARED_LIBS
152         init_extensions();
153 #endif
154
155         while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) {
156                 switch (c) {
157                 case 'b':
158                         show_binary = 1;
159                         break;
160
161                 case 'c':
162                         show_counters = 1;
163                         break;
164
165                 case 't':
166                         /* Select specific table. */
167                         tablename = optarg;
168                         break;
169                 case 'd':
170                         do_output(tablename);
171                         exit(0);
172                 }
173         }
174
175         if (optind < argc) {
176                 fprintf(stderr, "Unknown arguments found on commandline\n");
177                 exit(1);
178         }
179
180         return !do_output(tablename);
181 }