1 /* Code to save the ip6tables state, in human readable-form. */ 2 /* Author: Andras Kis-Szabo <kisza (at) sch.bme.hu> 3 * Original code: iptables-save 4 * Authors: Paul 'Rusty' Russel <rusty (at) linuxcare.com.au> and 5 * Harald Welte <laforge (at) 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 25 static int show_binary = 0, show_counters = 0; 26 27 static const struct option options[] = { 28 {.name = "binary", .has_arg = false, .val = 'b'}, 29 {.name = "counters", .has_arg = false, .val = 'c'}, 30 {.name = "dump", .has_arg = false, .val = 'd'}, 31 {.name = "table", .has_arg = true, .val = 't'}, 32 {.name = "modprobe", .has_arg = true, .val = 'M'}, 33 {NULL}, 34 }; 35 36 37 /* Debugging prototype. */ 38 static int for_each_table(int (*func)(const char *tablename)) 39 { 40 int ret = 1; 41 FILE *procfile = NULL; 42 char tablename[IP6T_TABLE_MAXNAMELEN+1]; 43 44 procfile = fopen("/proc/net/ip6_tables_names", "re"); 45 if (!procfile) 46 return ret; 47 48 while (fgets(tablename, sizeof(tablename), procfile)) { 49 if (tablename[strlen(tablename) - 1] != '\n') 50 xtables_error(OTHER_PROBLEM, 51 "Badly formed tablename `%s'\n", 52 tablename); 53 tablename[strlen(tablename) - 1] = '\0'; 54 ret &= func(tablename); 55 } 56 57 fclose(procfile); 58 return ret; 59 } 60 61 62 static int do_output(const char *tablename) 63 { 64 struct ip6tc_handle *h; 65 const char *chain = NULL; 66 67 if (!tablename) 68 return for_each_table(&do_output); 69 70 h = ip6tc_init(tablename); 71 if (h == NULL) { 72 xtables_load_ko(xtables_modprobe_program, false); 73 h = ip6tc_init(tablename); 74 } 75 if (!h) 76 xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n", 77 ip6tc_strerror(errno)); 78 79 if (!show_binary) { 80 time_t now = time(NULL); 81 82 printf("# Generated by ip6tables-save v%s on %s", 83 IPTABLES_VERSION, ctime(&now)); 84 printf("*%s\n", tablename); 85 86 /* Dump out chain names first, 87 * thereby preventing dependency conflicts */ 88 for (chain = ip6tc_first_chain(h); 89 chain; 90 chain = ip6tc_next_chain(h)) { 91 92 printf(":%s ", chain); 93 if (ip6tc_builtin(chain, h)) { 94 struct ip6t_counters count; 95 printf("%s ", 96 ip6tc_get_policy(chain, &count, h)); 97 printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); 98 } else { 99 printf("- [0:0]\n"); 100 } 101 } 102 103 104 for (chain = ip6tc_first_chain(h); 105 chain; 106 chain = ip6tc_next_chain(h)) { 107 const struct ip6t_entry *e; 108 109 /* Dump out rules */ 110 e = ip6tc_first_rule(chain, h); 111 while(e) { 112 print_rule6(e, h, chain, show_counters); 113 e = ip6tc_next_rule(e, h); 114 } 115 } 116 117 now = time(NULL); 118 printf("COMMIT\n"); 119 printf("# Completed on %s", ctime(&now)); 120 } else { 121 /* Binary, huh? OK. */ 122 xtables_error(OTHER_PROBLEM, "Binary NYI\n"); 123 } 124 125 ip6tc_free(h); 126 127 return 1; 128 } 129 130 /* Format: 131 * :Chain name POLICY packets bytes 132 * rule 133 */ 134 #ifdef IPTABLES_MULTI 135 int ip6tables_save_main(int argc, char *argv[]) 136 #else 137 int main(int argc, char *argv[]) 138 #endif 139 { 140 const char *tablename = NULL; 141 int c; 142 143 ip6tables_globals.program_name = "ip6tables-save"; 144 c = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6); 145 if (c < 0) { 146 fprintf(stderr, "%s/%s Failed to initialize xtables\n", 147 ip6tables_globals.program_name, 148 ip6tables_globals.program_version); 149 exit(1); 150 } 151 #if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) 152 init_extensions(); 153 init_extensions6(); 154 #endif 155 156 while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) { 157 switch (c) { 158 case 'b': 159 show_binary = 1; 160 break; 161 162 case 'c': 163 show_counters = 1; 164 break; 165 166 case 't': 167 /* Select specific table. */ 168 tablename = optarg; 169 break; 170 case 'M': 171 xtables_modprobe_program = optarg; 172 break; 173 case 'd': 174 do_output(tablename); 175 exit(0); 176 } 177 } 178 179 if (optind < argc) { 180 fprintf(stderr, "Unknown arguments found on commandline\n"); 181 exit(1); 182 } 183 184 return !do_output(tablename); 185 } 186