iptables-save.c revision dbb77543ad6afe29e9a1881b2d4fc212de621a55
1e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Code to save the iptables state, in human readable-form. */ 210a907f6736864f3f60d36f78c78e655b6bb64eeHarald Welte/* (C) 1999 by Paul 'Rusty' Russell <rusty@rustcorp.com.au> and 310a907f6736864f3f60d36f78c78e655b6bb64eeHarald Welte * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org> 410a907f6736864f3f60d36f78c78e655b6bb64eeHarald Welte * 510a907f6736864f3f60d36f78c78e655b6bb64eeHarald Welte * This code is distributed under the terms of GNU GPL v2 610a907f6736864f3f60d36f78c78e655b6bb64eeHarald Welte * 7ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte */ 8e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <getopt.h> 9e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <sys/errno.h> 10e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <stdio.h> 11ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte#include <fcntl.h> 12ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte#include <stdlib.h> 13ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte#include <string.h> 14e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#include <time.h> 15d8ac967249f78212e1fe5eb55e9a417ac1d737d6Harald Welte#include <netdb.h> 16b1f69befb5b35d0cbf607ed13a6e823a94cb79ffRusty Russell#include "libiptc/libiptc.h" 17b1f69befb5b35d0cbf607ed13a6e823a94cb79ffRusty Russell#include "iptables.h" 18e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 195a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS 205a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h> 215a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif 225a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger 23dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardtstatic int show_binary = 0, show_counters = 0; 24a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 25e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic struct option options[] = { 26a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell { "binary", 0, 0, 'b' }, 27a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell { "counters", 0, 0, 'c' }, 28a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell { "dump", 0, 0, 'd' }, 29a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell { "table", 1, 0, 't' }, 30e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher { 0 } 31e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 32e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 33e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#define IP_PARTS_NATIVE(n) \ 34e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher(unsigned int)((n)>>24)&0xFF, \ 35e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher(unsigned int)((n)>>16)&0xFF, \ 36e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher(unsigned int)((n)>>8)&0xFF, \ 37e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher(unsigned int)((n)&0xFF) 38e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 39e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n)) 40e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 41e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* This assumes that mask is contiguous, and byte-bounded. */ 42e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 43e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherprint_iface(char letter, const char *iface, const unsigned char *mask, 44e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int invert) 45e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 46e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 47e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 48e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (mask[0] == 0) 49e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return; 507e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 51e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("-%c %s", letter, invert ? "! " : ""); 52e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 53e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < IFNAMSIZ; i++) { 54e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (mask[i] != 0) { 55e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (iface[i] != '\0') 56e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("%c", iface[i]); 57e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 585b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann /* we can access iface[i-1] here, because 599535e687b3b5756ca7afec273d25cffdd62f653dHarald Welte * a few lines above we make sure that mask[0] != 0 */ 609535e687b3b5756ca7afec273d25cffdd62f653dHarald Welte if (iface[i-1] != '\0') 61e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("+"); 62e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 63e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 64e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 65ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 66ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf(" "); 67e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 68e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 69e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* These are hardcoded backups in iptables.c, so they are safe */ 70e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstruct pprot { 71e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher char *name; 72e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher u_int8_t num; 73e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 74e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 75764316a133db8e5e2d1f2a9d941ffae993d7c9d9András Kis-Szabó/* FIXME: why don't we use /etc/protocols ? */ 76e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic const struct pprot chain_protos[] = { 77e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher { "tcp", IPPROTO_TCP }, 78e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher { "udp", IPPROTO_UDP }, 79e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher { "icmp", IPPROTO_ICMP }, 80764316a133db8e5e2d1f2a9d941ffae993d7c9d9András Kis-Szabó { "esp", IPPROTO_ESP }, 81764316a133db8e5e2d1f2a9d941ffae993d7c9d9András Kis-Szabó { "ah", IPPROTO_AH }, 82129152307ba7b09c9ad667eee2c4e0d23f7c500bHarald Welte { "sctp", IPPROTO_SCTP }, 83e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 84e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 85e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void print_proto(u_int16_t proto, int invert) 86e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 87e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (proto) { 88e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 89e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *invertstr = invert ? "! " : ""; 90e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 910e3b3379abec1695a68871862b6c22b59de3c5a5Pedro Lamarão struct protoent *pent = getprotobynumber(proto); 920e3b3379abec1695a68871862b6c22b59de3c5a5Pedro Lamarão if (pent) { 930e3b3379abec1695a68871862b6c22b59de3c5a5Pedro Lamarão printf("-p %s%s ", invertstr, pent->p_name); 940e3b3379abec1695a68871862b6c22b59de3c5a5Pedro Lamarão return; 950e3b3379abec1695a68871862b6c22b59de3c5a5Pedro Lamarão } 960e3b3379abec1695a68871862b6c22b59de3c5a5Pedro Lamarão 97e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++) 98e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (chain_protos[i].num == proto) { 99e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("-p %s%s ", 100e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher invertstr, chain_protos[i].name); 101e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return; 102e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 103e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 104e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("-p %s%u ", invertstr, proto); 105e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 106e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 107e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 108ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte#if 0 109e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int non_zero(const void *ptr, size_t size) 110e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 111e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 112e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 113e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < size; i++) 114e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (((char *)ptr)[i]) 115e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 116e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 117e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 118e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 119ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte#endif 120ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 12132db524ab38b3258c6bae0b9b7fa76bff544085aHarald Weltestatic int print_match(const struct ipt_entry_match *e, 12232db524ab38b3258c6bae0b9b7fa76bff544085aHarald Welte const struct ipt_ip *ip) 123ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte{ 124ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte struct iptables_match *match 12578cafdaf474a333fa39efab4aa4c9aed88ab9518Martin Josefsson = find_match(e->u.user.name, TRY_LOAD, NULL); 126ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 127ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (match) { 128ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf("-m %s ", e->u.user.name); 129e81377974336cad22e721e55e142749182877065Harald Welte 130e81377974336cad22e721e55e142749182877065Harald Welte /* some matches don't provide a save function */ 131e81377974336cad22e721e55e142749182877065Harald Welte if (match->save) 132e81377974336cad22e721e55e142749182877065Harald Welte match->save(ip, e); 133ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte } else { 134ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (e->u.match_size) { 135ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte fprintf(stderr, 136ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte "Can't find library for match `%s'\n", 137ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte e->u.user.name); 138ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte exit(1); 139ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte } 140ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte } 141ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte return 0; 142ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte} 143ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 144ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte/* print a given ip including mask if neccessary */ 145ae1ff9f96a80379a650dec979b9902528a10d45aHarald Weltestatic void print_ip(char *prefix, u_int32_t ip, u_int32_t mask, int invert) 146ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte{ 147db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt u_int32_t bits, hmask = ntohl(mask); 148db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt int i; 149db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt 150f9b7af8bc031472e488eb1feaca06cebbfe28e83Patrick McHardy if (!mask && !ip && !invert) 151ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte return; 152ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 153ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf("%s %s%u.%u.%u.%u", 154ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte prefix, 155ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte invert ? "! " : "", 156ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte IP_PARTS(ip)); 157ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 158db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt if (mask == 0xFFFFFFFFU) { 159db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt printf("/32 "); 160db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt return; 161db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt } 162db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt 163db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt i = 32; 164db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt bits = 0xFFFFFFFEU; 165db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt while (--i >= 0 && hmask != bits) 166db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt bits <<= 1; 167db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt if (i >= 0) 168db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt printf("/%u ", i); 169ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte else 170db09b39196b537f3898b9454a5758e6540f9f121Jan Engelhardt printf("/%u.%u.%u.%u ", IP_PARTS(mask)); 171ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte} 172e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 173e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* We want this to be readable, so only print out neccessary fields. 174e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Because that's the kind of world I want to live in. */ 1755b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermannstatic void print_rule(const struct ipt_entry *e, 1769f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte iptc_handle_t *h, const char *chain, int counters) 177e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 178ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte struct ipt_entry_target *t; 179ace8a01d5a0ae1a0b99fc2dabdab64a5275c3259Harald Welte const char *target_name; 180ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 181ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte /* print counters */ 182e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (counters) 183a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson printf("[%llu:%llu] ", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt); 184e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1859f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte /* print chain name */ 1869f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte printf("-A %s ", chain); 1879f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte 188e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Print IP part. */ 189ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte print_ip("-s", e->ip.src.s_addr,e->ip.smsk.s_addr, 1905b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann e->ip.invflags & IPT_INV_SRCIP); 191ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 192ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte print_ip("-d", e->ip.dst.s_addr, e->ip.dmsk.s_addr, 193fa7625a99f77e78c686d8ad890ca0a278e9475a7Harald Welte e->ip.invflags & IPT_INV_DSTIP); 194e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 195e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_iface('i', e->ip.iniface, e->ip.iniface_mask, 196e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e->ip.invflags & IPT_INV_VIA_IN); 197ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 198e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_iface('o', e->ip.outiface, e->ip.outiface_mask, 199e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e->ip.invflags & IPT_INV_VIA_OUT); 200ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 201e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher print_proto(e->ip.proto, e->ip.invflags & IPT_INV_PROTO); 202e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 203e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (e->ip.flags & IPT_F_FRAG) 204e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("%s-f ", 205e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e->ip.invflags & IPT_INV_FRAG ? "! " : ""); 206e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 207e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Print matchinfo part */ 208ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (e->target_offset) { 20932db524ab38b3258c6bae0b9b7fa76bff544085aHarald Welte IPT_MATCH_ITERATE(e, print_match, &e->ip); 210e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 211e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2125b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann /* Print target name */ 2136f83cf034de43e3360675cff492c8ce01c47818aHarald Welte target_name = iptc_get_target(e, h); 2146f83cf034de43e3360675cff492c8ce01c47818aHarald Welte if (target_name && (*target_name != '\0')) 21572bd87e13b76818f5c690a9097080123ff698bc2Harald Welte#ifdef IPT_F_GOTO 21617fc163babc348780bae4321071845748f7b7985Henrik Nordstrom printf("-%c %s ", e->ip.flags & IPT_F_GOTO ? 'g' : 'j', target_name); 21772bd87e13b76818f5c690a9097080123ff698bc2Harald Welte#else 21872bd87e13b76818f5c690a9097080123ff698bc2Harald Welte printf("-j %s ", target_name); 21972bd87e13b76818f5c690a9097080123ff698bc2Harald Welte#endif 220ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte 221e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Print targinfo part */ 222082ba02f9ce9c64bb4beb76f7075e7324d738e41Rusty Russell t = ipt_get_target((struct ipt_entry *)e); 223ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (t->u.user.name[0]) { 224e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct iptables_target *target 225ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte = find_target(t->u.user.name, TRY_LOAD); 226e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 22731098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte if (!target) { 22831098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte fprintf(stderr, "Can't find library for target `%s'\n", 22931098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte t->u.user.name); 23031098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte exit(1); 23131098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte } 23231098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte 23331098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte if (target->save) 23432db524ab38b3258c6bae0b9b7fa76bff544085aHarald Welte target->save(&e->ip, t); 235e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else { 23631098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte /* If the target size is greater than ipt_entry_target 23731098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte * there is something to be saved, we just don't know 23831098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte * how to print it */ 2395b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann if (t->u.target_size != 24031098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte sizeof(struct ipt_entry_target)) { 24131098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte fprintf(stderr, "Target `%s' is missing " 24231098adc568dafa3e1e361f830a2dc514c107c8dHarald Welte "save function\n", 243ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte t->u.user.name); 244e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher exit(1); 245e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 246e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 247e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 248e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("\n"); 249e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 250e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 251e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Debugging prototype. */ 252a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russellstatic int for_each_table(int (*func)(const char *tablename)) 253e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2545b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann int ret = 1; 255ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte FILE *procfile = NULL; 256a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell char tablename[IPT_TABLE_MAXNAMELEN+1]; 257a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 258ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte procfile = fopen("/proc/net/ip_tables_names", "r"); 259a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell if (!procfile) 26065334ad262ffe9e7ad82a3b9b42ec4b03cd515e1Victor Stinner exit_error(OTHER_PROBLEM, 26165334ad262ffe9e7ad82a3b9b42ec4b03cd515e1Victor Stinner "Unable to open /proc/net/ip_tables_names: %s\n", 26265334ad262ffe9e7ad82a3b9b42ec4b03cd515e1Victor Stinner strerror(errno)); 263a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 264a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell while (fgets(tablename, sizeof(tablename), procfile)) { 265a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell if (tablename[strlen(tablename) - 1] != '\n') 266a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell exit_error(OTHER_PROBLEM, 267a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell "Badly formed tablename `%s'\n", 268a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell tablename); 269a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell tablename[strlen(tablename) - 1] = '\0'; 270a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell ret &= func(tablename); 271a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell } 272e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 273a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell return ret; 274a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell} 2755b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann 276e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 277a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russellstatic int do_output(const char *tablename) 278a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell{ 279a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell iptc_handle_t h; 280a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell const char *chain = NULL; 281e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 282a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell if (!tablename) 283a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell return for_each_table(&do_output); 284e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 285a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell h = iptc_init(tablename); 286a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell if (!h) 2875b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann exit_error(OTHER_PROBLEM, "Can't initialize: %s\n", 288a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell iptc_strerror(errno)); 289e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 290dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt if (!show_binary) { 291e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher time_t now = time(NULL); 292e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 293e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("# Generated by iptables-save v%s on %s", 29480fe35d6339b53a12ddaec41885613e4e37ed031Harald Welte IPTABLES_VERSION, ctime(&now)); 295ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte printf("*%s\n", tablename); 296e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2975b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann /* Dump out chain names first, 2989f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte * thereby preventing dependency conflicts */ 299a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell for (chain = iptc_first_chain(&h); 300a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell chain; 301a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell chain = iptc_next_chain(&h)) { 3025b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann 303e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf(":%s ", chain); 304ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte if (iptc_builtin(chain, h)) { 305e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_counters count; 306e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("%s ", 307e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_get_policy(chain, &count, &h)); 308a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); 309e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 310d8e6563430ab692cf093a81b9b6ac997739d9504Harald Welte printf("- [0:0]\n"); 311e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 3129f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte } 3135b76f682f722bebc2f0616fca4600eee2c08dfe2Max Kellermann 3149f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte 3159f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte for (chain = iptc_first_chain(&h); 3169f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte chain; 3179f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte chain = iptc_next_chain(&h)) { 3189f7fa49a6e1cd803de8a42fa849582d5d72822bfHarald Welte const struct ipt_entry *e; 319e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 320ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte /* Dump out rules */ 321ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte e = iptc_first_rule(chain, &h); 322ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte while(e) { 323dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt print_rule(e, &h, chain, show_counters); 324ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte e = iptc_next_rule(e, &h); 325e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 326e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 327e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 328e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher now = time(NULL); 329e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("COMMIT\n"); 330e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("# Completed on %s", ctime(&now)); 331e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 332e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Binary, huh? OK. */ 333a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell exit_error(OTHER_PROBLEM, "Binary NYI\n"); 334a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell } 335a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 336841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson iptc_free(&h); 337841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 338a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell return 1; 339a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell} 340a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 341a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell/* Format: 342a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell * :Chain name POLICY packets bytes 343a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell * rule 344a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell */ 3454e3771f04687657753f2a3666225341a3525f07eBastiaan Bakker#ifdef IPTABLES_MULTI 3464e3771f04687657753f2a3666225341a3525f07eBastiaan Bakkerint 3474e3771f04687657753f2a3666225341a3525f07eBastiaan Bakkeriptables_save_main(int argc, char *argv[]) 3484e3771f04687657753f2a3666225341a3525f07eBastiaan Bakker#else 3494e3771f04687657753f2a3666225341a3525f07eBastiaan Bakkerint 3504e3771f04687657753f2a3666225341a3525f07eBastiaan Bakkermain(int argc, char *argv[]) 3514e3771f04687657753f2a3666225341a3525f07eBastiaan Bakker#endif 352a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell{ 353a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell const char *tablename = NULL; 354a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell int c; 355a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 356a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell program_name = "iptables-save"; 35780fe35d6339b53a12ddaec41885613e4e37ed031Harald Welte program_version = IPTABLES_VERSION; 358a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 359357d59dcfcbd125e2aa8c07b30cea9635efec2a7Martin Josefsson lib_dir = getenv("IPTABLES_LIB_DIR"); 360357d59dcfcbd125e2aa8c07b30cea9635efec2a7Martin Josefsson if (!lib_dir) 361357d59dcfcbd125e2aa8c07b30cea9635efec2a7Martin Josefsson lib_dir = IPT_LIB_DIR; 362357d59dcfcbd125e2aa8c07b30cea9635efec2a7Martin Josefsson 3633efb6ead2e51fe1eca55bcb2b06afb4dc4b8cb7cHarald Welte#ifdef NO_SHARED_LIBS 3643efb6ead2e51fe1eca55bcb2b06afb4dc4b8cb7cHarald Welte init_extensions(); 3653efb6ead2e51fe1eca55bcb2b06afb4dc4b8cb7cHarald Welte#endif 3663efb6ead2e51fe1eca55bcb2b06afb4dc4b8cb7cHarald Welte 367163ad7801e93e4d8d3308741d34bcc1ee695d87bMarc Boucher while ((c = getopt_long(argc, argv, "bcdt:", options, NULL)) != -1) { 368a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell switch (c) { 369a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell case 'b': 370dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt show_binary = 1; 371a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell break; 372a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 373a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell case 'c': 374dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt show_counters = 1; 375a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell break; 376a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 377a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell case 't': 378a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell /* Select specific table. */ 379a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell tablename = optarg; 380a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell break; 381a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell case 'd': 382ae1ff9f96a80379a650dec979b9902528a10d45aHarald Welte do_output(tablename); 383a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell exit(0); 384a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell } 385a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell } 386a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell 387a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell if (optind < argc) { 388972af09e79618c5086e26ef6438bd38c45c4bb3fPavel Rusnak fprintf(stderr, "Unknown arguments found on commandline\n"); 389e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher exit(1); 390e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 391e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 392a8f033e89981d019c8a4214b9094f2b2411bea18Rusty Russell return !do_output(tablename); 393e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 394