12f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó/* Code to save the ip6tables state, in human readable-form. */
22f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó/* Author:  Andras Kis-Szabo <kisza@sch.bme.hu>
32f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó * Original code: iptables-save
42f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó * Authors: Paul 'Rusty' Russel <rusty@linuxcare.com.au> and
55b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann *          Harald Welte <laforge@gnumonks.org>
60c4188f446e7c0ed07076c69d1d7f336a92efc8bAndrás Kis-Szabó * This code is distributed under the terms of GNU GPL v2
72f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó */
82f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <getopt.h>
92f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <sys/errno.h>
102f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <stdio.h>
112f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <fcntl.h>
122f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <stdlib.h>
132f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <string.h>
142f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <time.h>
152f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <netdb.h>
162f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <arpa/inet.h>
172f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include "libiptc/libip6tc.h"
182f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include "ip6tables.h"
1933690a1aec0b6309ff90066ca56285b6e43013f2Jan Engelhardt#include "ip6tables-multi.h"
202f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
215a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS
225a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h>
235a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif
245a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger
25dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardtstatic int show_binary = 0, show_counters = 0;
262f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
277bc3cb7eec4c4db5edc4b503a5dfab799e0bce62Gáspár Lajosstatic const struct option options[] = {
287bc3cb7eec4c4db5edc4b503a5dfab799e0bce62Gáspár Lajos	{.name = "binary",   .has_arg = false, .val = 'b'},
297bc3cb7eec4c4db5edc4b503a5dfab799e0bce62Gáspár Lajos	{.name = "counters", .has_arg = false, .val = 'c'},
307bc3cb7eec4c4db5edc4b503a5dfab799e0bce62Gáspár Lajos	{.name = "dump",     .has_arg = false, .val = 'd'},
317bc3cb7eec4c4db5edc4b503a5dfab799e0bce62Gáspár Lajos	{.name = "table",    .has_arg = true,  .val = 't'},
32fbb5639c02218acfd84c4f25f134efecb564fee1Jan Engelhardt	{.name = "modprobe", .has_arg = true,  .val = 'M'},
337bc3cb7eec4c4db5edc4b503a5dfab799e0bce62Gáspár Lajos	{NULL},
342f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó};
352f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
362f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
372f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó/* Debugging prototype. */
382f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabóstatic int for_each_table(int (*func)(const char *tablename))
392f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó{
405b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann	int ret = 1;
412f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	FILE *procfile = NULL;
422f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	char tablename[IP6T_TABLE_MAXNAMELEN+1];
432f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
44a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	procfile = fopen("/proc/net/ip6_tables_names", "re");
452f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	if (!procfile)
46fbb5639c02218acfd84c4f25f134efecb564fee1Jan Engelhardt		return ret;
472f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
482f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	while (fgets(tablename, sizeof(tablename), procfile)) {
492f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		if (tablename[strlen(tablename) - 1] != '\n')
501829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt			xtables_error(OTHER_PROBLEM,
512f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				   "Badly formed tablename `%s'\n",
522f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				   tablename);
532f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		tablename[strlen(tablename) - 1] = '\0';
542f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		ret &= func(tablename);
552f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	}
562f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
57f1afcc896e7f8be3a6419681fd8cdee1d600a3aaJan Engelhardt	fclose(procfile);
582f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	return ret;
592f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó}
605b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann
612f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
622f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabóstatic int do_output(const char *tablename)
632f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó{
64fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt	struct ip6tc_handle *h;
652f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	const char *chain = NULL;
662f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
672f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	if (!tablename)
682f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		return for_each_table(&do_output);
692f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
702f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	h = ip6tc_init(tablename);
71fbb5639c02218acfd84c4f25f134efecb564fee1Jan Engelhardt	if (h == NULL) {
72fbb5639c02218acfd84c4f25f134efecb564fee1Jan Engelhardt		xtables_load_ko(xtables_modprobe_program, false);
73fbb5639c02218acfd84c4f25f134efecb564fee1Jan Engelhardt		h = ip6tc_init(tablename);
74fbb5639c02218acfd84c4f25f134efecb564fee1Jan Engelhardt	}
752f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	if (!h)
761829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt		xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n",
772f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			   ip6tc_strerror(errno));
782f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
79dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt	if (!show_binary) {
802f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		time_t now = time(NULL);
812f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
822f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		printf("# Generated by ip6tables-save v%s on %s",
83dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		       IPTABLES_VERSION, ctime(&now));
842f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		printf("*%s\n", tablename);
852f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
865b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann		/* Dump out chain names first,
87885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte		 * thereby preventing dependency conflicts */
881c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt		for (chain = ip6tc_first_chain(h);
892f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		     chain;
901c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt		     chain = ip6tc_next_chain(h)) {
912f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
922f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			printf(":%s ", chain);
932f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			if (ip6tc_builtin(chain, h)) {
942f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				struct ip6t_counters count;
952f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				printf("%s ",
961c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt				       ip6tc_get_policy(chain, &count, h));
97a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson				printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt);
982f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			} else {
992f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				printf("- [0:0]\n");
1002f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			}
101885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte		}
102885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
10397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó
1041c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt		for (chain = ip6tc_first_chain(h);
105885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte		     chain;
1061c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt		     chain = ip6tc_next_chain(h)) {
10797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			const struct ip6t_entry *e;
1082f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1092f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			/* Dump out rules */
1101c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt			e = ip6tc_first_rule(chain, h);
1112f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			while(e) {
1129680f2ecbdb7e5c61ab60e7399e9ca9f1013fd8dMaciej Zenczykowski				print_rule6(e, h, chain, show_counters);
1131c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt				e = ip6tc_next_rule(e, h);
1142f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			}
1152f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		}
1162f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1172f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		now = time(NULL);
1182f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		printf("COMMIT\n");
1192f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		printf("# Completed on %s", ctime(&now));
1202f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	} else {
1212f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		/* Binary, huh?  OK. */
1221829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt		xtables_error(OTHER_PROBLEM, "Binary NYI\n");
1232f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	}
1242f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1251c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt	ip6tc_free(h);
126841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson
1272f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	return 1;
1282f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó}
1292f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1302f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó/* Format:
1312f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó * :Chain name POLICY packets bytes
1322f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó * rule
1332f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó */
1344bc48331d2d1ef64ba452329f2c77137036f6437Hann-Huei Chiou#ifdef IPTABLES_MULTI
1354bc48331d2d1ef64ba452329f2c77137036f6437Hann-Huei Chiouint ip6tables_save_main(int argc, char *argv[])
1364bc48331d2d1ef64ba452329f2c77137036f6437Hann-Huei Chiou#else
1372f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabóint main(int argc, char *argv[])
1384bc48331d2d1ef64ba452329f2c77137036f6437Hann-Huei Chiou#endif
1392f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó{
1402f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	const char *tablename = NULL;
1412f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	int c;
1422f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
143617d3d140f4739558dce2ef8ed01aef251cf5487Jamal Hadi Salim	ip6tables_globals.program_name = "ip6tables-save";
1447e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	c = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6);
1457e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (c < 0) {
1467e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		fprintf(stderr, "%s/%s Failed to initialize xtables\n",
1477e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim				ip6tables_globals.program_name,
1487e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim				ip6tables_globals.program_version);
1497e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		exit(1);
1507e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	}
151b79ec69027fd8b65e7eccd78a445b6665e8ad53bJan Engelhardt#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
1529a9694fbf1796a6a5011b60b2a15c01fa3c61368Maciej Żenczykowski	init_extensions();
15349d8c5d564cad70c5c1bef2d5571e8e494454210Maciej Zenczykowski	init_extensions6();
1543efb6ead2e51fe1eca55bcb2b06afb4dc4b8cb7cHarald Welte#endif
1553efb6ead2e51fe1eca55bcb2b06afb4dc4b8cb7cHarald Welte
15697fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó	while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) {
1572f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		switch (c) {
1582f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		case 'b':
159dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt			show_binary = 1;
1602f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			break;
1612f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1622f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		case 'c':
163dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt			show_counters = 1;
1642f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			break;
1652f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1662f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		case 't':
1672f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			/* Select specific table. */
1682f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			tablename = optarg;
1692f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			break;
170fbb5639c02218acfd84c4f25f134efecb564fee1Jan Engelhardt		case 'M':
171fbb5639c02218acfd84c4f25f134efecb564fee1Jan Engelhardt			xtables_modprobe_program = optarg;
172fbb5639c02218acfd84c4f25f134efecb564fee1Jan Engelhardt			break;
1732f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		case 'd':
1742f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			do_output(tablename);
1752f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			exit(0);
1762f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		}
1772f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	}
1782f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1792f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	if (optind < argc) {
180972af09e79618c5086e26ef6438bd38c45c4bb3fPavel Rusnak		fprintf(stderr, "Unknown arguments found on commandline\n");
1812f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		exit(1);
1822f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	}
1832f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1842f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	return !do_output(tablename);
1852f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó}
186