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