summaryrefslogtreecommitdiffstats
path: root/iptables-save.c
diff options
context:
space:
mode:
authorHenrik Nordstrom <henrik@henriknordstrom.net>2008-05-13 13:08:26 +0200
committerPatrick McHardy <kaber@trash.net>2008-05-13 13:08:26 +0200
commit96296cfb7e01298234c7fa9403619f50391620d1 (patch)
tree8ae6e4457a0d70a40b573b606488744a62a7a3bb /iptables-save.c
parent48c1bc6fa2f3aa755e89518054ef3f612d7b2c1f (diff)
iptables --list-rules command
Adds iptables --list-rules (-S) command, acting as a combination of iptables --list and iptables-save. The primary motivation behind this patch is to get iptables-save like output capabilities in iptables-restore, allowing "iptables-restore -n" to be used as a consistent API to iptables for all kind of operations, not only blind updates.. As a bonus iptables also gets the capability of printing the rules as-is. This completely replaces the earlier patch which added the --rules option. Henrik Nordstrom <henrik@henriknordstrom.net>
Diffstat (limited to 'iptables-save.c')
-rw-r--r--iptables-save.c205
1 files changed, 0 insertions, 205 deletions
diff --git a/iptables-save.c b/iptables-save.c
index e8bdda2b..ecccac47 100644
--- a/iptables-save.c
+++ b/iptables-save.c
@@ -31,211 +31,6 @@ static const struct option options[] = {
{NULL},
};
-#define IP_PARTS_NATIVE(n) \
-(unsigned int)((n)>>24)&0xFF, \
-(unsigned int)((n)>>16)&0xFF, \
-(unsigned int)((n)>>8)&0xFF, \
-(unsigned int)((n)&0xFF)
-
-#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n))
-
-/* This assumes that mask is contiguous, and byte-bounded. */
-static void
-print_iface(char letter, const char *iface, const unsigned char *mask,
- int invert)
-{
- unsigned int i;
-
- if (mask[0] == 0)
- return;
-
- printf("-%c %s", letter, invert ? "! " : "");
-
- for (i = 0; i < IFNAMSIZ; i++) {
- if (mask[i] != 0) {
- if (iface[i] != '\0')
- printf("%c", iface[i]);
- } else {
- /* we can access iface[i-1] here, because
- * a few lines above we make sure that mask[0] != 0 */
- if (iface[i-1] != '\0')
- printf("+");
- break;
- }
- }
-
- printf(" ");
-}
-
-/* These are hardcoded backups in iptables.c, so they are safe */
-struct pprot {
- char *name;
- u_int8_t num;
-};
-
-/* FIXME: why don't we use /etc/protocols ? */
-static const struct pprot chain_protos[] = {
- { "tcp", IPPROTO_TCP },
- { "udp", IPPROTO_UDP },
- { "icmp", IPPROTO_ICMP },
- { "esp", IPPROTO_ESP },
- { "ah", IPPROTO_AH },
- { "sctp", IPPROTO_SCTP },
-};
-
-static void print_proto(u_int16_t proto, int invert)
-{
- if (proto) {
- unsigned int i;
- const char *invertstr = invert ? "! " : "";
-
- struct protoent *pent = getprotobynumber(proto);
- if (pent) {
- printf("-p %s%s ", invertstr, pent->p_name);
- return;
- }
-
- for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++)
- if (chain_protos[i].num == proto) {
- printf("-p %s%s ",
- invertstr, chain_protos[i].name);
- return;
- }
-
- printf("-p %s%u ", invertstr, proto);
- }
-}
-
-static int print_match(const struct ipt_entry_match *e,
- const struct ipt_ip *ip)
-{
- struct xtables_match *match
- = find_match(e->u.user.name, TRY_LOAD, NULL);
-
- if (match) {
- printf("-m %s ", e->u.user.name);
-
- /* some matches don't provide a save function */
- if (match->save)
- match->save(ip, e);
- } else {
- if (e->u.match_size) {
- fprintf(stderr,
- "Can't find library for match `%s'\n",
- e->u.user.name);
- exit(1);
- }
- }
- return 0;
-}
-
-/* print a given ip including mask if neccessary */
-static void print_ip(char *prefix, u_int32_t ip, u_int32_t mask, int invert)
-{
- u_int32_t bits, hmask = ntohl(mask);
- int i;
-
- if (!mask && !ip && !invert)
- return;
-
- printf("%s %s%u.%u.%u.%u",
- prefix,
- invert ? "! " : "",
- IP_PARTS(ip));
-
- if (mask == 0xFFFFFFFFU) {
- printf("/32 ");
- return;
- }
-
- i = 32;
- bits = 0xFFFFFFFEU;
- while (--i >= 0 && hmask != bits)
- bits <<= 1;
- if (i >= 0)
- printf("/%u ", i);
- else
- printf("/%u.%u.%u.%u ", IP_PARTS(mask));
-}
-
-/* We want this to be readable, so only print out neccessary fields.
- * Because that's the kind of world I want to live in. */
-static void print_rule(const struct ipt_entry *e,
- iptc_handle_t *h, const char *chain, int counters)
-{
- struct ipt_entry_target *t;
- const char *target_name;
-
- /* print counters */
- if (counters)
- printf("[%llu:%llu] ", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
-
- /* print chain name */
- printf("-A %s ", chain);
-
- /* Print IP part. */
- print_ip("-s", e->ip.src.s_addr,e->ip.smsk.s_addr,
- e->ip.invflags & IPT_INV_SRCIP);
-
- print_ip("-d", e->ip.dst.s_addr, e->ip.dmsk.s_addr,
- e->ip.invflags & IPT_INV_DSTIP);
-
- print_iface('i', e->ip.iniface, e->ip.iniface_mask,
- e->ip.invflags & IPT_INV_VIA_IN);
-
- print_iface('o', e->ip.outiface, e->ip.outiface_mask,
- e->ip.invflags & IPT_INV_VIA_OUT);
-
- print_proto(e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
-
- if (e->ip.flags & IPT_F_FRAG)
- printf("%s-f ",
- e->ip.invflags & IPT_INV_FRAG ? "! " : "");
-
- /* Print matchinfo part */
- if (e->target_offset) {
- IPT_MATCH_ITERATE(e, print_match, &e->ip);
- }
-
- /* Print target name */
- target_name = iptc_get_target(e, h);
- if (target_name && (*target_name != '\0'))
-#ifdef IPT_F_GOTO
- printf("-%c %s ", e->ip.flags & IPT_F_GOTO ? 'g' : 'j', target_name);
-#else
- printf("-j %s ", target_name);
-#endif
-
- /* Print targinfo part */
- t = ipt_get_target((struct ipt_entry *)e);
- if (t->u.user.name[0]) {
- struct xtables_target *target
- = find_target(t->u.user.name, TRY_LOAD);
-
- if (!target) {
- fprintf(stderr, "Can't find library for target `%s'\n",
- t->u.user.name);
- exit(1);
- }
-
- if (target->save)
- target->save(&e->ip, t);
- else {
- /* If the target size is greater than ipt_entry_target
- * there is something to be saved, we just don't know
- * how to print it */
- if (t->u.target_size !=
- sizeof(struct ipt_entry_target)) {
- fprintf(stderr, "Target `%s' is missing "
- "save function\n",
- t->u.user.name);
- exit(1);
- }
- }
- }
- printf("\n");
-}
-
/* Debugging prototype. */
static int for_each_table(int (*func)(const char *tablename))
{