iptables-save.c revision f643eb37e49a212d40eb060bcdfafbc366c0d616
1/* Code to save the iptables state, in human readable-form. */ 2/* (C) 1999 by Paul 'Rusty' Russell <rusty@rustcorp.com.au> and 3 * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org> 4 * 5 * This code is distributed under the terms of GNU GPL v2 6 * 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 "libiptc/libiptc.h" 17#include "iptables.h" 18#include "iptables-multi.h" 19 20#ifndef NO_SHARED_LIBS 21#include <dlfcn.h> 22#endif 23 24static int show_binary = 0, show_counters = 0; 25 26static const struct option options[] = { 27 {.name = "binary", .has_arg = false, .val = 'b'}, 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/* Debugging prototype. */ 36static int for_each_table(int (*func)(const char *tablename)) 37{ 38 int ret = 1; 39 FILE *procfile = NULL; 40 char tablename[IPT_TABLE_MAXNAMELEN+1]; 41 42 procfile = fopen("/proc/net/ip_tables_names", "re"); 43 if (!procfile) 44 return ret; 45 46 while (fgets(tablename, sizeof(tablename), procfile)) { 47 if (tablename[strlen(tablename) - 1] != '\n') 48 xtables_error(OTHER_PROBLEM, 49 "Badly formed tablename `%s'\n", 50 tablename); 51 tablename[strlen(tablename) - 1] = '\0'; 52 ret &= func(tablename); 53 } 54 55 fclose(procfile); 56 return ret; 57} 58 59 60static int do_output(const char *tablename) 61{ 62 struct iptc_handle *h; 63 const char *chain = NULL; 64 65 if (!tablename) 66 return for_each_table(&do_output); 67 68 h = iptc_init(tablename); 69 if (h == NULL) { 70 xtables_load_ko(xtables_modprobe_program, false); 71 h = iptc_init(tablename); 72 } 73 if (!h) 74 xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n", 75 iptc_strerror(errno)); 76 77 if (!show_binary) { 78 time_t now = time(NULL); 79 80 printf("# Generated by iptables-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 = iptc_first_chain(h); 87 chain; 88 chain = iptc_next_chain(h)) { 89 90 printf(":%s ", chain); 91 if (iptc_builtin(chain, h)) { 92 struct ipt_counters count; 93 printf("%s ", 94 iptc_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 102 for (chain = iptc_first_chain(h); 103 chain; 104 chain = iptc_next_chain(h)) { 105 const struct ipt_entry *e; 106 107 /* Dump out rules */ 108 e = iptc_first_rule(chain, h); 109 while(e) { 110 print_rule4(e, h, chain, show_counters); 111 e = iptc_next_rule(e, h); 112 } 113 } 114 115 now = time(NULL); 116 printf("COMMIT\n"); 117 printf("# Completed on %s", ctime(&now)); 118 } else { 119 /* Binary, huh? OK. */ 120 xtables_error(OTHER_PROBLEM, "Binary NYI\n"); 121 } 122 123 iptc_free(h); 124 125 return 1; 126} 127 128/* Format: 129 * :Chain name POLICY packets bytes 130 * rule 131 */ 132int 133iptables_save_main(int argc, char *argv[]) 134{ 135 const char *tablename = NULL; 136 int c; 137 138 iptables_globals.program_name = "iptables-save"; 139 c = xtables_init_all(&iptables_globals, NFPROTO_IPV4); 140 if (c < 0) { 141 fprintf(stderr, "%s/%s Failed to initialize xtables\n", 142 iptables_globals.program_name, 143 iptables_globals.program_version); 144 exit(1); 145 } 146#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) 147 init_extensions(); 148 init_extensions4(); 149#endif 150 151 while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) { 152 switch (c) { 153 case 'b': 154 show_binary = 1; 155 break; 156 157 case 'c': 158 show_counters = 1; 159 break; 160 161 case 't': 162 /* Select specific table. */ 163 tablename = optarg; 164 break; 165 case 'M': 166 xtables_modprobe_program = optarg; 167 break; 168 case 'd': 169 do_output(tablename); 170 exit(0); 171 } 172 } 173 174 if (optind < argc) { 175 fprintf(stderr, "Unknown arguments found on commandline\n"); 176 exit(1); 177 } 178 179 return !do_output(tablename); 180} 181