dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / router / iptables / ip6tables-save.c
blob9173af197ba3b7d3212045ceb05894a4b6cc734d
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 <sys/errno.h>
10 #include <stdio.h>
11 #include <fcntl.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <dlfcn.h>
15 #include <time.h>
16 #include <netdb.h>
17 #include <arpa/inet.h>
18 #include "libiptc/libip6tc.h"
19 #include "ip6tables.h"
21 static int binary = 0, counters = 0;
23 static struct option options[] = {
24 { "binary", 0, 0, 'b' },
25 { "counters", 0, 0, 'c' },
26 { "dump", 0, 0, 'd' },
27 { "table", 1, 0, 't' },
28 { 0 }
32 /* This assumes that mask is contiguous, and byte-bounded. */
33 static void
34 print_iface(char letter, const char *iface, const unsigned char *mask,
35 int invert)
37 unsigned int i;
39 if (mask[0] == 0)
40 return;
42 printf("-%c %s", letter, invert ? "! " : "");
44 for (i = 0; i < IFNAMSIZ; i++) {
45 if (mask[i] != 0) {
46 if (iface[i] != '\0')
47 printf("%c", iface[i]);
48 } else {
49 /* we can access iface[i-1] here, because
50 * a few lines above we make sure that mask[0] != 0 */
51 if (iface[i-1] != '\0')
52 printf("+");
53 break;
57 printf(" ");
60 /* These are hardcoded backups in ip6tables.c, so they are safe */
61 struct pprot {
62 char *name;
63 u_int8_t num;
66 static const struct pprot chain_protos[] = {
67 { "tcp", IPPROTO_TCP },
68 { "udp", IPPROTO_UDP },
69 { "icmpv6", IPPROTO_ICMPV6 },
70 { "esp", IPPROTO_ESP },
71 { "ah", IPPROTO_AH },
74 /* The ip6tables looks up the /etc/protocols. */
75 static void print_proto(u_int16_t proto, int invert)
77 if (proto) {
78 unsigned int i;
79 const char *invertstr = invert ? "! " : "";
81 struct protoent *pent = getprotobynumber(proto);
82 if (pent) {
83 printf("-p %s%s ",
84 invertstr, pent->p_name);
85 return;
88 for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++)
89 if (chain_protos[i].num == proto) {
90 printf("-p %s%s ",
91 invertstr, chain_protos[i].name);
92 return;
95 printf("-p %s%u ", invertstr, proto);
99 static int print_match(const struct ip6t_entry_match *e,
100 const struct ip6t_ip6 *ip)
102 struct ip6tables_match *match
103 = find_match(e->u.user.name, TRY_LOAD, NULL);
105 if (match) {
106 printf("-m %s ", e->u.user.name);
108 /* some matches don't provide a save function */
109 if (match->save)
110 match->save(ip, e);
111 } else {
112 if (e->u.match_size) {
113 fprintf(stderr,
114 "Can't find library for match `%s'\n",
115 e->u.user.name);
116 exit(1);
119 return 0;
122 /* print a given ip including mask if neccessary */
123 static void print_ip(char *prefix, const struct in6_addr *ip, const struct in6_addr *mask, int invert)
125 char buf[51];
126 int l = ipv6_prefix_length(mask);
128 if (l == 0 && !invert)
129 return;
131 printf("%s %s%s",
132 prefix,
133 invert ? "! " : "",
134 inet_ntop(AF_INET6, ip, buf, sizeof buf));
136 if (l == -1)
137 printf("/%s ", inet_ntop(AF_INET6, mask, buf, sizeof buf));
138 else
139 printf("/%d ", l);
142 /* We want this to be readable, so only print out neccessary fields.
143 * Because that's the kind of world I want to live in. */
144 static void print_rule(const struct ip6t_entry *e,
145 ip6tc_handle_t *h, const char *chain, int counters)
147 struct ip6t_entry_target *t;
148 const char *target_name;
150 /* print counters */
151 if (counters)
152 printf("[%llu:%llu] ", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
154 /* print chain name */
155 printf("-A %s ", chain);
157 /* Print IP part. */
158 print_ip("-s", &(e->ipv6.src), &(e->ipv6.smsk),
159 e->ipv6.invflags & IP6T_INV_SRCIP);
161 print_ip("-d", &(e->ipv6.dst), &(e->ipv6.dmsk),
162 e->ipv6.invflags & IP6T_INV_DSTIP);
164 print_iface('i', e->ipv6.iniface, e->ipv6.iniface_mask,
165 e->ipv6.invflags & IP6T_INV_VIA_IN);
167 print_iface('o', e->ipv6.outiface, e->ipv6.outiface_mask,
168 e->ipv6.invflags & IP6T_INV_VIA_OUT);
170 print_proto(e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO);
172 #if 0
173 /* not definied in ipv6
174 * FIXME: linux/netfilter_ipv6/ip6_tables: IP6T_INV_FRAG why definied? */
175 if (e->ipv6.flags & IPT_F_FRAG)
176 printf("%s-f ",
177 e->ipv6.invflags & IP6T_INV_FRAG ? "! " : "");
178 #endif
180 if (e->ipv6.flags & IP6T_F_TOS)
181 printf("%s-? %d ",
182 e->ipv6.invflags & IP6T_INV_TOS ? "! " : "",
183 e->ipv6.tos);
185 /* Print matchinfo part */
186 if (e->target_offset) {
187 IP6T_MATCH_ITERATE(e, print_match, &e->ipv6);
190 /* Print target name */
191 target_name = ip6tc_get_target(e, h);
192 if (target_name && (*target_name != '\0'))
193 #ifdef IP6T_F_GOTO
194 printf("-%c %s ", e->ipv6.flags & IP6T_F_GOTO ? 'g' : 'j', target_name);
195 #else
196 printf("-j %s ", target_name);
197 #endif
199 /* Print targinfo part */
200 t = ip6t_get_target((struct ip6t_entry *)e);
201 if (t->u.user.name[0]) {
202 struct ip6tables_target *target
203 = find_target(t->u.user.name, TRY_LOAD);
205 if (!target) {
206 fprintf(stderr, "Can't find library for target `%s'\n",
207 t->u.user.name);
208 exit(1);
211 if (target->save)
212 target->save(&e->ipv6, t);
213 else {
214 /* If the target size is greater than ip6t_entry_target
215 * there is something to be saved, we just don't know
216 * how to print it */
217 if (t->u.target_size !=
218 sizeof(struct ip6t_entry_target)) {
219 fprintf(stderr, "Target `%s' is missing "
220 "save function\n",
221 t->u.user.name);
222 exit(1);
226 printf("\n");
229 /* Debugging prototype. */
230 static int for_each_table(int (*func)(const char *tablename))
232 int ret = 1;
233 FILE *procfile = NULL;
234 char tablename[IP6T_TABLE_MAXNAMELEN+1];
236 procfile = fopen("/proc/net/ip6_tables_names", "r");
237 if (!procfile)
238 return 0;
240 while (fgets(tablename, sizeof(tablename), procfile)) {
241 if (tablename[strlen(tablename) - 1] != '\n')
242 exit_error(OTHER_PROBLEM,
243 "Badly formed tablename `%s'\n",
244 tablename);
245 tablename[strlen(tablename) - 1] = '\0';
246 ret &= func(tablename);
249 return ret;
253 static int do_output(const char *tablename)
255 ip6tc_handle_t h;
256 const char *chain = NULL;
258 if (!tablename)
259 return for_each_table(&do_output);
261 h = ip6tc_init(tablename);
262 if (!h)
263 exit_error(OTHER_PROBLEM, "Can't initialize: %s\n",
264 ip6tc_strerror(errno));
266 if (!binary) {
267 time_t now = time(NULL);
269 printf("# Generated by ip6tables-save v%s on %s",
270 IPTABLES_VERSION, ctime(&now));
271 printf("*%s\n", tablename);
273 /* Dump out chain names first,
274 * thereby preventing dependency conflicts */
275 for (chain = ip6tc_first_chain(&h);
276 chain;
277 chain = ip6tc_next_chain(&h)) {
279 printf(":%s ", chain);
280 if (ip6tc_builtin(chain, h)) {
281 struct ip6t_counters count;
282 printf("%s ",
283 ip6tc_get_policy(chain, &count, &h));
284 printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt);
285 } else {
286 printf("- [0:0]\n");
291 for (chain = ip6tc_first_chain(&h);
292 chain;
293 chain = ip6tc_next_chain(&h)) {
294 const struct ip6t_entry *e;
296 /* Dump out rules */
297 e = ip6tc_first_rule(chain, &h);
298 while(e) {
299 print_rule(e, &h, chain, counters);
300 e = ip6tc_next_rule(e, &h);
304 now = time(NULL);
305 printf("COMMIT\n");
306 printf("# Completed on %s", ctime(&now));
307 } else {
308 /* Binary, huh? OK. */
309 exit_error(OTHER_PROBLEM, "Binary NYI\n");
312 ip6tc_free(&h);
314 return 1;
317 /* Format:
318 * :Chain name POLICY packets bytes
319 * rule
321 #ifdef IPTABLES_MULTI
322 int ip6tables_save_main(int argc, char *argv[])
323 #else
324 int main(int argc, char *argv[])
325 #endif
327 const char *tablename = NULL;
328 int c;
330 program_name = "ip6tables-save";
331 program_version = IPTABLES_VERSION;
333 lib_dir = getenv("IP6TABLES_LIB_DIR");
334 if (!lib_dir)
335 lib_dir = IP6T_LIB_DIR;
337 #ifdef NO_SHARED_LIBS
338 init_extensions();
339 #endif
341 while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) {
342 switch (c) {
343 case 'b':
344 binary = 1;
345 break;
347 case 'c':
348 counters = 1;
349 break;
351 case 't':
352 /* Select specific table. */
353 tablename = optarg;
354 break;
355 case 'd':
356 do_output(tablename);
357 exit(0);
361 if (optind < argc) {
362 fprintf(stderr, "Unknown arguments found on commandline\n");
363 exit(1);
366 return !do_output(tablename);