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_binary = 0, show_counters = 0; 26 27static 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. */ 38static 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 62static 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 */ 134int ip6tables_save_main(int argc, char *argv[]) 135{ 136 const char *tablename = NULL; 137 int c; 138 139 ip6tables_globals.program_name = "ip6tables-save"; 140 c = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6); 141 if (c < 0) { 142 fprintf(stderr, "%s/%s Failed to initialize xtables\n", 143 ip6tables_globals.program_name, 144 ip6tables_globals.program_version); 145 exit(1); 146 } 147#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) 148 init_extensions(); 149 init_extensions6(); 150#endif 151 152 while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) { 153 switch (c) { 154 case 'b': 155 show_binary = 1; 156 break; 157 158 case 'c': 159 show_counters = 1; 160 break; 161 162 case 't': 163 /* Select specific table. */ 164 tablename = optarg; 165 break; 166 case 'M': 167 xtables_modprobe_program = optarg; 168 break; 169 case 'd': 170 do_output(tablename); 171 exit(0); 172 } 173 } 174 175 if (optind < argc) { 176 fprintf(stderr, "Unknown arguments found on commandline\n"); 177 exit(1); 178 } 179 180 return !do_output(tablename); 181} 182