iptables-save.c revision d8e6563430ab692cf093a81b9b6ac997739d9504
1e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Code to save the iptables state, in human readable-form. */ 2ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte/* Authors: Paul 'Rusty' Russel <rusty@linuxcare.com.au> and 3ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte * Harald Welte <laforge@gnumonks.org> 4ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte */ 5e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <getopt.h> 6e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <sys/errno.h> 7e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <stdio.h> 8ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte#include <fcntl.h> 9ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte#include <stdlib.h> 10ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte#include <string.h> 11e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <dlfcn.h> 12e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <time.h> 13b1f69befb5b35d0cbf607ed13a6e823a94cb79ffRusty Russell#include "libiptc/libiptc.h" 14b1f69befb5b35d0cbf607ed13a6e823a94cb79ffRusty Russell#include "iptables.h" 15e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 16a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russellstatic int binary = 0, counters = 0; 17a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 18e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic struct option options[] = { 19a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell { "binary", 0, 0, 'b' }, 20a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell { "counters", 0, 0, 'c' }, 21a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell { "dump", 0, 0, 'd' }, 22a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell { "table", 1, 0, 't' }, 23e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher { 0 } 24e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 25e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 26e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#define IP_PARTS_NATIVE(n) \ 27e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher(unsigned int)((n)>>24)&0xFF, \ 28e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher(unsigned int)((n)>>16)&0xFF, \ 29e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher(unsigned int)((n)>>8)&0xFF, \ 30e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher(unsigned int)((n)&0xFF) 31e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 32e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n)) 33e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 34e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* This assumes that mask is contiguous, and byte-bounded. */ 35e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 36e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherprint_iface(char letter, const char *iface, const unsigned char *mask, 37e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int invert) 38e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 39e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 40e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 41e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (mask[0] == 0) 42e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return; 437e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 44e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("-%c %s", letter, invert ? "! " : ""); 45e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 46e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < IFNAMSIZ; i++) { 47e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (mask[i] != 0) { 48e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (iface[i] != '\0') 49e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("%c", iface[i]); 50e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 51e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (iface[i] != '\0') 52e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("+"); 53e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 54e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 55e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 56ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 57ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf(" "); 58e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 59e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 60e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* These are hardcoded backups in iptables.c, so they are safe */ 61e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstruct pprot { 62e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher char *name; 63e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher u_int8_t num; 64e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 65e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 66ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte/* FIXME: why don't we use /etc/services ? */ 67e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic const struct pprot chain_protos[] = { 68e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher { "tcp", IPPROTO_TCP }, 69e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher { "udp", IPPROTO_UDP }, 70e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher { "icmp", IPPROTO_ICMP }, 71e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 72e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 73e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void print_proto(u_int16_t proto, int invert) 74e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 75e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (proto) { 76e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 77e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *invertstr = invert ? "! " : ""; 78e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 79e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++) 80e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (chain_protos[i].num == proto) { 81e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("-p %s%s ", 82e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher invertstr, chain_protos[i].name); 83e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return; 84e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 85e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 86e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("-p %s%u ", invertstr, proto); 87e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 88e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 89e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 90ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte#if 0 91e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int non_zero(const void *ptr, size_t size) 92e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 93e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 94e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 95e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < size; i++) 96e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (((char *)ptr)[i]) 97e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 98e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 99e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 100e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 101ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte#endif 102ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 103ae1ff9f96a80379a650dec979b9902528a10d45aHarald Weltestatic int print_match(const struct ipt_entry_match *e) 104ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte{ 105ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte struct iptables_match *match 106ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte = find_match(e->u.user.name, TRY_LOAD); 107ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 108ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (match) { 109ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf("-m %s ", e->u.user.name); 110ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte match->save(NULL, e); 111ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte } else { 112ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (e->u.match_size) { 113ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte fprintf(stderr, 114ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte "Can't find library for match `%s'\n", 115ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte e->u.user.name); 116ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte exit(1); 117ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte } 118ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte } 119ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte return 0; 120ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte} 121ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 122ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte/* print a given ip including mask if neccessary */ 123ae1ff9f96a80379a650dec979b9902528a10d45aHarald Weltestatic void print_ip(char *prefix, u_int32_t ip, u_int32_t mask, int invert) 124ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte{ 125ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (!mask && !ip) 126ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte return; 127ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 128ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf("%s %s%u.%u.%u.%u", 129ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte prefix, 130ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte invert ? "! " : "", 131ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte IP_PARTS(ip)); 132ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 133ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (mask != 0xffffffff) 134ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf("/%u.%u.%u.%u ", IP_PARTS(mask)); 135ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte else 136ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf(" "); 137ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte} 138e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 139e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* We want this to be readable, so only print out neccessary fields. 140e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Because that's the kind of world I want to live in. */ 141ae1ff9f96a80379a650dec979b9902528a10d45aHarald Weltestatic void print_rule(const struct ipt_entry *e, 142ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte iptc_handle_t *h, int counters) 143e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 144ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte struct ipt_entry_target *t; 145ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 146ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte /* print counters */ 147e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (counters) 148d8e6563430ab692cf093a81b9b6ac997739d9504Harald Welte printf("[%llu:%llu] ", e->counters.pcnt, e->counters.bcnt); 149e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 150e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Print IP part. */ 151ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte print_ip("-s", e->ip.src.s_addr,e->ip.smsk.s_addr, 152ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte e->ip.invflags & IPT_INV_SRCIP); 153ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 154ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte print_ip("-d", e->ip.dst.s_addr, e->ip.dmsk.s_addr, 155ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte e->ip.invflags & IPT_INV_SRCIP); 156e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 157e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_iface('i', e->ip.iniface, e->ip.iniface_mask, 158e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e->ip.invflags & IPT_INV_VIA_IN); 159ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 160e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_iface('o', e->ip.outiface, e->ip.outiface_mask, 161e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e->ip.invflags & IPT_INV_VIA_OUT); 162ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 163e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_proto(e->ip.proto, e->ip.invflags & IPT_INV_PROTO); 164e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 165e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (e->ip.flags & IPT_F_FRAG) 166e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("%s-f ", 167e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e->ip.invflags & IPT_INV_FRAG ? "! " : ""); 168e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 169e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Print matchinfo part */ 170ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (e->target_offset) { 171ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte IPT_MATCH_ITERATE(e, print_match); 172e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 173e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 174ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte /* Print target name */ 175ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf("-j %s ", iptc_get_target(e, h)); 176ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 177e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Print targinfo part */ 178ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte t = ipt_get_target(e); 179ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (t->u.user.name[0]) { 180e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct iptables_target *target 181ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte = find_target(t->u.user.name, TRY_LOAD); 182e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 183e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (target) 184ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte target->save(NULL, t); 185e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else { 186e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* If some bits are non-zero, it implies we *need* 187e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher to understand it */ 188ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (t->u.target_size) { 189e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher fprintf(stderr, 190e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher "Can't find library for target `%s'\n", 191ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte t->u.user.name); 192e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher exit(1); 193e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 194e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 195e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 196e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("\n"); 197e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 198e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 199e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Debugging prototype. */ 200a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russellstatic int for_each_table(int (*func)(const char *tablename)) 201e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 202a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell int ret = 1; 203ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte FILE *procfile = NULL; 204a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell char tablename[IPT_TABLE_MAXNAMELEN+1]; 205a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 206ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte procfile = fopen("/proc/net/ip_tables_names", "r"); 207a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell if (!procfile) 208a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell return 0; 209a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 210a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell while (fgets(tablename, sizeof(tablename), procfile)) { 211a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell if (tablename[strlen(tablename) - 1] != '\n') 212a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell exit_error(OTHER_PROBLEM, 213a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell "Badly formed tablename `%s'\n", 214a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell tablename); 215a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell tablename[strlen(tablename) - 1] = '\0'; 216a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell ret &= func(tablename); 217a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell } 218e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 219a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell return ret; 220a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell} 221a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 222e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 223a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russellstatic int do_output(const char *tablename) 224a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell{ 225a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell iptc_handle_t h; 226a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell const char *chain = NULL; 227e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 228a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell if (!tablename) 229a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell return for_each_table(&do_output); 230e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 231a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell h = iptc_init(tablename); 232a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell if (!h) 233a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell exit_error(OTHER_PROBLEM, "Can't initialize: %s\n", 234a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell iptc_strerror(errno)); 235e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 236e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!binary) { 237e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher time_t now = time(NULL); 238e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 239e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("# Generated by iptables-save v%s on %s", 240e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher NETFILTER_VERSION, ctime(&now)); 241ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf("*%s\n", tablename); 242e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 243e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Dump out chain names */ 244a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell for (chain = iptc_first_chain(&h); 245a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell chain; 246a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell chain = iptc_next_chain(&h)) { 247ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte const struct ipt_entry *e; 248ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 249e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf(":%s ", chain); 250ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (iptc_builtin(chain, h)) { 251e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_counters count; 252e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("%s ", 253e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_get_policy(chain, &count, &h)); 254d8e6563430ab692cf093a81b9b6ac997739d9504Harald Welte printf("[%llu:%llu]\n", count.pcnt, count.bcnt); 255e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 256d8e6563430ab692cf093a81b9b6ac997739d9504Harald Welte printf("- [0:0]\n"); 257e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 258e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 259ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte /* Dump out rules */ 260ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte e = iptc_first_rule(chain, &h); 261ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte while(e) { 262ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte print_rule(e, &h, counters); 263ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte e = iptc_next_rule(e, &h); 264e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 265e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 266e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 267e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher now = time(NULL); 268e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("COMMIT\n"); 269e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("# Completed on %s", ctime(&now)); 270e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 271e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Binary, huh? OK. */ 272a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell exit_error(OTHER_PROBLEM, "Binary NYI\n"); 273a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell } 274a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 275a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell return 1; 276a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell} 277a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 278a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell/* Format: 279a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell * :Chain name POLICY packets bytes 280a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell * rule 281a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell */ 282a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russellint main(int argc, char *argv[]) 283a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell{ 284a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell const char *tablename = NULL; 285a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell int c; 286a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 287a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell program_name = "iptables-save"; 288a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell program_version = NETFILTER_VERSION; 289a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 290a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell while ((c = getopt_long(argc, argv, "bc", options, NULL)) != -1) { 291a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell switch (c) { 292a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell case 'b': 293a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell binary = 1; 294a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell break; 295a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 296a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell case 'c': 297a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell counters = 1; 298a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell break; 299a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 300a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell case 't': 301a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell /* Select specific table. */ 302a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell tablename = optarg; 303a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell break; 304a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell case 'd': 305ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte do_output(tablename); 306a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell exit(0); 307a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell } 308a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell } 309a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 310a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell if (optind < argc) { 311a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell fprintf(stderr, "Unknown arguments found on commandline"); 312e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher exit(1); 313e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 314e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 315a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell return !do_output(tablename); 316e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 317