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 <time.h> 15#include <netdb.h> 16#include <arpa/inet.h> 17#include "libiptc/libip6tc.h" 18#include "ip6tables.h" 19#include "ip6tables-multi.h" 20 21#ifndef NO_SHARED_LIBS 22#include <dlfcn.h> 23#endif 24 25static int show_counters = 0; 26 27static const struct option options[] = { 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 {.name = "modprobe", .has_arg = true, .val = 'M'}, 32 {NULL}, 33}; 34 35 36/* Debugging prototype. */ 37static int for_each_table(int (*func)(const char *tablename)) 38{ 39 int ret = 1; 40 FILE *procfile = NULL; 41 char tablename[XT_TABLE_MAXNAMELEN+1]; 42 43 procfile = fopen("/proc/net/ip6_tables_names", "re"); 44 if (!procfile) 45 return ret; 46 47 while (fgets(tablename, sizeof(tablename), procfile)) { 48 if (tablename[strlen(tablename) - 1] != '\n') 49 xtables_error(OTHER_PROBLEM, 50 "Badly formed tablename `%s'\n", 51 tablename); 52 tablename[strlen(tablename) - 1] = '\0'; 53 ret &= func(tablename); 54 } 55 56 fclose(procfile); 57 return ret; 58} 59 60 61static int do_output(const char *tablename) 62{ 63 struct xtc_handle *h; 64 const char *chain = NULL; 65 66 if (!tablename) 67 return for_each_table(&do_output); 68 69 h = ip6tc_init(tablename); 70 if (h == NULL) { 71 xtables_load_ko(xtables_modprobe_program, false); 72 h = ip6tc_init(tablename); 73 } 74 if (!h) 75 xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n", 76 ip6tc_strerror(errno)); 77 78 time_t now = time(NULL); 79 80 printf("# Generated by ip6tables-save v%s on %s", 81 IPTABLES_VERSION, ctime(&now)); 82 printf("*%s\n", tablename); 83 84 /* Dump out chain names first, 85 * thereby preventing dependency conflicts */ 86 for (chain = ip6tc_first_chain(h); 87 chain; 88 chain = ip6tc_next_chain(h)) { 89 90 printf(":%s ", chain); 91 if (ip6tc_builtin(chain, h)) { 92 struct xt_counters count; 93 printf("%s ", 94 ip6tc_get_policy(chain, &count, h)); 95 printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); 96 } else { 97 printf("- [0:0]\n"); 98 } 99 } 100 101 for (chain = ip6tc_first_chain(h); 102 chain; 103 chain = ip6tc_next_chain(h)) { 104 const struct ip6t_entry *e; 105 106 /* Dump out rules */ 107 e = ip6tc_first_rule(chain, h); 108 while(e) { 109 print_rule6(e, h, chain, show_counters); 110 e = ip6tc_next_rule(e, h); 111 } 112 } 113 114 now = time(NULL); 115 printf("COMMIT\n"); 116 printf("# Completed on %s", ctime(&now)); 117 ip6tc_free(h); 118 119 return 1; 120} 121 122/* Format: 123 * :Chain name POLICY packets bytes 124 * rule 125 */ 126int ip6tables_save_main(int argc, char *argv[]) 127{ 128 const char *tablename = NULL; 129 int c; 130 131 ip6tables_globals.program_name = "ip6tables-save"; 132 c = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6); 133 if (c < 0) { 134 fprintf(stderr, "%s/%s Failed to initialize xtables\n", 135 ip6tables_globals.program_name, 136 ip6tables_globals.program_version); 137 exit(1); 138 } 139#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) 140 init_extensions(); 141 init_extensions6(); 142#endif 143 144 while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) { 145 switch (c) { 146 case 'c': 147 show_counters = 1; 148 break; 149 150 case 't': 151 /* Select specific table. */ 152 tablename = optarg; 153 break; 154 case 'M': 155 xtables_modprobe_program = optarg; 156 break; 157 case 'd': 158 do_output(tablename); 159 exit(0); 160 } 161 } 162 163 if (optind < argc) { 164 fprintf(stderr, "Unknown arguments found on commandline\n"); 165 exit(1); 166 } 167 168 return !do_output(tablename); 169} 170