cleanup junk, add spec file
authorMark Huang <mlhuang@cs.princeton.edu>
Mon, 1 Nov 2004 19:25:42 +0000 (19:25 +0000)
committerMark Huang <mlhuang@cs.princeton.edu>
Mon, 1 Nov 2004 19:25:42 +0000 (19:25 +0000)
12 files changed:
.#iptables.c.1.54 [deleted file]
.#iptables.c.1.55 [deleted file]
Makefile.nolibnsl [deleted file]
extensions/.#libipt_ECN.c.1.7 [deleted file]
extensions/.#libipt_recent.c.1.6 [deleted file]
extensions/libipt_icmp.c.print_type [deleted file]
ip6tables.c.selinux [deleted file]
iptables-restore.c.counters [deleted file]
iptables.c.selinux [deleted file]
iptables.spec [new file with mode: 0644]
libipq/libipq.c.netlink [deleted file]
libiptc2/.#libiptc.c.1.40 [deleted file]

diff --git a/.#iptables.c.1.54 b/.#iptables.c.1.54
deleted file mode 100644 (file)
index a838e56..0000000
+++ /dev/null
@@ -1,2298 +0,0 @@
-/* Code to take an iptables-style command line and do it. */
-
-/*
- * Author: Paul.Russell@rustcorp.com.au and mneuling@radlogic.com.au
- *
- * (C) 2000-2002 by the netfilter coreteam <coreteam@netfilter.org>:
- *                 Paul 'Rusty' Russell <rusty@rustcorp.com.au>
- *                 Marc Boucher <marc+nf@mbsi.ca>
- *                 James Morris <jmorris@intercode.com.au>
- *                 Harald Welte <laforge@gnumonks.org>
- *                 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <getopt.h>
-#include <string.h>
-#include <netdb.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <unistd.h>
-#include <iptables.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef IPT_LIB_DIR
-#define IPT_LIB_DIR "/usr/lib/iptables"
-#endif
-
-#ifndef PROC_SYS_MODPROBE
-#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
-#endif
-
-#define FMT_NUMERIC    0x0001
-#define FMT_NOCOUNTS   0x0002
-#define FMT_KILOMEGAGIGA 0x0004
-#define FMT_OPTIONS    0x0008
-#define FMT_NOTABLE    0x0010
-#define FMT_NOTARGET   0x0020
-#define FMT_VIA                0x0040
-#define FMT_NONEWLINE  0x0080
-#define FMT_LINENUMBERS 0x0100
-
-#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
-                       | FMT_NUMERIC | FMT_NOTABLE)
-#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
-
-
-#define CMD_NONE               0x0000U
-#define CMD_INSERT             0x0001U
-#define CMD_DELETE             0x0002U
-#define CMD_DELETE_NUM         0x0004U
-#define CMD_REPLACE            0x0008U
-#define CMD_APPEND             0x0010U
-#define CMD_LIST               0x0020U
-#define CMD_FLUSH              0x0040U
-#define CMD_ZERO               0x0080U
-#define CMD_NEW_CHAIN          0x0100U
-#define CMD_DELETE_CHAIN       0x0200U
-#define CMD_SET_POLICY         0x0400U
-#define CMD_CHECK              0x0800U
-#define CMD_RENAME_CHAIN       0x1000U
-#define NUMBER_OF_CMD  13
-static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
-                                'N', 'X', 'P', 'E' };
-
-#define OPTION_OFFSET 256
-
-#define OPT_NONE       0x00000U
-#define OPT_NUMERIC    0x00001U
-#define OPT_SOURCE     0x00002U
-#define OPT_DESTINATION        0x00004U
-#define OPT_PROTOCOL   0x00008U
-#define OPT_JUMP       0x00010U
-#define OPT_VERBOSE    0x00020U
-#define OPT_EXPANDED   0x00040U
-#define OPT_VIANAMEIN  0x00080U
-#define OPT_VIANAMEOUT 0x00100U
-#define OPT_FRAGMENT    0x00200U
-#define OPT_LINENUMBERS 0x00400U
-#define OPT_COUNTERS   0x00800U
-#define NUMBER_OF_OPT  12
-static const char optflags[NUMBER_OF_OPT]
-= { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', 'f', '3', 'c'};
-
-static struct option original_opts[] = {
-       { "append", 1, 0, 'A' },
-       { "delete", 1, 0,  'D' },
-       { "insert", 1, 0,  'I' },
-       { "replace", 1, 0,  'R' },
-       { "list", 2, 0,  'L' },
-       { "flush", 2, 0,  'F' },
-       { "zero", 2, 0,  'Z' },
-       { "new-chain", 1, 0,  'N' },
-       { "delete-chain", 2, 0,  'X' },
-       { "rename-chain", 1, 0,  'E' },
-       { "policy", 1, 0,  'P' },
-       { "source", 1, 0, 's' },
-       { "destination", 1, 0,  'd' },
-       { "src", 1, 0,  's' }, /* synonym */
-       { "dst", 1, 0,  'd' }, /* synonym */
-       { "protocol", 1, 0,  'p' },
-       { "in-interface", 1, 0, 'i' },
-       { "jump", 1, 0, 'j' },
-       { "table", 1, 0, 't' },
-       { "match", 1, 0, 'm' },
-       { "numeric", 0, 0, 'n' },
-       { "out-interface", 1, 0, 'o' },
-       { "verbose", 0, 0, 'v' },
-       { "exact", 0, 0, 'x' },
-       { "fragments", 0, 0, 'f' },
-       { "version", 0, 0, 'V' },
-       { "help", 2, 0, 'h' },
-       { "line-numbers", 0, 0, '0' },
-       { "modprobe", 1, 0, 'M' },
-       { "set-counters", 1, 0, 'c' },
-       { 0 }
-};
-
-/* we need this for iptables-restore.  iptables-restore.c sets line to the
- * current line of the input file, in order  to give a more precise error
- * message.  iptables itself doesn't need this, so it is initialized to the
- * magic number of -1 */
-int line = -1;
-
-#ifndef __OPTIMIZE__
-struct ipt_entry_target *
-ipt_get_target(struct ipt_entry *e)
-{
-       return (void *)e + e->target_offset;
-}
-#endif
-
-static struct option *opts = original_opts;
-static unsigned int global_option_offset = 0;
-
-/* Table of legal combinations of commands and options.  If any of the
- * given commands make an option legal, that option is legal (applies to
- * CMD_LIST and CMD_ZERO only).
- * Key:
- *  +  compulsory
- *  x  illegal
- *     optional
- */
-
-static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
-/* Well, it's better than "Re: Linux vs FreeBSD" */
-{
-       /*     -n  -s  -d  -p  -j  -v  -x  -i  -o  -f  --line */
-/*INSERT*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*DELETE*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*DELETE_NUM*/{'x','x','x','x','x',' ','x','x','x','x','x'},
-/*REPLACE*/   {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*APPEND*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*LIST*/      {' ','x','x','x','x',' ',' ','x','x','x',' '},
-/*FLUSH*/     {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*ZERO*/      {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*NEW_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*DEL_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x','x'},
-/*CHECK*/     {'x','+','+','+','x',' ','x',' ',' ',' ','x'},
-/*RENAME*/    {'x','x','x','x','x',' ','x','x','x','x','x'}
-};
-
-static int inverse_for_options[NUMBER_OF_OPT] =
-{
-/* -n */ 0,
-/* -s */ IPT_INV_SRCIP,
-/* -d */ IPT_INV_DSTIP,
-/* -p */ IPT_INV_PROTO,
-/* -j */ 0,
-/* -v */ 0,
-/* -x */ 0,
-/* -i */ IPT_INV_VIA_IN,
-/* -o */ IPT_INV_VIA_OUT,
-/* -f */ IPT_INV_FRAG,
-/*--line*/ 0
-};
-
-const char *program_version;
-const char *program_name;
-
-/* Keeping track of external matches and targets: linked lists.  */
-struct iptables_match *iptables_matches = NULL;
-struct iptables_target *iptables_targets = NULL;
-
-/* Extra debugging from libiptc */
-extern void dump_entries(const iptc_handle_t handle);
-
-/* A few hardcoded protocols for 'all' and in case the user has no
-   /etc/protocols */
-struct pprot {
-       char *name;
-       u_int8_t num;
-};
-
-/* Primitive headers... */
-/* defined in netinet/in.h */
-#if 0
-#ifndef IPPROTO_ESP
-#define IPPROTO_ESP 50
-#endif
-#ifndef IPPROTO_AH
-#define IPPROTO_AH 51
-#endif
-#endif
-
-static const struct pprot chain_protos[] = {
-       { "tcp", IPPROTO_TCP },
-       { "udp", IPPROTO_UDP },
-       { "icmp", IPPROTO_ICMP },
-       { "esp", IPPROTO_ESP },
-       { "ah", IPPROTO_AH },
-       { "all", 0 },
-};
-
-static char *
-proto_to_name(u_int8_t proto, int nolookup)
-{
-       unsigned int i;
-
-       if (proto && !nolookup) {
-               struct protoent *pent = getprotobynumber(proto);
-               if (pent)
-                       return pent->p_name;
-       }
-
-       for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++)
-               if (chain_protos[i].num == proto)
-                       return chain_protos[i].name;
-
-       return NULL;
-}
-
-struct in_addr *
-dotted_to_addr(const char *dotted)
-{
-       static struct in_addr addr;
-       unsigned char *addrp;
-       char *p, *q;
-       unsigned int onebyte;
-       int i;
-       char buf[20];
-
-       /* copy dotted string, because we need to modify it */
-       strncpy(buf, dotted, sizeof(buf) - 1);
-       addrp = (unsigned char *) &(addr.s_addr);
-
-       p = buf;
-       for (i = 0; i < 3; i++) {
-               if ((q = strchr(p, '.')) == NULL)
-                       return (struct in_addr *) NULL;
-
-               *q = '\0';
-               if (string_to_number(p, 0, 255, &onebyte) == -1)
-                       return (struct in_addr *) NULL;
-
-               addrp[i] = (unsigned char) onebyte;
-               p = q + 1;
-       }
-
-       /* we've checked 3 bytes, now we check the last one */
-       if (string_to_number(p, 0, 255, &onebyte) == -1)
-               return (struct in_addr *) NULL;
-
-       addrp[3] = (unsigned char) onebyte;
-
-       return &addr;
-}
-
-static struct in_addr *
-network_to_addr(const char *name)
-{
-       struct netent *net;
-       static struct in_addr addr;
-
-       if ((net = getnetbyname(name)) != NULL) {
-               if (net->n_addrtype != AF_INET)
-                       return (struct in_addr *) NULL;
-               addr.s_addr = htonl((unsigned long) net->n_net);
-               return &addr;
-       }
-
-       return (struct in_addr *) NULL;
-}
-
-static void
-inaddrcpy(struct in_addr *dst, struct in_addr *src)
-{
-       /* memcpy(dst, src, sizeof(struct in_addr)); */
-       dst->s_addr = src->s_addr;
-}
-
-void
-exit_error(enum exittype status, char *msg, ...)
-{
-       va_list args;
-
-       va_start(args, msg);
-       fprintf(stderr, "%s v%s: ", program_name, program_version);
-       vfprintf(stderr, msg, args);
-       va_end(args);
-       fprintf(stderr, "\n");
-       if (status == PARAMETER_PROBLEM)
-               exit_tryhelp(status);
-       if (status == VERSION_PROBLEM)
-               fprintf(stderr,
-                       "Perhaps iptables or your kernel needs to be upgraded.\n");
-       exit(status);
-}
-
-void
-exit_tryhelp(int status)
-{
-       if (line != -1)
-               fprintf(stderr, "Error occurred at line: %d\n", line);
-       fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
-                       program_name, program_name );
-       exit(status);
-}
-
-void
-exit_printhelp(void)
-{
-       struct iptables_match *m = NULL;
-       struct iptables_target *t = NULL;
-
-       printf("%s v%s\n\n"
-"Usage: %s -[AD] chain rule-specification [options]\n"
-"       %s -[RI] chain rulenum rule-specification [options]\n"
-"       %s -D chain rulenum [options]\n"
-"       %s -[LFZ] [chain] [options]\n"
-"       %s -[NX] chain\n"
-"       %s -E old-chain-name new-chain-name\n"
-"       %s -P chain target [options]\n"
-"       %s -h (print this help information)\n\n",
-              program_name, program_version, program_name, program_name,
-              program_name, program_name, program_name, program_name,
-              program_name, program_name);
-
-       printf(
-"Commands:\n"
-"Either long or short options are allowed.\n"
-"  --append  -A chain          Append to chain\n"
-"  --delete  -D chain          Delete matching rule from chain\n"
-"  --delete  -D chain rulenum\n"
-"                              Delete rule rulenum (1 = first) from chain\n"
-"  --insert  -I chain [rulenum]\n"
-"                              Insert in chain as rulenum (default 1=first)\n"
-"  --replace -R chain rulenum\n"
-"                              Replace rule rulenum (1 = first) in chain\n"
-"  --list    -L [chain]                List the rules in a chain or all chains\n"
-"  --flush   -F [chain]                Delete all rules in  chain or all chains\n"
-"  --zero    -Z [chain]                Zero counters in chain or all chains\n"
-"  --new     -N chain          Create a new user-defined chain\n"
-"  --delete-chain\n"
-"            -X [chain]                Delete a user-defined chain\n"
-"  --policy  -P chain target\n"
-"                              Change policy on chain to target\n"
-"  --rename-chain\n"
-"            -E old-chain new-chain\n"
-"                              Change chain name, (moving any references)\n"
-
-"Options:\n"
-"  --proto     -p [!] proto    protocol: by number or name, eg. `tcp'\n"
-"  --source    -s [!] address[/mask]\n"
-"                              source specification\n"
-"  --destination -d [!] address[/mask]\n"
-"                              destination specification\n"
-"  --in-interface -i [!] input name[+]\n"
-"                              network interface name ([+] for wildcard)\n"
-"  --jump      -j target\n"
-"                              target for rule (may load target extension)\n"
-"  --match     -m match\n"
-"                              extended match (may load extension)\n"
-"  --numeric   -n              numeric output of addresses and ports\n"
-"  --out-interface -o [!] output name[+]\n"
-"                              network interface name ([+] for wildcard)\n"
-"  --table     -t table        table to manipulate (default: `filter')\n"
-"  --verbose   -v              verbose mode\n"
-"  --line-numbers              print line numbers when listing\n"
-"  --exact     -x              expand numbers (display exact values)\n"
-"[!] --fragment        -f              match second or further fragments only\n"
-"  --modprobe=<command>                try to insert modules using this command\n"
-"  --set-counters PKTS BYTES   set the counter during insert/append\n"
-"[!] --version -V              print package version.\n");
-
-       /* Print out any special helps. A user might like to be able
-          to add a --help to the commandline, and see expected
-          results. So we call help for all matches & targets */
-       for (t=iptables_targets;t;t=t->next) {
-               printf("\n");
-               t->help();
-       }
-       for (m=iptables_matches;m;m=m->next) {
-               printf("\n");
-               m->help();
-       }
-       exit(0);
-}
-
-static void
-generic_opt_check(int command, int options)
-{
-       int i, j, legal = 0;
-
-       /* Check that commands are valid with options.  Complicated by the
-        * fact that if an option is legal with *any* command given, it is
-        * legal overall (ie. -z and -l).
-        */
-       for (i = 0; i < NUMBER_OF_OPT; i++) {
-               legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
-
-               for (j = 0; j < NUMBER_OF_CMD; j++) {
-                       if (!(command & (1<<j)))
-                               continue;
-
-                       if (!(options & (1<<i))) {
-                               if (commands_v_options[j][i] == '+')
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "You need to supply the `-%c' "
-                                                  "option for this command\n",
-                                                  optflags[i]);
-                       } else {
-                               if (commands_v_options[j][i] != 'x')
-                                       legal = 1;
-                               else if (legal == 0)
-                                       legal = -1;
-                       }
-               }
-               if (legal == -1)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Illegal option `-%c' with this command\n",
-                                  optflags[i]);
-       }
-}
-
-static char
-opt2char(int option)
-{
-       const char *ptr;
-       for (ptr = optflags; option > 1; option >>= 1, ptr++);
-
-       return *ptr;
-}
-
-static char
-cmd2char(int option)
-{
-       const char *ptr;
-       for (ptr = cmdflags; option > 1; option >>= 1, ptr++);
-
-       return *ptr;
-}
-
-static void
-add_command(int *cmd, const int newcmd, const int othercmds, int invert)
-{
-       if (invert)
-               exit_error(PARAMETER_PROBLEM, "unexpected ! flag");
-       if (*cmd & (~othercmds))
-               exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
-                          cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
-       *cmd |= newcmd;
-}
-
-int
-check_inverse(const char option[], int *invert, int *optind, int argc)
-{
-       if (option && strcmp(option, "!") == 0) {
-               if (*invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Multiple `!' flags not allowed");
-               *invert = TRUE;
-               if (optind) {
-                       *optind = *optind+1;
-                       if (argc && *optind > argc)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "no argument following `!'");
-               }
-
-               return TRUE;
-       }
-       return FALSE;
-}
-
-static void *
-fw_calloc(size_t count, size_t size)
-{
-       void *p;
-
-       if ((p = calloc(count, size)) == NULL) {
-               perror("iptables: calloc failed");
-               exit(1);
-       }
-       return p;
-}
-
-static void *
-fw_malloc(size_t size)
-{
-       void *p;
-
-       if ((p = malloc(size)) == NULL) {
-               perror("iptables: malloc failed");
-               exit(1);
-       }
-       return p;
-}
-
-static struct in_addr *
-host_to_addr(const char *name, unsigned int *naddr)
-{
-       struct hostent *host;
-       struct in_addr *addr;
-       unsigned int i;
-
-       *naddr = 0;
-       if ((host = gethostbyname(name)) != NULL) {
-               if (host->h_addrtype != AF_INET ||
-                   host->h_length != sizeof(struct in_addr))
-                       return (struct in_addr *) NULL;
-
-               while (host->h_addr_list[*naddr] != (char *) NULL)
-                       (*naddr)++;
-               addr = fw_calloc(*naddr, sizeof(struct in_addr));
-               for (i = 0; i < *naddr; i++)
-                       inaddrcpy(&(addr[i]),
-                                 (struct in_addr *) host->h_addr_list[i]);
-               return addr;
-       }
-
-       return (struct in_addr *) NULL;
-}
-
-static char *
-addr_to_host(const struct in_addr *addr)
-{
-       struct hostent *host;
-
-       if ((host = gethostbyaddr((char *) addr,
-                                 sizeof(struct in_addr), AF_INET)) != NULL)
-               return (char *) host->h_name;
-
-       return (char *) NULL;
-}
-
-/*
- *     All functions starting with "parse" should succeed, otherwise
- *     the program fails.
- *     Most routines return pointers to static data that may change
- *     between calls to the same or other routines with a few exceptions:
- *     "host_to_addr", "parse_hostnetwork", and "parse_hostnetworkmask"
- *     return global static data.
-*/
-
-static struct in_addr *
-parse_hostnetwork(const char *name, unsigned int *naddrs)
-{
-       struct in_addr *addrp, *addrptmp;
-
-       if ((addrptmp = dotted_to_addr(name)) != NULL ||
-           (addrptmp = network_to_addr(name)) != NULL) {
-               addrp = fw_malloc(sizeof(struct in_addr));
-               inaddrcpy(addrp, addrptmp);
-               *naddrs = 1;
-               return addrp;
-       }
-       if ((addrp = host_to_addr(name, naddrs)) != NULL)
-               return addrp;
-
-       exit_error(PARAMETER_PROBLEM, "host/network `%s' not found", name);
-}
-
-static struct in_addr *
-parse_mask(char *mask)
-{
-       static struct in_addr maskaddr;
-       struct in_addr *addrp;
-       unsigned int bits;
-
-       if (mask == NULL) {
-               /* no mask at all defaults to 32 bits */
-               maskaddr.s_addr = 0xFFFFFFFF;
-               return &maskaddr;
-       }
-       if ((addrp = dotted_to_addr(mask)) != NULL)
-               /* dotted_to_addr already returns a network byte order addr */
-               return addrp;
-       if (string_to_number(mask, 0, 32, &bits) == -1)
-               exit_error(PARAMETER_PROBLEM,
-                          "invalid mask `%s' specified", mask);
-       if (bits != 0) {
-               maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
-               return &maskaddr;
-       }
-
-       maskaddr.s_addr = 0L;
-       return &maskaddr;
-}
-
-void
-parse_hostnetworkmask(const char *name, struct in_addr **addrpp,
-                     struct in_addr *maskp, unsigned int *naddrs)
-{
-       struct in_addr *addrp;
-       char buf[256];
-       char *p;
-       int i, j, k, n;
-
-       strncpy(buf, name, sizeof(buf) - 1);
-       if ((p = strrchr(buf, '/')) != NULL) {
-               *p = '\0';
-               addrp = parse_mask(p + 1);
-       } else
-               addrp = parse_mask(NULL);
-       inaddrcpy(maskp, addrp);
-
-       /* if a null mask is given, the name is ignored, like in "any/0" */
-       if (maskp->s_addr == 0L)
-               strcpy(buf, "0.0.0.0");
-
-       addrp = *addrpp = parse_hostnetwork(buf, naddrs);
-       n = *naddrs;
-       for (i = 0, j = 0; i < n; i++) {
-               addrp[j++].s_addr &= maskp->s_addr;
-               for (k = 0; k < j - 1; k++) {
-                       if (addrp[k].s_addr == addrp[j - 1].s_addr) {
-                               (*naddrs)--;
-                               j--;
-                               break;
-                       }
-               }
-       }
-}
-
-struct iptables_match *
-find_match(const char *name, enum ipt_tryload tryload)
-{
-       struct iptables_match *ptr;
-
-       for (ptr = iptables_matches; ptr; ptr = ptr->next) {
-               if (strcmp(name, ptr->name) == 0)
-                       break;
-       }
-
-#ifndef NO_SHARED_LIBS
-       if (!ptr && tryload != DONT_LOAD) {
-               char path[sizeof(IPT_LIB_DIR) + sizeof("/libipt_.so")
-                        + strlen(name)];
-               sprintf(path, IPT_LIB_DIR "/libipt_%s.so", name);
-               if (dlopen(path, RTLD_NOW)) {
-                       /* Found library.  If it didn't register itself,
-                          maybe they specified target as match. */
-                       ptr = find_match(name, DONT_LOAD);
-
-                       if (!ptr)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Couldn't load match `%s'\n",
-                                          name);
-               } else if (tryload == LOAD_MUST_SUCCEED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Couldn't load match `%s':%s\n",
-                                  name, dlerror());
-       }
-#else
-       if (ptr && !ptr->loaded) {
-               if (tryload != DONT_LOAD)
-                       ptr->loaded = 1;
-               else
-                       ptr = NULL;
-       }
-       if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
-               exit_error(PARAMETER_PROBLEM,
-                          "Couldn't find match `%s'\n", name);
-       }
-#endif
-
-       if (ptr)
-               ptr->used = 1;
-
-       return ptr;
-}
-
-/* Christophe Burki wants `-p 6' to imply `-m tcp'.  */
-static struct iptables_match *
-find_proto(const char *pname, enum ipt_tryload tryload, int nolookup)
-{
-       unsigned int proto;
-
-       if (string_to_number(pname, 0, 255, &proto) != -1) {
-               char *protoname = proto_to_name(proto, nolookup);
-
-               if (protoname)
-                       return find_match(protoname, tryload);
-       } else
-               return find_match(pname, tryload);
-
-       return NULL;
-}
-
-u_int16_t
-parse_protocol(const char *s)
-{
-       unsigned int proto;
-
-       if (string_to_number(s, 0, 255, &proto) == -1) {
-               struct protoent *pent;
-
-               if ((pent = getprotobyname(s)))
-                       proto = pent->p_proto;
-               else {
-                       unsigned int i;
-                       for (i = 0;
-                            i < sizeof(chain_protos)/sizeof(struct pprot);
-                            i++) {
-                               if (strcmp(s, chain_protos[i].name) == 0) {
-                                       proto = chain_protos[i].num;
-                                       break;
-                               }
-                       }
-                       if (i == sizeof(chain_protos)/sizeof(struct pprot))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unknown protocol `%s' specified",
-                                          s);
-               }
-       }
-
-       return (u_int16_t)proto;
-}
-
-static void
-parse_interface(const char *arg, char *vianame, unsigned char *mask)
-{
-       int vialen = strlen(arg);
-       unsigned int i;
-
-       memset(mask, 0, IFNAMSIZ);
-       memset(vianame, 0, IFNAMSIZ);
-
-       if (vialen + 1 > IFNAMSIZ)
-               exit_error(PARAMETER_PROBLEM,
-                          "interface name `%s' must be shorter than IFNAMSIZ"
-                          " (%i)", arg, IFNAMSIZ-1);
-
-       strcpy(vianame, arg);
-       if (vialen == 0)
-               memset(mask, 0, IFNAMSIZ);
-       else if (vianame[vialen - 1] == '+') {
-               memset(mask, 0xFF, vialen - 1);
-               memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
-               /* Don't remove `+' here! -HW */
-       } else {
-               /* Include nul-terminator in match */
-               memset(mask, 0xFF, vialen + 1);
-               memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
-               for (i = 0; vianame[i]; i++) {
-                       if (!isalnum(vianame[i]) 
-                           && vianame[i] != '_' 
-                           && vianame[i] != '.') {
-                               printf("Warning: wierd character in interface"
-                                      " `%s' (No aliases, :, ! or *).\n",
-                                      vianame);
-                               break;
-                       }
-               }
-       }
-}
-
-/* Can't be zero. */
-static int
-parse_rulenumber(const char *rule)
-{
-       unsigned int rulenum;
-
-       if (string_to_number(rule, 1, INT_MAX, &rulenum) == -1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid rule number `%s'", rule);
-
-       return rulenum;
-}
-
-static const char *
-parse_target(const char *targetname)
-{
-       const char *ptr;
-
-       if (strlen(targetname) < 1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid target name (too short)");
-
-       if (strlen(targetname)+1 > sizeof(ipt_chainlabel))
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid target name `%s' (%i chars max)",
-                          targetname, sizeof(ipt_chainlabel)-1);
-
-       for (ptr = targetname; *ptr; ptr++)
-               if (isspace(*ptr))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Invalid target name `%s'", targetname);
-       return targetname;
-}
-
-static char *
-addr_to_network(const struct in_addr *addr)
-{
-       struct netent *net;
-
-       if ((net = getnetbyaddr((long) ntohl(addr->s_addr), AF_INET)) != NULL)
-               return (char *) net->n_name;
-
-       return (char *) NULL;
-}
-
-char *
-addr_to_dotted(const struct in_addr *addrp)
-{
-       static char buf[20];
-       const unsigned char *bytep;
-
-       bytep = (const unsigned char *) &(addrp->s_addr);
-       sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
-       return buf;
-}
-
-char *
-addr_to_anyname(const struct in_addr *addr)
-{
-       char *name;
-
-       if ((name = addr_to_host(addr)) != NULL ||
-           (name = addr_to_network(addr)) != NULL)
-               return name;
-
-       return addr_to_dotted(addr);
-}
-
-char *
-mask_to_dotted(const struct in_addr *mask)
-{
-       int i;
-       static char buf[20];
-       u_int32_t maskaddr, bits;
-
-       maskaddr = ntohl(mask->s_addr);
-
-       if (maskaddr == 0xFFFFFFFFL)
-               /* we don't want to see "/32" */
-               return "";
-
-       i = 32;
-       bits = 0xFFFFFFFEL;
-       while (--i >= 0 && maskaddr != bits)
-               bits <<= 1;
-       if (i >= 0)
-               sprintf(buf, "/%d", i);
-       else
-               /* mask was not a decent combination of 1's and 0's */
-               sprintf(buf, "/%s", addr_to_dotted(mask));
-
-       return buf;
-}
-
-int
-string_to_number(const char *s, unsigned int min, unsigned int max,
-                unsigned int *ret)
-{
-       long number;
-       char *end;
-
-       /* Handle hex, octal, etc. */
-       errno = 0;
-       number = strtol(s, &end, 0);
-       if (*end == '\0' && end != s) {
-               /* we parsed a number, let's see if we want this */
-               if (errno != ERANGE && min <= number && number <= max) {
-                       *ret = number;
-                       return 0;
-               }
-       }
-       return -1;
-}
-
-static void
-set_option(unsigned int *options, unsigned int option, u_int8_t *invflg,
-          int invert)
-{
-       if (*options & option)
-               exit_error(PARAMETER_PROBLEM, "multiple -%c flags not allowed",
-                          opt2char(option));
-       *options |= option;
-
-       if (invert) {
-               unsigned int i;
-               for (i = 0; 1 << i != option; i++);
-
-               if (!inverse_for_options[i])
-                       exit_error(PARAMETER_PROBLEM,
-                                  "cannot have ! before -%c",
-                                  opt2char(option));
-               *invflg |= inverse_for_options[i];
-       }
-}
-
-struct iptables_target *
-find_target(const char *name, enum ipt_tryload tryload)
-{
-       struct iptables_target *ptr;
-
-       /* Standard target? */
-       if (strcmp(name, "") == 0
-           || strcmp(name, IPTC_LABEL_ACCEPT) == 0
-           || strcmp(name, IPTC_LABEL_DROP) == 0
-           || strcmp(name, IPTC_LABEL_QUEUE) == 0
-           || strcmp(name, IPTC_LABEL_RETURN) == 0)
-               name = "standard";
-
-       for (ptr = iptables_targets; ptr; ptr = ptr->next) {
-               if (strcmp(name, ptr->name) == 0)
-                       break;
-       }
-
-#ifndef NO_SHARED_LIBS
-       if (!ptr && tryload != DONT_LOAD) {
-               char path[sizeof(IPT_LIB_DIR) + sizeof("/libipt_.so")
-                        + strlen(name)];
-               sprintf(path, IPT_LIB_DIR "/libipt_%s.so", name);
-               if (dlopen(path, RTLD_NOW)) {
-                       /* Found library.  If it didn't register itself,
-                          maybe they specified match as a target. */
-                       ptr = find_target(name, DONT_LOAD);
-                       if (!ptr)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Couldn't load target `%s'\n",
-                                          name);
-               } else if (tryload == LOAD_MUST_SUCCEED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Couldn't load target `%s':%s\n",
-                                  name, dlerror());
-       }
-#else
-       if (ptr && !ptr->loaded) {
-               if (tryload != DONT_LOAD)
-                       ptr->loaded = 1;
-               else
-                       ptr = NULL;
-       }
-       if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
-               exit_error(PARAMETER_PROBLEM,
-                          "Couldn't find target `%s'\n", name);
-       }
-#endif
-
-       if (ptr)
-               ptr->used = 1;
-
-       return ptr;
-}
-
-static struct option *
-merge_options(struct option *oldopts, const struct option *newopts,
-             unsigned int *option_offset)
-{
-       unsigned int num_old, num_new, i;
-       struct option *merge;
-
-       for (num_old = 0; oldopts[num_old].name; num_old++);
-       for (num_new = 0; newopts[num_new].name; num_new++);
-
-       global_option_offset += OPTION_OFFSET;
-       *option_offset = global_option_offset;
-
-       merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
-       memcpy(merge, oldopts, num_old * sizeof(struct option));
-       for (i = 0; i < num_new; i++) {
-               merge[num_old + i] = newopts[i];
-               merge[num_old + i].val += *option_offset;
-       }
-       memset(merge + num_old + num_new, 0, sizeof(struct option));
-
-       return merge;
-}
-
-void
-register_match(struct iptables_match *me)
-{
-       struct iptables_match **i;
-
-       if (strcmp(me->version, program_version) != 0) {
-               fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
-                       program_name, me->name, me->version, program_version);
-               exit(1);
-       }
-
-       if (find_match(me->name, DONT_LOAD)) {
-               fprintf(stderr, "%s: match `%s' already registered.\n",
-                       program_name, me->name);
-               exit(1);
-       }
-
-       if (me->size != IPT_ALIGN(me->size)) {
-               fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
-                       program_name, me->name, me->size);
-               exit(1);
-       }
-
-       /* Append to list. */
-       for (i = &iptables_matches; *i; i = &(*i)->next);
-       me->next = NULL;
-       *i = me;
-
-       me->m = NULL;
-       me->mflags = 0;
-}
-
-void
-register_target(struct iptables_target *me)
-{
-       if (strcmp(me->version, program_version) != 0) {
-               fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n",
-                       program_name, me->name, me->version, program_version);
-               exit(1);
-       }
-
-       if (find_target(me->name, DONT_LOAD)) {
-               fprintf(stderr, "%s: target `%s' already registered.\n",
-                       program_name, me->name);
-               exit(1);
-       }
-
-       if (me->size != IPT_ALIGN(me->size)) {
-               fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
-                       program_name, me->name, me->size);
-               exit(1);
-       }
-
-       /* Prepend to list. */
-       me->next = iptables_targets;
-       iptables_targets = me;
-       me->t = NULL;
-       me->tflags = 0;
-}
-
-static void
-print_num(u_int64_t number, unsigned int format)
-{
-       if (format & FMT_KILOMEGAGIGA) {
-               if (number > 99999) {
-                       number = (number + 500) / 1000;
-                       if (number > 9999) {
-                               number = (number + 500) / 1000;
-                               if (number > 9999) {
-                                       number = (number + 500) / 1000;
-                                       if (number > 9999) {
-                                               number = (number + 500) / 1000;
-                                               printf(FMT("%4lluT ","%lluT "), number);
-                                       }
-                                       else printf(FMT("%4lluG ","%lluG "), number);
-                               }
-                               else printf(FMT("%4lluM ","%lluM "), number);
-                       } else
-                               printf(FMT("%4lluK ","%lluK "), number);
-               } else
-                       printf(FMT("%5llu ","%llu "), number);
-       } else
-               printf(FMT("%8llu ","%llu "), number);
-}
-
-
-static void
-print_header(unsigned int format, const char *chain, iptc_handle_t *handle)
-{
-       struct ipt_counters counters;
-       const char *pol = iptc_get_policy(chain, &counters, handle);
-       printf("Chain %s", chain);
-       if (pol) {
-               printf(" (policy %s", pol);
-               if (!(format & FMT_NOCOUNTS)) {
-                       fputc(' ', stdout);
-                       print_num(counters.pcnt, (format|FMT_NOTABLE));
-                       fputs("packets, ", stdout);
-                       print_num(counters.bcnt, (format|FMT_NOTABLE));
-                       fputs("bytes", stdout);
-               }
-               printf(")\n");
-       } else {
-               unsigned int refs;
-               if (!iptc_get_references(&refs, chain, handle))
-                       printf(" (ERROR obtaining refs)\n");
-               else
-                       printf(" (%u references)\n", refs);
-       }
-
-       if (format & FMT_LINENUMBERS)
-               printf(FMT("%-4s ", "%s "), "num");
-       if (!(format & FMT_NOCOUNTS)) {
-               if (format & FMT_KILOMEGAGIGA) {
-                       printf(FMT("%5s ","%s "), "pkts");
-                       printf(FMT("%5s ","%s "), "bytes");
-               } else {
-                       printf(FMT("%8s ","%s "), "pkts");
-                       printf(FMT("%10s ","%s "), "bytes");
-               }
-       }
-       if (!(format & FMT_NOTARGET))
-               printf(FMT("%-9s ","%s "), "target");
-       fputs(" prot ", stdout);
-       if (format & FMT_OPTIONS)
-               fputs("opt", stdout);
-       if (format & FMT_VIA) {
-               printf(FMT(" %-6s ","%s "), "in");
-               printf(FMT("%-6s ","%s "), "out");
-       }
-       printf(FMT(" %-19s ","%s "), "source");
-       printf(FMT(" %-19s "," %s "), "destination");
-       printf("\n");
-}
-
-
-static int
-print_match(const struct ipt_entry_match *m,
-           const struct ipt_ip *ip,
-           int numeric)
-{
-       struct iptables_match *match = find_match(m->u.user.name, TRY_LOAD);
-
-       if (match) {
-               if (match->print)
-                       match->print(ip, m, numeric);
-               else
-                       printf("%s ", match->name);
-       } else {
-               if (m->u.user.name[0])
-                       printf("UNKNOWN match `%s' ", m->u.user.name);
-       }
-       /* Don't stop iterating. */
-       return 0;
-}
-
-/* e is called `fw' here for hysterical raisins */
-static void
-print_firewall(const struct ipt_entry *fw,
-              const char *targname,
-              unsigned int num,
-              unsigned int format,
-              const iptc_handle_t handle)
-{
-       struct iptables_target *target = NULL;
-       const struct ipt_entry_target *t;
-       u_int8_t flags;
-       char buf[BUFSIZ];
-
-       if (!iptc_is_chain(targname, handle))
-               target = find_target(targname, TRY_LOAD);
-       else
-               target = find_target(IPT_STANDARD_TARGET, LOAD_MUST_SUCCEED);
-
-       t = ipt_get_target((struct ipt_entry *)fw);
-       flags = fw->ip.flags;
-
-       if (format & FMT_LINENUMBERS)
-               printf(FMT("%-4u ", "%u "), num+1);
-
-       if (!(format & FMT_NOCOUNTS)) {
-               print_num(fw->counters.pcnt, format);
-               print_num(fw->counters.bcnt, format);
-       }
-
-       if (!(format & FMT_NOTARGET))
-               printf(FMT("%-9s ", "%s "), targname);
-
-       fputc(fw->ip.invflags & IPT_INV_PROTO ? '!' : ' ', stdout);
-       {
-               char *pname = proto_to_name(fw->ip.proto, format&FMT_NUMERIC);
-               if (pname)
-                       printf(FMT("%-5s", "%s "), pname);
-               else
-                       printf(FMT("%-5hu", "%hu "), fw->ip.proto);
-       }
-
-       if (format & FMT_OPTIONS) {
-               if (format & FMT_NOTABLE)
-                       fputs("opt ", stdout);
-               fputc(fw->ip.invflags & IPT_INV_FRAG ? '!' : '-', stdout);
-               fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout);
-               fputc(' ', stdout);
-       }
-
-       if (format & FMT_VIA) {
-               char iface[IFNAMSIZ+2];
-
-               if (fw->ip.invflags & IPT_INV_VIA_IN) {
-                       iface[0] = '!';
-                       iface[1] = '\0';
-               }
-               else iface[0] = '\0';
-
-               if (fw->ip.iniface[0] != '\0') {
-                       strcat(iface, fw->ip.iniface);
-               }
-               else if (format & FMT_NUMERIC) strcat(iface, "*");
-               else strcat(iface, "any");
-               printf(FMT(" %-6s ","in %s "), iface);
-
-               if (fw->ip.invflags & IPT_INV_VIA_OUT) {
-                       iface[0] = '!';
-                       iface[1] = '\0';
-               }
-               else iface[0] = '\0';
-
-               if (fw->ip.outiface[0] != '\0') {
-                       strcat(iface, fw->ip.outiface);
-               }
-               else if (format & FMT_NUMERIC) strcat(iface, "*");
-               else strcat(iface, "any");
-               printf(FMT("%-6s ","out %s "), iface);
-       }
-
-       fputc(fw->ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
-       if (fw->ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC))
-               printf(FMT("%-19s ","%s "), "anywhere");
-       else {
-               if (format & FMT_NUMERIC)
-                       sprintf(buf, "%s", addr_to_dotted(&(fw->ip.src)));
-               else
-                       sprintf(buf, "%s", addr_to_anyname(&(fw->ip.src)));
-               strcat(buf, mask_to_dotted(&(fw->ip.smsk)));
-               printf(FMT("%-19s ","%s "), buf);
-       }
-
-       fputc(fw->ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
-       if (fw->ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC))
-               printf(FMT("%-19s","-> %s"), "anywhere");
-       else {
-               if (format & FMT_NUMERIC)
-                       sprintf(buf, "%s", addr_to_dotted(&(fw->ip.dst)));
-               else
-                       sprintf(buf, "%s", addr_to_anyname(&(fw->ip.dst)));
-               strcat(buf, mask_to_dotted(&(fw->ip.dmsk)));
-               printf(FMT("%-19s","-> %s"), buf);
-       }
-
-       if (format & FMT_NOTABLE)
-               fputs("  ", stdout);
-
-       IPT_MATCH_ITERATE(fw, print_match, &fw->ip, format & FMT_NUMERIC);
-
-       if (target) {
-               if (target->print)
-                       /* Print the target information. */
-                       target->print(&fw->ip, t, format & FMT_NUMERIC);
-       } else if (t->u.target_size != sizeof(*t))
-               printf("[%u bytes of unknown target data] ",
-                      t->u.target_size - sizeof(*t));
-
-       if (!(format & FMT_NONEWLINE))
-               fputc('\n', stdout);
-}
-
-static void
-print_firewall_line(const struct ipt_entry *fw,
-                   const iptc_handle_t h)
-{
-       struct ipt_entry_target *t;
-
-       t = ipt_get_target((struct ipt_entry *)fw);
-       print_firewall(fw, t->u.user.name, 0, FMT_PRINT_RULE, h);
-}
-
-static int
-append_entry(const ipt_chainlabel chain,
-            struct ipt_entry *fw,
-            unsigned int nsaddrs,
-            const struct in_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in_addr daddrs[],
-            int verbose,
-            iptc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ip.src.s_addr = saddrs[i].s_addr;
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ip.dst.s_addr = daddrs[j].s_addr;
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= iptc_append_entry(chain, fw, handle);
-               }
-       }
-
-       return ret;
-}
-
-static int
-replace_entry(const ipt_chainlabel chain,
-             struct ipt_entry *fw,
-             unsigned int rulenum,
-             const struct in_addr *saddr,
-             const struct in_addr *daddr,
-             int verbose,
-             iptc_handle_t *handle)
-{
-       fw->ip.src.s_addr = saddr->s_addr;
-       fw->ip.dst.s_addr = daddr->s_addr;
-
-       if (verbose)
-               print_firewall_line(fw, *handle);
-       return iptc_replace_entry(chain, fw, rulenum, handle);
-}
-
-static int
-insert_entry(const ipt_chainlabel chain,
-            struct ipt_entry *fw,
-            unsigned int rulenum,
-            unsigned int nsaddrs,
-            const struct in_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in_addr daddrs[],
-            int verbose,
-            iptc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ip.src.s_addr = saddrs[i].s_addr;
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ip.dst.s_addr = daddrs[j].s_addr;
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= iptc_insert_entry(chain, fw, rulenum, handle);
-               }
-       }
-
-       return ret;
-}
-
-static unsigned char *
-make_delete_mask(struct ipt_entry *fw)
-{
-       /* Establish mask for comparison */
-       unsigned int size;
-       struct iptables_match *m;
-       unsigned char *mask, *mptr;
-
-       size = sizeof(struct ipt_entry);
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               size += IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
-       }
-
-       mask = fw_calloc(1, size
-                        + IPT_ALIGN(sizeof(struct ipt_entry_target))
-                        + iptables_targets->size);
-
-       memset(mask, 0xFF, sizeof(struct ipt_entry));
-       mptr = mask + sizeof(struct ipt_entry);
-
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               memset(mptr, 0xFF,
-                      IPT_ALIGN(sizeof(struct ipt_entry_match))
-                      + m->userspacesize);
-               mptr += IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
-       }
-
-       memset(mptr, 0xFF,
-              IPT_ALIGN(sizeof(struct ipt_entry_target))
-              + iptables_targets->userspacesize);
-
-       return mask;
-}
-
-static int
-delete_entry(const ipt_chainlabel chain,
-            struct ipt_entry *fw,
-            unsigned int nsaddrs,
-            const struct in_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in_addr daddrs[],
-            int verbose,
-            iptc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-       unsigned char *mask;
-
-       mask = make_delete_mask(fw);
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ip.src.s_addr = saddrs[i].s_addr;
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ip.dst.s_addr = daddrs[j].s_addr;
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= iptc_delete_entry(chain, fw, mask, handle);
-               }
-       }
-       return ret;
-}
-
-int
-for_each_chain(int (*fn)(const ipt_chainlabel, int, iptc_handle_t *),
-              int verbose, int builtinstoo, iptc_handle_t *handle)
-{
-        int ret = 1;
-       const char *chain;
-       char *chains;
-       unsigned int i, chaincount = 0;
-
-       chain = iptc_first_chain(handle);
-       while (chain) {
-               chaincount++;
-               chain = iptc_next_chain(handle);
-        }
-
-       chains = fw_malloc(sizeof(ipt_chainlabel) * chaincount);
-       i = 0;
-       chain = iptc_first_chain(handle);
-       while (chain) {
-               strcpy(chains + i*sizeof(ipt_chainlabel), chain);
-               i++;
-               chain = iptc_next_chain(handle);
-        }
-
-       for (i = 0; i < chaincount; i++) {
-               if (!builtinstoo
-                   && iptc_builtin(chains + i*sizeof(ipt_chainlabel),
-                                   *handle))
-                       continue;
-               ret &= fn(chains + i*sizeof(ipt_chainlabel), verbose, handle);
-       }
-
-       free(chains);
-        return ret;
-}
-
-int
-flush_entries(const ipt_chainlabel chain, int verbose,
-             iptc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(flush_entries, verbose, 1, handle);
-
-       if (verbose)
-               fprintf(stdout, "Flushing chain `%s'\n", chain);
-       return iptc_flush_entries(chain, handle);
-}
-
-static int
-zero_entries(const ipt_chainlabel chain, int verbose,
-            iptc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(zero_entries, verbose, 1, handle);
-
-       if (verbose)
-               fprintf(stdout, "Zeroing chain `%s'\n", chain);
-       return iptc_zero_entries(chain, handle);
-}
-
-int
-delete_chain(const ipt_chainlabel chain, int verbose,
-            iptc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(delete_chain, verbose, 0, handle);
-
-       if (verbose)
-               fprintf(stdout, "Deleting chain `%s'\n", chain);
-       return iptc_delete_chain(chain, handle);
-}
-
-static int
-list_entries(const ipt_chainlabel chain, int verbose, int numeric,
-            int expanded, int linenumbers, iptc_handle_t *handle)
-{
-       int found = 0;
-       unsigned int format;
-       const char *this;
-
-       format = FMT_OPTIONS;
-       if (!verbose)
-               format |= FMT_NOCOUNTS;
-       else
-               format |= FMT_VIA;
-
-       if (numeric)
-               format |= FMT_NUMERIC;
-
-       if (!expanded)
-               format |= FMT_KILOMEGAGIGA;
-
-       if (linenumbers)
-               format |= FMT_LINENUMBERS;
-
-       for (this = iptc_first_chain(handle);
-            this;
-            this = iptc_next_chain(handle)) {
-               const struct ipt_entry *i;
-               unsigned int num;
-
-               if (chain && strcmp(chain, this) != 0)
-                       continue;
-
-               if (found) printf("\n");
-
-               print_header(format, this, handle);
-               i = iptc_first_rule(this, handle);
-
-               num = 0;
-               while (i) {
-                       print_firewall(i,
-                                      iptc_get_target(i, handle),
-                                      num++,
-                                      format,
-                                      *handle);
-                       i = iptc_next_rule(i, handle);
-               }
-               found = 1;
-       }
-
-       errno = ENOENT;
-       return found;
-}
-
-static char *get_modprobe(void)
-{
-       int procfile;
-       char *ret;
-
-       procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
-       if (procfile < 0)
-               return NULL;
-
-       ret = malloc(1024);
-       if (ret) {
-               switch (read(procfile, ret, 1024)) {
-               case -1: goto fail;
-               case 1024: goto fail; /* Partial read.  Wierd */
-               }
-               if (ret[strlen(ret)-1]=='\n') 
-                       ret[strlen(ret)-1]=0;
-               close(procfile);
-               return ret;
-       }
- fail:
-       free(ret);
-       close(procfile);
-       return NULL;
-}
-
-int iptables_insmod(const char *modname, const char *modprobe)
-{
-       char *buf = NULL;
-       char *argv[3];
-
-       /* If they don't explicitly set it, read out of kernel */
-       if (!modprobe) {
-               buf = get_modprobe();
-               if (!buf)
-                       return -1;
-               modprobe = buf;
-       }
-
-       switch (fork()) {
-       case 0:
-               argv[0] = (char *)modprobe;
-               argv[1] = (char *)modname;
-               argv[2] = NULL;
-               execv(argv[0], argv);
-
-               /* not usually reached */
-               exit(0);
-       case -1:
-               return -1;
-
-       default: /* parent */
-               wait(NULL);
-       }
-
-       free(buf);
-       return 0;
-}
-
-static struct ipt_entry *
-generate_entry(const struct ipt_entry *fw,
-              struct iptables_match *matches,
-              struct ipt_entry_target *target)
-{
-       unsigned int size;
-       struct iptables_match *m;
-       struct ipt_entry *e;
-
-       size = sizeof(struct ipt_entry);
-       for (m = matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               size += m->m->u.match_size;
-       }
-
-       e = fw_malloc(size + target->u.target_size);
-       *e = *fw;
-       e->target_offset = size;
-       e->next_offset = size + target->u.target_size;
-
-       size = 0;
-       for (m = matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               memcpy(e->elems + size, m->m, m->m->u.match_size);
-               size += m->m->u.match_size;
-       }
-       memcpy(e->elems + size, target, target->u.target_size);
-
-       return e;
-}
-
-int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
-{
-       struct ipt_entry fw, *e = NULL;
-       int invert = 0;
-       unsigned int nsaddrs = 0, ndaddrs = 0;
-       struct in_addr *saddrs = NULL, *daddrs = NULL;
-
-       int c, verbose = 0;
-       const char *chain = NULL;
-       const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
-       const char *policy = NULL, *newname = NULL;
-       unsigned int rulenum = 0, options = 0, command = 0;
-       const char *pcnt = NULL, *bcnt = NULL;
-       int ret = 1;
-       struct iptables_match *m;
-       struct iptables_target *target = NULL;
-       struct iptables_target *t;
-       const char *jumpto = "";
-       char *protocol = NULL;
-       const char *modprobe = NULL;
-       int proto_used = 0;
-
-       memset(&fw, 0, sizeof(fw));
-
-       opts = original_opts;
-       global_option_offset = 0;
-
-       /* re-set optind to 0 in case do_command gets called
-        * a second time */
-       optind = 0;
-
-       /* clear mflags in case do_command gets called a second time
-        * (we clear the global list of all matches for security)*/
-       for (m = iptables_matches; m; m = m->next) {
-               m->mflags = 0;
-               m->used = 0;
-       }
-
-       for (t = iptables_targets; t; t = t->next) {
-               t->tflags = 0;
-               t->used = 0;
-       }
-
-       /* Suppress error messages: we may add new options if we
-           demand-load a protocol. */
-       opterr = 0;
-
-       while ((c = getopt_long(argc, argv,
-          "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:",
-                                          opts, NULL)) != -1) {
-               switch (c) {
-                       /*
-                        * Command selection
-                        */
-               case 'A':
-                       add_command(&command, CMD_APPEND, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       break;
-
-               case 'D':
-                       add_command(&command, CMD_DELETE, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!') {
-                               rulenum = parse_rulenumber(argv[optind++]);
-                               command = CMD_DELETE_NUM;
-                       }
-                       break;
-
-               case 'R':
-                       add_command(&command, CMD_REPLACE, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires a rule number",
-                                          cmd2char(CMD_REPLACE));
-                       break;
-
-               case 'I':
-                       add_command(&command, CMD_INSERT, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       else rulenum = 1;
-                       break;
-
-               case 'L':
-                       add_command(&command, CMD_LIST, CMD_ZERO,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'F':
-                       add_command(&command, CMD_FLUSH, CMD_NONE,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'Z':
-                       add_command(&command, CMD_ZERO, CMD_LIST,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                               && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'N':
-                       if (optarg && *optarg == '-')
-                               exit_error(PARAMETER_PROBLEM,
-                                          "chain name not allowed to start "
-                                          "with `-'\n");
-                       if (find_target(optarg, TRY_LOAD))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "chain name may not clash "
-                                          "with target name\n");
-                       add_command(&command, CMD_NEW_CHAIN, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       break;
-
-               case 'X':
-                       add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'E':
-                       add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               newname = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires old-chain-name and "
-                                          "new-chain-name",
-                                           cmd2char(CMD_RENAME_CHAIN));
-                       break;
-
-               case 'P':
-                       add_command(&command, CMD_SET_POLICY, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               policy = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires a chain and a policy",
-                                          cmd2char(CMD_SET_POLICY));
-                       break;
-
-               case 'h':
-                       if (!optarg)
-                               optarg = argv[optind];
-
-                       /* iptables -p icmp -h */
-                       if (!iptables_matches && protocol)
-                               find_match(protocol, TRY_LOAD);
-
-                       exit_printhelp();
-
-                       /*
-                        * Option selection
-                        */
-               case 'p':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_PROTOCOL, &fw.ip.invflags,
-                                  invert);
-
-                       /* Canonicalize into lower case */
-                       for (protocol = argv[optind-1]; *protocol; protocol++)
-                               *protocol = tolower(*protocol);
-
-                       protocol = argv[optind-1];
-                       fw.ip.proto = parse_protocol(protocol);
-
-                       if (fw.ip.proto == 0
-                           && (fw.ip.invflags & IPT_INV_PROTO))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "rule would never match protocol");
-                       fw.nfcache |= NFC_IP_PROTO;
-                       break;
-
-               case 's':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_SOURCE, &fw.ip.invflags,
-                                  invert);
-                       shostnetworkmask = argv[optind-1];
-                       fw.nfcache |= NFC_IP_SRC;
-                       break;
-
-               case 'd':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_DESTINATION, &fw.ip.invflags,
-                                  invert);
-                       dhostnetworkmask = argv[optind-1];
-                       fw.nfcache |= NFC_IP_DST;
-                       break;
-
-               case 'j':
-                       set_option(&options, OPT_JUMP, &fw.ip.invflags,
-                                  invert);
-                       jumpto = parse_target(optarg);
-                       /* TRY_LOAD (may be chain name) */
-                       target = find_target(jumpto, TRY_LOAD);
-
-                       if (target) {
-                               size_t size;
-
-                               size = IPT_ALIGN(sizeof(struct ipt_entry_target))
-                                       + target->size;
-
-                               target->t = fw_calloc(1, size);
-                               target->t->u.target_size = size;
-                               strcpy(target->t->u.user.name, jumpto);
-                               target->init(target->t, &fw.nfcache);
-                               opts = merge_options(opts, target->extra_opts, &target->option_offset);
-                       }
-                       break;
-
-
-               case 'i':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_VIANAMEIN, &fw.ip.invflags,
-                                  invert);
-                       parse_interface(argv[optind-1],
-                                       fw.ip.iniface,
-                                       fw.ip.iniface_mask);
-                       fw.nfcache |= NFC_IP_IF_IN;
-                       break;
-
-               case 'o':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_VIANAMEOUT, &fw.ip.invflags,
-                                  invert);
-                       parse_interface(argv[optind-1],
-                                       fw.ip.outiface,
-                                       fw.ip.outiface_mask);
-                       fw.nfcache |= NFC_IP_IF_OUT;
-                       break;
-
-               case 'f':
-                       set_option(&options, OPT_FRAGMENT, &fw.ip.invflags,
-                                  invert);
-                       fw.ip.flags |= IPT_F_FRAG;
-                       fw.nfcache |= NFC_IP_FRAG;
-                       break;
-
-               case 'v':
-                       if (!verbose)
-                               set_option(&options, OPT_VERBOSE,
-                                          &fw.ip.invflags, invert);
-                       verbose++;
-                       break;
-
-               case 'm': {
-                       size_t size;
-
-                       if (invert)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unexpected ! flag before --match");
-
-                       m = find_match(optarg, LOAD_MUST_SUCCEED);
-                       size = IPT_ALIGN(sizeof(struct ipt_entry_match))
-                                        + m->size;
-                       m->m = fw_calloc(1, size);
-                       m->m->u.match_size = size;
-                       strcpy(m->m->u.user.name, m->name);
-                       m->init(m->m, &fw.nfcache);
-                       opts = merge_options(opts, m->extra_opts, &m->option_offset);
-               }
-               break;
-
-               case 'n':
-                       set_option(&options, OPT_NUMERIC, &fw.ip.invflags,
-                                  invert);
-                       break;
-
-               case 't':
-                       if (invert)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unexpected ! flag before --table");
-                       *table = argv[optind-1];
-                       break;
-
-               case 'x':
-                       set_option(&options, OPT_EXPANDED, &fw.ip.invflags,
-                                  invert);
-                       break;
-
-               case 'V':
-                       if (invert)
-                               printf("Not %s ;-)\n", program_version);
-                       else
-                               printf("%s v%s\n",
-                                      program_name, program_version);
-                       exit(0);
-
-               case '0':
-                       set_option(&options, OPT_LINENUMBERS, &fw.ip.invflags,
-                                  invert);
-                       break;
-
-               case 'M':
-                       modprobe = optarg;
-                       break;
-
-               case 'c':
-
-                       set_option(&options, OPT_COUNTERS, &fw.ip.invflags,
-                                  invert);
-                       pcnt = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               bcnt = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c requires packet and byte counter",
-                                       opt2char(OPT_COUNTERS));
-
-                       if (sscanf(pcnt, "%llu", &fw.counters.pcnt) != 1)
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c packet counter not numeric",
-                                       opt2char(OPT_COUNTERS));
-
-                       if (sscanf(bcnt, "%llu", &fw.counters.bcnt) != 1)
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c byte counter not numeric",
-                                       opt2char(OPT_COUNTERS));
-                       
-                       break;
-
-
-               case 1: /* non option */
-                       if (optarg[0] == '!' && optarg[1] == '\0') {
-                               if (invert)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "multiple consecutive ! not"
-                                                  " allowed");
-                               invert = TRUE;
-                               optarg[0] = '\0';
-                               continue;
-                       }
-                       printf("Bad argument `%s'\n", optarg);
-                       exit_tryhelp(2);
-
-               default:
-                       /* FIXME: This scheme doesn't allow two of the same
-                          matches --RR */
-                       if (!target
-                           || !(target->parse(c - target->option_offset,
-                                              argv, invert,
-                                              &target->tflags,
-                                              &fw, &target->t))) {
-                               for (m = iptables_matches; m; m = m->next) {
-                                       if (!m->used)
-                                               continue;
-
-                                       if (m->parse(c - m->option_offset,
-                                                    argv, invert,
-                                                    &m->mflags,
-                                                    &fw,
-                                                    &fw.nfcache,
-                                                    &m->m))
-                                               break;
-                               }
-
-                               /* If you listen carefully, you can
-                                  actually hear this code suck. */
-
-                               /* some explanations (after four different bugs
-                                * in 3 different releases): If we encountere a
-                                * parameter, that has not been parsed yet,
-                                * it's not an option of an explicitly loaded
-                                * match or a target.  However, we support
-                                * implicit loading of the protocol match
-                                * extension.  '-p tcp' means 'l4 proto 6' and
-                                * at the same time 'load tcp protocol match on
-                                * demand if we specify --dport'.
-                                *
-                                * To make this work, we need to make sure:
-                                * - the parameter has not been parsed by
-                                *   a match (m above)
-                                * - a protocol has been specified
-                                * - the protocol extension has not been
-                                *   loaded yet, or is loaded and unused
-                                *   [think of iptables-restore!]
-                                * - the protocol extension can be successively
-                                *   loaded
-                                */
-                               if (m == NULL
-                                   && protocol
-                                   && (!find_proto(protocol, DONT_LOAD,
-                                                  options&OPT_NUMERIC) 
-                                       || (find_proto(protocol, DONT_LOAD,
-                                                       options&OPT_NUMERIC)
-                                           && (proto_used == 0))
-                                      )
-                                   && (m = find_proto(protocol, TRY_LOAD,
-                                                      options&OPT_NUMERIC))) {
-                                       /* Try loading protocol */
-                                       size_t size;
-                                       
-                                       proto_used = 1;
-
-                                       size = IPT_ALIGN(sizeof(struct ipt_entry_match))
-                                                        + m->size;
-
-                                       m->m = fw_calloc(1, size);
-                                       m->m->u.match_size = size;
-                                       strcpy(m->m->u.user.name, m->name);
-                                       m->init(m->m, &fw.nfcache);
-
-                                       opts = merge_options(opts,
-                                           m->extra_opts, &m->option_offset);
-
-                                       optind--;
-                                       continue;
-                               }
-                               if (!m)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "Unknown arg `%s'",
-                                                  argv[optind-1]);
-                       }
-               }
-               invert = FALSE;
-       }
-
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               m->final_check(m->mflags);
-       }
-
-       if (target)
-               target->final_check(target->tflags);
-
-       /* Fix me: must put inverse options checking here --MN */
-
-       if (optind < argc)
-               exit_error(PARAMETER_PROBLEM,
-                          "unknown arguments found on commandline");
-       if (!command)
-               exit_error(PARAMETER_PROBLEM, "no command specified");
-       if (invert)
-               exit_error(PARAMETER_PROBLEM,
-                          "nothing appropriate following !");
-
-       if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) {
-               if (!(options & OPT_DESTINATION))
-                       dhostnetworkmask = "0.0.0.0/0";
-               if (!(options & OPT_SOURCE))
-                       shostnetworkmask = "0.0.0.0/0";
-       }
-
-       if (shostnetworkmask)
-               parse_hostnetworkmask(shostnetworkmask, &saddrs,
-                                     &(fw.ip.smsk), &nsaddrs);
-
-       if (dhostnetworkmask)
-               parse_hostnetworkmask(dhostnetworkmask, &daddrs,
-                                     &(fw.ip.dmsk), &ndaddrs);
-
-       if ((nsaddrs > 1 || ndaddrs > 1) &&
-           (fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
-               exit_error(PARAMETER_PROBLEM, "! not allowed with multiple"
-                          " source or destination IP addresses");
-
-       if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
-               exit_error(PARAMETER_PROBLEM, "Replacement rule does not "
-                          "specify a unique address");
-
-       generic_opt_check(command, options);
-
-       if (chain && strlen(chain) > IPT_FUNCTION_MAXNAMELEN)
-               exit_error(PARAMETER_PROBLEM,
-                          "chain name `%s' too long (must be under %i chars)",
-                          chain, IPT_FUNCTION_MAXNAMELEN);
-
-       /* only allocate handle if we weren't called with a handle */
-       if (!*handle)
-               *handle = iptc_init(*table);
-
-       if (!*handle) {
-               /* try to insmod the module if iptc_init failed */
-               iptables_insmod("ip_tables", modprobe);
-               *handle = iptc_init(*table);
-       }
-
-       if (!*handle)
-               exit_error(VERSION_PROBLEM,
-                          "can't initialize iptables table `%s': %s",
-                          *table, iptc_strerror(errno));
-
-       if (command == CMD_APPEND
-           || command == CMD_DELETE
-           || command == CMD_INSERT
-           || command == CMD_REPLACE) {
-               if (strcmp(chain, "PREROUTING") == 0
-                   || strcmp(chain, "INPUT") == 0) {
-                       /* -o not valid with incoming packets. */
-                       if (options & OPT_VIANAMEOUT)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Can't use -%c with %s\n",
-                                          opt2char(OPT_VIANAMEOUT),
-                                          chain);
-               }
-
-               if (strcmp(chain, "POSTROUTING") == 0
-                   || strcmp(chain, "OUTPUT") == 0) {
-                       /* -i not valid with outgoing packets */
-                       if (options & OPT_VIANAMEIN)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Can't use -%c with %s\n",
-                                          opt2char(OPT_VIANAMEIN),
-                                          chain);
-               }
-
-               if (target && iptc_is_chain(jumpto, *handle)) {
-                       printf("Warning: using chain %s, not extension\n",
-                              jumpto);
-
-                       target = NULL;
-               }
-
-               /* If they didn't specify a target, or it's a chain
-                  name, use standard. */
-               if (!target
-                   && (strlen(jumpto) == 0
-                       || iptc_is_chain(jumpto, *handle))) {
-                       size_t size;
-
-                       target = find_target(IPT_STANDARD_TARGET,
-                                            LOAD_MUST_SUCCEED);
-
-                       size = sizeof(struct ipt_entry_target)
-                               + target->size;
-                       target->t = fw_calloc(1, size);
-                       target->t->u.target_size = size;
-                       strcpy(target->t->u.user.name, jumpto);
-                       target->init(target->t, &fw.nfcache);
-               }
-
-               if (!target) {
-                       /* it is no chain, and we can't load a plugin.
-                        * We cannot know if the plugin is corrupt, non
-                        * existant OR if the user just misspelled a
-                        * chain. */
-                       find_target(jumpto, LOAD_MUST_SUCCEED);
-               } else {
-                       e = generate_entry(&fw, iptables_matches, target->t);
-               }
-       }
-
-       switch (command) {
-       case CMD_APPEND:
-               ret = append_entry(chain, e,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_DELETE:
-               ret = delete_entry(chain, e,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_DELETE_NUM:
-               ret = iptc_delete_num_entry(chain, rulenum - 1, handle);
-               break;
-       case CMD_REPLACE:
-               ret = replace_entry(chain, e, rulenum - 1,
-                                   saddrs, daddrs, options&OPT_VERBOSE,
-                                   handle);
-               break;
-       case CMD_INSERT:
-               ret = insert_entry(chain, e, rulenum - 1,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_LIST:
-               ret = list_entries(chain,
-                                  options&OPT_VERBOSE,
-                                  options&OPT_NUMERIC,
-                                  options&OPT_EXPANDED,
-                                  options&OPT_LINENUMBERS,
-                                  handle);
-               break;
-       case CMD_FLUSH:
-               ret = flush_entries(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_ZERO:
-               ret = zero_entries(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_LIST|CMD_ZERO:
-               ret = list_entries(chain,
-                                  options&OPT_VERBOSE,
-                                  options&OPT_NUMERIC,
-                                  options&OPT_EXPANDED,
-                                  options&OPT_LINENUMBERS,
-                                  handle);
-               if (ret)
-                       ret = zero_entries(chain,
-                                          options&OPT_VERBOSE, handle);
-               break;
-       case CMD_NEW_CHAIN:
-               ret = iptc_create_chain(chain, handle);
-               break;
-       case CMD_DELETE_CHAIN:
-               ret = delete_chain(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_RENAME_CHAIN:
-               ret = iptc_rename_chain(chain, newname, handle);
-               break;
-       case CMD_SET_POLICY:
-               ret = iptc_set_policy(chain, policy, NULL, handle);
-               break;
-       default:
-               /* We should never reach this... */
-               exit_tryhelp(2);
-       }
-
-       if (verbose > 1)
-               dump_entries(*handle);
-
-       return ret;
-}
diff --git a/.#iptables.c.1.55 b/.#iptables.c.1.55
deleted file mode 100644 (file)
index b8087f1..0000000
+++ /dev/null
@@ -1,2303 +0,0 @@
-/* Code to take an iptables-style command line and do it. */
-
-/*
- * Author: Paul.Russell@rustcorp.com.au and mneuling@radlogic.com.au
- *
- * (C) 2000-2002 by the netfilter coreteam <coreteam@netfilter.org>:
- *                 Paul 'Rusty' Russell <rusty@rustcorp.com.au>
- *                 Marc Boucher <marc+nf@mbsi.ca>
- *                 James Morris <jmorris@intercode.com.au>
- *                 Harald Welte <laforge@gnumonks.org>
- *                 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <getopt.h>
-#include <string.h>
-#include <netdb.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <unistd.h>
-#include <iptables.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef IPT_LIB_DIR
-#define IPT_LIB_DIR "/usr/lib/iptables"
-#endif
-
-#ifndef PROC_SYS_MODPROBE
-#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
-#endif
-
-#define FMT_NUMERIC    0x0001
-#define FMT_NOCOUNTS   0x0002
-#define FMT_KILOMEGAGIGA 0x0004
-#define FMT_OPTIONS    0x0008
-#define FMT_NOTABLE    0x0010
-#define FMT_NOTARGET   0x0020
-#define FMT_VIA                0x0040
-#define FMT_NONEWLINE  0x0080
-#define FMT_LINENUMBERS 0x0100
-
-#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
-                       | FMT_NUMERIC | FMT_NOTABLE)
-#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
-
-
-#define CMD_NONE               0x0000U
-#define CMD_INSERT             0x0001U
-#define CMD_DELETE             0x0002U
-#define CMD_DELETE_NUM         0x0004U
-#define CMD_REPLACE            0x0008U
-#define CMD_APPEND             0x0010U
-#define CMD_LIST               0x0020U
-#define CMD_FLUSH              0x0040U
-#define CMD_ZERO               0x0080U
-#define CMD_NEW_CHAIN          0x0100U
-#define CMD_DELETE_CHAIN       0x0200U
-#define CMD_SET_POLICY         0x0400U
-#define CMD_CHECK              0x0800U
-#define CMD_RENAME_CHAIN       0x1000U
-#define NUMBER_OF_CMD  13
-static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
-                                'N', 'X', 'P', 'E' };
-
-#define OPTION_OFFSET 256
-
-#define OPT_NONE       0x00000U
-#define OPT_NUMERIC    0x00001U
-#define OPT_SOURCE     0x00002U
-#define OPT_DESTINATION        0x00004U
-#define OPT_PROTOCOL   0x00008U
-#define OPT_JUMP       0x00010U
-#define OPT_VERBOSE    0x00020U
-#define OPT_EXPANDED   0x00040U
-#define OPT_VIANAMEIN  0x00080U
-#define OPT_VIANAMEOUT 0x00100U
-#define OPT_FRAGMENT    0x00200U
-#define OPT_LINENUMBERS 0x00400U
-#define OPT_COUNTERS   0x00800U
-#define NUMBER_OF_OPT  12
-static const char optflags[NUMBER_OF_OPT]
-= { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', 'f', '3', 'c'};
-
-static struct option original_opts[] = {
-       { "append", 1, 0, 'A' },
-       { "delete", 1, 0,  'D' },
-       { "insert", 1, 0,  'I' },
-       { "replace", 1, 0,  'R' },
-       { "list", 2, 0,  'L' },
-       { "flush", 2, 0,  'F' },
-       { "zero", 2, 0,  'Z' },
-       { "new-chain", 1, 0,  'N' },
-       { "delete-chain", 2, 0,  'X' },
-       { "rename-chain", 1, 0,  'E' },
-       { "policy", 1, 0,  'P' },
-       { "source", 1, 0, 's' },
-       { "destination", 1, 0,  'd' },
-       { "src", 1, 0,  's' }, /* synonym */
-       { "dst", 1, 0,  'd' }, /* synonym */
-       { "protocol", 1, 0,  'p' },
-       { "in-interface", 1, 0, 'i' },
-       { "jump", 1, 0, 'j' },
-       { "table", 1, 0, 't' },
-       { "match", 1, 0, 'm' },
-       { "numeric", 0, 0, 'n' },
-       { "out-interface", 1, 0, 'o' },
-       { "verbose", 0, 0, 'v' },
-       { "exact", 0, 0, 'x' },
-       { "fragments", 0, 0, 'f' },
-       { "version", 0, 0, 'V' },
-       { "help", 2, 0, 'h' },
-       { "line-numbers", 0, 0, '0' },
-       { "modprobe", 1, 0, 'M' },
-       { "set-counters", 1, 0, 'c' },
-       { 0 }
-};
-
-/* we need this for iptables-restore.  iptables-restore.c sets line to the
- * current line of the input file, in order  to give a more precise error
- * message.  iptables itself doesn't need this, so it is initialized to the
- * magic number of -1 */
-int line = -1;
-
-#ifndef __OPTIMIZE__
-struct ipt_entry_target *
-ipt_get_target(struct ipt_entry *e)
-{
-       return (void *)e + e->target_offset;
-}
-#endif
-
-static struct option *opts = original_opts;
-static unsigned int global_option_offset = 0;
-
-/* Table of legal combinations of commands and options.  If any of the
- * given commands make an option legal, that option is legal (applies to
- * CMD_LIST and CMD_ZERO only).
- * Key:
- *  +  compulsory
- *  x  illegal
- *     optional
- */
-
-static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
-/* Well, it's better than "Re: Linux vs FreeBSD" */
-{
-       /*     -n  -s  -d  -p  -j  -v  -x  -i  -o  -f  --line */
-/*INSERT*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*DELETE*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*DELETE_NUM*/{'x','x','x','x','x',' ','x','x','x','x','x'},
-/*REPLACE*/   {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*APPEND*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*LIST*/      {' ','x','x','x','x',' ',' ','x','x','x',' '},
-/*FLUSH*/     {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*ZERO*/      {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*NEW_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*DEL_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x','x'},
-/*CHECK*/     {'x','+','+','+','x',' ','x',' ',' ',' ','x'},
-/*RENAME*/    {'x','x','x','x','x',' ','x','x','x','x','x'}
-};
-
-static int inverse_for_options[NUMBER_OF_OPT] =
-{
-/* -n */ 0,
-/* -s */ IPT_INV_SRCIP,
-/* -d */ IPT_INV_DSTIP,
-/* -p */ IPT_INV_PROTO,
-/* -j */ 0,
-/* -v */ 0,
-/* -x */ 0,
-/* -i */ IPT_INV_VIA_IN,
-/* -o */ IPT_INV_VIA_OUT,
-/* -f */ IPT_INV_FRAG,
-/*--line*/ 0
-};
-
-const char *program_version;
-const char *program_name;
-
-/* Keeping track of external matches and targets: linked lists.  */
-struct iptables_match *iptables_matches = NULL;
-struct iptables_target *iptables_targets = NULL;
-
-/* Extra debugging from libiptc */
-extern void dump_entries(const iptc_handle_t handle);
-
-/* A few hardcoded protocols for 'all' and in case the user has no
-   /etc/protocols */
-struct pprot {
-       char *name;
-       u_int8_t num;
-};
-
-/* Primitive headers... */
-/* defined in netinet/in.h */
-#if 0
-#ifndef IPPROTO_ESP
-#define IPPROTO_ESP 50
-#endif
-#ifndef IPPROTO_AH
-#define IPPROTO_AH 51
-#endif
-#endif
-
-static const struct pprot chain_protos[] = {
-       { "tcp", IPPROTO_TCP },
-       { "udp", IPPROTO_UDP },
-       { "icmp", IPPROTO_ICMP },
-       { "esp", IPPROTO_ESP },
-       { "ah", IPPROTO_AH },
-       { "all", 0 },
-};
-
-static char *
-proto_to_name(u_int8_t proto, int nolookup)
-{
-       unsigned int i;
-
-       if (proto && !nolookup) {
-               struct protoent *pent = getprotobynumber(proto);
-               if (pent)
-                       return pent->p_name;
-       }
-
-       for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++)
-               if (chain_protos[i].num == proto)
-                       return chain_protos[i].name;
-
-       return NULL;
-}
-
-struct in_addr *
-dotted_to_addr(const char *dotted)
-{
-       static struct in_addr addr;
-       unsigned char *addrp;
-       char *p, *q;
-       unsigned int onebyte;
-       int i;
-       char buf[20];
-
-       /* copy dotted string, because we need to modify it */
-       strncpy(buf, dotted, sizeof(buf) - 1);
-       addrp = (unsigned char *) &(addr.s_addr);
-
-       p = buf;
-       for (i = 0; i < 3; i++) {
-               if ((q = strchr(p, '.')) == NULL)
-                       return (struct in_addr *) NULL;
-
-               *q = '\0';
-               if (string_to_number(p, 0, 255, &onebyte) == -1)
-                       return (struct in_addr *) NULL;
-
-               addrp[i] = (unsigned char) onebyte;
-               p = q + 1;
-       }
-
-       /* we've checked 3 bytes, now we check the last one */
-       if (string_to_number(p, 0, 255, &onebyte) == -1)
-               return (struct in_addr *) NULL;
-
-       addrp[3] = (unsigned char) onebyte;
-
-       return &addr;
-}
-
-static struct in_addr *
-network_to_addr(const char *name)
-{
-       struct netent *net;
-       static struct in_addr addr;
-
-       if ((net = getnetbyname(name)) != NULL) {
-               if (net->n_addrtype != AF_INET)
-                       return (struct in_addr *) NULL;
-               addr.s_addr = htonl((unsigned long) net->n_net);
-               return &addr;
-       }
-
-       return (struct in_addr *) NULL;
-}
-
-static void
-inaddrcpy(struct in_addr *dst, struct in_addr *src)
-{
-       /* memcpy(dst, src, sizeof(struct in_addr)); */
-       dst->s_addr = src->s_addr;
-}
-
-void
-exit_error(enum exittype status, char *msg, ...)
-{
-       va_list args;
-
-       va_start(args, msg);
-       fprintf(stderr, "%s v%s: ", program_name, program_version);
-       vfprintf(stderr, msg, args);
-       va_end(args);
-       fprintf(stderr, "\n");
-       if (status == PARAMETER_PROBLEM)
-               exit_tryhelp(status);
-       if (status == VERSION_PROBLEM)
-               fprintf(stderr,
-                       "Perhaps iptables or your kernel needs to be upgraded.\n");
-       exit(status);
-}
-
-void
-exit_tryhelp(int status)
-{
-<<<<<<< iptables.c
-       if (line != -1)
-               fprintf(stderr, "Error occurred at line: %d\n", line);
-=======
-       if (line != -1)
-               fprintf(stderr, "Error occured at line: %d\n", line);
->>>>>>> 1.55
-       fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
-                       program_name, program_name );
-       exit(status);
-}
-
-void
-exit_printhelp(void)
-{
-       struct iptables_match *m = NULL;
-       struct iptables_target *t = NULL;
-
-       printf("%s v%s\n\n"
-"Usage: %s -[AD] chain rule-specification [options]\n"
-"       %s -[RI] chain rulenum rule-specification [options]\n"
-"       %s -D chain rulenum [options]\n"
-"       %s -[LFZ] [chain] [options]\n"
-"       %s -[NX] chain\n"
-"       %s -E old-chain-name new-chain-name\n"
-"       %s -P chain target [options]\n"
-"       %s -h (print this help information)\n\n",
-              program_name, program_version, program_name, program_name,
-              program_name, program_name, program_name, program_name,
-              program_name, program_name);
-
-       printf(
-"Commands:\n"
-"Either long or short options are allowed.\n"
-"  --append  -A chain          Append to chain\n"
-"  --delete  -D chain          Delete matching rule from chain\n"
-"  --delete  -D chain rulenum\n"
-"                              Delete rule rulenum (1 = first) from chain\n"
-"  --insert  -I chain [rulenum]\n"
-"                              Insert in chain as rulenum (default 1=first)\n"
-"  --replace -R chain rulenum\n"
-"                              Replace rule rulenum (1 = first) in chain\n"
-"  --list    -L [chain]                List the rules in a chain or all chains\n"
-"  --flush   -F [chain]                Delete all rules in  chain or all chains\n"
-"  --zero    -Z [chain]                Zero counters in chain or all chains\n"
-"  --new     -N chain          Create a new user-defined chain\n"
-"  --delete-chain\n"
-"            -X [chain]                Delete a user-defined chain\n"
-"  --policy  -P chain target\n"
-"                              Change policy on chain to target\n"
-"  --rename-chain\n"
-"            -E old-chain new-chain\n"
-"                              Change chain name, (moving any references)\n"
-
-"Options:\n"
-"  --proto     -p [!] proto    protocol: by number or name, eg. `tcp'\n"
-"  --source    -s [!] address[/mask]\n"
-"                              source specification\n"
-"  --destination -d [!] address[/mask]\n"
-"                              destination specification\n"
-"  --in-interface -i [!] input name[+]\n"
-"                              network interface name ([+] for wildcard)\n"
-"  --jump      -j target\n"
-"                              target for rule (may load target extension)\n"
-"  --match     -m match\n"
-"                              extended match (may load extension)\n"
-"  --numeric   -n              numeric output of addresses and ports\n"
-"  --out-interface -o [!] output name[+]\n"
-"                              network interface name ([+] for wildcard)\n"
-"  --table     -t table        table to manipulate (default: `filter')\n"
-"  --verbose   -v              verbose mode\n"
-"  --line-numbers              print line numbers when listing\n"
-"  --exact     -x              expand numbers (display exact values)\n"
-"[!] --fragment        -f              match second or further fragments only\n"
-"  --modprobe=<command>                try to insert modules using this command\n"
-"  --set-counters PKTS BYTES   set the counter during insert/append\n"
-"[!] --version -V              print package version.\n");
-
-       /* Print out any special helps. A user might like to be able
-          to add a --help to the commandline, and see expected
-          results. So we call help for all matches & targets */
-       for (t=iptables_targets;t;t=t->next) {
-               printf("\n");
-               t->help();
-       }
-       for (m=iptables_matches;m;m=m->next) {
-               printf("\n");
-               m->help();
-       }
-       exit(0);
-}
-
-static void
-generic_opt_check(int command, int options)
-{
-       int i, j, legal = 0;
-
-       /* Check that commands are valid with options.  Complicated by the
-        * fact that if an option is legal with *any* command given, it is
-        * legal overall (ie. -z and -l).
-        */
-       for (i = 0; i < NUMBER_OF_OPT; i++) {
-               legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
-
-               for (j = 0; j < NUMBER_OF_CMD; j++) {
-                       if (!(command & (1<<j)))
-                               continue;
-
-                       if (!(options & (1<<i))) {
-                               if (commands_v_options[j][i] == '+')
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "You need to supply the `-%c' "
-                                                  "option for this command\n",
-                                                  optflags[i]);
-                       } else {
-                               if (commands_v_options[j][i] != 'x')
-                                       legal = 1;
-                               else if (legal == 0)
-                                       legal = -1;
-                       }
-               }
-               if (legal == -1)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Illegal option `-%c' with this command\n",
-                                  optflags[i]);
-       }
-}
-
-static char
-opt2char(int option)
-{
-       const char *ptr;
-       for (ptr = optflags; option > 1; option >>= 1, ptr++);
-
-       return *ptr;
-}
-
-static char
-cmd2char(int option)
-{
-       const char *ptr;
-       for (ptr = cmdflags; option > 1; option >>= 1, ptr++);
-
-       return *ptr;
-}
-
-static void
-add_command(int *cmd, const int newcmd, const int othercmds, int invert)
-{
-       if (invert)
-               exit_error(PARAMETER_PROBLEM, "unexpected ! flag");
-       if (*cmd & (~othercmds))
-               exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
-                          cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
-       *cmd |= newcmd;
-}
-
-int
-check_inverse(const char option[], int *invert, int *optind, int argc)
-{
-       if (option && strcmp(option, "!") == 0) {
-               if (*invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Multiple `!' flags not allowed");
-               *invert = TRUE;
-               if (optind) {
-                       *optind = *optind+1;
-                       if (argc && *optind > argc)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "no argument following `!'");
-               }
-
-               return TRUE;
-       }
-       return FALSE;
-}
-
-static void *
-fw_calloc(size_t count, size_t size)
-{
-       void *p;
-
-       if ((p = calloc(count, size)) == NULL) {
-               perror("iptables: calloc failed");
-               exit(1);
-       }
-       return p;
-}
-
-static void *
-fw_malloc(size_t size)
-{
-       void *p;
-
-       if ((p = malloc(size)) == NULL) {
-               perror("iptables: malloc failed");
-               exit(1);
-       }
-       return p;
-}
-
-static struct in_addr *
-host_to_addr(const char *name, unsigned int *naddr)
-{
-       struct hostent *host;
-       struct in_addr *addr;
-       unsigned int i;
-
-       *naddr = 0;
-       if ((host = gethostbyname(name)) != NULL) {
-               if (host->h_addrtype != AF_INET ||
-                   host->h_length != sizeof(struct in_addr))
-                       return (struct in_addr *) NULL;
-
-               while (host->h_addr_list[*naddr] != (char *) NULL)
-                       (*naddr)++;
-               addr = fw_calloc(*naddr, sizeof(struct in_addr));
-               for (i = 0; i < *naddr; i++)
-                       inaddrcpy(&(addr[i]),
-                                 (struct in_addr *) host->h_addr_list[i]);
-               return addr;
-       }
-
-       return (struct in_addr *) NULL;
-}
-
-static char *
-addr_to_host(const struct in_addr *addr)
-{
-       struct hostent *host;
-
-       if ((host = gethostbyaddr((char *) addr,
-                                 sizeof(struct in_addr), AF_INET)) != NULL)
-               return (char *) host->h_name;
-
-       return (char *) NULL;
-}
-
-/*
- *     All functions starting with "parse" should succeed, otherwise
- *     the program fails.
- *     Most routines return pointers to static data that may change
- *     between calls to the same or other routines with a few exceptions:
- *     "host_to_addr", "parse_hostnetwork", and "parse_hostnetworkmask"
- *     return global static data.
-*/
-
-static struct in_addr *
-parse_hostnetwork(const char *name, unsigned int *naddrs)
-{
-       struct in_addr *addrp, *addrptmp;
-
-       if ((addrptmp = dotted_to_addr(name)) != NULL ||
-           (addrptmp = network_to_addr(name)) != NULL) {
-               addrp = fw_malloc(sizeof(struct in_addr));
-               inaddrcpy(addrp, addrptmp);
-               *naddrs = 1;
-               return addrp;
-       }
-       if ((addrp = host_to_addr(name, naddrs)) != NULL)
-               return addrp;
-
-       exit_error(PARAMETER_PROBLEM, "host/network `%s' not found", name);
-}
-
-static struct in_addr *
-parse_mask(char *mask)
-{
-       static struct in_addr maskaddr;
-       struct in_addr *addrp;
-       unsigned int bits;
-
-       if (mask == NULL) {
-               /* no mask at all defaults to 32 bits */
-               maskaddr.s_addr = 0xFFFFFFFF;
-               return &maskaddr;
-       }
-       if ((addrp = dotted_to_addr(mask)) != NULL)
-               /* dotted_to_addr already returns a network byte order addr */
-               return addrp;
-       if (string_to_number(mask, 0, 32, &bits) == -1)
-               exit_error(PARAMETER_PROBLEM,
-                          "invalid mask `%s' specified", mask);
-       if (bits != 0) {
-               maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
-               return &maskaddr;
-       }
-
-       maskaddr.s_addr = 0L;
-       return &maskaddr;
-}
-
-void
-parse_hostnetworkmask(const char *name, struct in_addr **addrpp,
-                     struct in_addr *maskp, unsigned int *naddrs)
-{
-       struct in_addr *addrp;
-       char buf[256];
-       char *p;
-       int i, j, k, n;
-
-       strncpy(buf, name, sizeof(buf) - 1);
-       if ((p = strrchr(buf, '/')) != NULL) {
-               *p = '\0';
-               addrp = parse_mask(p + 1);
-       } else
-               addrp = parse_mask(NULL);
-       inaddrcpy(maskp, addrp);
-
-       /* if a null mask is given, the name is ignored, like in "any/0" */
-       if (maskp->s_addr == 0L)
-               strcpy(buf, "0.0.0.0");
-
-       addrp = *addrpp = parse_hostnetwork(buf, naddrs);
-       n = *naddrs;
-       for (i = 0, j = 0; i < n; i++) {
-               addrp[j++].s_addr &= maskp->s_addr;
-               for (k = 0; k < j - 1; k++) {
-                       if (addrp[k].s_addr == addrp[j - 1].s_addr) {
-                               (*naddrs)--;
-                               j--;
-                               break;
-                       }
-               }
-       }
-}
-
-struct iptables_match *
-find_match(const char *name, enum ipt_tryload tryload)
-{
-       struct iptables_match *ptr;
-
-       for (ptr = iptables_matches; ptr; ptr = ptr->next) {
-               if (strcmp(name, ptr->name) == 0)
-                       break;
-       }
-
-#ifndef NO_SHARED_LIBS
-       if (!ptr && tryload != DONT_LOAD) {
-               char path[sizeof(IPT_LIB_DIR) + sizeof("/libipt_.so")
-                        + strlen(name)];
-               sprintf(path, IPT_LIB_DIR "/libipt_%s.so", name);
-               if (dlopen(path, RTLD_NOW)) {
-                       /* Found library.  If it didn't register itself,
-                          maybe they specified target as match. */
-                       ptr = find_match(name, DONT_LOAD);
-
-                       if (!ptr)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Couldn't load match `%s'\n",
-                                          name);
-               } else if (tryload == LOAD_MUST_SUCCEED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Couldn't load match `%s':%s\n",
-                                  name, dlerror());
-       }
-#else
-       if (ptr && !ptr->loaded) {
-               if (tryload != DONT_LOAD)
-                       ptr->loaded = 1;
-               else
-                       ptr = NULL;
-       }
-       if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
-               exit_error(PARAMETER_PROBLEM,
-                          "Couldn't find match `%s'\n", name);
-       }
-#endif
-
-       if (ptr)
-               ptr->used = 1;
-
-       return ptr;
-}
-
-/* Christophe Burki wants `-p 6' to imply `-m tcp'.  */
-static struct iptables_match *
-find_proto(const char *pname, enum ipt_tryload tryload, int nolookup)
-{
-       unsigned int proto;
-
-       if (string_to_number(pname, 0, 255, &proto) != -1) {
-               char *protoname = proto_to_name(proto, nolookup);
-
-               if (protoname)
-                       return find_match(protoname, tryload);
-       } else
-               return find_match(pname, tryload);
-
-       return NULL;
-}
-
-u_int16_t
-parse_protocol(const char *s)
-{
-       unsigned int proto;
-
-       if (string_to_number(s, 0, 255, &proto) == -1) {
-               struct protoent *pent;
-
-               if ((pent = getprotobyname(s)))
-                       proto = pent->p_proto;
-               else {
-                       unsigned int i;
-                       for (i = 0;
-                            i < sizeof(chain_protos)/sizeof(struct pprot);
-                            i++) {
-                               if (strcmp(s, chain_protos[i].name) == 0) {
-                                       proto = chain_protos[i].num;
-                                       break;
-                               }
-                       }
-                       if (i == sizeof(chain_protos)/sizeof(struct pprot))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unknown protocol `%s' specified",
-                                          s);
-               }
-       }
-
-       return (u_int16_t)proto;
-}
-
-static void
-parse_interface(const char *arg, char *vianame, unsigned char *mask)
-{
-       int vialen = strlen(arg);
-       unsigned int i;
-
-       memset(mask, 0, IFNAMSIZ);
-       memset(vianame, 0, IFNAMSIZ);
-
-       if (vialen + 1 > IFNAMSIZ)
-               exit_error(PARAMETER_PROBLEM,
-                          "interface name `%s' must be shorter than IFNAMSIZ"
-                          " (%i)", arg, IFNAMSIZ-1);
-
-       strcpy(vianame, arg);
-       if (vialen == 0)
-               memset(mask, 0, IFNAMSIZ);
-       else if (vianame[vialen - 1] == '+') {
-               memset(mask, 0xFF, vialen - 1);
-               memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
-               /* Don't remove `+' here! -HW */
-       } else {
-               /* Include nul-terminator in match */
-               memset(mask, 0xFF, vialen + 1);
-               memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
-               for (i = 0; vianame[i]; i++) {
-                       if (!isalnum(vianame[i]) 
-                           && vianame[i] != '_' 
-                           && vianame[i] != '.') {
-                               printf("Warning: wierd character in interface"
-                                      " `%s' (No aliases, :, ! or *).\n",
-                                      vianame);
-                               break;
-                       }
-               }
-       }
-}
-
-/* Can't be zero. */
-static int
-parse_rulenumber(const char *rule)
-{
-       unsigned int rulenum;
-
-       if (string_to_number(rule, 1, INT_MAX, &rulenum) == -1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid rule number `%s'", rule);
-
-       return rulenum;
-}
-
-static const char *
-parse_target(const char *targetname)
-{
-       const char *ptr;
-
-       if (strlen(targetname) < 1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid target name (too short)");
-
-       if (strlen(targetname)+1 > sizeof(ipt_chainlabel))
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid target name `%s' (%i chars max)",
-                          targetname, sizeof(ipt_chainlabel)-1);
-
-       for (ptr = targetname; *ptr; ptr++)
-               if (isspace(*ptr))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Invalid target name `%s'", targetname);
-       return targetname;
-}
-
-static char *
-addr_to_network(const struct in_addr *addr)
-{
-       struct netent *net;
-
-       if ((net = getnetbyaddr((long) ntohl(addr->s_addr), AF_INET)) != NULL)
-               return (char *) net->n_name;
-
-       return (char *) NULL;
-}
-
-char *
-addr_to_dotted(const struct in_addr *addrp)
-{
-       static char buf[20];
-       const unsigned char *bytep;
-
-       bytep = (const unsigned char *) &(addrp->s_addr);
-       sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
-       return buf;
-}
-
-char *
-addr_to_anyname(const struct in_addr *addr)
-{
-       char *name;
-
-       if ((name = addr_to_host(addr)) != NULL ||
-           (name = addr_to_network(addr)) != NULL)
-               return name;
-
-       return addr_to_dotted(addr);
-}
-
-char *
-mask_to_dotted(const struct in_addr *mask)
-{
-       int i;
-       static char buf[20];
-       u_int32_t maskaddr, bits;
-
-       maskaddr = ntohl(mask->s_addr);
-
-       if (maskaddr == 0xFFFFFFFFL)
-               /* we don't want to see "/32" */
-               return "";
-
-       i = 32;
-       bits = 0xFFFFFFFEL;
-       while (--i >= 0 && maskaddr != bits)
-               bits <<= 1;
-       if (i >= 0)
-               sprintf(buf, "/%d", i);
-       else
-               /* mask was not a decent combination of 1's and 0's */
-               sprintf(buf, "/%s", addr_to_dotted(mask));
-
-       return buf;
-}
-
-int
-string_to_number(const char *s, unsigned int min, unsigned int max,
-                unsigned int *ret)
-{
-       long number;
-       char *end;
-
-       /* Handle hex, octal, etc. */
-       errno = 0;
-       number = strtol(s, &end, 0);
-       if (*end == '\0' && end != s) {
-               /* we parsed a number, let's see if we want this */
-               if (errno != ERANGE && min <= number && number <= max) {
-                       *ret = number;
-                       return 0;
-               }
-       }
-       return -1;
-}
-
-static void
-set_option(unsigned int *options, unsigned int option, u_int8_t *invflg,
-          int invert)
-{
-       if (*options & option)
-               exit_error(PARAMETER_PROBLEM, "multiple -%c flags not allowed",
-                          opt2char(option));
-       *options |= option;
-
-       if (invert) {
-               unsigned int i;
-               for (i = 0; 1 << i != option; i++);
-
-               if (!inverse_for_options[i])
-                       exit_error(PARAMETER_PROBLEM,
-                                  "cannot have ! before -%c",
-                                  opt2char(option));
-               *invflg |= inverse_for_options[i];
-       }
-}
-
-struct iptables_target *
-find_target(const char *name, enum ipt_tryload tryload)
-{
-       struct iptables_target *ptr;
-
-       /* Standard target? */
-       if (strcmp(name, "") == 0
-           || strcmp(name, IPTC_LABEL_ACCEPT) == 0
-           || strcmp(name, IPTC_LABEL_DROP) == 0
-           || strcmp(name, IPTC_LABEL_QUEUE) == 0
-           || strcmp(name, IPTC_LABEL_RETURN) == 0)
-               name = "standard";
-
-       for (ptr = iptables_targets; ptr; ptr = ptr->next) {
-               if (strcmp(name, ptr->name) == 0)
-                       break;
-       }
-
-#ifndef NO_SHARED_LIBS
-       if (!ptr && tryload != DONT_LOAD) {
-               char path[sizeof(IPT_LIB_DIR) + sizeof("/libipt_.so")
-                        + strlen(name)];
-               sprintf(path, IPT_LIB_DIR "/libipt_%s.so", name);
-               if (dlopen(path, RTLD_NOW)) {
-                       /* Found library.  If it didn't register itself,
-                          maybe they specified match as a target. */
-                       ptr = find_target(name, DONT_LOAD);
-                       if (!ptr)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Couldn't load target `%s'\n",
-                                          name);
-               } else if (tryload == LOAD_MUST_SUCCEED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Couldn't load target `%s':%s\n",
-                                  name, dlerror());
-       }
-#else
-       if (ptr && !ptr->loaded) {
-               if (tryload != DONT_LOAD)
-                       ptr->loaded = 1;
-               else
-                       ptr = NULL;
-       }
-       if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
-               exit_error(PARAMETER_PROBLEM,
-                          "Couldn't find target `%s'\n", name);
-       }
-#endif
-
-       if (ptr)
-               ptr->used = 1;
-
-       return ptr;
-}
-
-static struct option *
-merge_options(struct option *oldopts, const struct option *newopts,
-             unsigned int *option_offset)
-{
-       unsigned int num_old, num_new, i;
-       struct option *merge;
-
-       for (num_old = 0; oldopts[num_old].name; num_old++);
-       for (num_new = 0; newopts[num_new].name; num_new++);
-
-       global_option_offset += OPTION_OFFSET;
-       *option_offset = global_option_offset;
-
-       merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
-       memcpy(merge, oldopts, num_old * sizeof(struct option));
-       for (i = 0; i < num_new; i++) {
-               merge[num_old + i] = newopts[i];
-               merge[num_old + i].val += *option_offset;
-       }
-       memset(merge + num_old + num_new, 0, sizeof(struct option));
-
-       return merge;
-}
-
-void
-register_match(struct iptables_match *me)
-{
-       struct iptables_match **i;
-
-       if (strcmp(me->version, program_version) != 0) {
-               fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
-                       program_name, me->name, me->version, program_version);
-               exit(1);
-       }
-
-       if (find_match(me->name, DONT_LOAD)) {
-               fprintf(stderr, "%s: match `%s' already registered.\n",
-                       program_name, me->name);
-               exit(1);
-       }
-
-       if (me->size != IPT_ALIGN(me->size)) {
-               fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
-                       program_name, me->name, me->size);
-               exit(1);
-       }
-
-       /* Append to list. */
-       for (i = &iptables_matches; *i; i = &(*i)->next);
-       me->next = NULL;
-       *i = me;
-
-       me->m = NULL;
-       me->mflags = 0;
-}
-
-void
-register_target(struct iptables_target *me)
-{
-       if (strcmp(me->version, program_version) != 0) {
-               fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n",
-                       program_name, me->name, me->version, program_version);
-               exit(1);
-       }
-
-       if (find_target(me->name, DONT_LOAD)) {
-               fprintf(stderr, "%s: target `%s' already registered.\n",
-                       program_name, me->name);
-               exit(1);
-       }
-
-       if (me->size != IPT_ALIGN(me->size)) {
-               fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
-                       program_name, me->name, me->size);
-               exit(1);
-       }
-
-       /* Prepend to list. */
-       me->next = iptables_targets;
-       iptables_targets = me;
-       me->t = NULL;
-       me->tflags = 0;
-}
-
-static void
-print_num(u_int64_t number, unsigned int format)
-{
-       if (format & FMT_KILOMEGAGIGA) {
-               if (number > 99999) {
-                       number = (number + 500) / 1000;
-                       if (number > 9999) {
-                               number = (number + 500) / 1000;
-                               if (number > 9999) {
-                                       number = (number + 500) / 1000;
-                                       if (number > 9999) {
-                                               number = (number + 500) / 1000;
-                                               printf(FMT("%4lluT ","%lluT "), number);
-                                       }
-                                       else printf(FMT("%4lluG ","%lluG "), number);
-                               }
-                               else printf(FMT("%4lluM ","%lluM "), number);
-                       } else
-                               printf(FMT("%4lluK ","%lluK "), number);
-               } else
-                       printf(FMT("%5llu ","%llu "), number);
-       } else
-               printf(FMT("%8llu ","%llu "), number);
-}
-
-
-static void
-print_header(unsigned int format, const char *chain, iptc_handle_t *handle)
-{
-       struct ipt_counters counters;
-       const char *pol = iptc_get_policy(chain, &counters, handle);
-       printf("Chain %s", chain);
-       if (pol) {
-               printf(" (policy %s", pol);
-               if (!(format & FMT_NOCOUNTS)) {
-                       fputc(' ', stdout);
-                       print_num(counters.pcnt, (format|FMT_NOTABLE));
-                       fputs("packets, ", stdout);
-                       print_num(counters.bcnt, (format|FMT_NOTABLE));
-                       fputs("bytes", stdout);
-               }
-               printf(")\n");
-       } else {
-               unsigned int refs;
-               if (!iptc_get_references(&refs, chain, handle))
-                       printf(" (ERROR obtaining refs)\n");
-               else
-                       printf(" (%u references)\n", refs);
-       }
-
-       if (format & FMT_LINENUMBERS)
-               printf(FMT("%-4s ", "%s "), "num");
-       if (!(format & FMT_NOCOUNTS)) {
-               if (format & FMT_KILOMEGAGIGA) {
-                       printf(FMT("%5s ","%s "), "pkts");
-                       printf(FMT("%5s ","%s "), "bytes");
-               } else {
-                       printf(FMT("%8s ","%s "), "pkts");
-                       printf(FMT("%10s ","%s "), "bytes");
-               }
-       }
-       if (!(format & FMT_NOTARGET))
-               printf(FMT("%-9s ","%s "), "target");
-       fputs(" prot ", stdout);
-       if (format & FMT_OPTIONS)
-               fputs("opt", stdout);
-       if (format & FMT_VIA) {
-               printf(FMT(" %-6s ","%s "), "in");
-               printf(FMT("%-6s ","%s "), "out");
-       }
-       printf(FMT(" %-19s ","%s "), "source");
-       printf(FMT(" %-19s "," %s "), "destination");
-       printf("\n");
-}
-
-
-static int
-print_match(const struct ipt_entry_match *m,
-           const struct ipt_ip *ip,
-           int numeric)
-{
-       struct iptables_match *match = find_match(m->u.user.name, TRY_LOAD);
-
-       if (match) {
-               if (match->print)
-                       match->print(ip, m, numeric);
-               else
-                       printf("%s ", match->name);
-       } else {
-               if (m->u.user.name[0])
-                       printf("UNKNOWN match `%s' ", m->u.user.name);
-       }
-       /* Don't stop iterating. */
-       return 0;
-}
-
-/* e is called `fw' here for hysterical raisins */
-static void
-print_firewall(const struct ipt_entry *fw,
-              const char *targname,
-              unsigned int num,
-              unsigned int format,
-              const iptc_handle_t handle)
-{
-       struct iptables_target *target = NULL;
-       const struct ipt_entry_target *t;
-       u_int8_t flags;
-       char buf[BUFSIZ];
-
-       if (!iptc_is_chain(targname, handle))
-               target = find_target(targname, TRY_LOAD);
-       else
-               target = find_target(IPT_STANDARD_TARGET, LOAD_MUST_SUCCEED);
-
-       t = ipt_get_target((struct ipt_entry *)fw);
-       flags = fw->ip.flags;
-
-       if (format & FMT_LINENUMBERS)
-               printf(FMT("%-4u ", "%u "), num+1);
-
-       if (!(format & FMT_NOCOUNTS)) {
-               print_num(fw->counters.pcnt, format);
-               print_num(fw->counters.bcnt, format);
-       }
-
-       if (!(format & FMT_NOTARGET))
-               printf(FMT("%-9s ", "%s "), targname);
-
-       fputc(fw->ip.invflags & IPT_INV_PROTO ? '!' : ' ', stdout);
-       {
-               char *pname = proto_to_name(fw->ip.proto, format&FMT_NUMERIC);
-               if (pname)
-                       printf(FMT("%-5s", "%s "), pname);
-               else
-                       printf(FMT("%-5hu", "%hu "), fw->ip.proto);
-       }
-
-       if (format & FMT_OPTIONS) {
-               if (format & FMT_NOTABLE)
-                       fputs("opt ", stdout);
-               fputc(fw->ip.invflags & IPT_INV_FRAG ? '!' : '-', stdout);
-               fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout);
-               fputc(' ', stdout);
-       }
-
-       if (format & FMT_VIA) {
-               char iface[IFNAMSIZ+2];
-
-               if (fw->ip.invflags & IPT_INV_VIA_IN) {
-                       iface[0] = '!';
-                       iface[1] = '\0';
-               }
-               else iface[0] = '\0';
-
-               if (fw->ip.iniface[0] != '\0') {
-                       strcat(iface, fw->ip.iniface);
-               }
-               else if (format & FMT_NUMERIC) strcat(iface, "*");
-               else strcat(iface, "any");
-               printf(FMT(" %-6s ","in %s "), iface);
-
-               if (fw->ip.invflags & IPT_INV_VIA_OUT) {
-                       iface[0] = '!';
-                       iface[1] = '\0';
-               }
-               else iface[0] = '\0';
-
-               if (fw->ip.outiface[0] != '\0') {
-                       strcat(iface, fw->ip.outiface);
-               }
-               else if (format & FMT_NUMERIC) strcat(iface, "*");
-               else strcat(iface, "any");
-               printf(FMT("%-6s ","out %s "), iface);
-       }
-
-       fputc(fw->ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
-       if (fw->ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC))
-               printf(FMT("%-19s ","%s "), "anywhere");
-       else {
-               if (format & FMT_NUMERIC)
-                       sprintf(buf, "%s", addr_to_dotted(&(fw->ip.src)));
-               else
-                       sprintf(buf, "%s", addr_to_anyname(&(fw->ip.src)));
-               strcat(buf, mask_to_dotted(&(fw->ip.smsk)));
-               printf(FMT("%-19s ","%s "), buf);
-       }
-
-       fputc(fw->ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
-       if (fw->ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC))
-               printf(FMT("%-19s","-> %s"), "anywhere");
-       else {
-               if (format & FMT_NUMERIC)
-                       sprintf(buf, "%s", addr_to_dotted(&(fw->ip.dst)));
-               else
-                       sprintf(buf, "%s", addr_to_anyname(&(fw->ip.dst)));
-               strcat(buf, mask_to_dotted(&(fw->ip.dmsk)));
-               printf(FMT("%-19s","-> %s"), buf);
-       }
-
-       if (format & FMT_NOTABLE)
-               fputs("  ", stdout);
-
-       IPT_MATCH_ITERATE(fw, print_match, &fw->ip, format & FMT_NUMERIC);
-
-       if (target) {
-               if (target->print)
-                       /* Print the target information. */
-                       target->print(&fw->ip, t, format & FMT_NUMERIC);
-       } else if (t->u.target_size != sizeof(*t))
-               printf("[%u bytes of unknown target data] ",
-                      t->u.target_size - sizeof(*t));
-
-       if (!(format & FMT_NONEWLINE))
-               fputc('\n', stdout);
-}
-
-static void
-print_firewall_line(const struct ipt_entry *fw,
-                   const iptc_handle_t h)
-{
-       struct ipt_entry_target *t;
-
-       t = ipt_get_target((struct ipt_entry *)fw);
-       print_firewall(fw, t->u.user.name, 0, FMT_PRINT_RULE, h);
-}
-
-static int
-append_entry(const ipt_chainlabel chain,
-            struct ipt_entry *fw,
-            unsigned int nsaddrs,
-            const struct in_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in_addr daddrs[],
-            int verbose,
-            iptc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ip.src.s_addr = saddrs[i].s_addr;
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ip.dst.s_addr = daddrs[j].s_addr;
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= iptc_append_entry(chain, fw, handle);
-               }
-       }
-
-       return ret;
-}
-
-static int
-replace_entry(const ipt_chainlabel chain,
-             struct ipt_entry *fw,
-             unsigned int rulenum,
-             const struct in_addr *saddr,
-             const struct in_addr *daddr,
-             int verbose,
-             iptc_handle_t *handle)
-{
-       fw->ip.src.s_addr = saddr->s_addr;
-       fw->ip.dst.s_addr = daddr->s_addr;
-
-       if (verbose)
-               print_firewall_line(fw, *handle);
-       return iptc_replace_entry(chain, fw, rulenum, handle);
-}
-
-static int
-insert_entry(const ipt_chainlabel chain,
-            struct ipt_entry *fw,
-            unsigned int rulenum,
-            unsigned int nsaddrs,
-            const struct in_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in_addr daddrs[],
-            int verbose,
-            iptc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ip.src.s_addr = saddrs[i].s_addr;
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ip.dst.s_addr = daddrs[j].s_addr;
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= iptc_insert_entry(chain, fw, rulenum, handle);
-               }
-       }
-
-       return ret;
-}
-
-static unsigned char *
-make_delete_mask(struct ipt_entry *fw)
-{
-       /* Establish mask for comparison */
-       unsigned int size;
-       struct iptables_match *m;
-       unsigned char *mask, *mptr;
-
-       size = sizeof(struct ipt_entry);
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               size += IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
-       }
-
-       mask = fw_calloc(1, size
-                        + IPT_ALIGN(sizeof(struct ipt_entry_target))
-                        + iptables_targets->size);
-
-       memset(mask, 0xFF, sizeof(struct ipt_entry));
-       mptr = mask + sizeof(struct ipt_entry);
-
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               memset(mptr, 0xFF,
-                      IPT_ALIGN(sizeof(struct ipt_entry_match))
-                      + m->userspacesize);
-               mptr += IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
-       }
-
-       memset(mptr, 0xFF,
-              IPT_ALIGN(sizeof(struct ipt_entry_target))
-              + iptables_targets->userspacesize);
-
-       return mask;
-}
-
-static int
-delete_entry(const ipt_chainlabel chain,
-            struct ipt_entry *fw,
-            unsigned int nsaddrs,
-            const struct in_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in_addr daddrs[],
-            int verbose,
-            iptc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-       unsigned char *mask;
-
-       mask = make_delete_mask(fw);
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ip.src.s_addr = saddrs[i].s_addr;
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ip.dst.s_addr = daddrs[j].s_addr;
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= iptc_delete_entry(chain, fw, mask, handle);
-               }
-       }
-       return ret;
-}
-
-int
-for_each_chain(int (*fn)(const ipt_chainlabel, int, iptc_handle_t *),
-              int verbose, int builtinstoo, iptc_handle_t *handle)
-{
-        int ret = 1;
-       const char *chain;
-       char *chains;
-       unsigned int i, chaincount = 0;
-
-       chain = iptc_first_chain(handle);
-       while (chain) {
-               chaincount++;
-               chain = iptc_next_chain(handle);
-        }
-
-       chains = fw_malloc(sizeof(ipt_chainlabel) * chaincount);
-       i = 0;
-       chain = iptc_first_chain(handle);
-       while (chain) {
-               strcpy(chains + i*sizeof(ipt_chainlabel), chain);
-               i++;
-               chain = iptc_next_chain(handle);
-        }
-
-       for (i = 0; i < chaincount; i++) {
-               if (!builtinstoo
-                   && iptc_builtin(chains + i*sizeof(ipt_chainlabel),
-                                   *handle))
-                       continue;
-               ret &= fn(chains + i*sizeof(ipt_chainlabel), verbose, handle);
-       }
-
-       free(chains);
-        return ret;
-}
-
-int
-flush_entries(const ipt_chainlabel chain, int verbose,
-             iptc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(flush_entries, verbose, 1, handle);
-
-       if (verbose)
-               fprintf(stdout, "Flushing chain `%s'\n", chain);
-       return iptc_flush_entries(chain, handle);
-}
-
-static int
-zero_entries(const ipt_chainlabel chain, int verbose,
-            iptc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(zero_entries, verbose, 1, handle);
-
-       if (verbose)
-               fprintf(stdout, "Zeroing chain `%s'\n", chain);
-       return iptc_zero_entries(chain, handle);
-}
-
-int
-delete_chain(const ipt_chainlabel chain, int verbose,
-            iptc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(delete_chain, verbose, 0, handle);
-
-       if (verbose)
-               fprintf(stdout, "Deleting chain `%s'\n", chain);
-       return iptc_delete_chain(chain, handle);
-}
-
-static int
-list_entries(const ipt_chainlabel chain, int verbose, int numeric,
-            int expanded, int linenumbers, iptc_handle_t *handle)
-{
-       int found = 0;
-       unsigned int format;
-       const char *this;
-
-       format = FMT_OPTIONS;
-       if (!verbose)
-               format |= FMT_NOCOUNTS;
-       else
-               format |= FMT_VIA;
-
-       if (numeric)
-               format |= FMT_NUMERIC;
-
-       if (!expanded)
-               format |= FMT_KILOMEGAGIGA;
-
-       if (linenumbers)
-               format |= FMT_LINENUMBERS;
-
-       for (this = iptc_first_chain(handle);
-            this;
-            this = iptc_next_chain(handle)) {
-               const struct ipt_entry *i;
-               unsigned int num;
-
-               if (chain && strcmp(chain, this) != 0)
-                       continue;
-
-               if (found) printf("\n");
-
-               print_header(format, this, handle);
-               i = iptc_first_rule(this, handle);
-
-               num = 0;
-               while (i) {
-                       print_firewall(i,
-                                      iptc_get_target(i, handle),
-                                      num++,
-                                      format,
-                                      *handle);
-                       i = iptc_next_rule(i, handle);
-               }
-               found = 1;
-       }
-
-       errno = ENOENT;
-       return found;
-}
-
-static char *get_modprobe(void)
-{
-       int procfile;
-       char *ret;
-
-       procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
-       if (procfile < 0)
-               return NULL;
-
-       ret = malloc(1024);
-       if (ret) {
-               switch (read(procfile, ret, 1024)) {
-               case -1: goto fail;
-               case 1024: goto fail; /* Partial read.  Wierd */
-               }
-               if (ret[strlen(ret)-1]=='\n') 
-                       ret[strlen(ret)-1]=0;
-               close(procfile);
-               return ret;
-       }
- fail:
-       free(ret);
-       close(procfile);
-       return NULL;
-}
-
-int iptables_insmod(const char *modname, const char *modprobe)
-{
-       char *buf = NULL;
-       char *argv[3];
-
-       /* If they don't explicitly set it, read out of kernel */
-       if (!modprobe) {
-               buf = get_modprobe();
-               if (!buf)
-                       return -1;
-               modprobe = buf;
-       }
-
-       switch (fork()) {
-       case 0:
-               argv[0] = (char *)modprobe;
-               argv[1] = (char *)modname;
-               argv[2] = NULL;
-               execv(argv[0], argv);
-
-               /* not usually reached */
-               exit(0);
-       case -1:
-               return -1;
-
-       default: /* parent */
-               wait(NULL);
-       }
-
-       free(buf);
-       return 0;
-}
-
-static struct ipt_entry *
-generate_entry(const struct ipt_entry *fw,
-              struct iptables_match *matches,
-              struct ipt_entry_target *target)
-{
-       unsigned int size;
-       struct iptables_match *m;
-       struct ipt_entry *e;
-
-       size = sizeof(struct ipt_entry);
-       for (m = matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               size += m->m->u.match_size;
-       }
-
-       e = fw_malloc(size + target->u.target_size);
-       *e = *fw;
-       e->target_offset = size;
-       e->next_offset = size + target->u.target_size;
-
-       size = 0;
-       for (m = matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               memcpy(e->elems + size, m->m, m->m->u.match_size);
-               size += m->m->u.match_size;
-       }
-       memcpy(e->elems + size, target, target->u.target_size);
-
-       return e;
-}
-
-int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
-{
-       struct ipt_entry fw, *e = NULL;
-       int invert = 0;
-       unsigned int nsaddrs = 0, ndaddrs = 0;
-       struct in_addr *saddrs = NULL, *daddrs = NULL;
-
-       int c, verbose = 0;
-       const char *chain = NULL;
-       const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
-       const char *policy = NULL, *newname = NULL;
-       unsigned int rulenum = 0, options = 0, command = 0;
-       const char *pcnt = NULL, *bcnt = NULL;
-       int ret = 1;
-       struct iptables_match *m;
-       struct iptables_target *target = NULL;
-       struct iptables_target *t;
-       const char *jumpto = "";
-       char *protocol = NULL;
-       const char *modprobe = NULL;
-       int proto_used = 0;
-
-       memset(&fw, 0, sizeof(fw));
-
-       opts = original_opts;
-       global_option_offset = 0;
-
-       /* re-set optind to 0 in case do_command gets called
-        * a second time */
-       optind = 0;
-
-       /* clear mflags in case do_command gets called a second time
-        * (we clear the global list of all matches for security)*/
-       for (m = iptables_matches; m; m = m->next) {
-               m->mflags = 0;
-               m->used = 0;
-       }
-
-       for (t = iptables_targets; t; t = t->next) {
-               t->tflags = 0;
-               t->used = 0;
-       }
-
-       /* Suppress error messages: we may add new options if we
-           demand-load a protocol. */
-       opterr = 0;
-
-       while ((c = getopt_long(argc, argv,
-          "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:",
-                                          opts, NULL)) != -1) {
-               switch (c) {
-                       /*
-                        * Command selection
-                        */
-               case 'A':
-                       add_command(&command, CMD_APPEND, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       break;
-
-               case 'D':
-                       add_command(&command, CMD_DELETE, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!') {
-                               rulenum = parse_rulenumber(argv[optind++]);
-                               command = CMD_DELETE_NUM;
-                       }
-                       break;
-
-               case 'R':
-                       add_command(&command, CMD_REPLACE, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires a rule number",
-                                          cmd2char(CMD_REPLACE));
-                       break;
-
-               case 'I':
-                       add_command(&command, CMD_INSERT, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       else rulenum = 1;
-                       break;
-
-               case 'L':
-                       add_command(&command, CMD_LIST, CMD_ZERO,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'F':
-                       add_command(&command, CMD_FLUSH, CMD_NONE,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'Z':
-                       add_command(&command, CMD_ZERO, CMD_LIST,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                               && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'N':
-                       if (optarg && *optarg == '-')
-                               exit_error(PARAMETER_PROBLEM,
-                                          "chain name not allowed to start "
-                                          "with `-'\n");
-                       if (find_target(optarg, TRY_LOAD))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "chain name may not clash "
-                                          "with target name\n");
-                       add_command(&command, CMD_NEW_CHAIN, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       break;
-
-               case 'X':
-                       add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'E':
-                       add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               newname = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires old-chain-name and "
-                                          "new-chain-name",
-                                           cmd2char(CMD_RENAME_CHAIN));
-                       break;
-
-               case 'P':
-                       add_command(&command, CMD_SET_POLICY, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               policy = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires a chain and a policy",
-                                          cmd2char(CMD_SET_POLICY));
-                       break;
-
-               case 'h':
-                       if (!optarg)
-                               optarg = argv[optind];
-
-                       /* iptables -p icmp -h */
-                       if (!iptables_matches && protocol)
-                               find_match(protocol, TRY_LOAD);
-
-                       exit_printhelp();
-
-                       /*
-                        * Option selection
-                        */
-               case 'p':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_PROTOCOL, &fw.ip.invflags,
-                                  invert);
-
-                       /* Canonicalize into lower case */
-                       for (protocol = argv[optind-1]; *protocol; protocol++)
-                               *protocol = tolower(*protocol);
-
-                       protocol = argv[optind-1];
-                       fw.ip.proto = parse_protocol(protocol);
-
-                       if (fw.ip.proto == 0
-                           && (fw.ip.invflags & IPT_INV_PROTO))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "rule would never match protocol");
-                       fw.nfcache |= NFC_IP_PROTO;
-                       break;
-
-               case 's':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_SOURCE, &fw.ip.invflags,
-                                  invert);
-                       shostnetworkmask = argv[optind-1];
-                       fw.nfcache |= NFC_IP_SRC;
-                       break;
-
-               case 'd':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_DESTINATION, &fw.ip.invflags,
-                                  invert);
-                       dhostnetworkmask = argv[optind-1];
-                       fw.nfcache |= NFC_IP_DST;
-                       break;
-
-               case 'j':
-                       set_option(&options, OPT_JUMP, &fw.ip.invflags,
-                                  invert);
-                       jumpto = parse_target(optarg);
-                       /* TRY_LOAD (may be chain name) */
-                       target = find_target(jumpto, TRY_LOAD);
-
-                       if (target) {
-                               size_t size;
-
-                               size = IPT_ALIGN(sizeof(struct ipt_entry_target))
-                                       + target->size;
-
-                               target->t = fw_calloc(1, size);
-                               target->t->u.target_size = size;
-                               strcpy(target->t->u.user.name, jumpto);
-                               target->init(target->t, &fw.nfcache);
-                               opts = merge_options(opts, target->extra_opts, &target->option_offset);
-                       }
-                       break;
-
-
-               case 'i':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_VIANAMEIN, &fw.ip.invflags,
-                                  invert);
-                       parse_interface(argv[optind-1],
-                                       fw.ip.iniface,
-                                       fw.ip.iniface_mask);
-                       fw.nfcache |= NFC_IP_IF_IN;
-                       break;
-
-               case 'o':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_VIANAMEOUT, &fw.ip.invflags,
-                                  invert);
-                       parse_interface(argv[optind-1],
-                                       fw.ip.outiface,
-                                       fw.ip.outiface_mask);
-                       fw.nfcache |= NFC_IP_IF_OUT;
-                       break;
-
-               case 'f':
-                       set_option(&options, OPT_FRAGMENT, &fw.ip.invflags,
-                                  invert);
-                       fw.ip.flags |= IPT_F_FRAG;
-                       fw.nfcache |= NFC_IP_FRAG;
-                       break;
-
-               case 'v':
-                       if (!verbose)
-                               set_option(&options, OPT_VERBOSE,
-                                          &fw.ip.invflags, invert);
-                       verbose++;
-                       break;
-
-               case 'm': {
-                       size_t size;
-
-                       if (invert)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unexpected ! flag before --match");
-
-                       m = find_match(optarg, LOAD_MUST_SUCCEED);
-                       size = IPT_ALIGN(sizeof(struct ipt_entry_match))
-                                        + m->size;
-                       m->m = fw_calloc(1, size);
-                       m->m->u.match_size = size;
-                       strcpy(m->m->u.user.name, m->name);
-                       m->init(m->m, &fw.nfcache);
-                       opts = merge_options(opts, m->extra_opts, &m->option_offset);
-               }
-               break;
-
-               case 'n':
-                       set_option(&options, OPT_NUMERIC, &fw.ip.invflags,
-                                  invert);
-                       break;
-
-               case 't':
-                       if (invert)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unexpected ! flag before --table");
-                       *table = argv[optind-1];
-                       break;
-
-               case 'x':
-                       set_option(&options, OPT_EXPANDED, &fw.ip.invflags,
-                                  invert);
-                       break;
-
-               case 'V':
-                       if (invert)
-                               printf("Not %s ;-)\n", program_version);
-                       else
-                               printf("%s v%s\n",
-                                      program_name, program_version);
-                       exit(0);
-
-               case '0':
-                       set_option(&options, OPT_LINENUMBERS, &fw.ip.invflags,
-                                  invert);
-                       break;
-
-               case 'M':
-                       modprobe = optarg;
-                       break;
-
-               case 'c':
-
-                       set_option(&options, OPT_COUNTERS, &fw.ip.invflags,
-                                  invert);
-                       pcnt = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               bcnt = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c requires packet and byte counter",
-                                       opt2char(OPT_COUNTERS));
-
-                       if (sscanf(pcnt, "%llu", &fw.counters.pcnt) != 1)
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c packet counter not numeric",
-                                       opt2char(OPT_COUNTERS));
-
-                       if (sscanf(bcnt, "%llu", &fw.counters.bcnt) != 1)
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c byte counter not numeric",
-                                       opt2char(OPT_COUNTERS));
-                       
-                       break;
-
-
-               case 1: /* non option */
-                       if (optarg[0] == '!' && optarg[1] == '\0') {
-                               if (invert)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "multiple consecutive ! not"
-                                                  " allowed");
-                               invert = TRUE;
-                               optarg[0] = '\0';
-                               continue;
-                       }
-                       printf("Bad argument `%s'\n", optarg);
-                       exit_tryhelp(2);
-
-               default:
-                       /* FIXME: This scheme doesn't allow two of the same
-                          matches --RR */
-                       if (!target
-                           || !(target->parse(c - target->option_offset,
-                                              argv, invert,
-                                              &target->tflags,
-                                              &fw, &target->t))) {
-                               for (m = iptables_matches; m; m = m->next) {
-                                       if (!m->used)
-                                               continue;
-
-                                       if (m->parse(c - m->option_offset,
-                                                    argv, invert,
-                                                    &m->mflags,
-                                                    &fw,
-                                                    &fw.nfcache,
-                                                    &m->m))
-                                               break;
-                               }
-
-                               /* If you listen carefully, you can
-                                  actually hear this code suck. */
-
-                               /* some explanations (after four different bugs
-                                * in 3 different releases): If we encountere a
-                                * parameter, that has not been parsed yet,
-                                * it's not an option of an explicitly loaded
-                                * match or a target.  However, we support
-                                * implicit loading of the protocol match
-                                * extension.  '-p tcp' means 'l4 proto 6' and
-                                * at the same time 'load tcp protocol match on
-                                * demand if we specify --dport'.
-                                *
-                                * To make this work, we need to make sure:
-                                * - the parameter has not been parsed by
-                                *   a match (m above)
-                                * - a protocol has been specified
-                                * - the protocol extension has not been
-                                *   loaded yet, or is loaded and unused
-                                *   [think of iptables-restore!]
-                                * - the protocol extension can be successively
-                                *   loaded
-                                */
-                               if (m == NULL
-                                   && protocol
-                                   && (!find_proto(protocol, DONT_LOAD,
-                                                  options&OPT_NUMERIC) 
-                                       || (find_proto(protocol, DONT_LOAD,
-                                                       options&OPT_NUMERIC)
-                                           && (proto_used == 0))
-                                      )
-                                   && (m = find_proto(protocol, TRY_LOAD,
-                                                      options&OPT_NUMERIC))) {
-                                       /* Try loading protocol */
-                                       size_t size;
-                                       
-                                       proto_used = 1;
-
-                                       size = IPT_ALIGN(sizeof(struct ipt_entry_match))
-                                                        + m->size;
-
-                                       m->m = fw_calloc(1, size);
-                                       m->m->u.match_size = size;
-                                       strcpy(m->m->u.user.name, m->name);
-                                       m->init(m->m, &fw.nfcache);
-
-                                       opts = merge_options(opts,
-                                           m->extra_opts, &m->option_offset);
-
-                                       optind--;
-                                       continue;
-                               }
-                               if (!m)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "Unknown arg `%s'",
-                                                  argv[optind-1]);
-                       }
-               }
-               invert = FALSE;
-       }
-
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               m->final_check(m->mflags);
-       }
-
-       if (target)
-               target->final_check(target->tflags);
-
-       /* Fix me: must put inverse options checking here --MN */
-
-       if (optind < argc)
-               exit_error(PARAMETER_PROBLEM,
-                          "unknown arguments found on commandline");
-       if (!command)
-               exit_error(PARAMETER_PROBLEM, "no command specified");
-       if (invert)
-               exit_error(PARAMETER_PROBLEM,
-                          "nothing appropriate following !");
-
-       if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) {
-               if (!(options & OPT_DESTINATION))
-                       dhostnetworkmask = "0.0.0.0/0";
-               if (!(options & OPT_SOURCE))
-                       shostnetworkmask = "0.0.0.0/0";
-       }
-
-       if (shostnetworkmask)
-               parse_hostnetworkmask(shostnetworkmask, &saddrs,
-                                     &(fw.ip.smsk), &nsaddrs);
-
-       if (dhostnetworkmask)
-               parse_hostnetworkmask(dhostnetworkmask, &daddrs,
-                                     &(fw.ip.dmsk), &ndaddrs);
-
-       if ((nsaddrs > 1 || ndaddrs > 1) &&
-           (fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
-               exit_error(PARAMETER_PROBLEM, "! not allowed with multiple"
-                          " source or destination IP addresses");
-
-       if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
-               exit_error(PARAMETER_PROBLEM, "Replacement rule does not "
-                          "specify a unique address");
-
-       generic_opt_check(command, options);
-
-       if (chain && strlen(chain) > IPT_FUNCTION_MAXNAMELEN)
-               exit_error(PARAMETER_PROBLEM,
-                          "chain name `%s' too long (must be under %i chars)",
-                          chain, IPT_FUNCTION_MAXNAMELEN);
-
-       /* only allocate handle if we weren't called with a handle */
-       if (!*handle)
-               *handle = iptc_init(*table);
-
-       if (!*handle) {
-               /* try to insmod the module if iptc_init failed */
-               iptables_insmod("ip_tables", modprobe);
-               *handle = iptc_init(*table);
-       }
-
-       if (!*handle)
-               exit_error(VERSION_PROBLEM,
-                          "can't initialize iptables table `%s': %s",
-                          *table, iptc_strerror(errno));
-
-       if (command == CMD_APPEND
-           || command == CMD_DELETE
-           || command == CMD_INSERT
-           || command == CMD_REPLACE) {
-               if (strcmp(chain, "PREROUTING") == 0
-                   || strcmp(chain, "INPUT") == 0) {
-                       /* -o not valid with incoming packets. */
-                       if (options & OPT_VIANAMEOUT)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Can't use -%c with %s\n",
-                                          opt2char(OPT_VIANAMEOUT),
-                                          chain);
-               }
-
-               if (strcmp(chain, "POSTROUTING") == 0
-                   || strcmp(chain, "OUTPUT") == 0) {
-                       /* -i not valid with outgoing packets */
-                       if (options & OPT_VIANAMEIN)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Can't use -%c with %s\n",
-                                          opt2char(OPT_VIANAMEIN),
-                                          chain);
-               }
-
-               if (target && iptc_is_chain(jumpto, *handle)) {
-                       printf("Warning: using chain %s, not extension\n",
-                              jumpto);
-
-                       target = NULL;
-               }
-
-               /* If they didn't specify a target, or it's a chain
-                  name, use standard. */
-               if (!target
-                   && (strlen(jumpto) == 0
-                       || iptc_is_chain(jumpto, *handle))) {
-                       size_t size;
-
-                       target = find_target(IPT_STANDARD_TARGET,
-                                            LOAD_MUST_SUCCEED);
-
-                       size = sizeof(struct ipt_entry_target)
-                               + target->size;
-                       target->t = fw_calloc(1, size);
-                       target->t->u.target_size = size;
-                       strcpy(target->t->u.user.name, jumpto);
-                       target->init(target->t, &fw.nfcache);
-               }
-
-               if (!target) {
-                       /* it is no chain, and we can't load a plugin.
-                        * We cannot know if the plugin is corrupt, non
-                        * existant OR if the user just misspelled a
-                        * chain. */
-                       find_target(jumpto, LOAD_MUST_SUCCEED);
-               } else {
-                       e = generate_entry(&fw, iptables_matches, target->t);
-               }
-       }
-
-       switch (command) {
-       case CMD_APPEND:
-               ret = append_entry(chain, e,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_DELETE:
-               ret = delete_entry(chain, e,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_DELETE_NUM:
-               ret = iptc_delete_num_entry(chain, rulenum - 1, handle);
-               break;
-       case CMD_REPLACE:
-               ret = replace_entry(chain, e, rulenum - 1,
-                                   saddrs, daddrs, options&OPT_VERBOSE,
-                                   handle);
-               break;
-       case CMD_INSERT:
-               ret = insert_entry(chain, e, rulenum - 1,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_LIST:
-               ret = list_entries(chain,
-                                  options&OPT_VERBOSE,
-                                  options&OPT_NUMERIC,
-                                  options&OPT_EXPANDED,
-                                  options&OPT_LINENUMBERS,
-                                  handle);
-               break;
-       case CMD_FLUSH:
-               ret = flush_entries(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_ZERO:
-               ret = zero_entries(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_LIST|CMD_ZERO:
-               ret = list_entries(chain,
-                                  options&OPT_VERBOSE,
-                                  options&OPT_NUMERIC,
-                                  options&OPT_EXPANDED,
-                                  options&OPT_LINENUMBERS,
-                                  handle);
-               if (ret)
-                       ret = zero_entries(chain,
-                                          options&OPT_VERBOSE, handle);
-               break;
-       case CMD_NEW_CHAIN:
-               ret = iptc_create_chain(chain, handle);
-               break;
-       case CMD_DELETE_CHAIN:
-               ret = delete_chain(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_RENAME_CHAIN:
-               ret = iptc_rename_chain(chain, newname, handle);
-               break;
-       case CMD_SET_POLICY:
-               ret = iptc_set_policy(chain, policy, NULL, handle);
-               break;
-       default:
-               /* We should never reach this... */
-               exit_tryhelp(2);
-       }
-
-       if (verbose > 1)
-               dump_entries(*handle);
-
-       return ret;
-}
diff --git a/Makefile.nolibnsl b/Makefile.nolibnsl
deleted file mode 100644 (file)
index 622a680..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-# uncomment this to get a fully statically linked version
-# NO_SHARED_LIBS = 1
-
-# uncomment this to disable IPv6 support
-# DO_IPV6 = 0
-
-######################################################################
-# YOU SHOULD NOT NEED TO TOUCH ANYTHING BELOW THIS LINE
-######################################################################
-
-# Standard part of Makefile for topdir.
-TOPLEVEL_INCLUDED=YES
-
-ifndef KERNEL_DIR
-KERNEL_DIR=/usr/src/linux
-endif
-IPTABLES_VERSION:=1.2.9
-OLD_IPTABLES_VERSION:=1.2.8
-
-PREFIX:=/usr
-LIBDIR:=$(PREFIX)/lib
-BINDIR:=$(PREFIX)/sbin
-MANDIR:=$(PREFIX)/man
-INCDIR:=$(PREFIX)/include
-
-# directory for new iptables releases
-RELEASE_DIR:=/tmp
-
-# Need libc6 for this.  FIXME: Should covert to autoconf.
-ifeq ($(shell [ -f /usr/include/netinet/ip6.h ] && echo YES), YES)
-DO_IPV6:=1
-endif
-
-COPT_FLAGS:=-O2
-CFLAGS:=$(COPT_FLAGS) -Wall -Wunused -I$(KERNEL_DIR)/include -Iinclude/ -DIPTABLES_VERSION=\"$(IPTABLES_VERSION)\" #-g -DDEBUG #-pg # -DIPTC_DEBUG
-
-ifdef NO_SHARED_LIBS
-CFLAGS += -DNO_SHARED_LIBS=1
-endif
-
-ifndef NO_SHARED_LIBS
-DEPFILES = $(SHARED_LIBS:%.so=%.d)
-SH_CFLAGS:=$(CFLAGS) -fPIC
-STATIC_LIBS  =
-STATIC6_LIBS =
-LDFLAGS      = -rdynamic
-LDLIBS       = -ldl -lnsl
-else
-DEPFILES = $(EXT_OBJS:%.o=%.d)
-STATIC_LIBS  = extensions/libext.a
-STATIC6_LIBS = extensions/libext6.a
-LDFLAGS      = -static
-LDLIBS       =
-endif
-
-EXTRAS+=iptables iptables.o
-EXTRA_INSTALLS+=$(DESTDIR)$(BINDIR)/iptables $(DESTDIR)$(MANDIR)/man8/iptables.8
-
-# No longer experimental.
-EXTRAS+=iptables-save iptables-restore
-EXTRA_INSTALLS+=$(DESTDIR)$(BINDIR)/iptables-save $(DESTDIR)$(BINDIR)/iptables-restore $(DESTDIR)$(MANDIR)/man8/iptables-restore.8 $(DESTDIR)$(MANDIR)/man8/iptables-save.8
-
-ifeq ($(DO_IPV6), 1)
-EXTRAS+=ip6tables ip6tables.o
-EXTRA_INSTALLS+=$(DESTDIR)$(BINDIR)/ip6tables $(DESTDIR)$(MANDIR)/man8/ip6tables.8
-EXTRAS_EXP+=ip6tables-save ip6tables-restore
-EXTRA_INSTALLS_EXP+=$(DESTDIR)$(BINDIR)/ip6tables-save $(DESTDIR)$(BINDIR)/ip6tables-restore # $(DESTDIR)$(MANDIR)/man8/iptables-restore.8 $(DESTDIR)$(MANDIR)/man8/iptables-save.8 $(DESTDIR)$(MANDIR)/man8/ip6tables-save.8 $(DESTDIR)$(MANDIR)/man8/ip6tables-restore.8
-endif
-
-# Sparc64 hack
-ifeq ($(shell uname -m),sparc64)
-# The kernel is 64-bit, even though userspace is 32.
-CFLAGS+=-DIPT_MIN_ALIGN=8 -DKERNEL_64_USERSPACE_32
-endif
-
-# HPPA hack
-ifeq ($(shell uname -m),parisc64)
-# The kernel is 64-bit, even though userspace is 32.
-CFLAGS+=-DIPT_MIN_ALIGN=8 -DKERNEL_64_USERSPACE_32
-endif
-
-ifndef IPT_LIBDIR
-IPT_LIBDIR:=$(LIBDIR)/iptables
-endif
-
-.PHONY: default
-default: print-extensions all
-
-.PHONY: print-extensions
-print-extensions:
-       @[ -n "$(OPTIONALS)" ] && echo Extensions found: $(OPTIONALS)
-
-iptables.o: iptables.c
-       $(CC) $(CFLAGS) -DIPT_LIB_DIR=\"$(IPT_LIBDIR)\" -c -o $@ $<
-
-iptables: iptables-standalone.c iptables.o $(STATIC_LIBS) libiptc/libiptc.a
-       $(CC) $(CFLAGS) -DIPT_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-$(DESTDIR)$(BINDIR)/iptables: iptables
-       @[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
-       cp $< $@
-
-iptables-save: iptables-save.c iptables.o $(STATIC_LIBS) libiptc/libiptc.a
-       $(CC) $(CFLAGS) -DIPT_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-$(DESTDIR)$(BINDIR)/iptables-save: iptables-save
-       @[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
-       cp $< $@
-
-iptables-restore: iptables-restore.c iptables.o $(STATIC_LIBS) libiptc/libiptc.a
-       $(CC) $(CFLAGS) -DIPT_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-$(DESTDIR)$(BINDIR)/iptables-restore: iptables-restore
-       @[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
-       cp $< $@
-
-ip6tables.o: ip6tables.c
-       $(CC) $(CFLAGS) -DIP6T_LIB_DIR=\"$(IPT_LIBDIR)\" -c -o $@ $<
-
-ip6tables: ip6tables-standalone.c ip6tables.o $(STATIC6_LIBS) libiptc/libiptc.a
-       $(CC) $(CFLAGS) -DIP6T_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-$(DESTDIR)$(BINDIR)/ip6tables: ip6tables
-       @[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
-       cp $< $@
-
-ip6tables-save: ip6tables-save.c ip6tables.o $(STATIC6_LIBS) libiptc/libiptc.a
-       $(CC) $(CFLAGS) -DIP6T_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-$(DESTDIR)$(BINDIR)/ip6tables-save: ip6tables-save
-       @[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
-       cp $< $@
-
-ip6tables-restore: ip6tables-restore.c ip6tables.o $(STATIC6_LIBS) libiptc/libiptc.a
-       $(CC) $(CFLAGS) -DIP6T_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-$(DESTDIR)$(BINDIR)/ip6tables-restore: ip6tables-restore
-       @[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
-       cp $< $@
-
-$(DESTDIR)$(MANDIR)/man8/%.8: %.8
-       @[ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8
-       cp $< $@
-
-EXTRA_DEPENDS+=iptables-standalone.d iptables.d
-
-iptables-standalone.d iptables.d: %.d: %.c
-       @-$(CC) -M -MG $(CFLAGS) $< | sed -e 's@^.*\.o:@$*.d $*.o:@' > $@
-
-
-# Development Targets
-.PHONY: install-devel-man3
-install-devel-man3: $(DEVEL_MAN3)
-       @[ -d $(DESTDIR)$(MANDIR)/man3 ] || mkdir -p $(DESTDIR)$(MANDIR)/man3
-       @cp -v $(DEVEL_MAN3) $(DESTDIR)$(MANDIR)/man3
-
-.PHONY: install-devel-headers
-install-devel-headers: $(DEVEL_HEADERS)
-       @[ -d $(DESTDIR)$(INCDIR) ] || mkdir -p $(DESTDIR)$(INCDIR)
-       @cp -v $(DEVEL_HEADERS) $(DESTDIR)$(INCDIR)
-
-.PHONY: install-devel-libs
-install-devel-libs: $(DEVEL_LIBS)
-       @[ -d $(DESTDIR)$(LIBDIR) ] || mkdir -p $(DESTDIR)$(LIBDIR)
-       @cp -v $(DEVEL_LIBS) $(DESTDIR)$(LIBDIR)
-
-.PHONY: install-devel
-install-devel: all install-devel-man3 install-devel-headers install-devel-libs
-
-.PHONY: distclean
-distclean: clean
-       @rm -f TAGS `find . -name '*~' -o -name '.*~'` `find . -name '*.rej'` `find . -name '*.d'` .makefirst
-
-# Rusty's distro magic.
-.PHONY: distrib
-distrib: check distclean delrelease $(RELEASE_DIR)/iptables-$(IPTABLES_VERSION).tar.bz2 diff md5sums # nowhitespace
-
-# Makefile must not define:
-# -g -pg -DIPTC_DEBUG
-.PHONY: check
-check:
-       @if echo $(CFLAGS) | egrep -e '-g|-pg|IPTC_DEBUG' >/dev/null; then echo Remove debugging flags; exit 1; else exit 0; fi
-
-.PHONY: nowhitespace
-nowhitespace:
-       @if grep -n '[  ]$$' `find . -name 'Makefile' -o -name '*.[ch]'`; then exit 1; else exit 0; fi
-
-.PHONY: delrelease
-delrelease:
-       rm -f $(RELEASE_DIR)/iptables-$(IPTABLES_VERSION).tar.bz2
-
-$(RELEASE_DIR)/iptables-$(IPTABLES_VERSION).tar.bz2:
-       cd .. && ln -sf userspace iptables-$(IPTABLES_VERSION) && tar cvf - --exclude CVS iptables-$(IPTABLES_VERSION)/. | bzip2 -9 > $@ && rm iptables-$(IPTABLES_VERSION)
-
-.PHONY: diff
-diff: $(RELEASE_DIR)/iptables-$(IPTABLES_VERSION).tar.bz2
-       @mkdir /tmp/diffdir
-       @cd /tmp/diffdir && tar -x --bzip2 -f $(RELEASE_DIR)/iptables-$(IPTABLES_VERSION).tar.bz2
-       @set -e; cd /tmp/diffdir; tar -x --bzip2 -f $(RELEASE_DIR)/iptables-$(OLD_IPTABLES_VERSION).tar.bz2; echo Creating patch-iptables-$(OLD_IPTABLES_VERSION)-$(IPTABLES_VERSION).bz2; diff -urN iptables-$(OLD_IPTABLES_VERSION) iptables-$(IPTABLES_VERSION) | bzip2 -9 > $(RELEASE_DIR)/patch-iptables-$(OLD_IPTABLES_VERSION)-$(IPTABLES_VERSION).bz2
-       @rm -rf /tmp/diffdir
-
-.PHONY: md5sums
-md5sums:
-       cd $(RELEASE_DIR)/ && md5sum patch-iptables-*-$(IPTABLES_VERSION).bz2 iptables-$(IPTABLES_VERSION).tar.bz2
-
-# $(wildcard) fails wierdly with make v.3.78.1.
-include $(shell echo */Makefile)
-include Rules.make
diff --git a/extensions/.#libipt_ECN.c.1.7 b/extensions/.#libipt_ECN.c.1.7
deleted file mode 100644 (file)
index 7bb0044..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Shared library add-on to iptables for ECN, $Version$
- *
- * (C) 2002 by Harald Welte <laforge@gnumonks.org>
- *
- * This program is distributed under the terms of GNU GPL v2, 1991
- *
- * libipt_ECN.c borrowed heavily from libipt_DSCP.c
- *
- * $Id: libipt_ECN.c,v 1.7 2002/05/29 15:11:36 laforge Exp $
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_ECN.h>
-
-static void init(struct ipt_entry_target *t, unsigned int *nfcache) 
-{
-}
-
-static void help(void) 
-{
-       printf(
-"ECN target v%s options\n"
-"  --ecn-tcp-remove            Remove all ECN bits from TCP header\n"
-"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n"
-"  --ecn-ip-ect                        Set the IPv4 ECT codepoint (0 to 3)\n"
-"  --ecn-tcp-cwr               Set the IPv4 CWR bit (0 or 1)\n"
-"  --ecn-tcp-ece               Set the IPv4 CWR bit (0 or 1)\n",
-               IPTABLES_VERSION, IPTABLES_VERSION
-);
-}
-
-static struct option opts[] = {
-       { "ecn-tcp-remove", 0, 0, 'F' },
-       { "ecn-tcp-cwr", 1, 0, 'G' },
-       { "ecn-tcp-ece", 1, 0, 'H' },
-       { "ecn-ip-ect", 1, 0, '9' },
-       { 0 }
-};
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      struct ipt_entry_target **target)
-{
-       unsigned int result;
-       struct ipt_ECN_info *einfo
-               = (struct ipt_ECN_info *)(*target)->data;
-
-       switch (c) {
-       case 'F':
-               if (*flags)
-                       exit_error(PARAMETER_PROBLEM,
-                               "ECN target: Only use --ecn-tcp-remove ONCE!");
-               einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR;
-               einfo->proto.tcp.ece = 0;
-               einfo->proto.tcp.cwr = 0;
-               *flags = 1;
-               break;
-       case 'G':
-               if (*flags & IPT_ECN_OP_SET_CWR)
-                       exit_error(PARAMETER_PROBLEM,
-                               "ECN target: Only use --ecn-tcp-cwr ONCE!");
-               if (string_to_number(optarg, 0, 1, &result))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "ECN target: Value out of range");
-               einfo->operation |= IPT_ECN_OP_SET_CWR;
-               einfo->proto.tcp.cwr = result;
-               *flags |= IPT_ECN_OP_SET_CWR;
-               break;
-       case 'H':
-               if (*flags & IPT_ECN_OP_SET_ECE)
-                       exit_error(PARAMETER_PROBLEM,
-                               "ECN target: Only use --ecn-tcp-ece ONCE!");
-               if (string_to_number(optarg, 0, 1, &result))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "ECN target: Value out of range");
-               einfo->operation |= IPT_ECN_OP_SET_ECE;
-               einfo->proto.tcp.ece = result;
-               *flags |= IPT_ECN_OP_SET_ECE;
-               break;
-       case '9':
-               if (*flags & IPT_ECN_OP_SET_IP)
-                       exit_error(PARAMETER_PROBLEM,
-                               "ECN target: Only use --ecn-ip-ect ONCE!");
-               if (string_to_number(optarg, 0, 3, &result))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "ECN target: Value out of range");
-               einfo->operation |= IPT_ECN_OP_SET_IP;
-               einfo->ip_ect = (result << IPT_ECN_SHIFT);
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
-       if (!flags)
-               exit_error(PARAMETER_PROBLEM,
-                          "ECN target: Parameter --ecn-remove is required");
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_target *target,
-      int numeric)
-{
-       const struct ipt_ECN_info *einfo =
-               (const struct ipt_ECN_info *)target->data;
-
-       printf("ECN ");
-
-       if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
-           && einfo->proto.tcp.ece == 0
-           && einfo->proto.tcp.cwr == 0)
-               printf("TCP remove ");
-       else {
-               if (einfo->operation & IPT_ECN_OP_SET_ECE)
-                       printf("ECE=%u ", einfo->proto.tcp.ece);
-
-               if (einfo->operation & IPT_ECN_OP_SET_CWR)
-                       printf("CWR=%u ", einfo->proto.tcp.cwr);
-
-               if (einfo->operation & IPT_ECN_OP_SET_IP)
-                       printf("ECT codepoint=%u ", einfo->ip_ect);
-       }
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
-       const struct ipt_ECN_info *einfo =
-               (const struct ipt_ECN_info *)target->data;
-
-       if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
-           && einfo->proto.tcp.ece == 0
-           && einfo->proto.tcp.cwr == 0)
-               printf("--ecn-tcp-remove ");
-       else {
-
-               if (einfo->operation & IPT_ECN_OP_SET_ECE)
-                       printf("--ecn-tcp-ece %d ", einfo->proto.tcp.ece);
-
-               if (einfo->operation & IPT_ECN_OP_SET_CWR)
-                       printf("--ecn-tcp-cwr %d ", einfo->proto.tcp.cwr);
-
-               if (einfo->operation & IPT_ECN_OP_SET_IP)
-                       printf("--ecn-ip-ect %d ", einfo->ip_ect);
-       }
-}
-
-static
-struct iptables_target ecn
-= { NULL,
-    "ECN",
-    IPTABLES_VERSION,
-    IPT_ALIGN(sizeof(struct ipt_ECN_info)),
-    IPT_ALIGN(sizeof(struct ipt_ECN_info)),
-    &help,
-    &init,
-    &parse,
-    &final_check,
-    &print,
-    &save,
-    opts
-};
-
-void _init(void)
-{
-       register_target(&ecn);
-}
diff --git a/extensions/.#libipt_recent.c.1.6 b/extensions/.#libipt_recent.c.1.6
deleted file mode 100644 (file)
index cb86597..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/* Shared library add-on to iptables to add recent matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_recent.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"recent v%s options:\n"
-"[!] --set                       Add source address to list, always matches.\n"
-"[!] --rcheck                    Match if source address in list.\n"
-"[!] --update                    Match if source address in list, also update last-seen time.\n"
-"[!] --remove                    Match if source address in list, also removes that address from list.\n"
-"    --seconds seconds           For check and update commands above.\n"
-"                                Specifies that the match will only occur if source address last seen within\n"
-"                                the last 'seconds' seconds.\n"
-"    --hitcount hits             For check and update commands above.\n"
-"                                Specifies that the match will only occur if source address seen hits times.\n"
-"                                May be used in conjunction with the seconds option.\n"
-"    --rttl                      For check and update commands above.\n"
-"                                Specifies that the match will only occur if the source address and the TTL\n"
-"                                match between this packet and the one which was set.\n"
-"                                Useful if you have problems with people spoofing their source address in order\n"
-"                                to DoS you via this module.\n"
-"    --name name                 Name of the recent list to be used.  DEFAULT used if none given.\n"
-"    --rsource                   Save the source address of each packet in the recent list table (default).\n"
-"    --rdest                     Save the destination address of each packet in the recent list table.\n"
-,
-IPTABLES_VERSION);
-
-}
-  
-static struct option opts[] = {
-       { "set", 0, 0, 201 }, 
-       { "rcheck", 0, 0, 202 }, 
-       { "update", 0, 0, 203 },
-       { "seconds", 1, 0, 204 }, 
-       { "hitcount", 1, 0, 205 },
-       { "remove",0, 0, 206 },
-       { "rttl",0, 0, 207 },
-       { "name", 1, 0, 208 },
-       { "rsource", 0, 0, 209 },
-       { "rdest", 0, 0, 210 },
-       {0}
-};
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *match, unsigned int *nfcache)
-{
-       struct ipt_recent_info *info = (struct ipt_recent_info *)(match)->data;
-
-       *nfcache |= NFC_UNKNOWN;
-
-       strncpy(info->name, "DEFAULT", 200);
-       info->side = IPT_RECENT_SOURCE;
-}
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       struct ipt_recent_info *info = (struct ipt_recent_info *)(*match)->data;
-       switch (c) {
-               case 201:
-                       if (*flags) 
-                               exit_error(PARAMETER_PROBLEM,
-                                       "recent: only one of `--set', `--check' "
-                                       "`--update' or `--remove' may be set");
-                       check_inverse(optarg, &invert, &optind, 0);
-                       info->check_set |= IPT_RECENT_SET;
-                       if (invert) 
-                               info->invert = 1;
-                       *flags = 1;
-                       break;
-                       
-               case 202:
-                       if (*flags) 
-                               exit_error(PARAMETER_PROBLEM,
-                                       "recent: only one of `--set', `--check' "
-                                       "`--update' or `--remove' may be set");
-                       check_inverse(optarg, &invert, &optind, 0);
-                       info->check_set |= IPT_RECENT_CHECK;
-                       if (invert)
-                               info->invert = 1;
-                       *flags = 1;
-                       break;
-
-               case 203:
-                       if (*flags)
-                               exit_error(PARAMETER_PROBLEM,
-                                       "recent: only one of `--set', `--check' "
-                                       "`--update' or `--remove' may be set");
-                       check_inverse(optarg, &invert, &optind, 0);
-                       info->check_set |= IPT_RECENT_UPDATE;
-                       if (invert)
-                               info->invert = 1;
-                       *flags = 1;
-                       break;
-
-               case 206:
-                       if (*flags)
-                               exit_error(PARAMETER_PROBLEM,
-                                       "recent: only one of `--set', `--check' "
-                                       "`--update' or `--remove' may be set");
-                       check_inverse(optarg, &invert, &optind, 0);
-                       info->check_set |= IPT_RECENT_REMOVE;
-                       if (invert)
-                               info->invert = 1;
-                       *flags = 1;
-                       break;
-
-               case 204:
-                       info->seconds = atoi(optarg);
-                       break;
-
-               case 205:
-                       info->hit_count = atoi(optarg);
-                       break;
-
-               case 207:
-                       info->check_set |= IPT_RECENT_TTL;
-                       break;
-
-               case 208:
-                       strncpy(info->name, optarg, 200);
-                       break;
-
-               case 209:
-                       info->side = IPT_RECENT_SOURCE;
-                       break;
-
-               case 210:
-                       info->side = IPT_RECENT_DEST;
-                       break;
-
-               default:
-                       return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; must have specified a specific option. */
-static void
-final_check(unsigned int flags)
-{
-
-       if (!flags)
-               exit_error(PARAMETER_PROBLEM,
-                       "recent: you must specify one of `--set', `--check' "
-                       "`--update' or `--remove'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       struct ipt_recent_info *info = (struct ipt_recent_info *)match->data;
-
-       if (info->invert) fputc('!', stdout);
-
-       printf("recent: ");
-       if(info->check_set & IPT_RECENT_SET) printf("SET ");
-       if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
-       if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
-       if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
-       if(info->seconds) printf("seconds: %d ", info->seconds);
-       if(info->hit_count) printf("hit_count: %d ", info->hit_count);
-       if(info->check_set & IPT_RECENT_TTL) printf("TTL-Match ");
-       if(info->name) printf("name: %s ", info->name);
-       if(info->side == IPT_RECENT_SOURCE) printf("side: source ");
-       if(info->side == IPT_RECENT_DEST) printf("side: dest");
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       struct ipt_recent_info *info = (struct ipt_recent_info *)match;
-
-       if (info->invert) fputc('!', stdout);
-
-       printf("recent: ");
-       if(info->check_set & IPT_RECENT_SET) printf("SET ");
-       if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
-       if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
-       if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
-       if(info->seconds) printf("seconds: %d ",info->seconds);
-       if(info->hit_count) printf("hit_count: %d ",info->hit_count);
-       if(info->check_set & IPT_RECENT_TTL) printf("TTL-Match ");
-       if(info->name) printf("name: %s ",info->name);
-       if(info->side == IPT_RECENT_SOURCE) printf("side: source ");
-       if(info->side == IPT_RECENT_DEST) printf("side: dest");
-}
-
-static
-struct iptables_match recent
-= { NULL,
-    "recent",
-    IPTABLES_VERSION,
-    IPT_ALIGN(sizeof(struct ipt_recent_info)),
-    IPT_ALIGN(sizeof(struct ipt_recent_info)),
-    &help,
-    &init,
-    &parse,
-    &final_check,
-    &print,
-    &save,
-    opts
-};
-
-void _init(void)
-{
-       register_match(&recent);
-}
diff --git a/extensions/libipt_icmp.c.print_type b/extensions/libipt_icmp.c.print_type
deleted file mode 100644 (file)
index 6c7b1c3..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/* Shared library add-on to iptables to add ICMP support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-/* special hack for icmp-type 'any': 
- * Up to kernel <=2.4.20 the problem was:
- * '-p icmp ' matches all icmp packets
- * '-p icmp -m icmp' matches _only_ ICMP type 0 :(
- * This is now fixed by initializing the field * to icmp type 0xFF
- * See: https://bugzilla.netfilter.org/cgi-bin/bugzilla/show_bug.cgi?id=37
- */
-
-struct icmp_names {
-       const char *name;
-       u_int8_t type;
-       u_int8_t code_min, code_max;
-};
-
-static const struct icmp_names icmp_codes[] = {
-       { "any", 0xFF, 0, 0xFF },
-       { "echo-reply", 0, 0, 0xFF },
-       /* Alias */ { "pong", 0, 0, 0xFF },
-
-       { "destination-unreachable", 3, 0, 0xFF },
-       {   "network-unreachable", 3, 0, 0 },
-       {   "host-unreachable", 3, 1, 1 },
-       {   "protocol-unreachable", 3, 2, 2 },
-       {   "port-unreachable", 3, 3, 3 },
-       {   "fragmentation-needed", 3, 4, 4 },
-       {   "source-route-failed", 3, 5, 5 },
-       {   "network-unknown", 3, 6, 6 },
-       {   "host-unknown", 3, 7, 7 },
-       {   "network-prohibited", 3, 9, 9 },
-       {   "host-prohibited", 3, 10, 10 },
-       {   "TOS-network-unreachable", 3, 11, 11 },
-       {   "TOS-host-unreachable", 3, 12, 12 },
-       {   "communication-prohibited", 3, 13, 13 },
-       {   "host-precedence-violation", 3, 14, 14 },
-       {   "precedence-cutoff", 3, 15, 15 },
-
-       { "source-quench", 4, 0, 0xFF },
-
-       { "redirect", 5, 0, 0xFF },
-       {   "network-redirect", 5, 0, 0 },
-       {   "host-redirect", 5, 1, 1 },
-       {   "TOS-network-redirect", 5, 2, 2 },
-       {   "TOS-host-redirect", 5, 3, 3 },
-
-       { "echo-request", 8, 0, 0xFF },
-       /* Alias */ { "ping", 8, 0, 0xFF },
-
-       { "router-advertisement", 9, 0, 0xFF },
-
-       { "router-solicitation", 10, 0, 0xFF },
-
-       { "time-exceeded", 11, 0, 0xFF },
-       /* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
-       {   "ttl-zero-during-transit", 11, 0, 0 },
-       {   "ttl-zero-during-reassembly", 11, 1, 1 },
-
-       { "parameter-problem", 12, 0, 0xFF },
-       {   "ip-header-bad", 12, 0, 0 },
-       {   "required-option-missing", 12, 1, 1 },
-
-       { "timestamp-request", 13, 0, 0xFF },
-
-       { "timestamp-reply", 14, 0, 0xFF },
-
-       { "address-mask-request", 17, 0, 0xFF },
-
-       { "address-mask-reply", 18, 0, 0xFF }
-};
-
-static void
-print_icmptypes()
-{
-       unsigned int i;
-       printf("Valid ICMP Types:");
-
-       for (i = 0; i < sizeof(icmp_codes)/sizeof(struct icmp_names); i++) {
-               if (i && icmp_codes[i].type == icmp_codes[i-1].type) {
-                       if (icmp_codes[i].code_min == icmp_codes[i-1].code_min
-                           && (icmp_codes[i].code_max
-                               == icmp_codes[i-1].code_max))
-                               printf(" (%s)", icmp_codes[i].name);
-                       else
-                               printf("\n   %s", icmp_codes[i].name);
-               }
-               else
-                       printf("\n%s", icmp_codes[i].name);
-       }
-       printf("\n");
-}
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"ICMP v%s options:\n"
-" --icmp-type [!] typename     match icmp type\n"
-"                              (or numeric type or type/code)\n"
-"\n", IPTABLES_VERSION);
-       print_icmptypes();
-}
-
-static struct option opts[] = {
-       { "icmp-type", 1, 0, '1' },
-       {0}
-};
-
-static unsigned int
-parse_icmp(const char *icmptype, u_int8_t *type, u_int8_t code[])
-{
-       unsigned int limit = sizeof(icmp_codes)/sizeof(struct icmp_names);
-       unsigned int match = limit;
-       unsigned int i;
-
-       for (i = 0; i < limit; i++) {
-               if (strncasecmp(icmp_codes[i].name, icmptype, strlen(icmptype))
-                   == 0) {
-                       if (match != limit)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Ambiguous ICMP type `%s':"
-                                          " `%s' or `%s'?",
-                                          icmptype,
-                                          icmp_codes[match].name,
-                                          icmp_codes[i].name);
-                       match = i;
-               }
-       }
-
-       if (match != limit) {
-               *type = icmp_codes[match].type;
-               code[0] = icmp_codes[match].code_min;
-               code[1] = icmp_codes[match].code_max;
-       } else {
-               char *slash;
-               char buffer[strlen(icmptype) + 1];
-               unsigned int number;
-
-               strcpy(buffer, icmptype);
-               slash = strchr(buffer, '/');
-
-               if (slash)
-                       *slash = '\0';
-
-               if (string_to_number(buffer, 0, 255, &number) == -1)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Invalid ICMP type `%s'\n", buffer);
-               *type = number;
-               if (slash) {
-                       if (string_to_number(slash+1, 0, 255, &number) == -1)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Invalid ICMP code `%s'\n",
-                                          slash+1);
-                       code[0] = code[1] = number;
-               } else {
-                       code[0] = 0;
-                       code[1] = 0xFF;
-               }
-       }
-
-       if (code[0] == 0 && code[1] == 0xFF)
-               return NFC_IP_SRC_PT;
-       else return NFC_IP_SRC_PT | NFC_IP_DST_PT;
-}
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
-       struct ipt_icmp *icmpinfo = (struct ipt_icmp *)m->data;
-
-       icmpinfo->type = 0xFF;
-       icmpinfo->code[1] = 0xFF;
-}
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       struct ipt_icmp *icmpinfo = (struct ipt_icmp *)(*match)->data;
-
-       switch (c) {
-       case '1':
-               check_inverse(optarg, &invert, &optind, 0);
-               *nfcache |= parse_icmp(argv[optind-1],
-                                      &icmpinfo->type,
-                                      icmpinfo->code);
-               if (invert)
-                       icmpinfo->invflags |= IPT_ICMP_INV;
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-static void print_icmptype(u_int8_t type,
-                          u_int8_t code_min, u_int8_t code_max,
-                          int invert,
-                          int numeric)
-{
-       if (!numeric) {
-               unsigned int i;
-
-               for (i = 0;
-                    i < sizeof(icmp_codes)/sizeof(struct icmp_names);
-                    i++) {
-                       if (icmp_codes[i].type == type
-                           && icmp_codes[i].code_min == code_min
-                           && icmp_codes[i].code_max == code_max)
-                               break;
-               }
-
-               if (i != sizeof(icmp_codes)/sizeof(struct icmp_names)) {
-                       printf("%s%s ",
-                              invert ? "!" : "",
-                              icmp_codes[i].name);
-                       return;
-               }
-       }
-
-       if (invert)
-               printf("!");
-
-       printf("type %u", type);
-       if (code_min == 0 && code_max == 0xFF)
-               printf(" ");
-       else if (code_min == code_max)
-               printf(" code %u ", code_min);
-       else
-               printf(" codes %u-%u ", code_min, code_max);
-}
-
-/* Prints out the union ipt_matchinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       const struct ipt_icmp *icmp = (struct ipt_icmp *)match->data;
-
-       printf("icmp ");
-       print_icmptype(icmp->type, icmp->code[0], icmp->code[1],
-                      icmp->invflags & IPT_ICMP_INV,
-                      numeric);
-
-       if (icmp->invflags & ~IPT_ICMP_INV)
-               printf("Unknown invflags: 0x%X ",
-                      icmp->invflags & ~IPT_ICMP_INV);
-}
-
-/* Saves the match in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       const struct ipt_icmp *icmp = (struct ipt_icmp *)match->data;
-
-       if (icmp->invflags & IPT_ICMP_INV)
-               printf("! ");
-
-       /* special hack for 'any' case */
-       if (icmp->type == 0xFF) {
-               print_icmptype(icmp->type, icmp->code[0], icmp->code[1],
-                               icmp->invflags & IPT_ICMP_INV, 0);
-       } else {
-               printf("--icmp-type %u", icmp->type);
-               if (icmp->code[0] != 0 || icmp->code[1] != 0xFF)
-                       printf("/%u", icmp->code[0]);
-               printf(" ");
-       }
-}
-
-/* Final check; we don't care. */
-static void final_check(unsigned int flags)
-{
-}
-
-static
-struct iptables_match icmp
-= { NULL,
-    "icmp",
-    IPTABLES_VERSION,
-    IPT_ALIGN(sizeof(struct ipt_icmp)),
-    IPT_ALIGN(sizeof(struct ipt_icmp)),
-    &help,
-    &init,
-    &parse,
-    &final_check,
-    &print,
-    &save,
-    opts
-};
-
-void _init(void)
-{
-       register_match(&icmp);
-}
diff --git a/ip6tables.c.selinux b/ip6tables.c.selinux
deleted file mode 100644 (file)
index fc4e284..0000000
+++ /dev/null
@@ -1,2300 +0,0 @@
-/* Code to take an iptables-style command line and do it. */
-
-/*
- * Author: Paul.Russell@rustcorp.com.au and mneuling@radlogic.com.au
- *
- * (C) 2000-2002 by the netfilter coreteam <coreteam@netfilter.org>:
- *                 Paul 'Rusty' Russell <rusty@rustcorp.com.au>
- *                 Marc Boucher <marc+nf@mbsi.ca>
- *                 James Morris <jmorris@intercode.com.au>
- *                 Harald Welte <laforge@gnumonks.org>
- *                 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <getopt.h>
-#include <string.h>
-#include <netdb.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <ip6tables.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef IP6T_LIB_DIR
-#define IP6T_LIB_DIR "/usr/lib/iptables"
-#endif
-
-#ifndef PROC_SYS_MODPROBE
-#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
-#endif
-
-#define FMT_NUMERIC    0x0001
-#define FMT_NOCOUNTS   0x0002
-#define FMT_KILOMEGAGIGA 0x0004
-#define FMT_OPTIONS    0x0008
-#define FMT_NOTABLE    0x0010
-#define FMT_NOTARGET   0x0020
-#define FMT_VIA                0x0040
-#define FMT_NONEWLINE  0x0080
-#define FMT_LINENUMBERS 0x0100
-
-#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
-                       | FMT_NUMERIC | FMT_NOTABLE)
-#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
-
-
-#define CMD_NONE               0x0000U
-#define CMD_INSERT             0x0001U
-#define CMD_DELETE             0x0002U
-#define CMD_DELETE_NUM         0x0004U
-#define CMD_REPLACE            0x0008U
-#define CMD_APPEND             0x0010U
-#define CMD_LIST               0x0020U
-#define CMD_FLUSH              0x0040U
-#define CMD_ZERO               0x0080U
-#define CMD_NEW_CHAIN          0x0100U
-#define CMD_DELETE_CHAIN       0x0200U
-#define CMD_SET_POLICY         0x0400U
-#define CMD_CHECK              0x0800U
-#define CMD_RENAME_CHAIN       0x1000U
-#define NUMBER_OF_CMD  13
-static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
-                                'N', 'X', 'P', 'E' };
-
-#define OPTION_OFFSET 256
-
-#define OPT_NONE       0x00000U
-#define OPT_NUMERIC    0x00001U
-#define OPT_SOURCE     0x00002U
-#define OPT_DESTINATION        0x00004U
-#define OPT_PROTOCOL   0x00008U
-#define OPT_JUMP       0x00010U
-#define OPT_VERBOSE    0x00020U
-#define OPT_EXPANDED   0x00040U
-#define OPT_VIANAMEIN  0x00080U
-#define OPT_VIANAMEOUT 0x00100U
-#define OPT_LINENUMBERS 0x00200U
-#define OPT_COUNTERS   0x00400U
-#define NUMBER_OF_OPT  11
-static const char optflags[NUMBER_OF_OPT]
-= { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', '3', 'c'};
-
-static struct option original_opts[] = {
-       { "append", 1, 0, 'A' },
-       { "delete", 1, 0,  'D' },
-       { "insert", 1, 0,  'I' },
-       { "replace", 1, 0,  'R' },
-       { "list", 2, 0,  'L' },
-       { "flush", 2, 0,  'F' },
-       { "zero", 2, 0,  'Z' },
-       { "new-chain", 1, 0,  'N' },
-       { "delete-chain", 2, 0,  'X' },
-       { "rename-chain", 1, 0,  'E' },
-       { "policy", 1, 0,  'P' },
-       { "source", 1, 0, 's' },
-       { "destination", 1, 0,  'd' },
-       { "src", 1, 0,  's' }, /* synonym */
-       { "dst", 1, 0,  'd' }, /* synonym */
-       { "protocol", 1, 0,  'p' },
-       { "in-interface", 1, 0, 'i' },
-       { "jump", 1, 0, 'j' },
-       { "table", 1, 0, 't' },
-       { "match", 1, 0, 'm' },
-       { "numeric", 0, 0, 'n' },
-       { "out-interface", 1, 0, 'o' },
-       { "verbose", 0, 0, 'v' },
-       { "exact", 0, 0, 'x' },
-       { "version", 0, 0, 'V' },
-       { "help", 2, 0, 'h' },
-       { "line-numbers", 0, 0, '0' },
-       { "modprobe", 1, 0, 'M' },
-       { "set-counters", 1, 0, 'c' },
-       { 0 }
-};
-
-/* we need this for ip6tables-restore. ip6tables-restore.c sets line to the
- * current line of the input file, in order to give a more precise error
- * message. ip6tables itself doesn't need this, so it is initialized to the
- * magic number of -1 */
-int line = -1;
-
-#ifndef __OPTIMIZE__
-struct ip6t_entry_target *
-ip6t_get_target(struct ip6t_entry *e)
-{
-       return (void *)e + e->target_offset;
-}
-#endif
-
-static struct option *opts = original_opts;
-static unsigned int global_option_offset = 0;
-
-/* Table of legal combinations of commands and options.  If any of the
- * given commands make an option legal, that option is legal (applies to
- * CMD_LIST and CMD_ZERO only).
- * Key:
- *  +  compulsory
- *  x  illegal
- *     optional
- */
-
-static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
-/* Well, it's better than "Re: Linux vs FreeBSD" */
-{
-       /*     -n  -s  -d  -p  -j  -v  -x  -i  -o  --line */
-/*INSERT*/    {'x',' ',' ',' ',' ',' ','x',' ',' ','x'},
-/*DELETE*/    {'x',' ',' ',' ',' ',' ','x',' ',' ','x'},
-/*DELETE_NUM*/{'x','x','x','x','x',' ','x','x','x','x'},
-/*REPLACE*/   {'x',' ',' ',' ',' ',' ','x',' ',' ','x'},
-/*APPEND*/    {'x',' ',' ',' ',' ',' ','x',' ',' ','x'},
-/*LIST*/      {' ','x','x','x','x',' ',' ','x','x',' '},
-/*FLUSH*/     {'x','x','x','x','x',' ','x','x','x','x'},
-/*ZERO*/      {'x','x','x','x','x',' ','x','x','x','x'},
-/*NEW_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x'},
-/*DEL_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x'},
-/*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x'},
-/*CHECK*/     {'x','+','+','+','x',' ','x',' ',' ','x'},
-/*RENAME*/    {'x','x','x','x','x',' ','x','x','x','x'}
-};
-
-static int inverse_for_options[NUMBER_OF_OPT] =
-{
-/* -n */ 0,
-/* -s */ IP6T_INV_SRCIP,
-/* -d */ IP6T_INV_DSTIP,
-/* -p */ IP6T_INV_PROTO,
-/* -j */ 0,
-/* -v */ 0,
-/* -x */ 0,
-/* -i */ IP6T_INV_VIA_IN,
-/* -o */ IP6T_INV_VIA_OUT,
-/*--line*/ 0
-};
-
-const char *program_version;
-const char *program_name;
-
-/* Keeping track of external matches and targets: linked lists.  */
-struct ip6tables_match *ip6tables_matches = NULL;
-struct ip6tables_target *ip6tables_targets = NULL;
-
-/* Extra debugging from libiptc */
-extern void dump_entries6(const ip6tc_handle_t handle);
-
-/* A few hardcoded protocols for 'all' and in case the user has no
-   /etc/protocols */
-struct pprot {
-       char *name;
-       u_int8_t num;
-};
-
-/* Primitive headers... */
-/* defined in netinet/in.h */
-#if 0
-#ifndef IPPROTO_ESP
-#define IPPROTO_ESP 50
-#endif
-#ifndef IPPROTO_AH
-#define IPPROTO_AH 51
-#endif
-#endif
-
-static const struct pprot chain_protos[] = {
-       { "tcp", IPPROTO_TCP },
-       { "udp", IPPROTO_UDP },
-       { "icmpv6", IPPROTO_ICMPV6 },
-       { "esp", IPPROTO_ESP },
-       { "ah", IPPROTO_AH },
-       { "all", 0 },
-};
-
-static char *
-proto_to_name(u_int8_t proto, int nolookup)
-{
-       unsigned int i;
-
-       if (proto && !nolookup) {
-               struct protoent *pent = getprotobynumber(proto);
-               if (pent)
-                       return pent->p_name;
-       }
-
-       for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++)
-               if (chain_protos[i].num == proto)
-                       return chain_protos[i].name;
-
-       return NULL;
-}
-
-static void
-in6addrcpy(struct in6_addr *dst, struct in6_addr *src)
-{
-       memcpy(dst, src, sizeof(struct in6_addr));
-       /* dst->s6_addr = src->s6_addr; */
-}
-
-void
-exit_error(enum exittype status, char *msg, ...)
-{
-       va_list args;
-
-       va_start(args, msg);
-       fprintf(stderr, "%s v%s: ", program_name, program_version);
-       vfprintf(stderr, msg, args);
-       va_end(args);
-       fprintf(stderr, "\n");
-       if (status == PARAMETER_PROBLEM)
-               exit_tryhelp(status);
-       if (status == VERSION_PROBLEM)
-               fprintf(stderr,
-                       "Perhaps iptables or your kernel needs to be upgraded.\n");
-       exit(status);
-}
-
-void
-exit_tryhelp(int status)
-{
-       if (line != -1)
-               fprintf(stderr, "Error occurred at line: %d\n", line);
-       fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
-                       program_name, program_name );
-       exit(status);
-}
-
-void
-exit_printhelp(void)
-{
-       struct ip6tables_match *m = NULL;
-       struct ip6tables_target *t = NULL;
-
-       printf("%s v%s\n\n"
-"Usage: %s -[AD] chain rule-specification [options]\n"
-"       %s -[RI] chain rulenum rule-specification [options]\n"
-"       %s -D chain rulenum [options]\n"
-"       %s -[LFZ] [chain] [options]\n"
-"       %s -[NX] chain\n"
-"       %s -E old-chain-name new-chain-name\n"
-"       %s -P chain target [options]\n"
-"       %s -h (print this help information)\n\n",
-              program_name, program_version, program_name, program_name,
-              program_name, program_name, program_name, program_name,
-              program_name, program_name);
-
-       printf(
-"Commands:\n"
-"Either long or short options are allowed.\n"
-"  --append  -A chain          Append to chain\n"
-"  --delete  -D chain          Delete matching rule from chain\n"
-"  --delete  -D chain rulenum\n"
-"                              Delete rule rulenum (1 = first) from chain\n"
-"  --insert  -I chain [rulenum]\n"
-"                              Insert in chain as rulenum (default 1=first)\n"
-"  --replace -R chain rulenum\n"
-"                              Replace rule rulenum (1 = first) in chain\n"
-"  --list    -L [chain]                List the rules in a chain or all chains\n"
-"  --flush   -F [chain]                Delete all rules in  chain or all chains\n"
-"  --zero    -Z [chain]                Zero counters in chain or all chains\n"
-"  --new     -N chain          Create a new user-defined chain\n"
-"  --delete-chain\n"
-"            -X [chain]                Delete a user-defined chain\n"
-"  --policy  -P chain target\n"
-"                              Change policy on chain to target\n"
-"  --rename-chain\n"
-"            -E old-chain new-chain\n"
-"                              Change chain name, (moving any references)\n"
-
-"Options:\n"
-"  --proto     -p [!] proto    protocol: by number or name, eg. `tcp'\n"
-"  --source    -s [!] address[/mask]\n"
-"                              source specification\n"
-"  --destination -d [!] address[/mask]\n"
-"                              destination specification\n"
-"  --in-interface -i [!] input name[+]\n"
-"                              network interface name ([+] for wildcard)\n"
-"  --jump      -j target\n"
-"                              target for rule (may load target extension)\n"
-"  --match     -m match\n"
-"                              extended match (may load extension)\n"
-"  --numeric   -n              numeric output of addresses and ports\n"
-"  --out-interface -o [!] output name[+]\n"
-"                              network interface name ([+] for wildcard)\n"
-"  --table     -t table        table to manipulate (default: `filter')\n"
-"  --verbose   -v              verbose mode\n"
-"  --line-numbers              print line numbers when listing\n"
-"  --exact     -x              expand numbers (display exact values)\n"
-/*"[!] --fragment      -f              match second or further fragments only\n"*/
-"  --modprobe=<command>                try to insert modules using this command\n"
-"  --set-counters PKTS BYTES   set the counter during insert/append\n"
-"[!] --version -V              print package version.\n");
-
-       /* Print out any special helps. A user might like to be able to add a --help 
-          to the commandline, and see expected results. So we call help for all 
-          matches & targets */
-       for (t=ip6tables_targets;t;t=t->next) {
-               printf("\n");
-               t->help();
-       }
-       for (m=ip6tables_matches;m;m=m->next) {
-               printf("\n");
-               m->help();
-       }
-       exit(0);
-}
-
-static void
-generic_opt_check(int command, int options)
-{
-       int i, j, legal = 0;
-
-       /* Check that commands are valid with options.  Complicated by the
-        * fact that if an option is legal with *any* command given, it is
-        * legal overall (ie. -z and -l).
-        */
-       for (i = 0; i < NUMBER_OF_OPT; i++) {
-               legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
-
-               for (j = 0; j < NUMBER_OF_CMD; j++) {
-                       if (!(command & (1<<j)))
-                               continue;
-
-                       if (!(options & (1<<i))) {
-                               if (commands_v_options[j][i] == '+')
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "You need to supply the `-%c' "
-                                                  "option for this command\n",
-                                                  optflags[i]);
-                       } else {
-                               if (commands_v_options[j][i] != 'x')
-                                       legal = 1;
-                               else if (legal == 0)
-                                       legal = -1;
-                       }
-               }
-               if (legal == -1)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Illegal option `-%c' with this command\n",
-                                  optflags[i]);
-       }
-}
-
-static char
-opt2char(int option)
-{
-       const char *ptr;
-       for (ptr = optflags; option > 1; option >>= 1, ptr++);
-
-       return *ptr;
-}
-
-static char
-cmd2char(int option)
-{
-       const char *ptr;
-       for (ptr = cmdflags; option > 1; option >>= 1, ptr++);
-
-       return *ptr;
-}
-
-static void
-add_command(int *cmd, const int newcmd, const int othercmds, int invert)
-{
-       if (invert)
-               exit_error(PARAMETER_PROBLEM, "unexpected ! flag");
-       if (*cmd & (~othercmds))
-               exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
-                          cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
-       *cmd |= newcmd;
-}
-
-int
-check_inverse(const char option[], int *invert, int *optind, int argc)
-{
-       if (option && strcmp(option, "!") == 0) {
-               if (*invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Multiple `!' flags not allowed");
-               *invert = TRUE;
-               if (optind) {
-                       *optind = *optind+1;
-                       if (argc && *optind > argc)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "no argument following `!'");
-               }
-
-               return TRUE;
-       }
-       return FALSE;
-}
-
-static void *
-fw_calloc(size_t count, size_t size)
-{
-       void *p;
-
-       if ((p = calloc(count, size)) == NULL) {
-               perror("ip6tables: calloc failed");
-               exit(1);
-       }
-       return p;
-}
-
-static void *
-fw_malloc(size_t size)
-{
-       void *p;
-
-       if ((p = malloc(size)) == NULL) {
-               perror("ip6tables: malloc failed");
-               exit(1);
-       }
-       return p;
-}
-
-static char *
-addr_to_numeric(const struct in6_addr *addrp)
-{
-       /* 0000:0000:0000:0000:0000:000.000.000.000
-        * 0000:0000:0000:0000:0000:0000:0000:0000 */
-       static char buf[50+1];
-       return (char *)inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
-}
-
-static struct in6_addr *
-numeric_to_addr(const char *num)
-{
-       static struct in6_addr ap;
-       int err;
-       if ((err=inet_pton(AF_INET6, num, &ap)) == 1)
-               return &ap;
-#ifdef DEBUG
-       fprintf(stderr, "\nnumeric2addr: %d\n", err);
-#endif
-       return (struct in6_addr *)NULL;
-}
-
-
-static struct in6_addr *
-host_to_addr(const char *name, unsigned int *naddr)
-{
-       struct addrinfo hints;
-        struct addrinfo *res;
-        static struct in6_addr *addr;
-       int err;
-
-       memset(&hints, 0, sizeof(hints));
-        hints.ai_flags=AI_CANONNAME;
-        hints.ai_family=AF_INET6;
-        hints.ai_socktype=SOCK_RAW;
-        hints.ai_protocol=41;
-        hints.ai_next=NULL;
-
-       *naddr = 0;
-        if ( (err=getaddrinfo(name, NULL, &hints, &res)) != 0 ){
-#ifdef DEBUG
-                fprintf(stderr,"Name2IP: %s\n",gai_strerror(err)); 
-#endif
-                return (struct in6_addr *) NULL;
-        } else {
-               if (res->ai_family != AF_INET6 ||
-                   res->ai_addrlen != sizeof(struct sockaddr_in6))
-                       return (struct in6_addr *) NULL;
-
-#ifdef DEBUG
-                fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen, 
-                    addr_to_numeric(&(((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)));
-#endif
-               /* Get the first element of the address-chain */
-               addr = fw_calloc(1, sizeof(struct in6_addr));
-               in6addrcpy(addr, (struct in6_addr *)
-                       &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr);
-               freeaddrinfo(res);
-               *naddr = 1;
-               return addr;
-       }
-
-       return (struct in6_addr *) NULL;
-}
-
-static char *
-addr_to_host(const struct in6_addr *addr)
-{
-       struct sockaddr_in6 saddr;
-       int err;
-       static char hostname[NI_MAXHOST];
-
-       memset(&saddr, 0, sizeof(struct sockaddr_in6));
-       in6addrcpy(&(saddr.sin6_addr),(struct in6_addr *)addr);
-       saddr.sin6_family = AF_INET6;
-
-        if ( (err=getnameinfo((struct sockaddr *)&saddr,
-                              sizeof(struct sockaddr_in6),
-                              hostname, sizeof(hostname)-1,
-                              NULL, 0, 0)) != 0 ){
-#ifdef DEBUG
-                fprintf(stderr,"IP2Name: %s\n",gai_strerror(err)); 
-#endif
-                return (char *) NULL;
-        } else {
-#ifdef DEBUG
-               fprintf (stderr, "\naddr2host: %s\n", hostname);
-#endif
-
-               return hostname;
-       }
-
-       return (char *) NULL;
-}
-
-static char *
-mask_to_numeric(const struct in6_addr *addrp)
-{
-       static char buf[50+2];
-       int l = ipv6_prefix_length(addrp);
-       if (l == -1) {
-               strcpy(buf, "/");
-               strcat(buf, addr_to_numeric(addrp));
-               return buf;
-       }
-       sprintf(buf, "/%d", l);
-       return buf;
-}
-
-static struct in6_addr *
-network_to_addr(const char *name)
-{
-       /*      abort();*/
-       /* TODO: not implemented yet, but the exception breaks the
-        *       name resolvation */
-       return (struct in6_addr *)NULL;
-}
-
-static char *
-addr_to_anyname(const struct in6_addr *addr)
-{
-       char *name;
-
-       if ((name = addr_to_host(addr)) != NULL)
-               return name;
-
-       return addr_to_numeric(addr);
-}
-
-/*
- *     All functions starting with "parse" should succeed, otherwise
- *     the program fails.
- *     Most routines return pointers to static data that may change
- *     between calls to the same or other routines with a few exceptions:
- *     "host_to_addr", "parse_hostnetwork", and "parse_hostnetworkmask"
- *     return global static data.
-*/
-
-static struct in6_addr *
-parse_hostnetwork(const char *name, unsigned int *naddrs)
-{
-       struct in6_addr *addrp, *addrptmp;
-
-       if ((addrptmp = numeric_to_addr(name)) != NULL ||
-           (addrptmp = network_to_addr(name)) != NULL) {
-               addrp = fw_malloc(sizeof(struct in6_addr));
-               in6addrcpy(addrp, addrptmp);
-               *naddrs = 1;
-               return addrp;
-       }
-       if ((addrp = host_to_addr(name, naddrs)) != NULL)
-               return addrp;
-
-       exit_error(PARAMETER_PROBLEM, "host/network `%s' not found", name);
-}
-
-static struct in6_addr *
-parse_mask(char *mask)
-{
-       static struct in6_addr maskaddr;
-       struct in6_addr *addrp;
-       unsigned int bits;
-
-       if (mask == NULL) {
-               /* no mask at all defaults to 128 bits */
-               memset(&maskaddr, 0xff, sizeof maskaddr);
-               return &maskaddr;
-       }
-       if ((addrp = numeric_to_addr(mask)) != NULL)
-               return addrp;
-       if (string_to_number(mask, 0, 128, &bits) == -1)
-               exit_error(PARAMETER_PROBLEM,
-                          "invalid mask `%s' specified", mask);
-       if (bits != 0) {
-               char *p = (char *)&maskaddr;
-               memset(p, 0xff, bits / 8);
-               memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
-               p[bits / 8] = 0xff << (8 - (bits & 7));
-               return &maskaddr;
-       }
-
-       memset(&maskaddr, 0, sizeof maskaddr);
-       return &maskaddr;
-}
-
-void
-parse_hostnetworkmask(const char *name, struct in6_addr **addrpp,
-                     struct in6_addr *maskp, unsigned int *naddrs)
-{
-       struct in6_addr *addrp;
-       char buf[256];
-       char *p;
-       int i, j, n;
-
-       strncpy(buf, name, sizeof(buf) - 1);
-       if ((p = strrchr(buf, '/')) != NULL) {
-               *p = '\0';
-               addrp = parse_mask(p + 1);
-       } else
-               addrp = parse_mask(NULL);
-       in6addrcpy(maskp, addrp);
-
-       /* if a null mask is given, the name is ignored, like in "any/0" */
-       if (!memcmp(maskp, &in6addr_any, sizeof(in6addr_any)))
-               strcpy(buf, "::");
-
-       addrp = *addrpp = parse_hostnetwork(buf, naddrs);
-       n = *naddrs;
-       for (i = 0, j = 0; i < n; i++) {
-               int k;
-               for (k = 0; k < 4; k++)
-                       addrp[j].in6_u.u6_addr32[k] &= maskp->in6_u.u6_addr32[k];
-               j++;
-               for (k = 0; k < j - 1; k++) {
-                       if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
-                               (*naddrs)--;
-                               j--;
-                               break;
-                       }
-               }
-       }
-}
-
-struct ip6tables_match *
-find_match(const char *name, enum ip6t_tryload tryload)
-{
-       struct ip6tables_match *ptr;
-       int icmphack = 0;
-  
-       /* This is ugly as hell. Nonetheless, there is no way of changing
-        * this without hurting backwards compatibility */
-       if ( (strcmp(name,"icmpv6") == 0) ||
-            (strcmp(name,"ipv6-icmp") == 0) ||
-            (strcmp(name,"icmp6") == 0) ) icmphack = 1;
-       if (!icmphack) {
-               for (ptr = ip6tables_matches; ptr; ptr = ptr->next) {
-                       if (strcmp(name, ptr->name) == 0)
-                               break;
-               }
-       } else {
-               for (ptr = ip6tables_matches; ptr; ptr = ptr->next) {
-                       if (strcmp("icmp6", ptr->name) == 0)
-                               break;
-               }
-       }
-
-#ifndef NO_SHARED_LIBS
-       if (!ptr && tryload != DONT_LOAD) {
-               char path[sizeof(IP6T_LIB_DIR) + sizeof("/libip6t_.so")
-                        + strlen(name)];
-               if (!icmphack)
-                       sprintf(path, IP6T_LIB_DIR "/libip6t_%s.so", name);
-               else
-                       sprintf(path, IP6T_LIB_DIR "/libip6t_%s.so", "icmpv6");
-               if (dlopen(path, RTLD_NOW)) {
-                       /* Found library.  If it didn't register itself,
-                          maybe they specified target as match. */
-                       ptr = find_match(name, DONT_LOAD);
-
-                       if (!ptr)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Couldn't load match `%s'\n",
-                                          name);
-               } else if (tryload == LOAD_MUST_SUCCEED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Couldn't load match `%s':%s\n",
-                                  name, dlerror());
-       }
-#else
-       if (ptr && !ptr->loaded) {
-               if (tryload != DONT_LOAD)
-                       ptr->loaded = 1;
-               else
-                       ptr = NULL;
-       }
-       if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
-               exit_error(PARAMETER_PROBLEM,
-                          "Couldn't find match `%s'\n", name);
-       }
-#endif
-
-       if (ptr)
-               ptr->used = 1;
-
-       return ptr;
-}
-
-/* Christophe Burki wants `-p 6' to imply `-m tcp'.  */
-static struct ip6tables_match *
-find_proto(const char *pname, enum ip6t_tryload tryload, int nolookup)
-{
-       unsigned int proto;
-
-       if (string_to_number(pname, 0, 255, &proto) != -1) {
-               char *protoname = proto_to_name(proto, nolookup);
-
-               if (protoname)
-                       return find_match(protoname, tryload);
-       } else
-               return find_match(pname, tryload);
-
-       return NULL;
-}
-
-u_int16_t
-parse_protocol(const char *s)
-{
-       unsigned int proto;
-
-       if (string_to_number(s, 0, 255, &proto) == -1) {
-               struct protoent *pent;
-
-               if ((pent = getprotobyname(s)))
-                       proto = pent->p_proto;
-               else {
-                       unsigned int i;
-                       for (i = 0;
-                            i < sizeof(chain_protos)/sizeof(struct pprot);
-                            i++) {
-                               if (strcmp(s, chain_protos[i].name) == 0) {
-                                       proto = chain_protos[i].num;
-                                       break;
-                               }
-                       }
-                       if (i == sizeof(chain_protos)/sizeof(struct pprot))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unknown protocol `%s' specified",
-                                          s);
-               }
-       }
-
-       return (u_int16_t)proto;
-}
-
-static void
-parse_interface(const char *arg, char *vianame, unsigned char *mask)
-{
-       int vialen = strlen(arg);
-       unsigned int i;
-
-       memset(mask, 0, IFNAMSIZ);
-       memset(vianame, 0, IFNAMSIZ);
-
-       if (vialen + 1 > IFNAMSIZ)
-               exit_error(PARAMETER_PROBLEM,
-                          "interface name `%s' must be shorter than IFNAMSIZ"
-                          " (%i)", arg, IFNAMSIZ-1);
-
-       strcpy(vianame, arg);
-       if (vialen == 0)
-               memset(mask, 0, IFNAMSIZ);
-       else if (vianame[vialen - 1] == '+') {
-               memset(mask, 0xFF, vialen - 1);
-               memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
-               /* Don't remove `+' here! -HW */
-       } else {
-               /* Include nul-terminator in match */
-               memset(mask, 0xFF, vialen + 1);
-               memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
-               for (i = 0; vianame[i]; i++) {
-                       if (!isalnum(vianame[i]) 
-                           && vianame[i] != '_' 
-                           && vianame[i] != '.') {
-                               printf("Warning: wierd character in interface"
-                                      " `%s' (No aliases, :, ! or *).\n",
-                                      vianame);
-                               break;
-                       }
-               }
-       }
-}
-
-/* Can't be zero. */
-static int
-parse_rulenumber(const char *rule)
-{
-       unsigned int rulenum;
-
-       if (string_to_number(rule, 1, INT_MAX, &rulenum) == -1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid rule number `%s'", rule);
-
-       return rulenum;
-}
-
-static const char *
-parse_target(const char *targetname)
-{
-       const char *ptr;
-
-       if (strlen(targetname) < 1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid target name (too short)");
-
-       if (strlen(targetname)+1 > sizeof(ip6t_chainlabel))
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid target name `%s' (%i chars max)",
-                          targetname, sizeof(ip6t_chainlabel)-1);
-
-       for (ptr = targetname; *ptr; ptr++)
-               if (isspace(*ptr))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Invalid target name `%s'", targetname);
-       return targetname;
-}
-
-int
-string_to_number(const char *s, unsigned int min, unsigned int max,
-                unsigned int *ret)
-{
-       long number;
-       char *end;
-
-       /* Handle hex, octal, etc. */
-       errno = 0;
-       number = strtol(s, &end, 0);
-       if (*end == '\0' && end != s) {
-               /* we parsed a number, let's see if we want this */
-               if (errno != ERANGE && min <= number && number <= max) {
-                       *ret = number;
-                       return 0;
-               }
-       }
-       return -1;
-}
-
-static void
-set_option(unsigned int *options, unsigned int option, u_int8_t *invflg,
-          int invert)
-{
-       if (*options & option)
-               exit_error(PARAMETER_PROBLEM, "multiple -%c flags not allowed",
-                          opt2char(option));
-       *options |= option;
-
-       if (invert) {
-               unsigned int i;
-               for (i = 0; 1 << i != option; i++);
-
-               if (!inverse_for_options[i])
-                       exit_error(PARAMETER_PROBLEM,
-                                  "cannot have ! before -%c",
-                                  opt2char(option));
-               *invflg |= inverse_for_options[i];
-       }
-}
-
-struct ip6tables_target *
-find_target(const char *name, enum ip6t_tryload tryload)
-{
-       struct ip6tables_target *ptr;
-
-       /* Standard target? */
-       if (strcmp(name, "") == 0
-           || strcmp(name, IP6TC_LABEL_ACCEPT) == 0
-           || strcmp(name, IP6TC_LABEL_DROP) == 0
-           || strcmp(name, IP6TC_LABEL_QUEUE) == 0
-           || strcmp(name, IP6TC_LABEL_RETURN) == 0)
-               name = "standard";
-
-       for (ptr = ip6tables_targets; ptr; ptr = ptr->next) {
-               if (strcmp(name, ptr->name) == 0)
-                       break;
-       }
-
-#ifndef NO_SHARED_LIBS
-       if (!ptr && tryload != DONT_LOAD) {
-               char path[sizeof(IP6T_LIB_DIR) + sizeof("/libip6t_.so")
-                        + strlen(name)];
-               sprintf(path, IP6T_LIB_DIR "/libip6t_%s.so", name);
-               if (dlopen(path, RTLD_NOW)) {
-                       /* Found library.  If it didn't register itself,
-                          maybe they specified match as a target. */
-                       ptr = find_target(name, DONT_LOAD);
-                       if (!ptr)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Couldn't load target `%s'\n",
-                                          name);
-               } else if (tryload == LOAD_MUST_SUCCEED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Couldn't load target `%s':%s\n",
-                                  name, dlerror());
-       }
-#else
-       if (ptr && !ptr->loaded) {
-               if (tryload != DONT_LOAD)
-                       ptr->loaded = 1;
-               else
-                       ptr = NULL;
-       }
-       if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
-               exit_error(PARAMETER_PROBLEM,
-                          "Couldn't find target `%s'\n", name);
-       }
-#endif
-
-       if (ptr)
-               ptr->used = 1;
-
-       return ptr;
-}
-
-static struct option *
-merge_options(struct option *oldopts, const struct option *newopts,
-             unsigned int *option_offset)
-{
-       unsigned int num_old, num_new, i;
-       struct option *merge;
-
-       for (num_old = 0; oldopts[num_old].name; num_old++);
-       for (num_new = 0; newopts[num_new].name; num_new++);
-
-       global_option_offset += OPTION_OFFSET;
-       *option_offset = global_option_offset;
-
-       merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
-       memcpy(merge, oldopts, num_old * sizeof(struct option));
-       for (i = 0; i < num_new; i++) {
-               merge[num_old + i] = newopts[i];
-               merge[num_old + i].val += *option_offset;
-       }
-       memset(merge + num_old + num_new, 0, sizeof(struct option));
-
-       return merge;
-}
-
-void
-register_match6(struct ip6tables_match *me)
-{
-       struct ip6tables_match **i;
-
-       if (strcmp(me->version, program_version) != 0) {
-               fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
-                       program_name, me->name, me->version, program_version);
-               exit(1);
-       }
-
-       if (find_match(me->name, DONT_LOAD)) {
-               fprintf(stderr, "%s: match `%s' already registered.\n",
-                       program_name, me->name);
-               exit(1);
-       }
-
-       if (me->size != IP6T_ALIGN(me->size)) {
-               fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
-                       program_name, me->name, me->size);
-               exit(1);
-       }
-
-       /* Append to list. */
-       for (i = &ip6tables_matches; *i; i = &(*i)->next);
-       me->next = NULL;
-       *i = me;
-
-       me->m = NULL;
-       me->mflags = 0;
-}
-
-void
-register_target6(struct ip6tables_target *me)
-{
-       if (strcmp(me->version, program_version) != 0) {
-               fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n",
-                       program_name, me->name, me->version, program_version);
-               exit(1);
-       }
-
-       if (find_target(me->name, DONT_LOAD)) {
-               fprintf(stderr, "%s: target `%s' already registered.\n",
-                       program_name, me->name);
-               exit(1);
-       }
-
-       if (me->size != IP6T_ALIGN(me->size)) {
-               fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
-                       program_name, me->name, me->size);
-               exit(1);
-       }
-
-       /* Prepend to list. */
-       me->next = ip6tables_targets;
-       ip6tables_targets = me;
-       me->t = NULL;
-       me->tflags = 0;
-}
-
-static void
-print_num(u_int64_t number, unsigned int format)
-{
-       if (format & FMT_KILOMEGAGIGA) {
-               if (number > 99999) {
-                       number = (number + 500) / 1000;
-                       if (number > 9999) {
-                               number = (number + 500) / 1000;
-                               if (number > 9999) {
-                                       number = (number + 500) / 1000;
-                                       if (number > 9999) {
-                                               number = (number + 500) / 1000;
-                                               printf(FMT("%4lluT ","%lluT "), number);
-                                       }
-                                       else printf(FMT("%4lluG ","%lluG "), number);
-                               }
-                               else printf(FMT("%4lluM ","%lluM "), number);
-                       } else
-                               printf(FMT("%4lluK ","%lluK "), number);
-               } else
-                       printf(FMT("%5llu ","%llu "), number);
-       } else
-               printf(FMT("%8llu ","%llu "), number);
-}
-
-
-static void
-print_header(unsigned int format, const char *chain, ip6tc_handle_t *handle)
-{
-       struct ip6t_counters counters;
-       const char *pol = ip6tc_get_policy(chain, &counters, handle);
-       printf("Chain %s", chain);
-       if (pol) {
-               printf(" (policy %s", pol);
-               if (!(format & FMT_NOCOUNTS)) {
-                       fputc(' ', stdout);
-                       print_num(counters.pcnt, (format|FMT_NOTABLE));
-                       fputs("packets, ", stdout);
-                       print_num(counters.bcnt, (format|FMT_NOTABLE));
-                       fputs("bytes", stdout);
-               }
-               printf(")\n");
-       } else {
-               unsigned int refs;
-               if (!ip6tc_get_references(&refs, chain, handle))
-                       printf(" (ERROR obtaining refs)\n");
-               else
-                       printf(" (%u references)\n", refs);
-       }
-
-       if (format & FMT_LINENUMBERS)
-               printf(FMT("%-4s ", "%s "), "num");
-       if (!(format & FMT_NOCOUNTS)) {
-               if (format & FMT_KILOMEGAGIGA) {
-                       printf(FMT("%5s ","%s "), "pkts");
-                       printf(FMT("%5s ","%s "), "bytes");
-               } else {
-                       printf(FMT("%8s ","%s "), "pkts");
-                       printf(FMT("%10s ","%s "), "bytes");
-               }
-       }
-       if (!(format & FMT_NOTARGET))
-               printf(FMT("%-9s ","%s "), "target");
-       fputs(" prot ", stdout);
-       if (format & FMT_OPTIONS)
-               fputs("opt", stdout);
-       if (format & FMT_VIA) {
-               printf(FMT(" %-6s ","%s "), "in");
-               printf(FMT("%-6s ","%s "), "out");
-       }
-       printf(FMT(" %-19s ","%s "), "source");
-       printf(FMT(" %-19s "," %s "), "destination");
-       printf("\n");
-}
-
-
-static int
-print_match(const struct ip6t_entry_match *m,
-           const struct ip6t_ip6 *ip,
-           int numeric)
-{
-       struct ip6tables_match *match = find_match(m->u.user.name, TRY_LOAD);
-
-       if (match) {
-               if (match->print)
-                       match->print(ip, m, numeric);
-               else
-                       printf("%s ", match->name);
-       } else {
-               if (m->u.user.name[0])
-                       printf("UNKNOWN match `%s' ", m->u.user.name);
-       }
-       /* Don't stop iterating. */
-       return 0;
-}
-
-/* e is called `fw' here for hysterical raisins */
-static void
-print_firewall(const struct ip6t_entry *fw,
-              const char *targname,
-              unsigned int num,
-              unsigned int format,
-              const ip6tc_handle_t handle)
-{
-       struct ip6tables_target *target = NULL;
-       const struct ip6t_entry_target *t;
-       u_int8_t flags;
-       char buf[BUFSIZ];
-
-       if (!ip6tc_is_chain(targname, handle))
-               target = find_target(targname, TRY_LOAD);
-       else
-               target = find_target(IP6T_STANDARD_TARGET, LOAD_MUST_SUCCEED);
-
-       t = ip6t_get_target((struct ip6t_entry *)fw);
-       flags = fw->ipv6.flags;
-
-       if (format & FMT_LINENUMBERS)
-               printf(FMT("%-4u ", "%u "), num+1);
-
-       if (!(format & FMT_NOCOUNTS)) {
-               print_num(fw->counters.pcnt, format);
-               print_num(fw->counters.bcnt, format);
-       }
-
-       if (!(format & FMT_NOTARGET))
-               printf(FMT("%-9s ", "%s "), targname);
-
-       fputc(fw->ipv6.invflags & IP6T_INV_PROTO ? '!' : ' ', stdout);
-       {
-               char *pname = proto_to_name(fw->ipv6.proto, format&FMT_NUMERIC);
-               if (pname)
-                       printf(FMT("%-5s", "%s "), pname);
-               else
-                       printf(FMT("%-5hu", "%hu "), fw->ipv6.proto);
-       }
-
-       if (format & FMT_OPTIONS) {
-               if (format & FMT_NOTABLE)
-                       fputs("opt ", stdout);
-               fputc(' ', stdout); /* Invert flag of FRAG */
-               fputc(' ', stdout); /* -f */
-               fputc(' ', stdout);
-       }
-
-       if (format & FMT_VIA) {
-               char iface[IFNAMSIZ+2];
-
-               if (fw->ipv6.invflags & IP6T_INV_VIA_IN) {
-                       iface[0] = '!';
-                       iface[1] = '\0';
-               }
-               else iface[0] = '\0';
-
-               if (fw->ipv6.iniface[0] != '\0') {
-                       strcat(iface, fw->ipv6.iniface);
-               }
-               else if (format & FMT_NUMERIC) strcat(iface, "*");
-               else strcat(iface, "any");
-               printf(FMT(" %-6s ","in %s "), iface);
-
-               if (fw->ipv6.invflags & IP6T_INV_VIA_OUT) {
-                       iface[0] = '!';
-                       iface[1] = '\0';
-               }
-               else iface[0] = '\0';
-
-               if (fw->ipv6.outiface[0] != '\0') {
-                       strcat(iface, fw->ipv6.outiface);
-               }
-               else if (format & FMT_NUMERIC) strcat(iface, "*");
-               else strcat(iface, "any");
-               printf(FMT("%-6s ","out %s "), iface);
-       }
-
-       fputc(fw->ipv6.invflags & IP6T_INV_SRCIP ? '!' : ' ', stdout);
-       if (!memcmp(&fw->ipv6.smsk, &in6addr_any, sizeof in6addr_any) 
-           && !(format & FMT_NUMERIC))
-               printf(FMT("%-19s ","%s "), "anywhere");
-       else {
-               if (format & FMT_NUMERIC)
-                       sprintf(buf, "%s", addr_to_numeric(&(fw->ipv6.src)));
-               else
-                       sprintf(buf, "%s", addr_to_anyname(&(fw->ipv6.src)));
-               strcat(buf, mask_to_numeric(&(fw->ipv6.smsk)));
-               printf(FMT("%-19s ","%s "), buf);
-       }
-
-       fputc(fw->ipv6.invflags & IP6T_INV_DSTIP ? '!' : ' ', stdout);
-       if (!memcmp(&fw->ipv6.dmsk, &in6addr_any, sizeof in6addr_any)
-           && !(format & FMT_NUMERIC))
-               printf(FMT("%-19s","-> %s"), "anywhere");
-       else {
-               if (format & FMT_NUMERIC)
-                       sprintf(buf, "%s", addr_to_numeric(&(fw->ipv6.dst)));
-               else
-                       sprintf(buf, "%s", addr_to_anyname(&(fw->ipv6.dst)));
-               strcat(buf, mask_to_numeric(&(fw->ipv6.dmsk)));
-               printf(FMT("%-19s","-> %s"), buf);
-       }
-
-       if (format & FMT_NOTABLE)
-               fputs("  ", stdout);
-
-       IP6T_MATCH_ITERATE(fw, print_match, &fw->ipv6, format & FMT_NUMERIC);
-
-       if (target) {
-               if (target->print)
-                       /* Print the target information. */
-                       target->print(&fw->ipv6, t, format & FMT_NUMERIC);
-       } else if (t->u.target_size != sizeof(*t))
-               printf("[%u bytes of unknown target data] ",
-                      t->u.target_size - sizeof(*t));
-
-       if (!(format & FMT_NONEWLINE))
-               fputc('\n', stdout);
-}
-
-static void
-print_firewall_line(const struct ip6t_entry *fw,
-                   const ip6tc_handle_t h)
-{
-       struct ip6t_entry_target *t;
-
-       t = ip6t_get_target((struct ip6t_entry *)fw);
-       print_firewall(fw, t->u.user.name, 0, FMT_PRINT_RULE, h);
-}
-
-static int
-append_entry(const ip6t_chainlabel chain,
-            struct ip6t_entry *fw,
-            unsigned int nsaddrs,
-            const struct in6_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in6_addr daddrs[],
-            int verbose,
-            ip6tc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ipv6.src = saddrs[i];
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ipv6.dst = daddrs[j];
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= ip6tc_append_entry(chain, fw, handle);
-               }
-       }
-
-       return ret;
-}
-
-static int
-replace_entry(const ip6t_chainlabel chain,
-             struct ip6t_entry *fw,
-             unsigned int rulenum,
-             const struct in6_addr *saddr,
-             const struct in6_addr *daddr,
-             int verbose,
-             ip6tc_handle_t *handle)
-{
-       fw->ipv6.src = *saddr;
-       fw->ipv6.dst = *daddr;
-
-       if (verbose)
-               print_firewall_line(fw, *handle);
-       return ip6tc_replace_entry(chain, fw, rulenum, handle);
-}
-
-static int
-insert_entry(const ip6t_chainlabel chain,
-            struct ip6t_entry *fw,
-            unsigned int rulenum,
-            unsigned int nsaddrs,
-            const struct in6_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in6_addr daddrs[],
-            int verbose,
-            ip6tc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ipv6.src = saddrs[i];
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ipv6.dst = daddrs[j];
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= ip6tc_insert_entry(chain, fw, rulenum, handle);
-               }
-       }
-
-       return ret;
-}
-
-static unsigned char *
-make_delete_mask(struct ip6t_entry *fw)
-{
-       /* Establish mask for comparison */
-       unsigned int size;
-       struct ip6tables_match *m;
-       unsigned char *mask, *mptr;
-
-       size = sizeof(struct ip6t_entry);
-       for (m = ip6tables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               size += IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + m->size;
-       }
-
-       mask = fw_calloc(1, size
-                        + IP6T_ALIGN(sizeof(struct ip6t_entry_target))
-                        + ip6tables_targets->size);
-
-       memset(mask, 0xFF, sizeof(struct ip6t_entry));
-       mptr = mask + sizeof(struct ip6t_entry);
-
-       for (m = ip6tables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               memset(mptr, 0xFF,
-                      IP6T_ALIGN(sizeof(struct ip6t_entry_match))
-                      + m->userspacesize);
-               mptr += IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + m->size;
-       }
-
-       memset(mptr, 0xFF, 
-              IP6T_ALIGN(sizeof(struct ip6t_entry_target))
-              + ip6tables_targets->userspacesize);
-
-       return mask;
-}
-
-static int
-delete_entry(const ip6t_chainlabel chain,
-            struct ip6t_entry *fw,
-            unsigned int nsaddrs,
-            const struct in6_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in6_addr daddrs[],
-            int verbose,
-            ip6tc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-       unsigned char *mask;
-
-       mask = make_delete_mask(fw);
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ipv6.src = saddrs[i];
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ipv6.dst = daddrs[j];
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= ip6tc_delete_entry(chain, fw, mask, handle);
-               }
-       }
-       return ret;
-}
-
-int
-for_each_chain(int (*fn)(const ip6t_chainlabel, int, ip6tc_handle_t *),
-              int verbose, int builtinstoo, ip6tc_handle_t *handle)
-{
-        int ret = 1;
-       const char *chain;
-       char *chains;
-       unsigned int i, chaincount = 0;
-
-       chain = ip6tc_first_chain(handle);
-       while (chain) {
-               chaincount++;
-               chain = ip6tc_next_chain(handle);
-        }
-
-       chains = fw_malloc(sizeof(ip6t_chainlabel) * chaincount);
-       i = 0;
-       chain = ip6tc_first_chain(handle);
-       while (chain) {
-               strcpy(chains + i*sizeof(ip6t_chainlabel), chain);
-               i++;
-               chain = ip6tc_next_chain(handle);
-        }
-
-       for (i = 0; i < chaincount; i++) {
-               if (!builtinstoo
-                   && ip6tc_builtin(chains + i*sizeof(ip6t_chainlabel),
-                                   *handle))
-                       continue;
-               ret &= fn(chains + i*sizeof(ip6t_chainlabel), verbose, handle);
-       }
-
-       free(chains);
-        return ret;
-}
-
-int
-flush_entries(const ip6t_chainlabel chain, int verbose,
-             ip6tc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(flush_entries, verbose, 1, handle);
-
-       if (verbose)
-               fprintf(stdout, "Flushing chain `%s'\n", chain);
-       return ip6tc_flush_entries(chain, handle);
-}
-
-static int
-zero_entries(const ip6t_chainlabel chain, int verbose,
-            ip6tc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(zero_entries, verbose, 1, handle);
-
-       if (verbose)
-               fprintf(stdout, "Zeroing chain `%s'\n", chain);
-       return ip6tc_zero_entries(chain, handle);
-}
-
-int
-delete_chain(const ip6t_chainlabel chain, int verbose,
-            ip6tc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(delete_chain, verbose, 0, handle);
-
-       if (verbose)
-               fprintf(stdout, "Deleting chain `%s'\n", chain);
-       return ip6tc_delete_chain(chain, handle);
-}
-
-static int
-list_entries(const ip6t_chainlabel chain, int verbose, int numeric,
-            int expanded, int linenumbers, ip6tc_handle_t *handle)
-{
-       int found = 0;
-       unsigned int format;
-       const char *this;
-
-       format = FMT_OPTIONS;
-       if (!verbose)
-               format |= FMT_NOCOUNTS;
-       else
-               format |= FMT_VIA;
-
-       if (numeric)
-               format |= FMT_NUMERIC;
-
-       if (!expanded)
-               format |= FMT_KILOMEGAGIGA;
-
-       if (linenumbers)
-               format |= FMT_LINENUMBERS;
-
-       for (this = ip6tc_first_chain(handle);
-            this;
-            this = ip6tc_next_chain(handle)) {
-               const struct ip6t_entry *i;
-               unsigned int num;
-
-               if (chain && strcmp(chain, this) != 0)
-                       continue;
-
-               if (found) printf("\n");
-
-               print_header(format, this, handle);
-               i = ip6tc_first_rule(this, handle);
-
-               num = 0;
-               while (i) {
-                       print_firewall(i,
-                                      ip6tc_get_target(i, handle),
-                                      num++,
-                                      format,
-                                      *handle);
-                       i = ip6tc_next_rule(i, handle);
-               }
-               found = 1;
-       }
-
-       errno = ENOENT;
-       return found;
-}
-
-static char *get_modprobe(void)
-{
-       int procfile;
-       char *ret;
-
-       procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
-       if (procfile < 0)
-               return NULL;
-
-       ret = malloc(1024);
-       if (ret) {
-               switch (read(procfile, ret, 1024)) {
-               case -1: goto fail;
-               case 1024: goto fail; /* Partial read.  Wierd */
-               }
-               if (ret[strlen(ret)-1]=='\n') 
-                       ret[strlen(ret)-1]=0;
-               close(procfile);
-               return ret;
-       }
- fail:
-       free(ret);
-       close(procfile);
-       return NULL;
-}
-
-int ip6tables_insmod(const char *modname, const char *modprobe)
-{
-       char *buf = NULL;
-       char *argv[3];
-
-       /* If they don't explicitly set it, read out of kernel */
-       if (!modprobe) {
-               buf = get_modprobe();
-               if (!buf)
-                       return -1;
-               modprobe = buf;
-       }
-
-       switch (fork()) {
-       case 0:
-               argv[0] = (char *)modprobe;
-               argv[1] = (char *)modname;
-               argv[2] = NULL;
-               execv(argv[0], argv);
-
-               /* not usually reached */
-               exit(0);
-       case -1:
-               return -1;
-
-       default: /* parent */
-               wait(NULL);
-       }
-
-       free(buf);
-       return 0;
-}
-
-static struct ip6t_entry *
-generate_entry(const struct ip6t_entry *fw,
-              struct ip6tables_match *matches,
-              struct ip6t_entry_target *target)
-{
-       unsigned int size;
-       struct ip6tables_match *m;
-       struct ip6t_entry *e;
-
-       size = sizeof(struct ip6t_entry);
-       for (m = matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               size += m->m->u.match_size;
-       }
-
-       e = fw_malloc(size + target->u.target_size);
-       *e = *fw;
-       e->target_offset = size;
-       e->next_offset = size + target->u.target_size;
-
-       size = 0;
-       for (m = matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               memcpy(e->elems + size, m->m, m->m->u.match_size);
-               size += m->m->u.match_size;
-       }
-       memcpy(e->elems + size, target, target->u.target_size);
-
-       return e;
-}
-
-int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
-{
-       struct ip6t_entry fw, *e = NULL;
-       int invert = 0;
-       unsigned int nsaddrs = 0, ndaddrs = 0;
-       struct in6_addr *saddrs = NULL, *daddrs = NULL;
-
-       int c, verbose = 0;
-       const char *chain = NULL;
-       const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
-       const char *policy = NULL, *newname = NULL;
-       unsigned int rulenum = 0, options = 0, command = 0;
-       const char *pcnt = NULL, *bcnt = NULL;
-       int ret = 1;
-       struct ip6tables_match *m;
-       struct ip6tables_target *target = NULL;
-       struct ip6tables_target *t;
-       const char *jumpto = "";
-       char *protocol = NULL;
-       const char *modprobe = NULL;
-       int proto_used = 0;
-       char icmp6p[] = "icmpv6";
-
-       memset(&fw, 0, sizeof(fw));
-
-       opts = original_opts;
-       global_option_offset = 0;
-
-       /* re-set optind to 0 in case do_command gets called
-        * a second time */
-       optind = 0;
-
-       /* clear mflags in case do_command gets called a second time
-        * (we clear the global list of all matches for security)*/
-       for (m = ip6tables_matches; m; m = m->next) {
-               m->mflags = 0;
-               m->used = 0;
-       }
-
-       for (t = ip6tables_targets; t; t = t->next) {
-               t->tflags = 0;
-               t->used = 0;
-       }
-
-       /* Suppress error messages: we may add new options if we
-           demand-load a protocol. */
-       opterr = 0;
-
-       while ((c = getopt_long(argc, argv,
-          "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvnt:m:xc:",
-                                          opts, NULL)) != -1) {
-               switch (c) {
-                       /*
-                        * Command selection
-                        */
-               case 'A':
-                       add_command(&command, CMD_APPEND, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       break;
-
-               case 'D':
-                       add_command(&command, CMD_DELETE, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!') {
-                               rulenum = parse_rulenumber(argv[optind++]);
-                               command = CMD_DELETE_NUM;
-                       }
-                       break;
-
-               case 'R':
-                       add_command(&command, CMD_REPLACE, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires a rule number",
-                                          cmd2char(CMD_REPLACE));
-                       break;
-
-               case 'I':
-                       add_command(&command, CMD_INSERT, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       else rulenum = 1;
-                       break;
-
-               case 'L':
-                       add_command(&command, CMD_LIST, CMD_ZERO,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'F':
-                       add_command(&command, CMD_FLUSH, CMD_NONE,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'Z':
-                       add_command(&command, CMD_ZERO, CMD_LIST,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                               && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'N':
-                       if (optarg && *optarg == '-')
-                               exit_error(PARAMETER_PROBLEM,
-                                          "chain name not allowed to start "
-                                          "with `-'\n");
-                       if (find_target(optarg, TRY_LOAD))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "chain name may not clash "
-                                          "with target name\n");
-                       add_command(&command, CMD_NEW_CHAIN, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       break;
-
-               case 'X':
-                       add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'E':
-                       add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               newname = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires old-chain-name and "
-                                          "new-chain-name",
-                                           cmd2char(CMD_RENAME_CHAIN));
-                       break;
-
-               case 'P':
-                       add_command(&command, CMD_SET_POLICY, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               policy = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires a chain and a policy",
-                                          cmd2char(CMD_SET_POLICY));
-                       break;
-
-               case 'h':
-                       if (!optarg)
-                               optarg = argv[optind];
-
-                       /* iptables -p icmp -h */
-                       if (!ip6tables_matches && protocol)
-                               find_match(protocol, TRY_LOAD);
-
-                       exit_printhelp();
-
-                       /*
-                        * Option selection
-                        */
-               case 'p':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_PROTOCOL, &fw.ipv6.invflags,
-                                  invert);
-
-                       /* Canonicalize into lower case */
-                       for (protocol = argv[optind-1]; *protocol; protocol++)
-                               *protocol = tolower(*protocol);
-
-                       protocol = argv[optind-1];
-                       if ( strcmp(protocol,"ipv6-icmp") == 0)
-                               protocol = icmp6p;
-                       fw.ipv6.proto = parse_protocol(protocol);
-                       fw.ipv6.flags |= IP6T_F_PROTO;
-
-                       if (fw.ipv6.proto == 0
-                           && (fw.ipv6.invflags & IP6T_INV_PROTO))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "rule would never match protocol");
-                       fw.nfcache |= NFC_IP6_PROTO;
-                       break;
-
-               case 's':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_SOURCE, &fw.ipv6.invflags,
-                                  invert);
-                       shostnetworkmask = argv[optind-1];
-                       fw.nfcache |= NFC_IP6_SRC;
-                       break;
-
-               case 'd':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_DESTINATION, &fw.ipv6.invflags,
-                                  invert);
-                       dhostnetworkmask = argv[optind-1];
-                       fw.nfcache |= NFC_IP6_DST;
-                       break;
-
-               case 'j':
-                       set_option(&options, OPT_JUMP, &fw.ipv6.invflags,
-                                  invert);
-                       jumpto = parse_target(optarg);
-                       /* TRY_LOAD (may be chain name) */
-                       target = find_target(jumpto, TRY_LOAD);
-
-                       if (target) {
-                               size_t size;
-
-                               size = IP6T_ALIGN(sizeof(struct ip6t_entry_target))
-                                       + target->size;
-
-                               target->t = fw_calloc(1, size);
-                               target->t->u.target_size = size;
-                               strcpy(target->t->u.user.name, jumpto);
-                               target->init(target->t, &fw.nfcache);
-                               opts = merge_options(opts, target->extra_opts, &target->option_offset);
-                       }
-                       break;
-
-
-               case 'i':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_VIANAMEIN, &fw.ipv6.invflags,
-                                  invert);
-                       parse_interface(argv[optind-1],
-                                       fw.ipv6.iniface,
-                                       fw.ipv6.iniface_mask);
-                       fw.nfcache |= NFC_IP6_IF_IN;
-                       break;
-
-               case 'o':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_VIANAMEOUT, &fw.ipv6.invflags,
-                                  invert);
-                       parse_interface(argv[optind-1],
-                                       fw.ipv6.outiface,
-                                       fw.ipv6.outiface_mask);
-                       fw.nfcache |= NFC_IP6_IF_OUT;
-                       break;
-
-               case 'v':
-                       if (!verbose)
-                               set_option(&options, OPT_VERBOSE,
-                                          &fw.ipv6.invflags, invert);
-                       verbose++;
-                       break;
-
-               case 'm': {
-                       size_t size;
-
-                       if (invert)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unexpected ! flag before --match");
-
-                       m = find_match(optarg, LOAD_MUST_SUCCEED);
-                       size = IP6T_ALIGN(sizeof(struct ip6t_entry_match))
-                                        + m->size;
-                       m->m = fw_calloc(1, size);
-                       m->m->u.match_size = size;
-                       strcpy(m->m->u.user.name, m->name);
-                       m->init(m->m, &fw.nfcache);
-                       opts = merge_options(opts, m->extra_opts, &m->option_offset);
-               }
-               break;
-
-               case 'n':
-                       set_option(&options, OPT_NUMERIC, &fw.ipv6.invflags,
-                                  invert);
-                       break;
-
-               case 't':
-                       if (invert)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unexpected ! flag before --table");
-                       *table = argv[optind-1];
-                       break;
-
-               case 'x':
-                       set_option(&options, OPT_EXPANDED, &fw.ipv6.invflags,
-                                  invert);
-                       break;
-
-               case 'V':
-                       if (invert)
-                               printf("Not %s ;-)\n", program_version);
-                       else
-                               printf("%s v%s\n",
-                                      program_name, program_version);
-                       exit(0);
-
-               case '0':
-                       set_option(&options, OPT_LINENUMBERS, &fw.ipv6.invflags,
-                                  invert);
-                       break;
-
-               case 'M':
-                       modprobe = optarg;
-                       break;
-
-               case 'c':
-
-                       set_option(&options, OPT_COUNTERS, &fw.ipv6.invflags,
-                                  invert);
-                       pcnt = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               bcnt = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c requires packet and byte counter",
-                                       opt2char(OPT_COUNTERS));
-
-                       if (sscanf(pcnt, "%llu", &fw.counters.pcnt) != 1)
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c packet counter not numeric",
-                                       opt2char(OPT_COUNTERS));
-
-                       if (sscanf(bcnt, "%llu", &fw.counters.bcnt) != 1)
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c byte counter not numeric",
-                                       opt2char(OPT_COUNTERS));
-                       
-                       break;
-
-
-               case 1: /* non option */
-                       if (optarg[0] == '!' && optarg[1] == '\0') {
-                               if (invert)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "multiple consecutive ! not"
-                                                  " allowed");
-                               invert = TRUE;
-                               optarg[0] = '\0';
-                               continue;
-                       }
-                       printf("Bad argument `%s'\n", optarg);
-                       exit_tryhelp(2);
-
-               default:
-                       /* FIXME: This scheme doesn't allow two of the same
-                          matches --RR */
-                       if (!target
-                           || !(target->parse(c - target->option_offset,
-                                              argv, invert,
-                                              &target->tflags,
-                                              &fw, &target->t))) {
-                               for (m = ip6tables_matches; m; m = m->next) {
-                                       if (!m->used)
-                                               continue;
-
-                                       if (m->parse(c - m->option_offset,
-                                                    argv, invert,
-                                                    &m->mflags,
-                                                    &fw,
-                                                    &fw.nfcache,
-                                                    &m->m))
-                                               break;
-                               }
-
-                               /* If you listen carefully, you can
-                                  actually hear this code suck. */
-
-                               /* some explanations (after four different bugs
-                                * in 3 different releases): If we encountere a
-                                * parameter, that has not been parsed yet,
-                                * it's not an option of an explicitly loaded
-                                * match or a target.  However, we support
-                                * implicit loading of the protocol match
-                                * extension.  '-p tcp' means 'l4 proto 6' and
-                                * at the same time 'load tcp protocol match on
-                                * demand if we specify --dport'.
-                                *
-                                * To make this work, we need to make sure:
-                                * - the parameter has not been parsed by
-                                *   a match (m above)
-                                * - a protocol has been specified
-                                * - the protocol extension has not been
-                                *   loaded yet, or is loaded and unused
-                                *   [think of iptables-restore!]
-                                * - the protocol extension can be successively
-                                *   loaded
-                                */
-                               if (m == NULL
-                                   && protocol
-                                   && (!find_proto(protocol, DONT_LOAD,
-                                                  options&OPT_NUMERIC) 
-                                       || (find_proto(protocol, DONT_LOAD,
-                                                       options&OPT_NUMERIC)
-                                           && (proto_used == 0))
-                                      )
-                                   && (m = find_proto(protocol, TRY_LOAD,
-                                                      options&OPT_NUMERIC))) {
-                                       /* Try loading protocol */
-                                       size_t size;
-                                       
-                                       proto_used = 1;
-
-                                       size = IP6T_ALIGN(sizeof(struct ip6t_entry_match))
-                                                        + m->size;
-
-                                       m->m = fw_calloc(1, size);
-                                       m->m->u.match_size = size;
-                                       strcpy(m->m->u.user.name, m->name);
-                                       m->init(m->m, &fw.nfcache);
-
-                                       opts = merge_options(opts,
-                                           m->extra_opts, &m->option_offset);
-
-                                       optind--;
-                                       continue;
-                               }
-
-                               if (!m)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "Unknown arg `%s'",
-                                                  argv[optind-1]);
-                       }
-               }
-               invert = FALSE;
-       }
-
-       for (m = ip6tables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               m->final_check(m->mflags);
-       }
-
-       if (target)
-               target->final_check(target->tflags);
-
-       /* Fix me: must put inverse options checking here --MN */
-
-       if (optind < argc)
-               exit_error(PARAMETER_PROBLEM,
-                          "unknown arguments found on commandline");
-       if (!command)
-               exit_error(PARAMETER_PROBLEM, "no command specified");
-       if (invert)
-               exit_error(PARAMETER_PROBLEM,
-                          "nothing appropriate following !");
-
-       if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) {
-               if (!(options & OPT_DESTINATION))
-                       dhostnetworkmask = "::0/0";
-               if (!(options & OPT_SOURCE))
-                       shostnetworkmask = "::0/0";
-       }
-
-       if (shostnetworkmask)
-               parse_hostnetworkmask(shostnetworkmask, &saddrs,
-                                     &(fw.ipv6.smsk), &nsaddrs);
-
-       if (dhostnetworkmask)
-               parse_hostnetworkmask(dhostnetworkmask, &daddrs,
-                                     &(fw.ipv6.dmsk), &ndaddrs);
-
-       if ((nsaddrs > 1 || ndaddrs > 1) &&
-           (fw.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP)))
-               exit_error(PARAMETER_PROBLEM, "! not allowed with multiple"
-                          " source or destination IP addresses");
-
-       if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
-               exit_error(PARAMETER_PROBLEM, "Replacement rule does not "
-                          "specify a unique address");
-
-       generic_opt_check(command, options);
-
-       if (chain && strlen(chain) > IP6T_FUNCTION_MAXNAMELEN)
-               exit_error(PARAMETER_PROBLEM,
-                          "chain name `%s' too long (must be under %i chars)",
-                          chain, IP6T_FUNCTION_MAXNAMELEN);
-
-       /* only allocate handle if we weren't called with a handle */
-       if (!*handle)
-               *handle = ip6tc_init(*table);
-
-       if (!*handle) {
-               /* try to insmod the module if iptc_init failed */
-               ip6tables_insmod("ip6_tables", modprobe);
-               *handle = ip6tc_init(*table);
-       }
-
-       if (!*handle)
-               exit_error(VERSION_PROBLEM,
-                       "can't initialize ip6tables table `%s': %s",
-                       *table, ip6tc_strerror(errno));
-
-       if (command == CMD_APPEND
-           || command == CMD_DELETE
-           || command == CMD_INSERT
-           || command == CMD_REPLACE) {
-               if (strcmp(chain, "PREROUTING") == 0
-                   || strcmp(chain, "INPUT") == 0) {
-                       /* -o not valid with incoming packets. */
-                       if (options & OPT_VIANAMEOUT)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Can't use -%c with %s\n",
-                                          opt2char(OPT_VIANAMEOUT),
-                                          chain);
-               }
-
-               if (strcmp(chain, "POSTROUTING") == 0
-                   || strcmp(chain, "OUTPUT") == 0) {
-                       /* -i not valid with outgoing packets */
-                       if (options & OPT_VIANAMEIN)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Can't use -%c with %s\n",
-                                          opt2char(OPT_VIANAMEIN),
-                                          chain);
-               }
-
-               if (target && ip6tc_is_chain(jumpto, *handle)) {
-                       printf("Warning: using chain %s, not extension\n",
-                              jumpto);
-
-                       target = NULL;
-               }
-
-               /* If they didn't specify a target, or it's a chain
-                  name, use standard. */
-               if (!target
-                   && (strlen(jumpto) == 0
-                       || ip6tc_is_chain(jumpto, *handle))) {
-                       size_t size;
-
-                       target = find_target(IP6T_STANDARD_TARGET,
-                                            LOAD_MUST_SUCCEED);
-
-                       size = sizeof(struct ip6t_entry_target)
-                               + target->size;
-                       target->t = fw_calloc(1, size);
-                       target->t->u.target_size = size;
-                       strcpy(target->t->u.user.name, jumpto);
-                       target->init(target->t, &fw.nfcache);
-               }
-
-               if (!target) {
-                       /* it is no chain, and we can't load a plugin.
-                        * We cannot know if the plugin is corrupt, non
-                        * existant OR if the user just misspelled a
-                        * chain. */
-                       find_target(jumpto, LOAD_MUST_SUCCEED);
-               } else {
-                       e = generate_entry(&fw, ip6tables_matches, target->t);
-               }
-       }
-
-       switch (command) {
-       case CMD_APPEND:
-               ret = append_entry(chain, e,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_DELETE:
-               ret = delete_entry(chain, e,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_DELETE_NUM:
-               ret = ip6tc_delete_num_entry(chain, rulenum - 1, handle);
-               break;
-       case CMD_REPLACE:
-               ret = replace_entry(chain, e, rulenum - 1,
-                                   saddrs, daddrs, options&OPT_VERBOSE,
-                                   handle);
-               break;
-       case CMD_INSERT:
-               ret = insert_entry(chain, e, rulenum - 1,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_LIST:
-               ret = list_entries(chain,
-                                  options&OPT_VERBOSE,
-                                  options&OPT_NUMERIC,
-                                  options&OPT_EXPANDED,
-                                  options&OPT_LINENUMBERS,
-                                  handle);
-               break;
-       case CMD_FLUSH:
-               ret = flush_entries(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_ZERO:
-               ret = zero_entries(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_LIST|CMD_ZERO:
-               ret = list_entries(chain,
-                                  options&OPT_VERBOSE,
-                                  options&OPT_NUMERIC,
-                                  options&OPT_EXPANDED,
-                                  options&OPT_LINENUMBERS,
-                                  handle);
-               if (ret)
-                       ret = zero_entries(chain,
-                                          options&OPT_VERBOSE, handle);
-               break;
-       case CMD_NEW_CHAIN:
-               ret = ip6tc_create_chain(chain, handle);
-               break;
-       case CMD_DELETE_CHAIN:
-               ret = delete_chain(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_RENAME_CHAIN:
-               ret = ip6tc_rename_chain(chain, newname,        handle);
-               break;
-       case CMD_SET_POLICY:
-               ret = ip6tc_set_policy(chain, policy, NULL, handle);
-               break;
-       default:
-               /* We should never reach this... */
-               exit_tryhelp(2);
-       }
-
-       if (verbose > 1)
-               dump_entries6(*handle);
-
-       return ret;
-}
diff --git a/iptables-restore.c.counters b/iptables-restore.c.counters
deleted file mode 100644 (file)
index b40630c..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-/* Code to restore the iptables state, from file by iptables-save. 
- * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
- * based on previous code from Rusty Russell <rusty@linuxcare.com.au>
- *
- * This code is distributed under the terms of GNU GPL v2
- *
- * $Id: iptables-restore.c,v 1.26 2003/05/02 15:30:11 laforge Exp $
- */
-
-#include <getopt.h>
-#include <sys/errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "iptables.h"
-#include "libiptc/libiptc.h"
-
-#ifdef DEBUG
-#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
-#else
-#define DEBUGP(x, args...) 
-#endif
-
-static int binary = 0, counters = 0, verbose = 0, noflush = 0;
-
-/* Keeping track of external matches and targets.  */
-static struct option options[] = {
-       { "binary", 0, 0, 'b' },
-       { "counters", 0, 0, 'c' },
-       { "verbose", 1, 0, 'v' },
-       { "help", 0, 0, 'h' },
-       { "noflush", 0, 0, 'n'},
-       { "modprobe", 1, 0, 'M'},
-       { 0 }
-};
-
-static void print_usage(const char *name, const char *version) __attribute__((noreturn));
-
-static void print_usage(const char *name, const char *version)
-{
-       fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-h]\n"
-                       "          [ --binary ]\n"
-                       "          [ --counters ]\n"
-                       "          [ --verbose ]\n"
-                       "          [ --help ]\n"
-                       "          [ --noflush ]\n"
-                       "          [ --modprobe=<command>]\n", name);
-               
-       exit(1);
-}
-
-iptc_handle_t create_handle(const char *tablename, const char* modprobe )
-{
-       iptc_handle_t handle;
-
-       handle = iptc_init(tablename);
-
-       if (!handle) {
-               /* try to insmod the module if iptc_init failed */
-               iptables_insmod("ip_tables", modprobe);
-               handle = iptc_init(tablename);
-       }
-
-       if (!handle) {
-               exit_error(PARAMETER_PROBLEM, "%s: unable to initialize"
-                       "table '%s'\n", program_name, tablename);
-               exit(1);
-       }
-       return handle;
-}
-
-int parse_counters(char *string, struct ipt_counters *ctr)
-{
-       return (sscanf(string, "[%llu:%llu]", &ctr->pcnt, &ctr->bcnt) == 2);
-}
-
-/* global new argv and argc */
-static char *newargv[255];
-static int newargc;
-
-/* function adding one argument to newargv, updating newargc 
- * returns true if argument added, false otherwise */
-static int add_argv(char *what) {
-       DEBUGP("add_argv: %s\n", what);
-       if (what && ((newargc + 1) < sizeof(newargv)/sizeof(char *))) {
-               newargv[newargc] = strdup(what);
-               newargc++;
-               return 1;
-       } else 
-               return 0;
-}
-
-static void free_argv(void) {
-       int i;
-
-       for (i = 0; i < newargc; i++)
-               free(newargv[i]);
-}
-
-int main(int argc, char *argv[])
-{
-       iptc_handle_t handle = NULL;
-       char buffer[10240];
-       int c;
-       char curtable[IPT_TABLE_MAXNAMELEN + 1];
-       FILE *in;
-       const char *modprobe = 0;
-       int in_table = 0;
-
-       program_name = "iptables-restore";
-       program_version = IPTABLES_VERSION;
-       line = 0;
-
-#ifdef NO_SHARED_LIBS
-       init_extensions();
-#endif
-
-       while ((c = getopt_long(argc, argv, "bcvhnM:", options, NULL)) != -1) {
-               switch (c) {
-                       case 'b':
-                               binary = 1;
-                               break;
-                       case 'c':
-                               counters = 1;
-                               break;
-                       case 'v':
-                               verbose = 1;
-                               break;
-                       case 'h':
-                               print_usage("iptables-restore",
-                                           IPTABLES_VERSION);
-                               break;
-                       case 'n':
-                               noflush = 1;
-                               break;
-                       case 'M':
-                               modprobe = optarg;
-                               break;
-               }
-       }
-       
-       if (optind == argc - 1) {
-               in = fopen(argv[optind], "r");
-               if (!in) {
-                       fprintf(stderr, "Can't open %s: %s", argv[optind],
-                               strerror(errno));
-                       exit(1);
-               }
-       }
-       else if (optind < argc) {
-               fprintf(stderr, "Unknown arguments found on commandline");
-               exit(1);
-       }
-       else in = stdin;
-       
-       /* Grab standard input. */
-       while (fgets(buffer, sizeof(buffer), in)) {
-               int ret = 0;
-
-               line++;
-               if (buffer[0] == '\n') continue;
-               else if (buffer[0] == '#') {
-                       if (verbose) fputs(buffer, stdout);
-                       continue;
-               } else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
-                       DEBUGP("Calling commit\n");
-                       ret = iptc_commit(&handle);
-                       in_table = 0;
-               } else if ((buffer[0] == '*') && (!in_table)) {
-                       /* New table */
-                       char *table;
-
-                       table = strtok(buffer+1, " \t\n");
-                       DEBUGP("line %u, table '%s'\n", line, table);
-                       if (!table) {
-                               exit_error(PARAMETER_PROBLEM, 
-                                       "%s: line %u table name invalid\n",
-                                       program_name, line);
-                               exit(1);
-                       }
-                       strncpy(curtable, table, IPT_TABLE_MAXNAMELEN);
-
-                       if (handle)
-                               iptc_free(&handle);
-
-                       handle = create_handle(table, modprobe);
-                       if (noflush == 0) {
-                               DEBUGP("Cleaning all chains of table '%s'\n",
-                                       table);
-                               for_each_chain(flush_entries, verbose, 1, 
-                                               &handle);
-       
-                               DEBUGP("Deleting all user-defined chains "
-                                      "of table '%s'\n", table);
-                               for_each_chain(delete_chain, verbose, 0, 
-                                               &handle) ;
-                       }
-
-                       ret = 1;
-                       in_table = 1;
-
-               } else if ((buffer[0] == ':') && (in_table)) {
-                       /* New chain. */
-                       char *policy, *chain;
-
-                       chain = strtok(buffer+1, " \t\n");
-                       DEBUGP("line %u, chain '%s'\n", line, chain);
-                       if (!chain) {
-                               exit_error(PARAMETER_PROBLEM,
-                                          "%s: line %u chain name invalid\n",
-                                          program_name, line);
-                               exit(1);
-                       }
-
-                       if (!iptc_builtin(chain, handle)) {
-                               DEBUGP("Creating new chain '%s'\n", chain);
-                               if (!iptc_create_chain(chain, &handle)) 
-                                       exit_error(PARAMETER_PROBLEM, 
-                                                  "error creating chain "
-                                                  "'%s':%s\n", chain, 
-                                                  strerror(errno));
-                       }
-
-                       policy = strtok(NULL, " \t\n");
-                       DEBUGP("line %u, policy '%s'\n", line, policy);
-                       if (!policy) {
-                               exit_error(PARAMETER_PROBLEM,
-                                          "%s: line %u policy invalid\n",
-                                          program_name, line);
-                               exit(1);
-                       }
-
-                       if (strcmp(policy, "-") != 0) {
-                               struct ipt_counters count;
-
-                               if (counters) {
-                                       char *ctrs;
-                                       ctrs = strtok(NULL, " \t\n");
-
-                                       parse_counters(ctrs, &count);
-
-                               } else {
-                                       memset(&count, 0, 
-                                              sizeof(struct ipt_counters));
-                               }
-
-                               DEBUGP("Setting policy of chain %s to %s\n",
-                                       chain, policy);
-
-                               if (!iptc_set_policy(chain, policy, &count,
-                                                    &handle))
-                                       exit_error(OTHER_PROBLEM,
-                                               "Can't set policy `%s'"
-                                               " on `%s' line %u: %s\n",
-                                               chain, policy, line,
-                                               iptc_strerror(errno));
-                       }
-
-                       ret = 1;
-
-               } else if (in_table) {
-                       int a;
-                       char *ptr = buffer;
-                       char *pcnt = NULL;
-                       char *bcnt = NULL;
-                       char *parsestart;
-
-                       /* the parser */
-                       char *param_start, *curchar;
-                       int quote_open;
-
-                       /* reset the newargv */
-                       newargc = 0;
-
-                       if (buffer[0] == '[') {
-                               /* we have counters in our input */
-                               ptr = strchr(buffer, ']');
-                               if (!ptr)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "Bad line %u: need ]\n",
-                                                  line);
-
-                               pcnt = strtok(buffer+1, ":");
-                               if (!pcnt)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "Bad line %u: need :\n",
-                                                  line);
-
-                               bcnt = strtok(NULL, "]");
-                               if (!bcnt)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "Bad line %u: need ]\n",
-                                                  line);
-
-                               /* start command parsing after counter */
-                               parsestart = ptr + 1;
-                       } else {
-                               /* start command parsing at start of line */
-                               parsestart = buffer;
-                       }
-
-                       add_argv(argv[0]);
-                       add_argv("-t");
-                       add_argv((char *) &curtable);
-                       
-                       if (counters && pcnt && bcnt) {
-                               add_argv("--set-counters");
-                               add_argv((char *) pcnt);
-                               add_argv((char *) bcnt);
-                       }
-
-                       /* After fighting with strtok enough, here's now
-                        * a 'real' parser. According to Rusty I'm now no
-                        * longer a real hacker, but I can live with that */
-
-                       quote_open = 0;
-                       param_start = parsestart;
-                       
-                       for (curchar = parsestart; *curchar; curchar++) {
-                               if (*curchar == '"') {
-                                       if (quote_open) {
-                                               quote_open = 0;
-                                               *curchar = ' ';
-                                       } else {
-                                               quote_open = 1;
-                                               param_start++;
-                                       }
-                               } 
-                               if (*curchar == ' '
-                                   || *curchar == '\t'
-                                   || * curchar == '\n') {
-                                       char param_buffer[1024];
-                                       int param_len = curchar-param_start;
-
-                                       if (quote_open)
-                                               continue;
-
-                                       if (!param_len) {
-                                               /* two spaces? */
-                                               param_start++;
-                                               continue;
-                                       }
-                                       
-                                       /* end of one parameter */
-                                       strncpy(param_buffer, param_start,
-                                               param_len);
-                                       *(param_buffer+param_len) = '\0';
-
-                                       /* check if table name specified */
-                                       if (!strncmp(param_buffer, "-t", 3)
-                                            || !strncmp(param_buffer, "--table", 8)) {
-                                               exit_error(PARAMETER_PROBLEM, 
-                                                  "Line %u seems to have a "
-                                                  "-t table option.\n", line);
-                                               exit(1);
-                                       }
-
-                                       add_argv(param_buffer);
-                                       param_start += param_len + 1;
-                               } else {
-                                       /* regular character, skip */
-                               }
-                       }
-
-                       DEBUGP("calling do_command(%u, argv, &%s, handle):\n",
-                               newargc, curtable);
-
-                       for (a = 0; a < newargc; a++)
-                               DEBUGP("argv[%u]: %s\n", a, newargv[a]);
-
-                       ret = do_command(newargc, newargv, 
-                                        &newargv[2], &handle);
-
-                       free_argv();
-               }
-               if (!ret) {
-                       fprintf(stderr, "%s: line %u failed\n",
-                                       program_name, line);
-                       exit(1);
-               }
-       }
-
-       return 0;
-}
diff --git a/iptables.c.selinux b/iptables.c.selinux
deleted file mode 100644 (file)
index 187fd86..0000000
+++ /dev/null
@@ -1,2298 +0,0 @@
-/* Code to take an iptables-style command line and do it. */
-
-/*
- * Author: Paul.Russell@rustcorp.com.au and mneuling@radlogic.com.au
- *
- * (C) 2000-2002 by the netfilter coreteam <coreteam@netfilter.org>:
- *                 Paul 'Rusty' Russell <rusty@rustcorp.com.au>
- *                 Marc Boucher <marc+nf@mbsi.ca>
- *                 James Morris <jmorris@intercode.com.au>
- *                 Harald Welte <laforge@gnumonks.org>
- *                 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <getopt.h>
-#include <string.h>
-#include <netdb.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <unistd.h>
-#include <iptables.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef IPT_LIB_DIR
-#define IPT_LIB_DIR "/usr/lib/iptables"
-#endif
-
-#ifndef PROC_SYS_MODPROBE
-#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
-#endif
-
-#define FMT_NUMERIC    0x0001
-#define FMT_NOCOUNTS   0x0002
-#define FMT_KILOMEGAGIGA 0x0004
-#define FMT_OPTIONS    0x0008
-#define FMT_NOTABLE    0x0010
-#define FMT_NOTARGET   0x0020
-#define FMT_VIA                0x0040
-#define FMT_NONEWLINE  0x0080
-#define FMT_LINENUMBERS 0x0100
-
-#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
-                       | FMT_NUMERIC | FMT_NOTABLE)
-#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
-
-
-#define CMD_NONE               0x0000U
-#define CMD_INSERT             0x0001U
-#define CMD_DELETE             0x0002U
-#define CMD_DELETE_NUM         0x0004U
-#define CMD_REPLACE            0x0008U
-#define CMD_APPEND             0x0010U
-#define CMD_LIST               0x0020U
-#define CMD_FLUSH              0x0040U
-#define CMD_ZERO               0x0080U
-#define CMD_NEW_CHAIN          0x0100U
-#define CMD_DELETE_CHAIN       0x0200U
-#define CMD_SET_POLICY         0x0400U
-#define CMD_CHECK              0x0800U
-#define CMD_RENAME_CHAIN       0x1000U
-#define NUMBER_OF_CMD  13
-static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
-                                'N', 'X', 'P', 'E' };
-
-#define OPTION_OFFSET 256
-
-#define OPT_NONE       0x00000U
-#define OPT_NUMERIC    0x00001U
-#define OPT_SOURCE     0x00002U
-#define OPT_DESTINATION        0x00004U
-#define OPT_PROTOCOL   0x00008U
-#define OPT_JUMP       0x00010U
-#define OPT_VERBOSE    0x00020U
-#define OPT_EXPANDED   0x00040U
-#define OPT_VIANAMEIN  0x00080U
-#define OPT_VIANAMEOUT 0x00100U
-#define OPT_FRAGMENT    0x00200U
-#define OPT_LINENUMBERS 0x00400U
-#define OPT_COUNTERS   0x00800U
-#define NUMBER_OF_OPT  12
-static const char optflags[NUMBER_OF_OPT]
-= { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', 'f', '3', 'c'};
-
-static struct option original_opts[] = {
-       { "append", 1, 0, 'A' },
-       { "delete", 1, 0,  'D' },
-       { "insert", 1, 0,  'I' },
-       { "replace", 1, 0,  'R' },
-       { "list", 2, 0,  'L' },
-       { "flush", 2, 0,  'F' },
-       { "zero", 2, 0,  'Z' },
-       { "new-chain", 1, 0,  'N' },
-       { "delete-chain", 2, 0,  'X' },
-       { "rename-chain", 1, 0,  'E' },
-       { "policy", 1, 0,  'P' },
-       { "source", 1, 0, 's' },
-       { "destination", 1, 0,  'd' },
-       { "src", 1, 0,  's' }, /* synonym */
-       { "dst", 1, 0,  'd' }, /* synonym */
-       { "protocol", 1, 0,  'p' },
-       { "in-interface", 1, 0, 'i' },
-       { "jump", 1, 0, 'j' },
-       { "table", 1, 0, 't' },
-       { "match", 1, 0, 'm' },
-       { "numeric", 0, 0, 'n' },
-       { "out-interface", 1, 0, 'o' },
-       { "verbose", 0, 0, 'v' },
-       { "exact", 0, 0, 'x' },
-       { "fragments", 0, 0, 'f' },
-       { "version", 0, 0, 'V' },
-       { "help", 2, 0, 'h' },
-       { "line-numbers", 0, 0, '0' },
-       { "modprobe", 1, 0, 'M' },
-       { "set-counters", 1, 0, 'c' },
-       { 0 }
-};
-
-/* we need this for iptables-restore.  iptables-restore.c sets line to the
- * current line of the input file, in order  to give a more precise error
- * message.  iptables itself doesn't need this, so it is initialized to the
- * magic number of -1 */
-int line = -1;
-
-#ifndef __OPTIMIZE__
-struct ipt_entry_target *
-ipt_get_target(struct ipt_entry *e)
-{
-       return (void *)e + e->target_offset;
-}
-#endif
-
-static struct option *opts = original_opts;
-static unsigned int global_option_offset = 0;
-
-/* Table of legal combinations of commands and options.  If any of the
- * given commands make an option legal, that option is legal (applies to
- * CMD_LIST and CMD_ZERO only).
- * Key:
- *  +  compulsory
- *  x  illegal
- *     optional
- */
-
-static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
-/* Well, it's better than "Re: Linux vs FreeBSD" */
-{
-       /*     -n  -s  -d  -p  -j  -v  -x  -i  -o  -f  --line */
-/*INSERT*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*DELETE*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*DELETE_NUM*/{'x','x','x','x','x',' ','x','x','x','x','x'},
-/*REPLACE*/   {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*APPEND*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*LIST*/      {' ','x','x','x','x',' ',' ','x','x','x',' '},
-/*FLUSH*/     {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*ZERO*/      {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*NEW_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*DEL_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x','x'},
-/*CHECK*/     {'x','+','+','+','x',' ','x',' ',' ',' ','x'},
-/*RENAME*/    {'x','x','x','x','x',' ','x','x','x','x','x'}
-};
-
-static int inverse_for_options[NUMBER_OF_OPT] =
-{
-/* -n */ 0,
-/* -s */ IPT_INV_SRCIP,
-/* -d */ IPT_INV_DSTIP,
-/* -p */ IPT_INV_PROTO,
-/* -j */ 0,
-/* -v */ 0,
-/* -x */ 0,
-/* -i */ IPT_INV_VIA_IN,
-/* -o */ IPT_INV_VIA_OUT,
-/* -f */ IPT_INV_FRAG,
-/*--line*/ 0
-};
-
-const char *program_version;
-const char *program_name;
-
-/* Keeping track of external matches and targets: linked lists.  */
-struct iptables_match *iptables_matches = NULL;
-struct iptables_target *iptables_targets = NULL;
-
-/* Extra debugging from libiptc */
-extern void dump_entries(const iptc_handle_t handle);
-
-/* A few hardcoded protocols for 'all' and in case the user has no
-   /etc/protocols */
-struct pprot {
-       char *name;
-       u_int8_t num;
-};
-
-/* Primitive headers... */
-/* defined in netinet/in.h */
-#if 0
-#ifndef IPPROTO_ESP
-#define IPPROTO_ESP 50
-#endif
-#ifndef IPPROTO_AH
-#define IPPROTO_AH 51
-#endif
-#endif
-
-static const struct pprot chain_protos[] = {
-       { "tcp", IPPROTO_TCP },
-       { "udp", IPPROTO_UDP },
-       { "icmp", IPPROTO_ICMP },
-       { "esp", IPPROTO_ESP },
-       { "ah", IPPROTO_AH },
-       { "all", 0 },
-};
-
-static char *
-proto_to_name(u_int8_t proto, int nolookup)
-{
-       unsigned int i;
-
-       if (proto && !nolookup) {
-               struct protoent *pent = getprotobynumber(proto);
-               if (pent)
-                       return pent->p_name;
-       }
-
-       for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++)
-               if (chain_protos[i].num == proto)
-                       return chain_protos[i].name;
-
-       return NULL;
-}
-
-struct in_addr *
-dotted_to_addr(const char *dotted)
-{
-       static struct in_addr addr;
-       unsigned char *addrp;
-       char *p, *q;
-       unsigned int onebyte;
-       int i;
-       char buf[20];
-
-       /* copy dotted string, because we need to modify it */
-       strncpy(buf, dotted, sizeof(buf) - 1);
-       addrp = (unsigned char *) &(addr.s_addr);
-
-       p = buf;
-       for (i = 0; i < 3; i++) {
-               if ((q = strchr(p, '.')) == NULL)
-                       return (struct in_addr *) NULL;
-
-               *q = '\0';
-               if (string_to_number(p, 0, 255, &onebyte) == -1)
-                       return (struct in_addr *) NULL;
-
-               addrp[i] = (unsigned char) onebyte;
-               p = q + 1;
-       }
-
-       /* we've checked 3 bytes, now we check the last one */
-       if (string_to_number(p, 0, 255, &onebyte) == -1)
-               return (struct in_addr *) NULL;
-
-       addrp[3] = (unsigned char) onebyte;
-
-       return &addr;
-}
-
-static struct in_addr *
-network_to_addr(const char *name)
-{
-       struct netent *net;
-       static struct in_addr addr;
-
-       if ((net = getnetbyname(name)) != NULL) {
-               if (net->n_addrtype != AF_INET)
-                       return (struct in_addr *) NULL;
-               addr.s_addr = htonl((unsigned long) net->n_net);
-               return &addr;
-       }
-
-       return (struct in_addr *) NULL;
-}
-
-static void
-inaddrcpy(struct in_addr *dst, struct in_addr *src)
-{
-       /* memcpy(dst, src, sizeof(struct in_addr)); */
-       dst->s_addr = src->s_addr;
-}
-
-void
-exit_error(enum exittype status, char *msg, ...)
-{
-       va_list args;
-
-       va_start(args, msg);
-       fprintf(stderr, "%s v%s: ", program_name, program_version);
-       vfprintf(stderr, msg, args);
-       va_end(args);
-       fprintf(stderr, "\n");
-       if (status == PARAMETER_PROBLEM)
-               exit_tryhelp(status);
-       if (status == VERSION_PROBLEM)
-               fprintf(stderr,
-                       "Perhaps iptables or your kernel needs to be upgraded.\n");
-       exit(status);
-}
-
-void
-exit_tryhelp(int status)
-{
-       if (line != -1)
-               fprintf(stderr, "Error occurred at line: %d\n", line);
-       fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
-                       program_name, program_name );
-       exit(status);
-}
-
-void
-exit_printhelp(void)
-{
-       struct iptables_match *m = NULL;
-       struct iptables_target *t = NULL;
-
-       printf("%s v%s\n\n"
-"Usage: %s -[AD] chain rule-specification [options]\n"
-"       %s -[RI] chain rulenum rule-specification [options]\n"
-"       %s -D chain rulenum [options]\n"
-"       %s -[LFZ] [chain] [options]\n"
-"       %s -[NX] chain\n"
-"       %s -E old-chain-name new-chain-name\n"
-"       %s -P chain target [options]\n"
-"       %s -h (print this help information)\n\n",
-              program_name, program_version, program_name, program_name,
-              program_name, program_name, program_name, program_name,
-              program_name, program_name);
-
-       printf(
-"Commands:\n"
-"Either long or short options are allowed.\n"
-"  --append  -A chain          Append to chain\n"
-"  --delete  -D chain          Delete matching rule from chain\n"
-"  --delete  -D chain rulenum\n"
-"                              Delete rule rulenum (1 = first) from chain\n"
-"  --insert  -I chain [rulenum]\n"
-"                              Insert in chain as rulenum (default 1=first)\n"
-"  --replace -R chain rulenum\n"
-"                              Replace rule rulenum (1 = first) in chain\n"
-"  --list    -L [chain]                List the rules in a chain or all chains\n"
-"  --flush   -F [chain]                Delete all rules in  chain or all chains\n"
-"  --zero    -Z [chain]                Zero counters in chain or all chains\n"
-"  --new     -N chain          Create a new user-defined chain\n"
-"  --delete-chain\n"
-"            -X [chain]                Delete a user-defined chain\n"
-"  --policy  -P chain target\n"
-"                              Change policy on chain to target\n"
-"  --rename-chain\n"
-"            -E old-chain new-chain\n"
-"                              Change chain name, (moving any references)\n"
-
-"Options:\n"
-"  --proto     -p [!] proto    protocol: by number or name, eg. `tcp'\n"
-"  --source    -s [!] address[/mask]\n"
-"                              source specification\n"
-"  --destination -d [!] address[/mask]\n"
-"                              destination specification\n"
-"  --in-interface -i [!] input name[+]\n"
-"                              network interface name ([+] for wildcard)\n"
-"  --jump      -j target\n"
-"                              target for rule (may load target extension)\n"
-"  --match     -m match\n"
-"                              extended match (may load extension)\n"
-"  --numeric   -n              numeric output of addresses and ports\n"
-"  --out-interface -o [!] output name[+]\n"
-"                              network interface name ([+] for wildcard)\n"
-"  --table     -t table        table to manipulate (default: `filter')\n"
-"  --verbose   -v              verbose mode\n"
-"  --line-numbers              print line numbers when listing\n"
-"  --exact     -x              expand numbers (display exact values)\n"
-"[!] --fragment        -f              match second or further fragments only\n"
-"  --modprobe=<command>                try to insert modules using this command\n"
-"  --set-counters PKTS BYTES   set the counter during insert/append\n"
-"[!] --version -V              print package version.\n");
-
-       /* Print out any special helps. A user might like to be able
-          to add a --help to the commandline, and see expected
-          results. So we call help for all matches & targets */
-       for (t=iptables_targets;t;t=t->next) {
-               printf("\n");
-               t->help();
-       }
-       for (m=iptables_matches;m;m=m->next) {
-               printf("\n");
-               m->help();
-       }
-       exit(0);
-}
-
-static void
-generic_opt_check(int command, int options)
-{
-       int i, j, legal = 0;
-
-       /* Check that commands are valid with options.  Complicated by the
-        * fact that if an option is legal with *any* command given, it is
-        * legal overall (ie. -z and -l).
-        */
-       for (i = 0; i < NUMBER_OF_OPT; i++) {
-               legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
-
-               for (j = 0; j < NUMBER_OF_CMD; j++) {
-                       if (!(command & (1<<j)))
-                               continue;
-
-                       if (!(options & (1<<i))) {
-                               if (commands_v_options[j][i] == '+')
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "You need to supply the `-%c' "
-                                                  "option for this command\n",
-                                                  optflags[i]);
-                       } else {
-                               if (commands_v_options[j][i] != 'x')
-                                       legal = 1;
-                               else if (legal == 0)
-                                       legal = -1;
-                       }
-               }
-               if (legal == -1)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Illegal option `-%c' with this command\n",
-                                  optflags[i]);
-       }
-}
-
-static char
-opt2char(int option)
-{
-       const char *ptr;
-       for (ptr = optflags; option > 1; option >>= 1, ptr++);
-
-       return *ptr;
-}
-
-static char
-cmd2char(int option)
-{
-       const char *ptr;
-       for (ptr = cmdflags; option > 1; option >>= 1, ptr++);
-
-       return *ptr;
-}
-
-static void
-add_command(int *cmd, const int newcmd, const int othercmds, int invert)
-{
-       if (invert)
-               exit_error(PARAMETER_PROBLEM, "unexpected ! flag");
-       if (*cmd & (~othercmds))
-               exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
-                          cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
-       *cmd |= newcmd;
-}
-
-int
-check_inverse(const char option[], int *invert, int *optind, int argc)
-{
-       if (option && strcmp(option, "!") == 0) {
-               if (*invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Multiple `!' flags not allowed");
-               *invert = TRUE;
-               if (optind) {
-                       *optind = *optind+1;
-                       if (argc && *optind > argc)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "no argument following `!'");
-               }
-
-               return TRUE;
-       }
-       return FALSE;
-}
-
-static void *
-fw_calloc(size_t count, size_t size)
-{
-       void *p;
-
-       if ((p = calloc(count, size)) == NULL) {
-               perror("iptables: calloc failed");
-               exit(1);
-       }
-       return p;
-}
-
-static void *
-fw_malloc(size_t size)
-{
-       void *p;
-
-       if ((p = malloc(size)) == NULL) {
-               perror("iptables: malloc failed");
-               exit(1);
-       }
-       return p;
-}
-
-static struct in_addr *
-host_to_addr(const char *name, unsigned int *naddr)
-{
-       struct hostent *host;
-       struct in_addr *addr;
-       unsigned int i;
-
-       *naddr = 0;
-       if ((host = gethostbyname(name)) != NULL) {
-               if (host->h_addrtype != AF_INET ||
-                   host->h_length != sizeof(struct in_addr))
-                       return (struct in_addr *) NULL;
-
-               while (host->h_addr_list[*naddr] != (char *) NULL)
-                       (*naddr)++;
-               addr = fw_calloc(*naddr, sizeof(struct in_addr));
-               for (i = 0; i < *naddr; i++)
-                       inaddrcpy(&(addr[i]),
-                                 (struct in_addr *) host->h_addr_list[i]);
-               return addr;
-       }
-
-       return (struct in_addr *) NULL;
-}
-
-static char *
-addr_to_host(const struct in_addr *addr)
-{
-       struct hostent *host;
-
-       if ((host = gethostbyaddr((char *) addr,
-                                 sizeof(struct in_addr), AF_INET)) != NULL)
-               return (char *) host->h_name;
-
-       return (char *) NULL;
-}
-
-/*
- *     All functions starting with "parse" should succeed, otherwise
- *     the program fails.
- *     Most routines return pointers to static data that may change
- *     between calls to the same or other routines with a few exceptions:
- *     "host_to_addr", "parse_hostnetwork", and "parse_hostnetworkmask"
- *     return global static data.
-*/
-
-static struct in_addr *
-parse_hostnetwork(const char *name, unsigned int *naddrs)
-{
-       struct in_addr *addrp, *addrptmp;
-
-       if ((addrptmp = dotted_to_addr(name)) != NULL ||
-           (addrptmp = network_to_addr(name)) != NULL) {
-               addrp = fw_malloc(sizeof(struct in_addr));
-               inaddrcpy(addrp, addrptmp);
-               *naddrs = 1;
-               return addrp;
-       }
-       if ((addrp = host_to_addr(name, naddrs)) != NULL)
-               return addrp;
-
-       exit_error(PARAMETER_PROBLEM, "host/network `%s' not found", name);
-}
-
-static struct in_addr *
-parse_mask(char *mask)
-{
-       static struct in_addr maskaddr;
-       struct in_addr *addrp;
-       unsigned int bits;
-
-       if (mask == NULL) {
-               /* no mask at all defaults to 32 bits */
-               maskaddr.s_addr = 0xFFFFFFFF;
-               return &maskaddr;
-       }
-       if ((addrp = dotted_to_addr(mask)) != NULL)
-               /* dotted_to_addr already returns a network byte order addr */
-               return addrp;
-       if (string_to_number(mask, 0, 32, &bits) == -1)
-               exit_error(PARAMETER_PROBLEM,
-                          "invalid mask `%s' specified", mask);
-       if (bits != 0) {
-               maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
-               return &maskaddr;
-       }
-
-       maskaddr.s_addr = 0L;
-       return &maskaddr;
-}
-
-void
-parse_hostnetworkmask(const char *name, struct in_addr **addrpp,
-                     struct in_addr *maskp, unsigned int *naddrs)
-{
-       struct in_addr *addrp;
-       char buf[256];
-       char *p;
-       int i, j, k, n;
-
-       strncpy(buf, name, sizeof(buf) - 1);
-       if ((p = strrchr(buf, '/')) != NULL) {
-               *p = '\0';
-               addrp = parse_mask(p + 1);
-       } else
-               addrp = parse_mask(NULL);
-       inaddrcpy(maskp, addrp);
-
-       /* if a null mask is given, the name is ignored, like in "any/0" */
-       if (maskp->s_addr == 0L)
-               strcpy(buf, "0.0.0.0");
-
-       addrp = *addrpp = parse_hostnetwork(buf, naddrs);
-       n = *naddrs;
-       for (i = 0, j = 0; i < n; i++) {
-               addrp[j++].s_addr &= maskp->s_addr;
-               for (k = 0; k < j - 1; k++) {
-                       if (addrp[k].s_addr == addrp[j - 1].s_addr) {
-                               (*naddrs)--;
-                               j--;
-                               break;
-                       }
-               }
-       }
-}
-
-struct iptables_match *
-find_match(const char *name, enum ipt_tryload tryload)
-{
-       struct iptables_match *ptr;
-
-       for (ptr = iptables_matches; ptr; ptr = ptr->next) {
-               if (strcmp(name, ptr->name) == 0)
-                       break;
-       }
-
-#ifndef NO_SHARED_LIBS
-       if (!ptr && tryload != DONT_LOAD) {
-               char path[sizeof(IPT_LIB_DIR) + sizeof("/libipt_.so")
-                        + strlen(name)];
-               sprintf(path, IPT_LIB_DIR "/libipt_%s.so", name);
-               if (dlopen(path, RTLD_NOW)) {
-                       /* Found library.  If it didn't register itself,
-                          maybe they specified target as match. */
-                       ptr = find_match(name, DONT_LOAD);
-
-                       if (!ptr)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Couldn't load match `%s'\n",
-                                          name);
-               } else if (tryload == LOAD_MUST_SUCCEED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Couldn't load match `%s':%s\n",
-                                  name, dlerror());
-       }
-#else
-       if (ptr && !ptr->loaded) {
-               if (tryload != DONT_LOAD)
-                       ptr->loaded = 1;
-               else
-                       ptr = NULL;
-       }
-       if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
-               exit_error(PARAMETER_PROBLEM,
-                          "Couldn't find match `%s'\n", name);
-       }
-#endif
-
-       if (ptr)
-               ptr->used = 1;
-
-       return ptr;
-}
-
-/* Christophe Burki wants `-p 6' to imply `-m tcp'.  */
-static struct iptables_match *
-find_proto(const char *pname, enum ipt_tryload tryload, int nolookup)
-{
-       unsigned int proto;
-
-       if (string_to_number(pname, 0, 255, &proto) != -1) {
-               char *protoname = proto_to_name(proto, nolookup);
-
-               if (protoname)
-                       return find_match(protoname, tryload);
-       } else
-               return find_match(pname, tryload);
-
-       return NULL;
-}
-
-u_int16_t
-parse_protocol(const char *s)
-{
-       unsigned int proto;
-
-       if (string_to_number(s, 0, 255, &proto) == -1) {
-               struct protoent *pent;
-
-               if ((pent = getprotobyname(s)))
-                       proto = pent->p_proto;
-               else {
-                       unsigned int i;
-                       for (i = 0;
-                            i < sizeof(chain_protos)/sizeof(struct pprot);
-                            i++) {
-                               if (strcmp(s, chain_protos[i].name) == 0) {
-                                       proto = chain_protos[i].num;
-                                       break;
-                               }
-                       }
-                       if (i == sizeof(chain_protos)/sizeof(struct pprot))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unknown protocol `%s' specified",
-                                          s);
-               }
-       }
-
-       return (u_int16_t)proto;
-}
-
-static void
-parse_interface(const char *arg, char *vianame, unsigned char *mask)
-{
-       int vialen = strlen(arg);
-       unsigned int i;
-
-       memset(mask, 0, IFNAMSIZ);
-       memset(vianame, 0, IFNAMSIZ);
-
-       if (vialen + 1 > IFNAMSIZ)
-               exit_error(PARAMETER_PROBLEM,
-                          "interface name `%s' must be shorter than IFNAMSIZ"
-                          " (%i)", arg, IFNAMSIZ-1);
-
-       strcpy(vianame, arg);
-       if (vialen == 0)
-               memset(mask, 0, IFNAMSIZ);
-       else if (vianame[vialen - 1] == '+') {
-               memset(mask, 0xFF, vialen - 1);
-               memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
-               /* Don't remove `+' here! -HW */
-       } else {
-               /* Include nul-terminator in match */
-               memset(mask, 0xFF, vialen + 1);
-               memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
-               for (i = 0; vianame[i]; i++) {
-                       if (!isalnum(vianame[i]) 
-                           && vianame[i] != '_' 
-                           && vianame[i] != '.') {
-                               printf("Warning: wierd character in interface"
-                                      " `%s' (No aliases, :, ! or *).\n",
-                                      vianame);
-                               break;
-                       }
-               }
-       }
-}
-
-/* Can't be zero. */
-static int
-parse_rulenumber(const char *rule)
-{
-       unsigned int rulenum;
-
-       if (string_to_number(rule, 1, INT_MAX, &rulenum) == -1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid rule number `%s'", rule);
-
-       return rulenum;
-}
-
-static const char *
-parse_target(const char *targetname)
-{
-       const char *ptr;
-
-       if (strlen(targetname) < 1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid target name (too short)");
-
-       if (strlen(targetname)+1 > sizeof(ipt_chainlabel))
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid target name `%s' (%i chars max)",
-                          targetname, sizeof(ipt_chainlabel)-1);
-
-       for (ptr = targetname; *ptr; ptr++)
-               if (isspace(*ptr))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Invalid target name `%s'", targetname);
-       return targetname;
-}
-
-static char *
-addr_to_network(const struct in_addr *addr)
-{
-       struct netent *net;
-
-       if ((net = getnetbyaddr((long) ntohl(addr->s_addr), AF_INET)) != NULL)
-               return (char *) net->n_name;
-
-       return (char *) NULL;
-}
-
-char *
-addr_to_dotted(const struct in_addr *addrp)
-{
-       static char buf[20];
-       const unsigned char *bytep;
-
-       bytep = (const unsigned char *) &(addrp->s_addr);
-       sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
-       return buf;
-}
-
-char *
-addr_to_anyname(const struct in_addr *addr)
-{
-       char *name;
-
-       if ((name = addr_to_host(addr)) != NULL ||
-           (name = addr_to_network(addr)) != NULL)
-               return name;
-
-       return addr_to_dotted(addr);
-}
-
-char *
-mask_to_dotted(const struct in_addr *mask)
-{
-       int i;
-       static char buf[20];
-       u_int32_t maskaddr, bits;
-
-       maskaddr = ntohl(mask->s_addr);
-
-       if (maskaddr == 0xFFFFFFFFL)
-               /* we don't want to see "/32" */
-               return "";
-
-       i = 32;
-       bits = 0xFFFFFFFEL;
-       while (--i >= 0 && maskaddr != bits)
-               bits <<= 1;
-       if (i >= 0)
-               sprintf(buf, "/%d", i);
-       else
-               /* mask was not a decent combination of 1's and 0's */
-               sprintf(buf, "/%s", addr_to_dotted(mask));
-
-       return buf;
-}
-
-int
-string_to_number(const char *s, unsigned int min, unsigned int max,
-                unsigned int *ret)
-{
-       long number;
-       char *end;
-
-       /* Handle hex, octal, etc. */
-       errno = 0;
-       number = strtol(s, &end, 0);
-       if (*end == '\0' && end != s) {
-               /* we parsed a number, let's see if we want this */
-               if (errno != ERANGE && min <= number && number <= max) {
-                       *ret = number;
-                       return 0;
-               }
-       }
-       return -1;
-}
-
-static void
-set_option(unsigned int *options, unsigned int option, u_int8_t *invflg,
-          int invert)
-{
-       if (*options & option)
-               exit_error(PARAMETER_PROBLEM, "multiple -%c flags not allowed",
-                          opt2char(option));
-       *options |= option;
-
-       if (invert) {
-               unsigned int i;
-               for (i = 0; 1 << i != option; i++);
-
-               if (!inverse_for_options[i])
-                       exit_error(PARAMETER_PROBLEM,
-                                  "cannot have ! before -%c",
-                                  opt2char(option));
-               *invflg |= inverse_for_options[i];
-       }
-}
-
-struct iptables_target *
-find_target(const char *name, enum ipt_tryload tryload)
-{
-       struct iptables_target *ptr;
-
-       /* Standard target? */
-       if (strcmp(name, "") == 0
-           || strcmp(name, IPTC_LABEL_ACCEPT) == 0
-           || strcmp(name, IPTC_LABEL_DROP) == 0
-           || strcmp(name, IPTC_LABEL_QUEUE) == 0
-           || strcmp(name, IPTC_LABEL_RETURN) == 0)
-               name = "standard";
-
-       for (ptr = iptables_targets; ptr; ptr = ptr->next) {
-               if (strcmp(name, ptr->name) == 0)
-                       break;
-       }
-
-#ifndef NO_SHARED_LIBS
-       if (!ptr && tryload != DONT_LOAD) {
-               char path[sizeof(IPT_LIB_DIR) + sizeof("/libipt_.so")
-                        + strlen(name)];
-               sprintf(path, IPT_LIB_DIR "/libipt_%s.so", name);
-               if (dlopen(path, RTLD_NOW)) {
-                       /* Found library.  If it didn't register itself,
-                          maybe they specified match as a target. */
-                       ptr = find_target(name, DONT_LOAD);
-                       if (!ptr)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Couldn't load target `%s'\n",
-                                          name);
-               } else if (tryload == LOAD_MUST_SUCCEED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Couldn't load target `%s':%s\n",
-                                  name, dlerror());
-       }
-#else
-       if (ptr && !ptr->loaded) {
-               if (tryload != DONT_LOAD)
-                       ptr->loaded = 1;
-               else
-                       ptr = NULL;
-       }
-       if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
-               exit_error(PARAMETER_PROBLEM,
-                          "Couldn't find target `%s'\n", name);
-       }
-#endif
-
-       if (ptr)
-               ptr->used = 1;
-
-       return ptr;
-}
-
-static struct option *
-merge_options(struct option *oldopts, const struct option *newopts,
-             unsigned int *option_offset)
-{
-       unsigned int num_old, num_new, i;
-       struct option *merge;
-
-       for (num_old = 0; oldopts[num_old].name; num_old++);
-       for (num_new = 0; newopts[num_new].name; num_new++);
-
-       global_option_offset += OPTION_OFFSET;
-       *option_offset = global_option_offset;
-
-       merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
-       memcpy(merge, oldopts, num_old * sizeof(struct option));
-       for (i = 0; i < num_new; i++) {
-               merge[num_old + i] = newopts[i];
-               merge[num_old + i].val += *option_offset;
-       }
-       memset(merge + num_old + num_new, 0, sizeof(struct option));
-
-       return merge;
-}
-
-void
-register_match(struct iptables_match *me)
-{
-       struct iptables_match **i;
-
-       if (strcmp(me->version, program_version) != 0) {
-               fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
-                       program_name, me->name, me->version, program_version);
-               exit(1);
-       }
-
-       if (find_match(me->name, DONT_LOAD)) {
-               fprintf(stderr, "%s: match `%s' already registered.\n",
-                       program_name, me->name);
-               exit(1);
-       }
-
-       if (me->size != IPT_ALIGN(me->size)) {
-               fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
-                       program_name, me->name, me->size);
-               exit(1);
-       }
-
-       /* Append to list. */
-       for (i = &iptables_matches; *i; i = &(*i)->next);
-       me->next = NULL;
-       *i = me;
-
-       me->m = NULL;
-       me->mflags = 0;
-}
-
-void
-register_target(struct iptables_target *me)
-{
-       if (strcmp(me->version, program_version) != 0) {
-               fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n",
-                       program_name, me->name, me->version, program_version);
-               exit(1);
-       }
-
-       if (find_target(me->name, DONT_LOAD)) {
-               fprintf(stderr, "%s: target `%s' already registered.\n",
-                       program_name, me->name);
-               exit(1);
-       }
-
-       if (me->size != IPT_ALIGN(me->size)) {
-               fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
-                       program_name, me->name, me->size);
-               exit(1);
-       }
-
-       /* Prepend to list. */
-       me->next = iptables_targets;
-       iptables_targets = me;
-       me->t = NULL;
-       me->tflags = 0;
-}
-
-static void
-print_num(u_int64_t number, unsigned int format)
-{
-       if (format & FMT_KILOMEGAGIGA) {
-               if (number > 99999) {
-                       number = (number + 500) / 1000;
-                       if (number > 9999) {
-                               number = (number + 500) / 1000;
-                               if (number > 9999) {
-                                       number = (number + 500) / 1000;
-                                       if (number > 9999) {
-                                               number = (number + 500) / 1000;
-                                               printf(FMT("%4lluT ","%lluT "), number);
-                                       }
-                                       else printf(FMT("%4lluG ","%lluG "), number);
-                               }
-                               else printf(FMT("%4lluM ","%lluM "), number);
-                       } else
-                               printf(FMT("%4lluK ","%lluK "), number);
-               } else
-                       printf(FMT("%5llu ","%llu "), number);
-       } else
-               printf(FMT("%8llu ","%llu "), number);
-}
-
-
-static void
-print_header(unsigned int format, const char *chain, iptc_handle_t *handle)
-{
-       struct ipt_counters counters;
-       const char *pol = iptc_get_policy(chain, &counters, handle);
-       printf("Chain %s", chain);
-       if (pol) {
-               printf(" (policy %s", pol);
-               if (!(format & FMT_NOCOUNTS)) {
-                       fputc(' ', stdout);
-                       print_num(counters.pcnt, (format|FMT_NOTABLE));
-                       fputs("packets, ", stdout);
-                       print_num(counters.bcnt, (format|FMT_NOTABLE));
-                       fputs("bytes", stdout);
-               }
-               printf(")\n");
-       } else {
-               unsigned int refs;
-               if (!iptc_get_references(&refs, chain, handle))
-                       printf(" (ERROR obtaining refs)\n");
-               else
-                       printf(" (%u references)\n", refs);
-       }
-
-       if (format & FMT_LINENUMBERS)
-               printf(FMT("%-4s ", "%s "), "num");
-       if (!(format & FMT_NOCOUNTS)) {
-               if (format & FMT_KILOMEGAGIGA) {
-                       printf(FMT("%5s ","%s "), "pkts");
-                       printf(FMT("%5s ","%s "), "bytes");
-               } else {
-                       printf(FMT("%8s ","%s "), "pkts");
-                       printf(FMT("%10s ","%s "), "bytes");
-               }
-       }
-       if (!(format & FMT_NOTARGET))
-               printf(FMT("%-9s ","%s "), "target");
-       fputs(" prot ", stdout);
-       if (format & FMT_OPTIONS)
-               fputs("opt", stdout);
-       if (format & FMT_VIA) {
-               printf(FMT(" %-6s ","%s "), "in");
-               printf(FMT("%-6s ","%s "), "out");
-       }
-       printf(FMT(" %-19s ","%s "), "source");
-       printf(FMT(" %-19s "," %s "), "destination");
-       printf("\n");
-}
-
-
-static int
-print_match(const struct ipt_entry_match *m,
-           const struct ipt_ip *ip,
-           int numeric)
-{
-       struct iptables_match *match = find_match(m->u.user.name, TRY_LOAD);
-
-       if (match) {
-               if (match->print)
-                       match->print(ip, m, numeric);
-               else
-                       printf("%s ", match->name);
-       } else {
-               if (m->u.user.name[0])
-                       printf("UNKNOWN match `%s' ", m->u.user.name);
-       }
-       /* Don't stop iterating. */
-       return 0;
-}
-
-/* e is called `fw' here for hysterical raisins */
-static void
-print_firewall(const struct ipt_entry *fw,
-              const char *targname,
-              unsigned int num,
-              unsigned int format,
-              const iptc_handle_t handle)
-{
-       struct iptables_target *target = NULL;
-       const struct ipt_entry_target *t;
-       u_int8_t flags;
-       char buf[BUFSIZ];
-
-       if (!iptc_is_chain(targname, handle))
-               target = find_target(targname, TRY_LOAD);
-       else
-               target = find_target(IPT_STANDARD_TARGET, LOAD_MUST_SUCCEED);
-
-       t = ipt_get_target((struct ipt_entry *)fw);
-       flags = fw->ip.flags;
-
-       if (format & FMT_LINENUMBERS)
-               printf(FMT("%-4u ", "%u "), num+1);
-
-       if (!(format & FMT_NOCOUNTS)) {
-               print_num(fw->counters.pcnt, format);
-               print_num(fw->counters.bcnt, format);
-       }
-
-       if (!(format & FMT_NOTARGET))
-               printf(FMT("%-9s ", "%s "), targname);
-
-       fputc(fw->ip.invflags & IPT_INV_PROTO ? '!' : ' ', stdout);
-       {
-               char *pname = proto_to_name(fw->ip.proto, format&FMT_NUMERIC);
-               if (pname)
-                       printf(FMT("%-5s", "%s "), pname);
-               else
-                       printf(FMT("%-5hu", "%hu "), fw->ip.proto);
-       }
-
-       if (format & FMT_OPTIONS) {
-               if (format & FMT_NOTABLE)
-                       fputs("opt ", stdout);
-               fputc(fw->ip.invflags & IPT_INV_FRAG ? '!' : '-', stdout);
-               fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout);
-               fputc(' ', stdout);
-       }
-
-       if (format & FMT_VIA) {
-               char iface[IFNAMSIZ+2];
-
-               if (fw->ip.invflags & IPT_INV_VIA_IN) {
-                       iface[0] = '!';
-                       iface[1] = '\0';
-               }
-               else iface[0] = '\0';
-
-               if (fw->ip.iniface[0] != '\0') {
-                       strcat(iface, fw->ip.iniface);
-               }
-               else if (format & FMT_NUMERIC) strcat(iface, "*");
-               else strcat(iface, "any");
-               printf(FMT(" %-6s ","in %s "), iface);
-
-               if (fw->ip.invflags & IPT_INV_VIA_OUT) {
-                       iface[0] = '!';
-                       iface[1] = '\0';
-               }
-               else iface[0] = '\0';
-
-               if (fw->ip.outiface[0] != '\0') {
-                       strcat(iface, fw->ip.outiface);
-               }
-               else if (format & FMT_NUMERIC) strcat(iface, "*");
-               else strcat(iface, "any");
-               printf(FMT("%-6s ","out %s "), iface);
-       }
-
-       fputc(fw->ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
-       if (fw->ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC))
-               printf(FMT("%-19s ","%s "), "anywhere");
-       else {
-               if (format & FMT_NUMERIC)
-                       sprintf(buf, "%s", addr_to_dotted(&(fw->ip.src)));
-               else
-                       sprintf(buf, "%s", addr_to_anyname(&(fw->ip.src)));
-               strcat(buf, mask_to_dotted(&(fw->ip.smsk)));
-               printf(FMT("%-19s ","%s "), buf);
-       }
-
-       fputc(fw->ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
-       if (fw->ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC))
-               printf(FMT("%-19s ","-> %s"), "anywhere");
-       else {
-               if (format & FMT_NUMERIC)
-                       sprintf(buf, "%s", addr_to_dotted(&(fw->ip.dst)));
-               else
-                       sprintf(buf, "%s", addr_to_anyname(&(fw->ip.dst)));
-               strcat(buf, mask_to_dotted(&(fw->ip.dmsk)));
-               printf(FMT("%-19s ","-> %s"), buf);
-       }
-
-       if (format & FMT_NOTABLE)
-               fputs("  ", stdout);
-
-       IPT_MATCH_ITERATE(fw, print_match, &fw->ip, format & FMT_NUMERIC);
-
-       if (target) {
-               if (target->print)
-                       /* Print the target information. */
-                       target->print(&fw->ip, t, format & FMT_NUMERIC);
-       } else if (t->u.target_size != sizeof(*t))
-               printf("[%u bytes of unknown target data] ",
-                      t->u.target_size - sizeof(*t));
-
-       if (!(format & FMT_NONEWLINE))
-               fputc('\n', stdout);
-}
-
-static void
-print_firewall_line(const struct ipt_entry *fw,
-                   const iptc_handle_t h)
-{
-       struct ipt_entry_target *t;
-
-       t = ipt_get_target((struct ipt_entry *)fw);
-       print_firewall(fw, t->u.user.name, 0, FMT_PRINT_RULE, h);
-}
-
-static int
-append_entry(const ipt_chainlabel chain,
-            struct ipt_entry *fw,
-            unsigned int nsaddrs,
-            const struct in_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in_addr daddrs[],
-            int verbose,
-            iptc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ip.src.s_addr = saddrs[i].s_addr;
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ip.dst.s_addr = daddrs[j].s_addr;
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= iptc_append_entry(chain, fw, handle);
-               }
-       }
-
-       return ret;
-}
-
-static int
-replace_entry(const ipt_chainlabel chain,
-             struct ipt_entry *fw,
-             unsigned int rulenum,
-             const struct in_addr *saddr,
-             const struct in_addr *daddr,
-             int verbose,
-             iptc_handle_t *handle)
-{
-       fw->ip.src.s_addr = saddr->s_addr;
-       fw->ip.dst.s_addr = daddr->s_addr;
-
-       if (verbose)
-               print_firewall_line(fw, *handle);
-       return iptc_replace_entry(chain, fw, rulenum, handle);
-}
-
-static int
-insert_entry(const ipt_chainlabel chain,
-            struct ipt_entry *fw,
-            unsigned int rulenum,
-            unsigned int nsaddrs,
-            const struct in_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in_addr daddrs[],
-            int verbose,
-            iptc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ip.src.s_addr = saddrs[i].s_addr;
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ip.dst.s_addr = daddrs[j].s_addr;
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= iptc_insert_entry(chain, fw, rulenum, handle);
-               }
-       }
-
-       return ret;
-}
-
-static unsigned char *
-make_delete_mask(struct ipt_entry *fw)
-{
-       /* Establish mask for comparison */
-       unsigned int size;
-       struct iptables_match *m;
-       unsigned char *mask, *mptr;
-
-       size = sizeof(struct ipt_entry);
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               size += IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
-       }
-
-       mask = fw_calloc(1, size
-                        + IPT_ALIGN(sizeof(struct ipt_entry_target))
-                        + iptables_targets->size);
-
-       memset(mask, 0xFF, sizeof(struct ipt_entry));
-       mptr = mask + sizeof(struct ipt_entry);
-
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               memset(mptr, 0xFF,
-                      IPT_ALIGN(sizeof(struct ipt_entry_match))
-                      + m->userspacesize);
-               mptr += IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
-       }
-
-       memset(mptr, 0xFF,
-              IPT_ALIGN(sizeof(struct ipt_entry_target))
-              + iptables_targets->userspacesize);
-
-       return mask;
-}
-
-static int
-delete_entry(const ipt_chainlabel chain,
-            struct ipt_entry *fw,
-            unsigned int nsaddrs,
-            const struct in_addr saddrs[],
-            unsigned int ndaddrs,
-            const struct in_addr daddrs[],
-            int verbose,
-            iptc_handle_t *handle)
-{
-       unsigned int i, j;
-       int ret = 1;
-       unsigned char *mask;
-
-       mask = make_delete_mask(fw);
-       for (i = 0; i < nsaddrs; i++) {
-               fw->ip.src.s_addr = saddrs[i].s_addr;
-               for (j = 0; j < ndaddrs; j++) {
-                       fw->ip.dst.s_addr = daddrs[j].s_addr;
-                       if (verbose)
-                               print_firewall_line(fw, *handle);
-                       ret &= iptc_delete_entry(chain, fw, mask, handle);
-               }
-       }
-       return ret;
-}
-
-int
-for_each_chain(int (*fn)(const ipt_chainlabel, int, iptc_handle_t *),
-              int verbose, int builtinstoo, iptc_handle_t *handle)
-{
-        int ret = 1;
-       const char *chain;
-       char *chains;
-       unsigned int i, chaincount = 0;
-
-       chain = iptc_first_chain(handle);
-       while (chain) {
-               chaincount++;
-               chain = iptc_next_chain(handle);
-        }
-
-       chains = fw_malloc(sizeof(ipt_chainlabel) * chaincount);
-       i = 0;
-       chain = iptc_first_chain(handle);
-       while (chain) {
-               strcpy(chains + i*sizeof(ipt_chainlabel), chain);
-               i++;
-               chain = iptc_next_chain(handle);
-        }
-
-       for (i = 0; i < chaincount; i++) {
-               if (!builtinstoo
-                   && iptc_builtin(chains + i*sizeof(ipt_chainlabel),
-                                   *handle))
-                       continue;
-               ret &= fn(chains + i*sizeof(ipt_chainlabel), verbose, handle);
-       }
-
-       free(chains);
-        return ret;
-}
-
-int
-flush_entries(const ipt_chainlabel chain, int verbose,
-             iptc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(flush_entries, verbose, 1, handle);
-
-       if (verbose)
-               fprintf(stdout, "Flushing chain `%s'\n", chain);
-       return iptc_flush_entries(chain, handle);
-}
-
-static int
-zero_entries(const ipt_chainlabel chain, int verbose,
-            iptc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(zero_entries, verbose, 1, handle);
-
-       if (verbose)
-               fprintf(stdout, "Zeroing chain `%s'\n", chain);
-       return iptc_zero_entries(chain, handle);
-}
-
-int
-delete_chain(const ipt_chainlabel chain, int verbose,
-            iptc_handle_t *handle)
-{
-       if (!chain)
-               return for_each_chain(delete_chain, verbose, 0, handle);
-
-       if (verbose)
-               fprintf(stdout, "Deleting chain `%s'\n", chain);
-       return iptc_delete_chain(chain, handle);
-}
-
-static int
-list_entries(const ipt_chainlabel chain, int verbose, int numeric,
-            int expanded, int linenumbers, iptc_handle_t *handle)
-{
-       int found = 0;
-       unsigned int format;
-       const char *this;
-
-       format = FMT_OPTIONS;
-       if (!verbose)
-               format |= FMT_NOCOUNTS;
-       else
-               format |= FMT_VIA;
-
-       if (numeric)
-               format |= FMT_NUMERIC;
-
-       if (!expanded)
-               format |= FMT_KILOMEGAGIGA;
-
-       if (linenumbers)
-               format |= FMT_LINENUMBERS;
-
-       for (this = iptc_first_chain(handle);
-            this;
-            this = iptc_next_chain(handle)) {
-               const struct ipt_entry *i;
-               unsigned int num;
-
-               if (chain && strcmp(chain, this) != 0)
-                       continue;
-
-               if (found) printf("\n");
-
-               print_header(format, this, handle);
-               i = iptc_first_rule(this, handle);
-
-               num = 0;
-               while (i) {
-                       print_firewall(i,
-                                      iptc_get_target(i, handle),
-                                      num++,
-                                      format,
-                                      *handle);
-                       i = iptc_next_rule(i, handle);
-               }
-               found = 1;
-       }
-
-       errno = ENOENT;
-       return found;
-}
-
-static char *get_modprobe(void)
-{
-       int procfile;
-       char *ret;
-
-       procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
-       if (procfile < 0)
-               return NULL;
-
-       ret = malloc(1024);
-       if (ret) {
-               switch (read(procfile, ret, 1024)) {
-               case -1: goto fail;
-               case 1024: goto fail; /* Partial read.  Wierd */
-               }
-               if (ret[strlen(ret)-1]=='\n') 
-                       ret[strlen(ret)-1]=0;
-               close(procfile);
-               return ret;
-       }
- fail:
-       free(ret);
-       close(procfile);
-       return NULL;
-}
-
-int iptables_insmod(const char *modname, const char *modprobe)
-{
-       char *buf = NULL;
-       char *argv[3];
-
-       /* If they don't explicitly set it, read out of kernel */
-       if (!modprobe) {
-               buf = get_modprobe();
-               if (!buf)
-                       return -1;
-               modprobe = buf;
-       }
-
-       switch (fork()) {
-       case 0:
-               argv[0] = (char *)modprobe;
-               argv[1] = (char *)modname;
-               argv[2] = NULL;
-               execv(argv[0], argv);
-
-               /* not usually reached */
-               exit(0);
-       case -1:
-               return -1;
-
-       default: /* parent */
-               wait(NULL);
-       }
-
-       free(buf);
-       return 0;
-}
-
-static struct ipt_entry *
-generate_entry(const struct ipt_entry *fw,
-              struct iptables_match *matches,
-              struct ipt_entry_target *target)
-{
-       unsigned int size;
-       struct iptables_match *m;
-       struct ipt_entry *e;
-
-       size = sizeof(struct ipt_entry);
-       for (m = matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               size += m->m->u.match_size;
-       }
-
-       e = fw_malloc(size + target->u.target_size);
-       *e = *fw;
-       e->target_offset = size;
-       e->next_offset = size + target->u.target_size;
-
-       size = 0;
-       for (m = matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               memcpy(e->elems + size, m->m, m->m->u.match_size);
-               size += m->m->u.match_size;
-       }
-       memcpy(e->elems + size, target, target->u.target_size);
-
-       return e;
-}
-
-int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
-{
-       struct ipt_entry fw, *e = NULL;
-       int invert = 0;
-       unsigned int nsaddrs = 0, ndaddrs = 0;
-       struct in_addr *saddrs = NULL, *daddrs = NULL;
-
-       int c, verbose = 0;
-       const char *chain = NULL;
-       const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
-       const char *policy = NULL, *newname = NULL;
-       unsigned int rulenum = 0, options = 0, command = 0;
-       const char *pcnt = NULL, *bcnt = NULL;
-       int ret = 1;
-       struct iptables_match *m;
-       struct iptables_target *target = NULL;
-       struct iptables_target *t;
-       const char *jumpto = "";
-       char *protocol = NULL;
-       const char *modprobe = NULL;
-       int proto_used = 0;
-
-       memset(&fw, 0, sizeof(fw));
-
-       opts = original_opts;
-       global_option_offset = 0;
-
-       /* re-set optind to 0 in case do_command gets called
-        * a second time */
-       optind = 0;
-
-       /* clear mflags in case do_command gets called a second time
-        * (we clear the global list of all matches for security)*/
-       for (m = iptables_matches; m; m = m->next) {
-               m->mflags = 0;
-               m->used = 0;
-       }
-
-       for (t = iptables_targets; t; t = t->next) {
-               t->tflags = 0;
-               t->used = 0;
-       }
-
-       /* Suppress error messages: we may add new options if we
-           demand-load a protocol. */
-       opterr = 0;
-
-       while ((c = getopt_long(argc, argv,
-          "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:",
-                                          opts, NULL)) != -1) {
-               switch (c) {
-                       /*
-                        * Command selection
-                        */
-               case 'A':
-                       add_command(&command, CMD_APPEND, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       break;
-
-               case 'D':
-                       add_command(&command, CMD_DELETE, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!') {
-                               rulenum = parse_rulenumber(argv[optind++]);
-                               command = CMD_DELETE_NUM;
-                       }
-                       break;
-
-               case 'R':
-                       add_command(&command, CMD_REPLACE, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires a rule number",
-                                          cmd2char(CMD_REPLACE));
-                       break;
-
-               case 'I':
-                       add_command(&command, CMD_INSERT, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               rulenum = parse_rulenumber(argv[optind++]);
-                       else rulenum = 1;
-                       break;
-
-               case 'L':
-                       add_command(&command, CMD_LIST, CMD_ZERO,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'F':
-                       add_command(&command, CMD_FLUSH, CMD_NONE,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'Z':
-                       add_command(&command, CMD_ZERO, CMD_LIST,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                               && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'N':
-                       if (optarg && *optarg == '-')
-                               exit_error(PARAMETER_PROBLEM,
-                                          "chain name not allowed to start "
-                                          "with `-'\n");
-                       if (find_target(optarg, TRY_LOAD))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "chain name may not clash "
-                                          "with target name\n");
-                       add_command(&command, CMD_NEW_CHAIN, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       break;
-
-               case 'X':
-                       add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
-                                   invert);
-                       if (optarg) chain = optarg;
-                       else if (optind < argc && argv[optind][0] != '-'
-                                && argv[optind][0] != '!')
-                               chain = argv[optind++];
-                       break;
-
-               case 'E':
-                       add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               newname = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires old-chain-name and "
-                                          "new-chain-name",
-                                           cmd2char(CMD_RENAME_CHAIN));
-                       break;
-
-               case 'P':
-                       add_command(&command, CMD_SET_POLICY, CMD_NONE,
-                                   invert);
-                       chain = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               policy = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires a chain and a policy",
-                                          cmd2char(CMD_SET_POLICY));
-                       break;
-
-               case 'h':
-                       if (!optarg)
-                               optarg = argv[optind];
-
-                       /* iptables -p icmp -h */
-                       if (!iptables_matches && protocol)
-                               find_match(protocol, TRY_LOAD);
-
-                       exit_printhelp();
-
-                       /*
-                        * Option selection
-                        */
-               case 'p':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_PROTOCOL, &fw.ip.invflags,
-                                  invert);
-
-                       /* Canonicalize into lower case */
-                       for (protocol = argv[optind-1]; *protocol; protocol++)
-                               *protocol = tolower(*protocol);
-
-                       protocol = argv[optind-1];
-                       fw.ip.proto = parse_protocol(protocol);
-
-                       if (fw.ip.proto == 0
-                           && (fw.ip.invflags & IPT_INV_PROTO))
-                               exit_error(PARAMETER_PROBLEM,
-                                          "rule would never match protocol");
-                       fw.nfcache |= NFC_IP_PROTO;
-                       break;
-
-               case 's':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_SOURCE, &fw.ip.invflags,
-                                  invert);
-                       shostnetworkmask = argv[optind-1];
-                       fw.nfcache |= NFC_IP_SRC;
-                       break;
-
-               case 'd':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_DESTINATION, &fw.ip.invflags,
-                                  invert);
-                       dhostnetworkmask = argv[optind-1];
-                       fw.nfcache |= NFC_IP_DST;
-                       break;
-
-               case 'j':
-                       set_option(&options, OPT_JUMP, &fw.ip.invflags,
-                                  invert);
-                       jumpto = parse_target(optarg);
-                       /* TRY_LOAD (may be chain name) */
-                       target = find_target(jumpto, TRY_LOAD);
-
-                       if (target) {
-                               size_t size;
-
-                               size = IPT_ALIGN(sizeof(struct ipt_entry_target))
-                                       + target->size;
-
-                               target->t = fw_calloc(1, size);
-                               target->t->u.target_size = size;
-                               strcpy(target->t->u.user.name, jumpto);
-                               target->init(target->t, &fw.nfcache);
-                               opts = merge_options(opts, target->extra_opts, &target->option_offset);
-                       }
-                       break;
-
-
-               case 'i':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_VIANAMEIN, &fw.ip.invflags,
-                                  invert);
-                       parse_interface(argv[optind-1],
-                                       fw.ip.iniface,
-                                       fw.ip.iniface_mask);
-                       fw.nfcache |= NFC_IP_IF_IN;
-                       break;
-
-               case 'o':
-                       check_inverse(optarg, &invert, &optind, argc);
-                       set_option(&options, OPT_VIANAMEOUT, &fw.ip.invflags,
-                                  invert);
-                       parse_interface(argv[optind-1],
-                                       fw.ip.outiface,
-                                       fw.ip.outiface_mask);
-                       fw.nfcache |= NFC_IP_IF_OUT;
-                       break;
-
-               case 'f':
-                       set_option(&options, OPT_FRAGMENT, &fw.ip.invflags,
-                                  invert);
-                       fw.ip.flags |= IPT_F_FRAG;
-                       fw.nfcache |= NFC_IP_FRAG;
-                       break;
-
-               case 'v':
-                       if (!verbose)
-                               set_option(&options, OPT_VERBOSE,
-                                          &fw.ip.invflags, invert);
-                       verbose++;
-                       break;
-
-               case 'm': {
-                       size_t size;
-
-                       if (invert)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unexpected ! flag before --match");
-
-                       m = find_match(optarg, LOAD_MUST_SUCCEED);
-                       size = IPT_ALIGN(sizeof(struct ipt_entry_match))
-                                        + m->size;
-                       m->m = fw_calloc(1, size);
-                       m->m->u.match_size = size;
-                       strcpy(m->m->u.user.name, m->name);
-                       m->init(m->m, &fw.nfcache);
-                       opts = merge_options(opts, m->extra_opts, &m->option_offset);
-               }
-               break;
-
-               case 'n':
-                       set_option(&options, OPT_NUMERIC, &fw.ip.invflags,
-                                  invert);
-                       break;
-
-               case 't':
-                       if (invert)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "unexpected ! flag before --table");
-                       *table = argv[optind-1];
-                       break;
-
-               case 'x':
-                       set_option(&options, OPT_EXPANDED, &fw.ip.invflags,
-                                  invert);
-                       break;
-
-               case 'V':
-                       if (invert)
-                               printf("Not %s ;-)\n", program_version);
-                       else
-                               printf("%s v%s\n",
-                                      program_name, program_version);
-                       exit(0);
-
-               case '0':
-                       set_option(&options, OPT_LINENUMBERS, &fw.ip.invflags,
-                                  invert);
-                       break;
-
-               case 'M':
-                       modprobe = optarg;
-                       break;
-
-               case 'c':
-
-                       set_option(&options, OPT_COUNTERS, &fw.ip.invflags,
-                                  invert);
-                       pcnt = optarg;
-                       if (optind < argc && argv[optind][0] != '-'
-                           && argv[optind][0] != '!')
-                               bcnt = argv[optind++];
-                       else
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c requires packet and byte counter",
-                                       opt2char(OPT_COUNTERS));
-
-                       if (sscanf(pcnt, "%llu", &fw.counters.pcnt) != 1)
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c packet counter not numeric",
-                                       opt2char(OPT_COUNTERS));
-
-                       if (sscanf(bcnt, "%llu", &fw.counters.bcnt) != 1)
-                               exit_error(PARAMETER_PROBLEM,
-                                       "-%c byte counter not numeric",
-                                       opt2char(OPT_COUNTERS));
-                       
-                       break;
-
-
-               case 1: /* non option */
-                       if (optarg[0] == '!' && optarg[1] == '\0') {
-                               if (invert)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "multiple consecutive ! not"
-                                                  " allowed");
-                               invert = TRUE;
-                               optarg[0] = '\0';
-                               continue;
-                       }
-                       printf("Bad argument `%s'\n", optarg);
-                       exit_tryhelp(2);
-
-               default:
-                       /* FIXME: This scheme doesn't allow two of the same
-                          matches --RR */
-                       if (!target
-                           || !(target->parse(c - target->option_offset,
-                                              argv, invert,
-                                              &target->tflags,
-                                              &fw, &target->t))) {
-                               for (m = iptables_matches; m; m = m->next) {
-                                       if (!m->used)
-                                               continue;
-
-                                       if (m->parse(c - m->option_offset,
-                                                    argv, invert,
-                                                    &m->mflags,
-                                                    &fw,
-                                                    &fw.nfcache,
-                                                    &m->m))
-                                               break;
-                               }
-
-                               /* If you listen carefully, you can
-                                  actually hear this code suck. */
-
-                               /* some explanations (after four different bugs
-                                * in 3 different releases): If we encountere a
-                                * parameter, that has not been parsed yet,
-                                * it's not an option of an explicitly loaded
-                                * match or a target.  However, we support
-                                * implicit loading of the protocol match
-                                * extension.  '-p tcp' means 'l4 proto 6' and
-                                * at the same time 'load tcp protocol match on
-                                * demand if we specify --dport'.
-                                *
-                                * To make this work, we need to make sure:
-                                * - the parameter has not been parsed by
-                                *   a match (m above)
-                                * - a protocol has been specified
-                                * - the protocol extension has not been
-                                *   loaded yet, or is loaded and unused
-                                *   [think of iptables-restore!]
-                                * - the protocol extension can be successively
-                                *   loaded
-                                */
-                               if (m == NULL
-                                   && protocol
-                                   && (!find_proto(protocol, DONT_LOAD,
-                                                  options&OPT_NUMERIC) 
-                                       || (find_proto(protocol, DONT_LOAD,
-                                                       options&OPT_NUMERIC)
-                                           && (proto_used == 0))
-                                      )
-                                   && (m = find_proto(protocol, TRY_LOAD,
-                                                      options&OPT_NUMERIC))) {
-                                       /* Try loading protocol */
-                                       size_t size;
-                                       
-                                       proto_used = 1;
-
-                                       size = IPT_ALIGN(sizeof(struct ipt_entry_match))
-                                                        + m->size;
-
-                                       m->m = fw_calloc(1, size);
-                                       m->m->u.match_size = size;
-                                       strcpy(m->m->u.user.name, m->name);
-                                       m->init(m->m, &fw.nfcache);
-
-                                       opts = merge_options(opts,
-                                           m->extra_opts, &m->option_offset);
-
-                                       optind--;
-                                       continue;
-                               }
-                               if (!m)
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "Unknown arg `%s'",
-                                                  argv[optind-1]);
-                       }
-               }
-               invert = FALSE;
-       }
-
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               m->final_check(m->mflags);
-       }
-
-       if (target)
-               target->final_check(target->tflags);
-
-       /* Fix me: must put inverse options checking here --MN */
-
-       if (optind < argc)
-               exit_error(PARAMETER_PROBLEM,
-                          "unknown arguments found on commandline");
-       if (!command)
-               exit_error(PARAMETER_PROBLEM, "no command specified");
-       if (invert)
-               exit_error(PARAMETER_PROBLEM,
-                          "nothing appropriate following !");
-
-       if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) {
-               if (!(options & OPT_DESTINATION))
-                       dhostnetworkmask = "0.0.0.0/0";
-               if (!(options & OPT_SOURCE))
-                       shostnetworkmask = "0.0.0.0/0";
-       }
-
-       if (shostnetworkmask)
-               parse_hostnetworkmask(shostnetworkmask, &saddrs,
-                                     &(fw.ip.smsk), &nsaddrs);
-
-       if (dhostnetworkmask)
-               parse_hostnetworkmask(dhostnetworkmask, &daddrs,
-                                     &(fw.ip.dmsk), &ndaddrs);
-
-       if ((nsaddrs > 1 || ndaddrs > 1) &&
-           (fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
-               exit_error(PARAMETER_PROBLEM, "! not allowed with multiple"
-                          " source or destination IP addresses");
-
-       if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
-               exit_error(PARAMETER_PROBLEM, "Replacement rule does not "
-                          "specify a unique address");
-
-       generic_opt_check(command, options);
-
-       if (chain && strlen(chain) > IPT_FUNCTION_MAXNAMELEN)
-               exit_error(PARAMETER_PROBLEM,
-                          "chain name `%s' too long (must be under %i chars)",
-                          chain, IPT_FUNCTION_MAXNAMELEN);
-
-       /* only allocate handle if we weren't called with a handle */
-       if (!*handle)
-               *handle = iptc_init(*table);
-
-       if (!*handle) {
-               /* try to insmod the module if iptc_init failed */
-               iptables_insmod("ip_tables", modprobe);
-               *handle = iptc_init(*table);
-       }
-
-       if (!*handle)
-               exit_error(VERSION_PROBLEM,
-                          "can't initialize iptables table `%s': %s",
-                          *table, iptc_strerror(errno));
-
-       if (command == CMD_APPEND
-           || command == CMD_DELETE
-           || command == CMD_INSERT
-           || command == CMD_REPLACE) {
-               if (strcmp(chain, "PREROUTING") == 0
-                   || strcmp(chain, "INPUT") == 0) {
-                       /* -o not valid with incoming packets. */
-                       if (options & OPT_VIANAMEOUT)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Can't use -%c with %s\n",
-                                          opt2char(OPT_VIANAMEOUT),
-                                          chain);
-               }
-
-               if (strcmp(chain, "POSTROUTING") == 0
-                   || strcmp(chain, "OUTPUT") == 0) {
-                       /* -i not valid with outgoing packets */
-                       if (options & OPT_VIANAMEIN)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Can't use -%c with %s\n",
-                                          opt2char(OPT_VIANAMEIN),
-                                          chain);
-               }
-
-               if (target && iptc_is_chain(jumpto, *handle)) {
-                       printf("Warning: using chain %s, not extension\n",
-                              jumpto);
-
-                       target = NULL;
-               }
-
-               /* If they didn't specify a target, or it's a chain
-                  name, use standard. */
-               if (!target
-                   && (strlen(jumpto) == 0
-                       || iptc_is_chain(jumpto, *handle))) {
-                       size_t size;
-
-                       target = find_target(IPT_STANDARD_TARGET,
-                                            LOAD_MUST_SUCCEED);
-
-                       size = sizeof(struct ipt_entry_target)
-                               + target->size;
-                       target->t = fw_calloc(1, size);
-                       target->t->u.target_size = size;
-                       strcpy(target->t->u.user.name, jumpto);
-                       target->init(target->t, &fw.nfcache);
-               }
-
-               if (!target) {
-                       /* it is no chain, and we can't load a plugin.
-                        * We cannot know if the plugin is corrupt, non
-                        * existant OR if the user just misspelled a
-                        * chain. */
-                       find_target(jumpto, LOAD_MUST_SUCCEED);
-               } else {
-                       e = generate_entry(&fw, iptables_matches, target->t);
-               }
-       }
-
-       switch (command) {
-       case CMD_APPEND:
-               ret = append_entry(chain, e,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_DELETE:
-               ret = delete_entry(chain, e,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_DELETE_NUM:
-               ret = iptc_delete_num_entry(chain, rulenum - 1, handle);
-               break;
-       case CMD_REPLACE:
-               ret = replace_entry(chain, e, rulenum - 1,
-                                   saddrs, daddrs, options&OPT_VERBOSE,
-                                   handle);
-               break;
-       case CMD_INSERT:
-               ret = insert_entry(chain, e, rulenum - 1,
-                                  nsaddrs, saddrs, ndaddrs, daddrs,
-                                  options&OPT_VERBOSE,
-                                  handle);
-               break;
-       case CMD_LIST:
-               ret = list_entries(chain,
-                                  options&OPT_VERBOSE,
-                                  options&OPT_NUMERIC,
-                                  options&OPT_EXPANDED,
-                                  options&OPT_LINENUMBERS,
-                                  handle);
-               break;
-       case CMD_FLUSH:
-               ret = flush_entries(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_ZERO:
-               ret = zero_entries(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_LIST|CMD_ZERO:
-               ret = list_entries(chain,
-                                  options&OPT_VERBOSE,
-                                  options&OPT_NUMERIC,
-                                  options&OPT_EXPANDED,
-                                  options&OPT_LINENUMBERS,
-                                  handle);
-               if (ret)
-                       ret = zero_entries(chain,
-                                          options&OPT_VERBOSE, handle);
-               break;
-       case CMD_NEW_CHAIN:
-               ret = iptc_create_chain(chain, handle);
-               break;
-       case CMD_DELETE_CHAIN:
-               ret = delete_chain(chain, options&OPT_VERBOSE, handle);
-               break;
-       case CMD_RENAME_CHAIN:
-               ret = iptc_rename_chain(chain, newname, handle);
-               break;
-       case CMD_SET_POLICY:
-               ret = iptc_set_policy(chain, policy, NULL, handle);
-               break;
-       default:
-               /* We should never reach this... */
-               exit_tryhelp(2);
-       }
-
-       if (verbose > 1)
-               dump_entries(*handle);
-
-       return ret;
-}
diff --git a/iptables.spec b/iptables.spec
new file mode 100644 (file)
index 0000000..695c2ae
--- /dev/null
@@ -0,0 +1,360 @@
+%define build_devel 1
+%define linux_header 0
+
+Name: iptables
+Summary: Tools for managing Linux kernel packet filtering capabilities.
+Version: 1.2.9
+Release: 2.3.1
+Source: http://www.netfilter.org/%{name}-%{version}.tar.bz2
+Source1: iptables.init
+Source2: iptables-config
+%if %{linux_header}
+Source3: netfilter-2.4.20.tar.gz
+%endif
+Patch2: iptables-1.2.8-nolibnsl.patch
+Patch3: iptables-1.2.8-print_type.patch
+Patch4: iptables-1.2.9-netlink.patch
+Patch5: iptables-1.2.9-selinux.patch
+Patch6: iptables-1.2.9-counters.patch
+Group: System Environment/Base
+URL: http://www.netfilter.org/
+BuildRoot: %{_tmppath}/%{name}-buildroot
+License: GPL
+BuildPrereq: /usr/bin/perl
+Requires: kernel >= 2.4.20
+Requires(post,postun): chkconfig
+Prefix: %{_prefix}
+
+%package ipv6
+Summary: IPv6 support for iptables.
+Group: System Environment/Base
+Requires: %{name} = %{version}
+
+%if %{build_devel}
+%package devel
+Summary: Development package for iptables.
+Group: System Environment/Base
+Requires: %{name} = %{version}
+%endif
+
+%description
+The iptables utility controls the network packet filtering code in the
+Linux kernel. If you need to set up firewalls and/or IP masquerading,
+you should install this package.
+
+%description ipv6
+The iptables package contains IPv6 (the next version of the IP
+protocol) support for iptables. Iptables controls the Linux kernel
+network packet filtering code, allowing you to set up firewalls and IP
+masquerading. 
+
+Install iptables-ipv6 if you need to set up firewalling for your
+network and you are using ipv6.
+
+%if %{build_devel}
+%description devel
+The iptables utility controls the network packet filtering code in the
+Linux kernel. If you need to set up firewalls and/or IP masquerading,
+you should install this package.
+%endif
+
+%prep
+rm -rf %{buildroot}
+
+%setup -q
+%if %{linux_header}
+cd include 
+tar -zxf %{SOURCE3}
+cd ..
+%endif
+%patch2 -p1 -b .nolibnsl
+%patch3 -p1 -b .print_type
+%patch4 -p1 -b .netlink
+%patch5 -p1 -b .selinux
+%patch6 -p1 -b .counters
+
+# Put it to a reasonable place
+find . -type f -exec perl -pi -e "s,/usr/local,%{prefix},g" {} \;
+
+%build
+TOPDIR=`pwd`
+OPT="$RPM_OPT_FLAGS -I$TOPDIR/include"
+make COPT_FLAGS="$OPT" KERNEL_DIR=/usr LIBDIR=/%{_lib}
+make COPT_FLAGS="$OPT" KERNEL_DIR=/usr LIBDIR=/%{_lib} iptables-save iptables-restore
+make COPT_FLAGS="$OPT" KERNEL_DIR=/usr LIBDIR=/%{_lib} ip6tables-save ip6tables-restore
+
+%install
+make install DESTDIR=%{buildroot} KERNEL_DIR=/usr BINDIR=/sbin LIBDIR=/%{_lib} MANDIR=%{_mandir}
+%if %{build_devel}
+make install-devel DESTDIR=%{buildroot} KERNEL_DIR=/usr BINDIR=/sbin LIBDIR=%{_libdir} MANDIR=%{_mandir}
+%endif
+cp ip{6,}tables-{save,restore} $RPM_BUILD_ROOT/sbin
+cp iptables-*.8 $RPM_BUILD_ROOT%{_mandir}/man8
+mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
+install -c -m755 %{SOURCE1} $RPM_BUILD_ROOT/etc/rc.d/init.d/iptables
+sed -e 's;iptables;ip6tables;g' -e 's;IPTABLES;IP6TABLES;g' < %{SOURCE1} > ip6tables.init
+install -c -m755 ip6tables.init $RPM_BUILD_ROOT/etc/rc.d/init.d/ip6tables
+mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
+install -c -m755 %{SOURCE2} $RPM_BUILD_ROOT/etc/sysconfig/iptables-config
+sed -e 's;iptables;ip6tables;g' -e 's;IPTABLES;IP6TABLES;g' < %{SOURCE2} > ip6tables-config
+install -c -m755 ip6tables-config $RPM_BUILD_ROOT/etc/sysconfig/ip6tables-config
+
+%clean
+rm -rf $RPM_BUILD_ROOT 
+
+%post
+/sbin/chkconfig --add iptables
+
+%preun
+if [ "$1" = 0 ]; then
+       /sbin/chkconfig --del iptables
+fi
+
+%post ipv6
+/sbin/chkconfig --add ip6tables
+
+%preun ipv6
+if [ "$1" = 0 ]; then
+       /sbin/chkconfig --del ip6tables
+fi
+
+%files
+%defattr(-,root,root,0755)
+%doc COPYING INSTALL INCOMPATIBILITIES
+%config %attr(0755,root,root) /etc/rc.d/init.d/iptables
+%config(noreplace) %attr(0600,root,root) /etc/sysconfig/iptables-config
+/sbin/iptables*
+%{_mandir}/man8/iptables*
+%dir /%{_lib}/iptables
+/%{_lib}/iptables/libipt*
+
+%files ipv6
+%defattr(-,root,root,0755)
+%config %attr(0755,root,root) /etc/rc.d/init.d/ip6tables
+%config(noreplace) %attr(0600,root,root) /etc/sysconfig/ip6tables-config
+/sbin/ip6tables*
+%{_mandir}/man8/ip6tables*
+/%{_lib}/iptables/libip6t*
+
+%if %{build_devel}
+%files devel
+%defattr(-,root,root,0755)
+%{_includedir}/libipq.h
+%{_libdir}/libipq.a
+%{_libdir}/libiptc.a
+%{_mandir}/man3/*
+%endif
+
+%changelog
+* Tue Mar 02 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Thu Feb 26 2004 Thomas Woerner <twoerner@redhat.com> 1.2.9-2.3
+- fixed iptables-restore -c fault if there are no counters (#116421)
+
+* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Sun Jan  25 2004 Dan Walsh <dwalsh@redhat.com> 1.2.9-1.2
+- Close File descriptors to prevent SELinux error message
+
+* Wed Jan  7 2004 Thomas Woerner <twoerner@redhat.com> 1.2.9-1.1
+- rebuild
+
+* Wed Dec 17 2003 Thomas Woerner <twoerner@redhat.com> 1.2.9-1
+- vew version 1.2.9
+- new config options in ipXtables-config:
+  IPTABLES_MODULES_UNLOAD
+- more documentation in ipXtables-config
+- fix for netlink security issue in libipq (devel package)
+- print fix for libipt_icmp (#109546)
+
+* Thu Oct 23 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-13
+- marked all messages in iptables init script for translation (#107462)
+- enabled devel package (#105884, #106101)
+- bumped build for fedora for libipt_recent.so (#106002)
+
+* Tue Sep 23 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-12.1
+- fixed lost udp port range in ip6tables-save (#104484)
+- fixed non numeric multiport port output in ipXtables-savs
+
+* Mon Sep 22 2003 Florian La Roche <Florian.LaRoche@redhat.de> 1.2.8-11
+- do not link against -lnsl
+
+* Wed Sep 17 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-10
+- made variables in rmmod_r local
+
+* Tue Jul 22 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-9
+- fixed permission for init script
+
+* Sat Jul 19 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-8
+- fixed save when iptables file is missing and iptables-config permissions
+
+* Tue Jul  8 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-7
+- fixes for ip6tables: module unloading, setting policy only for existing 
+  tables
+
+* Thu Jul  3 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-6
+- IPTABLES_SAVE_COUNTER defaults to no, now
+- install config file in /etc/sysconfig
+- exchange unload of ip_tables and ip_conntrack
+- fixed start function
+
+* Wed Jul  2 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-5
+- new config option IPTABLES_SAVE_ON_RESTART
+- init script: new status, save and restart
+- fixes #44905, #65389, #80785, #82860, #91040, #91560 and #91374
+
+* Mon Jun 30 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-4
+- new config option IPTABLES_STATUS_NUMERIC
+- cleared IPTABLES_MODULES in iptables-config
+
+* Mon Jun 30 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-3
+- new init scripts
+
+* Sat Jun 28 2003 Florian La Roche <Florian.LaRoche@redhat.de>
+- remove check for very old kernel versions in init scripts
+- sync up both init scripts and remove some further ugly things
+- add some docu into rpm
+
+* Thu Jun 26  2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-2
+- rebuild
+
+* Mon Jun 16 2003 Thomas Woerner <twoerner@redhat.com> 1.2.8-1
+- update to 1.2.8
+
+* Wed Jan 22 2003 Tim Powers <timp@redhat.com>
+- rebuilt
+
+* Mon Jan 13 2003 Bill Nottingham <notting@redhat.com> 1.2.7a-1
+- update to 1.2.7a
+- add a plethora of bugfixes courtesy Michael Schwendt <mschewndt@yahoo.com>
+
+* Fri Dec 13 2002 Elliot Lee <sopwith@redhat.com> 1.2.6a-3
+- Fix multilib
+
+* Wed Aug 07 2002 Karsten Hopp <karsten@redhat.de>
+- fixed iptables and ip6tables initscript output, based on #70511
+- check return status of all iptables calls, not just the last one
+  in a 'for' loop.
+
+* Mon Jul 29 2002 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.6a-1
+- 1.2.6a (bugfix release, #69747)
+
+* Fri Jun 21 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Thu May 23 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Mon Mar  4 2002 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.5-3
+- Add some fixes from CVS, fixing bug #60465
+
+* Tue Feb 12 2002 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.5-2
+- Merge ip6tables improvements from Ian Prowell <iprowell@prowell.org>
+  #59402
+- Update URL (#59354)
+- Use /sbin/chkconfig rather than chkconfig in %postun script
+
+* Fri Jan 11 2002 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.5-1
+- 1.2.5
+
+* Wed Jan 09 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Mon Nov  5 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.4-2
+- Fix %preun script
+
+* Tue Oct 30 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.4-1
+- Update to 1.2.4 (various fixes, including security fixes; among others:
+  #42990, #50500, #53325, #54280)
+- Fix init script (#31133)
+
+* Mon Sep  3 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.3-1
+- 1.2.3 (5 security fixes, some other fixes)
+- Fix updating (#53032)
+
+* Mon Aug 27 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.2-4
+- Fix #50990
+- Add some fixes from current CVS; should fix #52620
+
+* Mon Jul 16 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.2-3
+- Add some fixes from the current CVS tree; fixes #49154 and some IPv6
+  issues
+
+* Tue Jun 26 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.2-2
+- Fix iptables-save reject-with (#45632), Patch from Michael Schwendt
+  <mschwendt@yahoo.com>
+
+* Tue May  8 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.2-1
+- 1.2.2
+
+* Wed Mar 21 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- 1.2.1a, fixes #28412, #31136, #31460, #31133
+
+* Thu Mar  1 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- Yet another initscript fix (#30173)
+- Fix the fixes; they fixed some issues but broke more important
+  stuff :/ (#30176)
+
+* Tue Feb 27 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- Fix up initscript (#27962)
+- Add fixes from CVS to iptables-{restore,save}, fixing #28412
+
+* Fri Feb 09 2001 Karsten Hopp <karsten@redhat.de>
+- create /etc/sysconfig/iptables mode 600 (same problem as #24245)
+
+* Mon Feb 05 2001 Karsten Hopp <karsten@redhat.de>
+- fix bugzilla #25986 (initscript not marked as config file)
+- fix bugzilla #25962 (iptables-restore)
+- mv chkconfig --del from postun to preun
+
+* Thu Feb  1 2001 Trond Eivind Glomsrød <teg@redhat.com>
+- Fix check for ipchains
+
+* Mon Jan 29 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- Some fixes to init scripts
+
+* Wed Jan 24 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- Add some fixes from CVS, fixes among other things Bug #24732
+
+* Wed Jan 17 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- Add missing man pages, fix up init script (Bug #17676)
+
+* Mon Jan 15 2001 Bill Nottingham <notting@redhat.com>
+- add init script
+
+* Mon Jan 15 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- 1.2
+- fix up ipv6 split
+- add init script
+- Move the plugins from /usr/lib/iptables to /lib/iptables.
+  This needs to work before /usr is mounted...
+- Use -O1 on alpha (compiler bug)
+
+* Sat Jan  6 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- 1.1.2
+- Add IPv6 support (in separate package)
+
+* Thu Aug 17 2000 Bill Nottingham <notting@redhat.com>
+- build everywhere
+
+* Tue Jul 25 2000 Bernhard Rosenkraenzer <bero@redhat.com>
+- 1.1.1
+
+* Thu Jul 13 2000 Prospector <bugzilla@redhat.com>
+- automatic rebuild
+
+* Tue Jun 27 2000 Preston Brown <pbrown@redhat.com>
+- move iptables to /sbin.
+- excludearch alpha for now, not building there because of compiler bug(?)
+
+* Fri Jun  9 2000 Bill Nottingham <notting@redhat.com>
+- don't obsolete ipchains either
+- update to 1.1.0
+
+* Mon Jun  4 2000 Bill Nottingham <notting@redhat.com>
+- remove explicit kernel requirement
+
+* Tue May  2 2000 Bernhard Rosenkränzer <bero@redhat.com>
+- initial package
diff --git a/libipq/libipq.c.netlink b/libipq/libipq.c.netlink
deleted file mode 100644 (file)
index 709c8a2..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * libipq.c
- *
- * IPQ userspace library.
- *
- * Please note that this library is still developmental, and there may
- * be some API changes.
- *
- * Author: James Morris <jmorris@intercode.com.au>
- *
- * 07-11-2001 Modified by Fernando Anton to add support for IPv6.
- *
- * Copyright (c) 2000-2001 Netfilter Core Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#include <libipq/libipq.h>
-
-/****************************************************************************
- *
- * Private interface
- *
- ****************************************************************************/
-
-enum {
-       IPQ_ERR_NONE = 0,
-       IPQ_ERR_IMPL,
-       IPQ_ERR_HANDLE,
-       IPQ_ERR_SOCKET,
-       IPQ_ERR_BIND,
-       IPQ_ERR_BUFFER,
-       IPQ_ERR_RECV,
-       IPQ_ERR_NLEOF,
-       IPQ_ERR_ADDRLEN,
-       IPQ_ERR_STRUNC,
-       IPQ_ERR_RTRUNC,
-       IPQ_ERR_NLRECV,
-       IPQ_ERR_SEND,
-       IPQ_ERR_SUPP,
-       IPQ_ERR_RECVBUF,
-       IPQ_ERR_TIMEOUT,
-        IPQ_ERR_PROTOCOL
-};
-#define IPQ_MAXERR IPQ_ERR_PROTOCOL
-
-struct ipq_errmap_t {
-       int errcode;
-       char *message;
-} ipq_errmap[] = {
-       { IPQ_ERR_NONE, "Unknown error" },
-       { IPQ_ERR_IMPL, "Implementation error" },
-       { IPQ_ERR_HANDLE, "Unable to create netlink handle" },
-       { IPQ_ERR_SOCKET, "Unable to create netlink socket" },
-       { IPQ_ERR_BIND, "Unable to bind netlink socket" },
-       { IPQ_ERR_BUFFER, "Unable to allocate buffer" },
-       { IPQ_ERR_RECV, "Failed to receive netlink message" },
-       { IPQ_ERR_NLEOF, "Received EOF on netlink socket" },
-       { IPQ_ERR_ADDRLEN, "Invalid peer address length" },
-       { IPQ_ERR_STRUNC, "Sent message truncated" },
-       { IPQ_ERR_RTRUNC, "Received message truncated" },
-       { IPQ_ERR_NLRECV, "Received error from netlink" },
-       { IPQ_ERR_SEND, "Failed to send netlink message" },
-       { IPQ_ERR_SUPP, "Operation not supported" },
-       { IPQ_ERR_RECVBUF, "Receive buffer size invalid" },
-       { IPQ_ERR_TIMEOUT, "Timeout"},
-       { IPQ_ERR_PROTOCOL, "Invalid protocol specified" }
-};
-
-static int ipq_errno = IPQ_ERR_NONE;
-
-static ssize_t ipq_netlink_sendto(const struct ipq_handle *h,
-                                  const void *msg, size_t len);
-
-static ssize_t ipq_netlink_recvfrom(const struct ipq_handle *h,
-                                    unsigned char *buf, size_t len,
-                                    int timeout);
-
-static ssize_t ipq_netlink_sendmsg(const struct ipq_handle *h,
-                                   const struct msghdr *msg,
-                                   unsigned int flags);
-
-static char *ipq_strerror(int errcode);
-
-static ssize_t ipq_netlink_sendto(const struct ipq_handle *h,
-                                  const void *msg, size_t len)
-{
-       int status = sendto(h->fd, msg, len, 0,
-                           (struct sockaddr *)&h->peer, sizeof(h->peer));
-       if (status < 0)
-               ipq_errno = IPQ_ERR_SEND;
-       return status;
-}
-
-static ssize_t ipq_netlink_sendmsg(const struct ipq_handle *h,
-                                   const struct msghdr *msg,
-                                   unsigned int flags)
-{
-       int status = sendmsg(h->fd, msg, flags);
-       if (status < 0)
-               ipq_errno = IPQ_ERR_SEND;
-       return status;
-}
-
-static ssize_t ipq_netlink_recvfrom(const struct ipq_handle *h,
-                                    unsigned char *buf, size_t len,
-                                    int timeout)
-{
-       int addrlen, status;
-       struct nlmsghdr *nlh;
-
-       if (len < sizeof(struct nlmsgerr)) {
-               ipq_errno = IPQ_ERR_RECVBUF;
-               return -1;
-       }
-       addrlen = sizeof(h->peer);
-
-       if (timeout != 0) {
-               int ret;
-               struct timeval tv;
-               fd_set read_fds;
-               
-               if (timeout < 0) {
-                       /* non-block non-timeout */
-                       tv.tv_sec = 0;
-                       tv.tv_usec = 0;
-               } else {
-                       tv.tv_sec = timeout / 1000000;
-                       tv.tv_usec = timeout % 1000000;
-               }
-
-               FD_ZERO(&read_fds);
-               FD_SET(h->fd, &read_fds);
-               ret = select(h->fd+1, &read_fds, NULL, NULL, &tv);
-               if (ret < 0) {
-                       if (errno == EINTR) {
-                               return 0;
-                       } else {
-                               ipq_errno = IPQ_ERR_RECV;
-                               return -1;
-                       }
-               }
-               if (!FD_ISSET(h->fd, &read_fds)) {
-                       ipq_errno = IPQ_ERR_TIMEOUT;
-                       return 0;
-               }
-       }
-       status = recvfrom(h->fd, buf, len, 0,
-                             (struct sockaddr *)&h->peer, &addrlen);
-       if (status < 0) {
-               ipq_errno = IPQ_ERR_RECV;
-               return status;
-       }
-       if (addrlen != sizeof(h->peer)) {
-               ipq_errno = IPQ_ERR_RECV;
-               return -1;
-       }
-       if (status == 0) {
-               ipq_errno = IPQ_ERR_NLEOF;
-               return -1;
-       }
-       nlh = (struct nlmsghdr *)buf;
-       if (nlh->nlmsg_flags & MSG_TRUNC || nlh->nlmsg_len > status) {
-               ipq_errno = IPQ_ERR_RTRUNC;
-               return -1;
-       }
-       return status;
-}
-
-static char *ipq_strerror(int errcode)
-{
-       if (errcode < 0 || errcode > IPQ_MAXERR)
-               errcode = IPQ_ERR_IMPL;
-       return ipq_errmap[errcode].message;
-}
-
-/****************************************************************************
- *
- * Public interface
- *
- ****************************************************************************/
-
-/*
- * Create and initialise an ipq handle.
- */
-struct ipq_handle *ipq_create_handle(u_int32_t flags, u_int32_t protocol)
-{
-       int status;
-       struct ipq_handle *h;
-
-       h = (struct ipq_handle *)malloc(sizeof(struct ipq_handle));
-       if (h == NULL) {
-               ipq_errno = IPQ_ERR_HANDLE;
-               return NULL;
-       }
-       
-       memset(h, 0, sizeof(struct ipq_handle));
-       
-        if (protocol == PF_INET)
-                h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_FIREWALL);
-        else if (protocol == PF_INET6)
-                h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_IP6_FW);
-        else {
-               ipq_errno = IPQ_ERR_PROTOCOL;
-               free(h);
-               return NULL;
-        }
-        
-       if (h->fd == -1) {
-               ipq_errno = IPQ_ERR_SOCKET;
-               close(h->fd);
-               free(h);
-               return NULL;
-       }
-       memset(&h->local, 0, sizeof(struct sockaddr_nl));
-       h->local.nl_family = AF_NETLINK;
-       h->local.nl_pid = getpid();
-       h->local.nl_groups = 0;
-       status = bind(h->fd, (struct sockaddr *)&h->local, sizeof(h->local));
-       if (status == -1) {
-               ipq_errno = IPQ_ERR_BIND;
-               close(h->fd);
-               free(h);
-               return NULL;
-       }
-       memset(&h->peer, 0, sizeof(struct sockaddr_nl));
-       h->peer.nl_family = AF_NETLINK;
-       h->peer.nl_pid = 0;
-       h->peer.nl_groups = 0;
-       return h;
-}
-
-/*
- * No error condition is checked here at this stage, but it may happen
- * if/when reliable messaging is implemented.
- */
-int ipq_destroy_handle(struct ipq_handle *h)
-{
-       if (h) {
-               close(h->fd);
-               free(h);
-       }
-       return 0;
-}
-
-int ipq_set_mode(const struct ipq_handle *h,
-                 u_int8_t mode, size_t range)
-{
-       struct {
-               struct nlmsghdr nlh;
-               ipq_peer_msg_t pm;
-       } req;
-
-       memset(&req, 0, sizeof(req));
-       req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(req));
-       req.nlh.nlmsg_flags = NLM_F_REQUEST;
-       req.nlh.nlmsg_type = IPQM_MODE;
-       req.nlh.nlmsg_pid = h->local.nl_pid;
-       req.pm.msg.mode.value = mode;
-       req.pm.msg.mode.range = range;
-       return ipq_netlink_sendto(h, (void *)&req, req.nlh.nlmsg_len);
-}
-
-/*
- * timeout is in microseconds (1 second is 1000000 (1 million) microseconds)
- *
- */
-ssize_t ipq_read(const struct ipq_handle *h,
-                 unsigned char *buf, size_t len, int timeout)
-{
-       return ipq_netlink_recvfrom(h, buf, len, timeout);
-}
-
-int ipq_message_type(const unsigned char *buf)
-{
-       return ((struct nlmsghdr*)buf)->nlmsg_type;
-}
-
-int ipq_get_msgerr(const unsigned char *buf)
-{
-       struct nlmsghdr *h = (struct nlmsghdr *)buf;
-       struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
-       return -err->error;
-}
-
-ipq_packet_msg_t *ipq_get_packet(const unsigned char *buf)
-{
-       return NLMSG_DATA((struct nlmsghdr *)(buf));
-}
-
-int ipq_set_verdict(const struct ipq_handle *h,
-                    ipq_id_t id,
-                    unsigned int verdict,
-                    size_t data_len,
-                    unsigned char *buf)
-{
-       unsigned char nvecs;
-       size_t tlen;
-       struct nlmsghdr nlh;
-       ipq_peer_msg_t pm;
-       struct iovec iov[3];
-       struct msghdr msg;
-
-       memset(&nlh, 0, sizeof(nlh));
-       nlh.nlmsg_flags = NLM_F_REQUEST;
-       nlh.nlmsg_type = IPQM_VERDICT;
-       nlh.nlmsg_pid = h->local.nl_pid;
-       memset(&pm, 0, sizeof(pm));
-       pm.msg.verdict.value = verdict;
-       pm.msg.verdict.id = id;
-       pm.msg.verdict.data_len = data_len;
-       iov[0].iov_base = &nlh;
-       iov[0].iov_len = sizeof(nlh);
-       iov[1].iov_base = &pm;
-       iov[1].iov_len = sizeof(pm);
-       tlen = sizeof(nlh) + sizeof(pm);
-       nvecs = 2;
-       if (data_len && buf) {
-               iov[2].iov_base = buf;
-               iov[2].iov_len = data_len;
-               tlen += data_len;
-               nvecs++;
-       }
-       msg.msg_name = (void *)&h->peer;
-       msg.msg_namelen = sizeof(h->peer);
-       msg.msg_iov = iov;
-       msg.msg_iovlen = nvecs;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = 0;
-       nlh.nlmsg_len = tlen;
-       return ipq_netlink_sendmsg(h, &msg, 0);
-}
-
-/* Not implemented yet */
-int ipq_ctl(const struct ipq_handle *h, int request, ...)
-{
-       return 1;
-}
-
-char *ipq_errstr(void)
-{
-       return ipq_strerror(ipq_errno);
-}
-
-void ipq_perror(const char *s)
-{
-       if (s)
-               fputs(s, stderr);
-       else
-               fputs("ERROR", stderr);
-       if (ipq_errno)
-               fprintf(stderr, ": %s", ipq_errstr());
-       if (errno)
-               fprintf(stderr, ": %s", strerror(errno));
-       fputc('\n', stderr);
-}
diff --git a/libiptc2/.#libiptc.c.1.40 b/libiptc2/.#libiptc.c.1.40
deleted file mode 100644 (file)
index ce4af9b..0000000
+++ /dev/null
@@ -1,1972 +0,0 @@
-/* Library which manipulates firewall rules.  Version $Revision: 1.40 $ */
-
-/* Architecture of firewall rules is as follows:
- *
- * Chains go INPUT, FORWARD, OUTPUT then user chains.
- * Each user chain starts with an ERROR node.
- * Every chain ends with an unconditional jump: a RETURN for user chains,
- * and a POLICY for built-ins.
- */
-
-/* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
- * COPYING for details). 
- * (C) 2000-2003 by the Netfilter Core Team <coreteam@netfilter.org>
- *
- * 2003-Jun-20: Harald Welte <laforge@netfilter.org>:
- *     - Reimplementation of chain cache to use offsets instead of entries
- * 2003-Jun-23: Harald Welte <laforge@netfilter.org>:
- *     - speed optimization, sponsored by Astaro AG (http://www.astaro.com/)
- *       don't rebuild the chain cache after every operation, instead fix it
- *       up after a ruleset change.  
- * 2003-Jun-30: Harald Welte <laforge@netfilter.org>:
- *     - total reimplementation
- */
-#include "linux_listhelp.h"
-
-#ifndef IPT_LIB_DIR
-#define IPT_LIB_DIR "/usr/lib/iptables"
-#endif
-
-static int sockfd = -1;
-static void *iptc_fn = NULL;
-
-static const char *hooknames[]
-= { [HOOK_PRE_ROUTING]  "PREROUTING",
-    [HOOK_LOCAL_IN]     "INPUT",
-    [HOOK_FORWARD]      "FORWARD",
-    [HOOK_LOCAL_OUT]    "OUTPUT",
-    [HOOK_POST_ROUTING] "POSTROUTING",
-#ifdef HOOK_DROPPING
-    [HOOK_DROPPING]    "DROPPING"
-#endif
-};
-
-struct counter_map
-{
-       enum {
-               COUNTER_MAP_NOMAP,
-               COUNTER_MAP_NORMAL_MAP,
-               COUNTER_MAP_ZEROED,
-               COUNTER_MAP_SET
-       } maptype;
-       unsigned int mappos;
-};
-
-/* Convenience structures */
-struct ipt_error_target
-{
-       STRUCT_ENTRY_TARGET t;
-       char error[TABLE_MAXNAMELEN];
-};
-
-struct rule_head
-{
-       struct list_head list;          /* list of rules in chain */
-       
-       struct chain_head *chain;       /* we're part of this chain */
-       struct rule_head *target;       /* target of this rule, in case
-                                          it is a jump rule */
-
-
-       unsigned int size;              /* size of rule */
-       STRUCT_ENTRY *entry_blob;       /* pointer to entry in blob */
-       STRUCT_ENTRY entry[0];
-};
-
-struct chain_head
-{
-       struct list_head list;
-
-       char name[TABLE_MAXNAMELEN];
-       unsigned int hooknum;
-       struct list_head rules;
-};
-
-STRUCT_TC_HANDLE
-{
-       /* Have changes been made? */
-       int changed;
-
-       /* linked list of chains in this table */
-       struct list_head chains;
-       
-       /* current position of first_chain() / next_chain() */
-       struct chain_head *chain_iterator_cur;
-
-       /* current position of first_rule() / next_rule() */
-       struct rule_head *rule_iterator_cur;
-
-       struct counter_map *counter_map;
-
-       /* the structure we receive from getsockopt() */
-       STRUCT_GETINFO info;
-
-       /* Array of hook names */
-       const char **hooknames;
-#if 0
-       /* Size in here reflects original state. */
-
-
-       /* Cached position of chain heads (NULL = no cache). */
-       unsigned int cache_num_chains;
-       unsigned int cache_num_builtins;
-       struct chain_cache *cache_chain_heads;
-
-       /* Chain iterator: current chain cache entry. */
-       struct chain_cache *cache_chain_iteration;
-
-       /* Rule iterator: terminal rule */
-       STRUCT_ENTRY *cache_rule_end;
-
-       /* Number in here reflects current state. */
-       unsigned int new_number;
-#endif
-       STRUCT_GET_ENTRIES entries;
-};
-
-static void
-set_changed(TC_HANDLE_T h)
-{
-       h->changed = 1;
-}
-
-#ifdef IPTC_DEBUG
-static void do_check(TC_HANDLE_T h, unsigned int line);
-#define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0)
-#else
-#define CHECK(h)
-#endif
-
-static struct rule_head *ruleh_alloc(unsigned int size)
-{
-       struct rule_head *ruleh = malloc(sizeof(*ruleh)+size);
-       if (!ruleh)
-               return NULL;
-       
-       memset(ruleh, 0, sizeof(*ruleh)+size);
-       ruleh->size = size;
-
-       return ruleh;
-}
-
-static void ruleh_free(struct rule_head *ruleh)
-{
-       list_del(&ruleh->list);
-       free(ruleh);
-}
-
-static struct rule_head *ruleh_get_n(struct chain_head *chain, int num)
-{
-       return NULL;
-}
-
-static struct chain_head *chainh_alloc(TC_HANDLE_T h, const char *name)
-{
-       struct chain_head *chainh = malloc(sizeof(*chainh));
-       if (!chainh)
-               return NULL;
-
-       memset(chainh, 0, sizeof(*chainh));
-       strncpy(chainh->name, name, sizeof(&chainh->name));
-       list_append(&chainh->list, &h->chains);
-
-       return chainh;
-}
-
-static void
-chainh_free(struct chain_head *chainh)
-{
-       /* FIXME */
-       struct list_head *cur_item, *item2;
-
-       list_for_each_safe(cur_item, item2, &chainh->rules) {
-               struct rule_head *ruleh = list_entry(cur_item, 
-                                                    struct rule_head,
-                                                   list);
-               ruleh_free(ruleh);
-       }
-
-       list_del(&chainh->list);
-}
-
-#if 0
-static inline int
-get_number(const STRUCT_ENTRY *i,
-          const STRUCT_ENTRY *seek,
-          unsigned int *pos)
-{
-       if (i == seek)
-               return 1;
-       (*pos)++;
-       return 0;
-}
-#endif
-
-static struct chain_head *
-chainh_find(TC_HANDLE_T h, const IPT_CHAINLABEL name)
-{
-       struct list_head *cur;
-
-       list_for_each(cur, &h->chains) {
-               struct chain_head *ch = list_entry(cur, struct chain_head, 
-                                                  list);
-               if (!strcmp(name, ch->name))
-                       return ch;
-       }
-       return NULL;
-}
-
-static inline unsigned long
-entry2offset(const TC_HANDLE_T h, const STRUCT_ENTRY *e)
-{
-       return (void *)e - (void *)h->entries.entrytable;
-}
-
-#if 0
-static unsigned int
-entry2index(const TC_HANDLE_T h, const STRUCT_ENTRY *seek)
-{
-       unsigned int pos = 0;
-
-       if (ENTRY_ITERATE(h->entries.entrytable, h->entries.size,
-                         get_number, seek, &pos) == 0) {
-               fprintf(stderr, "ERROR: offset %i not an entry!\n",
-                       (char *)seek - (char *)h->entries.entrytable);
-               abort();
-       }
-       return pos;
-}
-
-static inline int
-get_entry_n(STRUCT_ENTRY *i,
-           unsigned int number,
-           unsigned int *pos,
-           STRUCT_ENTRY **pe)
-{
-       if (*pos == number) {
-               *pe = i;
-               return 1;
-       }
-       (*pos)++;
-       return 0;
-}
-
-static STRUCT_ENTRY *
-index2entry(TC_HANDLE_T h, unsigned int index)
-{
-       unsigned int pos = 0;
-       STRUCT_ENTRY *ret = NULL;
-
-       ENTRY_ITERATE(h->entries.entrytable, h->entries.size,
-                     get_entry_n, index, &pos, &ret);
-
-       return ret;
-}
-
-static inline STRUCT_ENTRY *
-get_entry(TC_HANDLE_T h, unsigned int offset)
-{
-       return (STRUCT_ENTRY *)((char *)h->entries.entrytable + offset);
-}
-
-
-static inline unsigned long
-index2offset(TC_HANDLE_T h, unsigned int index)
-{
-       return entry2offset(h, index2entry(h, index));
-}
-
-static inline STRUCT_ENTRY *
-offset2entry(TC_HANDLE_T h, unsigned int offset)
-{
-       return (STRUCT_ENTRY *) ((void *)h->entries.entrytable+offset);
-}
-
-static inline unsigned int
-offset2index(const TC_HANDLE_T h, unsigned int offset)
-{
-       return entry2index(h, offset2entry(h, offset));
-}
-
-
-static const char *
-get_errorlabel(TC_HANDLE_T h, unsigned int offset)
-{
-       STRUCT_ENTRY *e;
-
-       e = get_entry(h, offset);
-       if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) != 0) {
-               fprintf(stderr, "ERROR: offset %u not an error node!\n",
-                       offset);
-               abort();
-       }
-
-       return (const char *)GET_TARGET(e)->data;
-}
-#endif
-
-/* Allocate handle of given size */
-static TC_HANDLE_T
-alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
-{
-       size_t len;
-       TC_HANDLE_T h;
-
-       len = sizeof(STRUCT_TC_HANDLE)
-               + size
-               + num_rules * sizeof(struct counter_map);
-
-       if ((h = malloc(len)) == NULL) {
-               errno = ENOMEM;
-               return NULL;
-       }
-
-       h->changed = 0;
-
-       h->counter_map = (void *)h
-               + sizeof(STRUCT_TC_HANDLE)
-               + size;
-       strcpy(h->info.name, tablename);
-       strcpy(h->entries.name, tablename);
-       INIT_LIST_HEAD(&h->chains);
-
-       return h;
-}
-
-struct rule_head *
-append_entrycopy(STRUCT_ENTRY *e, struct chain_head *chain)
-{
-       struct rule_head *ruleh = ruleh_alloc(e->next_offset);
-       if (!ruleh)
-               return NULL;
-       
-       memcpy(&ruleh->entry, e, e->next_offset);
-       ruleh->chain = chain;
-       ruleh->entry_blob = e;
-       list_append(&ruleh->list, &chain->rules);
-
-       return ruleh;
-}
-
-
-/* have to return 0 on success, bcf ENTRY_ITERATE */
-static inline int 
-parse_entry(STRUCT_ENTRY *e, TC_HANDLE_T h, struct chain_head **curchain)
-{
-       int i;
-       union tgt_u {
-               STRUCT_ENTRY_TARGET ent;
-               STRUCT_STANDARD_TARGET std;
-               struct ipt_error_target err;
-       } *tgt;
-
-       tgt = (union tgt_u *) GET_TARGET(e);
-
-       if (e->target_offset == sizeof(STRUCT_ENTRY)
-           && (strcmp(tgt->ent.u.user.name, IPT_STANDARD_TARGET) == 0)) {
-               /* jump to somewhere else */
-               append_entrycopy(e, *curchain);
-               /* FIXME: */
-       } else if (e->target_offset == sizeof(STRUCT_ENTRY)
-                  && e->next_offset == sizeof(STRUCT_ENTRY)
-                                       + ALIGN(sizeof(struct ipt_error_target))
-                  && !strcmp(tgt->ent.u.user.name, ERROR_TARGET)) {
-               /* chain head */
-               *curchain = chainh_find(h, tgt->err.error);
-               if (*curchain) {
-                       /* FIXME: error handling */
-                       return 1;
-               }
-
-               *curchain = chainh_alloc(h, tgt->err.error);
-               /* FIXME: error handling */
-               append_entrycopy(e, *curchain);
-       } else if (e->target_offset == sizeof(STRUCT_ENTRY)
-                  && e->next_offset == sizeof(STRUCT_ENTRY)
-                                       + ALIGN(sizeof(STRUCT_STANDARD_TARGET))
-                  && tgt->std.verdict == RETURN) {
-               /* chain end */
-               append_entrycopy(e, *curchain);
-               *curchain = NULL;
-       } else {
-               /* normal rule */
-               append_entrycopy(e, *curchain);
-       }
-
-       /* iterate over hook_entries, needed to connect builtin
-        * chains with hook numbers */
-       for (i = 0; i < NUMHOOKS; i++) {
-               if (!(h->info.valid_hooks & (1 << i)))
-                       continue;
-               if (h->info.hook_entry[i] == entry2offset(h, e)) {
-                       /* found hook entry point */
-                       if (*curchain)
-                               (*curchain)->hooknum = i;
-               }
-               if (h->info.underflow[i] == entry2offset(h, e)) {
-                       /* found underflow point */
-               }
-       }
-
-       return 0;
-}
-
-static int parse_ruleset(TC_HANDLE_T h)
-{
-       struct chain_head *curchain;
-       
-       /* iterate over ruleset; create linked list of rule_head/chain_head */
-       if (ENTRY_ITERATE(h->entries.entrytable, h->entries.size, 
-                     parse_entry, h, &curchain)) {
-               /* some error happened while iterating */
-               return 0;
-       }
-
-       return 1;
-}
-
-TC_HANDLE_T
-TC_INIT(const char *tablename)
-{
-       TC_HANDLE_T h;
-       STRUCT_GETINFO info;
-       unsigned int i;
-       int tmp;
-       socklen_t s;
-
-       iptc_fn = TC_INIT;
-
-       if (sockfd != -1) {
-               close(sockfd);
-               sockfd = -1;
-       }
-
-       if (strlen(tablename) >= TABLE_MAXNAMELEN) {
-               errno = EINVAL;
-               return NULL;
-       }
-       
-       sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
-       if (sockfd < 0)
-               return NULL;
-
-       s = sizeof(info);
-
-       strcpy(info.name, tablename);
-       if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0)
-               return NULL;
-
-       if ((h = alloc_handle(info.name, info.size, info.num_entries))
-           == NULL) {
-               close(sockfd);
-               sockfd = -1;
-               return NULL;
-       }
-
-/* Too hard --RR */
-#if 0
-       sprintf(pathname, "%s/%s", IPT_LIB_DIR, info.name);
-       dynlib = dlopen(pathname, RTLD_NOW);
-       if (!dynlib) {
-               errno = ENOENT;
-               return NULL;
-       }
-       h->hooknames = dlsym(dynlib, "hooknames");
-       if (!h->hooknames) {
-               errno = ENOENT;
-               return NULL;
-       }
-#else
-       h->hooknames = hooknames;
-#endif
-
-       /* Initialize current state */
-       h->info = info;
-       //h->new_number = h->info.num_entries;
-       for (i = 0; i < h->info.num_entries; i++)
-               h->counter_map[i]
-                       = ((struct counter_map){COUNTER_MAP_NORMAL_MAP, i});
-
-       h->entries.size = h->info.size;
-
-       tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size;
-
-       if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, &h->entries,
-                      &tmp) < 0) {
-               close(sockfd);
-               sockfd = -1;
-               free(h);
-               return NULL;
-       }
-
-       CHECK(h);
-       parse_ruleset(h);
-
-       return h;
-}
-
-void
-TC_FREE(TC_HANDLE_T *h)
-{
-       struct list_head *cur_item, *item2;
-
-       close(sockfd);
-       sockfd = -1;
-
-       /* free all chains */
-       list_for_each_safe(cur_item, item2, (*h)->chains.next) {
-               struct chain_head *chead = list_entry(cur_item,
-                                                     struct chain_head,
-                                                     list);
-               chainh_free(chead);
-       }
-
-       /* FIXME: free all other ressources we might be using */
-
-       free(*h);
-       *h = NULL;
-}
-
-static inline int
-print_match(const STRUCT_ENTRY_MATCH *m)
-{
-       printf("Match name: `%s'\n", m->u.user.name);
-       return 0;
-}
-
-static int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle);
-#if 0
-void
-TC_DUMP_ENTRIES(const TC_HANDLE_T handle)
-{
-       CHECK(handle);
-
-       printf("libiptc v%s.  %u entries, %u bytes.\n",
-              IPTABLES_VERSION,
-              handle->new_number, handle->entries.size);
-       printf("Table `%s'\n", handle->info.name);
-       printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n",
-              handle->info.hook_entry[HOOK_PRE_ROUTING],
-              handle->info.hook_entry[HOOK_LOCAL_IN],
-              handle->info.hook_entry[HOOK_FORWARD],
-              handle->info.hook_entry[HOOK_LOCAL_OUT],
-              handle->info.hook_entry[HOOK_POST_ROUTING]);
-       printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n",
-              handle->info.underflow[HOOK_PRE_ROUTING],
-              handle->info.underflow[HOOK_LOCAL_IN],
-              handle->info.underflow[HOOK_FORWARD],
-              handle->info.underflow[HOOK_LOCAL_OUT],
-              handle->info.underflow[HOOK_POST_ROUTING]);
-
-       ENTRY_ITERATE(handle->entries.entrytable, handle->entries.size,
-                     dump_entry, handle);
-}
-
-/* Returns 0 if not hook entry, else hooknumber + 1 */
-static inline unsigned int
-is_hook_entry(STRUCT_ENTRY *e, TC_HANDLE_T h)
-{
-       unsigned int i;
-
-       for (i = 0; i < NUMHOOKS; i++) {
-               if ((h->info.valid_hooks & (1 << i))
-                   && get_entry(h, h->info.hook_entry[i]) == e)
-                       return i+1;
-       }
-       return 0;
-}
-
-
-static int alphasort(const void *a, const void *b)
-{
-       return strcmp(((struct chain_cache *)a)->name,
-                     ((struct chain_cache *)b)->name);
-}
-#endif
-
-/* Returns chain head if found, otherwise NULL. */
-static struct chain_head *
-find_label(const char *name, TC_HANDLE_T handle)
-{
-       struct list_head *pos;
-
-       if (list_empty(&handle->chains))
-               return NULL;
-
-       list_for_each(pos, &handle->chains) {
-               struct chain_head *c = list_entry(pos, struct chain_head, list);
-               if (!strcmp(c->name, name))
-                       return c;
-       }
-
-       return NULL;
-}
-
-/* Does this chain exist? */
-int TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle)
-{
-       return find_label(chain, handle) != NULL;
-}
-
-#if 0
-/* Returns the position of the final (ie. unconditional) element. */
-static unsigned int
-get_chain_end(const TC_HANDLE_T handle, unsigned int start)
-{
-       unsigned int last_off, off;
-       STRUCT_ENTRY *e;
-
-       last_off = start;
-       e = get_entry(handle, start);
-
-       /* Terminate when we meet a error label or a hook entry. */
-       for (off = start + e->next_offset;
-            off < handle->entries.size;
-            last_off = off, off += e->next_offset) {
-               STRUCT_ENTRY_TARGET *t;
-               unsigned int i;
-
-               e = get_entry(handle, off);
-
-               /* We hit an entry point. */
-               for (i = 0; i < NUMHOOKS; i++) {
-                       if ((handle->info.valid_hooks & (1 << i))
-                           && off == handle->info.hook_entry[i])
-                               return last_off;
-               }
-
-               /* We hit a user chain label */
-               t = GET_TARGET(e);
-               if (strcmp(t->u.user.name, ERROR_TARGET) == 0)
-                       return last_off;
-       }
-       /* SHOULD NEVER HAPPEN */
-       fprintf(stderr, "ERROR: Off end (%u) of chain from %u!\n",
-               handle->entries.size, off);
-       abort();
-}
-#endif
-
-/* Iterator functions to run through the chains. */
-const char *
-TC_FIRST_CHAIN(TC_HANDLE_T *handle)
-{
-       struct chain_head *firsthead = list_entry((*handle)->chains.next,
-                                                  struct chain_head, list);
-       (*handle)->chain_iterator_cur = firsthead;
-
-       return firsthead->name;
-}
-
-/* Iterator functions to run through the chains.  Returns NULL at end. */
-const char *
-TC_NEXT_CHAIN(TC_HANDLE_T *handle)
-{
-       struct chain_head *next = list_entry(&(*handle)->chain_iterator_cur->list.next, struct chain_head, list);
-       (*handle)->chain_iterator_cur = next;
-
-       if (&next->list == &(*handle)->chains)
-               return NULL;
-
-       return next->name;
-}
-
-/* Get first rule in the given chain: NULL for empty chain. */
-const STRUCT_ENTRY *
-TC_FIRST_RULE(const char *chain, TC_HANDLE_T *handle)
-{
-       struct chain_head *c;
-       struct rule_head *r;
-
-       c = find_label(chain, *handle);
-       if (!c) {
-               errno = ENOENT;
-               return NULL;
-       }
-
-       /* Empty chain: single return/policy rule */
-       if (list_empty(&c->rules))
-               return NULL;
-
-       r = list_entry(c->rules.next, struct rule_head, list);
-       (*handle)->rule_iterator_cur = r;
-
-       return r->entry;
-}
-
-/* Returns NULL when rules run out. */
-const STRUCT_ENTRY *
-TC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle)
-{
-       struct rule_head *r = list_entry((*handle)->rule_iterator_cur->list.next, struct rule_head, list);
-
-       if (&r->list == &r->chain->rules)
-               return NULL;
-
-       /* NOTE: prev is without any influence ! */
-       return r->entry;
-}
-
-#if 0
-/* How many rules in this chain? */
-unsigned int
-TC_NUM_RULES(const char *chain, TC_HANDLE_T *handle)
-{
-       unsigned int off = 0;
-       STRUCT_ENTRY *start, *end;
-
-       CHECK(*handle);
-       if (!find_label(&off, chain, *handle)) {
-               errno = ENOENT;
-               return (unsigned int)-1;
-       }
-
-       start = get_entry(*handle, off);
-       end = get_entry(*handle, get_chain_end(*handle, off));
-
-       return entry2index(*handle, end) - entry2index(*handle, start);
-}
-
-/* Get n'th rule in this chain. */
-const STRUCT_ENTRY *TC_GET_RULE(const char *chain,
-                               unsigned int n,
-                               TC_HANDLE_T *handle)
-{
-       unsigned int pos = 0, chainindex;
-
-       CHECK(*handle);
-       if (!find_label(&pos, chain, *handle)) {
-               errno = ENOENT;
-               return NULL;
-       }
-
-       chainindex = entry2index(*handle, get_entry(*handle, pos));
-
-       return index2entry(*handle, chainindex + n);
-}
-#endif
-
-static const char *
-target_name(TC_HANDLE_T handle, const STRUCT_ENTRY *ce)
-{
-       int spos;
-       unsigned int labelidx;
-       STRUCT_ENTRY *jumpto;
-
-       /* To avoid const warnings */
-       STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce;
-
-       if (strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET) != 0)
-               return GET_TARGET(e)->u.user.name;
-
-       /* Standard target: evaluate */
-       spos = *(int *)GET_TARGET(e)->data;
-       if (spos < 0) {
-               if (spos == RETURN)
-                       return LABEL_RETURN;
-               else if (spos == -NF_ACCEPT-1)
-                       return LABEL_ACCEPT;
-               else if (spos == -NF_DROP-1)
-                       return LABEL_DROP;
-               else if (spos == -NF_QUEUE-1)
-                       return LABEL_QUEUE;
-
-               fprintf(stderr, "ERROR: off %lu/%u not a valid target (%d)\n",
-                       entry2offset(handle, e), handle->entries.size,
-                       spos);
-               abort();
-       }
-
-       jumpto = get_entry(handle, spos);
-
-       /* Fall through rule */
-       if (jumpto == (void *)e + e->next_offset)
-               return "";
-
-       /* Must point to head of a chain: ie. after error rule */
-       /* FIXME: this needs to deal with internal jump targets */
-       labelidx = entry2index(handle, jumpto) - 1;
-       return get_errorlabel(handle, index2offset(handle, labelidx));
-}
-
-/* Returns a pointer to the target name of this position. */
-const char *TC_GET_TARGET(const STRUCT_ENTRY *e,
-                         TC_HANDLE_T *handle)
-{
-       return target_name(*handle, e);
-}
-
-/* Is this a built-in chain?  Actually returns hook + 1. */
-int
-TC_BUILTIN(const char *chain, const TC_HANDLE_T handle)
-{
-       unsigned int i;
-
-       for (i = 0; i < NUMHOOKS; i++) {
-               if ((handle->info.valid_hooks & (1 << i))
-                   && handle->hooknames[i]
-                   && strcmp(handle->hooknames[i], chain) == 0)
-                       return i+1;
-       }
-       return 0;
-}
-
-/* Get the policy of a given built-in chain */
-const char *
-TC_GET_POLICY(const char *chain,
-             STRUCT_COUNTERS *counters,
-             TC_HANDLE_T *handle)
-{
-       unsigned int start;
-       STRUCT_ENTRY *e;
-       int hook;
-
-       hook = TC_BUILTIN(chain, *handle);
-       if (hook != 0)
-               start = (*handle)->info.hook_entry[hook-1];
-       else
-               return NULL;
-
-       e = get_entry(*handle, get_chain_end(*handle, start));
-       *counters = e->counters;
-
-       return target_name(*handle, e);
-}
-
-static int
-correct_verdict(STRUCT_ENTRY *e,
-               char *base,
-               unsigned int offset, int delta_offset)
-{
-       STRUCT_STANDARD_TARGET *t = (void *)GET_TARGET(e);
-       unsigned int curr = (char *)e - base;
-
-       /* Trap: insert of fall-through rule.  Don't change fall-through
-          verdict to jump-over-next-rule. */
-       if (strcmp(t->target.u.user.name, STANDARD_TARGET) == 0
-           && t->verdict > (int)offset
-           && !(curr == offset &&
-                t->verdict == curr + e->next_offset)) {
-               t->verdict += delta_offset;
-       }
-
-       return 0;
-}
-
-/* Adjusts standard verdict jump positions after an insertion/deletion. */
-static int
-set_verdict(unsigned int offset, int delta_offset, TC_HANDLE_T *handle)
-{
-       ENTRY_ITERATE((*handle)->entries.entrytable,
-                     (*handle)->entries.size,
-                     correct_verdict, (char *)(*handle)->entries.entrytable,
-                     offset, delta_offset);
-
-       set_changed(*handle);
-       return 1;
-}
-
-/* If prepend is set, then we are prepending to a chain: if the
- * insertion position is an entry point, keep the entry point. */
-static int
-insert_rules(unsigned int num_rules, unsigned int rules_size,
-            const STRUCT_ENTRY *insert,
-            unsigned int offset, unsigned int num_rules_offset,
-            int prepend,
-            TC_HANDLE_T *handle)
-{
-       TC_HANDLE_T newh;
-       STRUCT_GETINFO newinfo;
-       unsigned int i;
-
-       if (offset >= (*handle)->entries.size) {
-               errno = EINVAL;
-               return 0;
-       }
-
-       newinfo = (*handle)->info;
-
-       /* Fix up entry points. */
-       for (i = 0; i < NUMHOOKS; i++) {
-               /* Entry points to START of chain, so keep same if
-                   inserting on at that point. */
-               if ((*handle)->info.hook_entry[i] > offset)
-                       newinfo.hook_entry[i] += rules_size;
-
-               /* Underflow always points to END of chain (policy),
-                  so if something is inserted at same point, it
-                  should be advanced. */
-               if ((*handle)->info.underflow[i] >= offset)
-                       newinfo.underflow[i] += rules_size;
-       }
-
-       newh = alloc_handle((*handle)->info.name,
-                           (*handle)->entries.size + rules_size,
-                           (*handle)->new_number + num_rules);
-       if (!newh)
-               return 0;
-       newh->info = newinfo;
-
-       /* Copy pre... */
-       memcpy(newh->entries.entrytable, (*handle)->entries.entrytable,offset);
-       /* ... Insert new ... */
-       memcpy((char *)newh->entries.entrytable + offset, insert, rules_size);
-       /* ... copy post */
-       memcpy((char *)newh->entries.entrytable + offset + rules_size,
-              (char *)(*handle)->entries.entrytable + offset,
-              (*handle)->entries.size - offset);
-
-       /* Move counter map. */
-       /* Copy pre... */
-       memcpy(newh->counter_map, (*handle)->counter_map,
-              sizeof(struct counter_map) * num_rules_offset);
-       /* ... copy post */
-       memcpy(newh->counter_map + num_rules_offset + num_rules,
-              (*handle)->counter_map + num_rules_offset,
-              sizeof(struct counter_map) * ((*handle)->new_number
-                                            - num_rules_offset));
-       /* Set intermediates to no counter copy */
-       for (i = 0; i < num_rules; i++)
-               newh->counter_map[num_rules_offset+i]
-                       = ((struct counter_map){ COUNTER_MAP_SET, 0 });
-
-       newh->new_number = (*handle)->new_number + num_rules;
-       newh->entries.size = (*handle)->entries.size + rules_size;
-       newh->hooknames = (*handle)->hooknames;
-
-       if ((*handle)->cache_chain_heads)
-               free((*handle)->cache_chain_heads);
-       free(*handle);
-       *handle = newh;
-
-       return set_verdict(offset, rules_size, handle);
-}
-
-static int
-delete_rules(unsigned int num_rules, unsigned int rules_size,
-            unsigned int offset, unsigned int num_rules_offset,
-            TC_HANDLE_T *handle)
-{
-       unsigned int i;
-
-       if (offset + rules_size > (*handle)->entries.size) {
-               errno = EINVAL;
-               return 0;
-       }
-
-       /* Fix up entry points. */
-       for (i = 0; i < NUMHOOKS; i++) {
-               /* In practice, we never delete up to a hook entry,
-                  since the built-in chains are always first,
-                  so these two are never equal */
-               if ((*handle)->info.hook_entry[i] >= offset + rules_size)
-                       (*handle)->info.hook_entry[i] -= rules_size;
-               else if ((*handle)->info.hook_entry[i] > offset) {
-                       fprintf(stderr, "ERROR: Deleting entry %u %u %u\n",
-                               i, (*handle)->info.hook_entry[i], offset);
-                       abort();
-               }
-
-               /* Underflow points to policy (terminal) rule in
-                   built-in, so sequality is valid here (when deleting
-                   the last rule). */
-               if ((*handle)->info.underflow[i] >= offset + rules_size)
-                       (*handle)->info.underflow[i] -= rules_size;
-               else if ((*handle)->info.underflow[i] > offset) {
-                       fprintf(stderr, "ERROR: Deleting uflow %u %u %u\n",
-                               i, (*handle)->info.underflow[i], offset);
-                       abort();
-               }
-       }
-
-       /* Move the rules down. */
-       memmove((char *)(*handle)->entries.entrytable + offset,
-               (char *)(*handle)->entries.entrytable + offset + rules_size,
-               (*handle)->entries.size - (offset + rules_size));
-
-       /* Move the counter map down. */
-       memmove(&(*handle)->counter_map[num_rules_offset],
-               &(*handle)->counter_map[num_rules_offset + num_rules],
-               sizeof(struct counter_map)
-               * ((*handle)->new_number - (num_rules + num_rules_offset)));
-
-       /* Fix numbers */
-       (*handle)->new_number -= num_rules;
-       (*handle)->entries.size -= rules_size;
-
-       return set_verdict(offset, -(int)rules_size, handle);
-}
-
-static int
-standard_map(STRUCT_ENTRY *e, int verdict)
-{
-       STRUCT_STANDARD_TARGET *t;
-
-       t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
-
-       if (t->target.u.target_size
-           != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) {
-               errno = EINVAL;
-               return 0;
-       }
-       /* memset for memcmp convenience on delete/replace */
-       memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
-       strcpy(t->target.u.user.name, STANDARD_TARGET);
-       t->verdict = verdict;
-
-       return 1;
-}
-
-static int
-map_target(const TC_HANDLE_T handle,
-          STRUCT_ENTRY *e,
-          unsigned int offset,
-          STRUCT_ENTRY_TARGET *old)
-{
-       STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
-
-       /* Save old target (except data, which we don't change, except for
-          standard case, where we don't care). */
-       *old = *t;
-
-       /* Maybe it's empty (=> fall through) */
-       if (strcmp(t->u.user.name, "") == 0)
-               return standard_map(e, offset + e->next_offset);
-       /* Maybe it's a standard target name... */
-       else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0)
-               return standard_map(e, -NF_ACCEPT - 1);
-       else if (strcmp(t->u.user.name, LABEL_DROP) == 0)
-               return standard_map(e, -NF_DROP - 1);
-       else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0)
-               return standard_map(e, -NF_QUEUE - 1);
-       else if (strcmp(t->u.user.name, LABEL_RETURN) == 0)
-               return standard_map(e, RETURN);
-       else if (TC_BUILTIN(t->u.user.name, handle)) {
-               /* Can't jump to builtins. */
-               errno = EINVAL;
-               return 0;
-       } else {
-               /* Maybe it's an existing chain name. */
-               struct chain_cache *c;
-
-               c = find_label(t->u.user.name, handle);
-               if (c)
-                       return standard_map(e, c->start_off);
-       }
-
-       /* Must be a module?  If not, kernel will reject... */
-       /* memset to all 0 for your memcmp convenience. */
-       memset(t->u.user.name + strlen(t->u.user.name),
-              0,
-              FUNCTION_MAXNAMELEN - strlen(t->u.user.name));
-       return 1;
-}
-
-static void
-unmap_target(STRUCT_ENTRY *e, STRUCT_ENTRY_TARGET *old)
-{
-       STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
-
-       /* Save old target (except data, which we don't change, except for
-          standard case, where we don't care). */
-       *t = *old;
-}
-
-/* Insert the entry `fw' in chain `chain' into position `rulenum'. */
-int
-TC_INSERT_ENTRY(const IPT_CHAINLABEL chain,
-               const STRUCT_ENTRY *e,
-               unsigned int rulenum,
-               TC_HANDLE_T *handle)
-{
-       unsigned int chainindex, offset;
-       STRUCT_ENTRY_TARGET old;
-       struct chain_cache *c;
-       STRUCT_ENTRY *tmp;
-       int ret;
-
-       iptc_fn = TC_INSERT_ENTRY;
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       chainindex = offset2index(*handle, c->start_off);
-
-       tmp = index2entry(*handle, chainindex + rulenum);
-       if (!tmp || tmp > offset2entry(*handle, c->end_off)) {
-               errno = E2BIG;
-               return 0;
-       }
-       offset = index2offset(*handle, chainindex + rulenum);
-
-       /* Mapping target actually alters entry, but that's
-           transparent to the caller. */
-       if (!map_target(*handle, (STRUCT_ENTRY *)e, offset, &old))
-               return 0;
-
-       ret = insert_rules(1, e->next_offset, e, offset,
-                          chainindex + rulenum, rulenum == 0, handle);
-       unmap_target((STRUCT_ENTRY *)e, &old);
-       return ret;
-}
-
-/* Atomically replace rule `rulenum' in `chain' with `fw'. */
-int
-TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain,
-                const STRUCT_ENTRY *e,
-                unsigned int rulenum,
-                TC_HANDLE_T *handle)
-{
-       unsigned int chainindex, offset;
-       STRUCT_ENTRY_TARGET old;
-       struct chain_cache *c;
-       STRUCT_ENTRY *tmp;
-       int ret;
-
-       iptc_fn = TC_REPLACE_ENTRY;
-
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       chainindex = offset2index(*handle, c->start_off);
-
-       tmp = index2entry(*handle, chainindex + rulenum);
-       if (!tmp || tmp >= offset2entry(*handle, c->end_off)) {
-               errno = E2BIG;
-               return 0;
-       }
-
-       offset = index2offset(*handle, chainindex + rulenum);
-       /* Replace = delete and insert. */
-       if (!delete_rules(1, get_entry(*handle, offset)->next_offset,
-                         offset, chainindex + rulenum, handle))
-               return 0;
-
-       if (!map_target(*handle, (STRUCT_ENTRY *)e, offset, &old))
-               return 0;
-
-       ret = insert_rules(1, e->next_offset, e, offset,
-                          chainindex + rulenum, 1, handle);
-       unmap_target((STRUCT_ENTRY *)e, &old);
-       return ret;
-}
-
-/* Append entry `fw' to chain `chain'.  Equivalent to insert with
-   rulenum = length of chain. */
-int
-TC_APPEND_ENTRY(const IPT_CHAINLABEL chain,
-               const STRUCT_ENTRY *e,
-               TC_HANDLE_T *handle)
-{
-       struct chain_cache *c;
-       STRUCT_ENTRY_TARGET old;
-       int ret;
-
-       iptc_fn = TC_APPEND_ENTRY;
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       if (!map_target(*handle, (STRUCT_ENTRY *)e,
-                       c->end_off, &old))
-               return 0;
-
-       ret = insert_rules(1, e->next_offset, e, c->end_off, 
-                          offset2index(*handle, c->end_off), 0, handle);
-       unmap_target((STRUCT_ENTRY *)e, &old);
-       return ret;
-}
-
-static inline int
-match_different(const STRUCT_ENTRY_MATCH *a,
-               const unsigned char *a_elems,
-               const unsigned char *b_elems,
-               unsigned char **maskptr)
-{
-       const STRUCT_ENTRY_MATCH *b;
-       unsigned int i;
-
-       /* Offset of b is the same as a. */
-       b = (void *)b_elems + ((unsigned char *)a - a_elems);
-
-       if (a->u.match_size != b->u.match_size)
-               return 1;
-
-       if (strcmp(a->u.user.name, b->u.user.name) != 0)
-               return 1;
-
-       *maskptr += ALIGN(sizeof(*a));
-
-       for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++)
-               if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
-                       return 1;
-       *maskptr += i;
-       return 0;
-}
-
-static inline int
-target_different(const unsigned char *a_targdata,
-                const unsigned char *b_targdata,
-                unsigned int tdatasize,
-                const unsigned char *mask)
-{
-       unsigned int i;
-       for (i = 0; i < tdatasize; i++)
-               if (((a_targdata[i] ^ b_targdata[i]) & mask[i]) != 0)
-                       return 1;
-
-       return 0;
-}
-
-static int
-is_same(const STRUCT_ENTRY *a,
-       const STRUCT_ENTRY *b,
-       unsigned char *matchmask);
-
-/* Delete the first rule in `chain' which matches `fw'. */
-int
-TC_DELETE_ENTRY(const IPT_CHAINLABEL chain,
-               const STRUCT_ENTRY *origfw,
-               unsigned char *matchmask,
-               TC_HANDLE_T *handle)
-{
-       unsigned int offset;
-       struct chain_cache *c;
-       STRUCT_ENTRY *e, *fw;
-
-       iptc_fn = TC_DELETE_ENTRY;
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       fw = malloc(origfw->next_offset);
-       if (fw == NULL) {
-               errno = ENOMEM;
-               return 0;
-       }
-
-       for (offset = c->start_off; offset < c->end_off;
-            offset += e->next_offset) {
-               STRUCT_ENTRY_TARGET discard;
-
-               memcpy(fw, origfw, origfw->next_offset);
-
-               /* FIXME: handle this in is_same --RR */
-               if (!map_target(*handle, fw, offset, &discard)) {
-                       free(fw);
-                       return 0;
-               }
-               e = get_entry(*handle, offset);
-
-#if 0
-               printf("Deleting:\n");
-               dump_entry(newe);
-#endif
-               if (is_same(e, fw, matchmask)) {
-                       int ret;
-                       ret = delete_rules(1, e->next_offset,
-                                          offset, entry2index(*handle, e),
-                                          handle);
-                       free(fw);
-                       return ret;
-               }
-       }
-
-       free(fw);
-       errno = ENOENT;
-       return 0;
-}
-
-/* Delete the rule in position `rulenum' in `chain'. */
-int
-TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain,
-                   unsigned int rulenum,
-                   TC_HANDLE_T *handle)
-{
-       unsigned int index;
-       int ret;
-       STRUCT_ENTRY *e;
-       struct chain_cache *c;
-
-       iptc_fn = TC_DELETE_NUM_ENTRY;
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       index = offset2index(*handle, c->start_off) + rulenum;
-
-       if (index >= offset2index(*handle, c->end_off)) {
-               errno = E2BIG;
-               return 0;
-       }
-
-       e = index2entry(*handle, index);
-       if (e == NULL) {
-               errno = EINVAL;
-               return 0;
-       }
-
-       ret = delete_rules(1, e->next_offset, entry2offset(*handle, e),
-                          index, handle);
-       return ret;
-}
-
-/* Check the packet `fw' on chain `chain'.  Returns the verdict, or
-   NULL and sets errno. */
-const char *
-TC_CHECK_PACKET(const IPT_CHAINLABEL chain,
-               STRUCT_ENTRY *entry,
-               TC_HANDLE_T *handle)
-{
-       errno = ENOSYS;
-       return NULL;
-}
-
-/* Flushes the entries in the given chain (ie. empties chain). */
-int
-TC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
-{
-       unsigned int startindex, endindex;
-       STRUCT_ENTRY *startentry, *endentry;
-       struct chain_cache *c;
-       int ret;
-
-       iptc_fn = TC_FLUSH_ENTRIES;
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-       startindex = offset2index(*handle, c->start_off);
-       endindex = offset2index(*handle, c->end_off);
-       startentry = offset2entry(*handle, c->start_off);
-       endentry = offset2entry(*handle, c->end_off);
-
-       ret = delete_rules(endindex - startindex,
-                          (char *)endentry - (char *)startentry,
-                          c->start_off, startindex,
-                          handle);
-       return ret;
-}
-
-/* Zeroes the counters in a chain. */
-int
-TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
-{
-       unsigned int i, end;
-       struct chain_cache *c;
-
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       i = offset2index(*handle, c->start_off);
-       end = offset2index(*handle, c->end_off);
-
-       for (; i <= end; i++) {
-               if ((*handle)->counter_map[i].maptype ==COUNTER_MAP_NORMAL_MAP)
-                       (*handle)->counter_map[i].maptype = COUNTER_MAP_ZEROED;
-       }
-       set_changed(*handle);
-
-       return 1;
-}
-
-STRUCT_COUNTERS *
-TC_READ_COUNTER(const IPT_CHAINLABEL chain,
-               unsigned int rulenum,
-               TC_HANDLE_T *handle)
-{
-       STRUCT_ENTRY *e;
-       struct chain_cache *c;
-       unsigned int chainindex, end;
-
-       iptc_fn = TC_READ_COUNTER;
-       CHECK(*handle);
-
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return NULL;
-       }
-
-       chainindex = offset2index(*handle, c->start_off);
-       end = offset2index(*handle, c->end_off);
-
-       if (chainindex + rulenum > end) {
-               errno = E2BIG;
-               return NULL;
-       }
-
-       e = index2entry(*handle, chainindex + rulenum);
-
-       return &e->counters;
-}
-
-int
-TC_ZERO_COUNTER(const IPT_CHAINLABEL chain,
-               unsigned int rulenum,
-               TC_HANDLE_T *handle)
-{
-       STRUCT_ENTRY *e;
-       struct chain_cache *c;
-       unsigned int chainindex, end;
-       
-       iptc_fn = TC_ZERO_COUNTER;
-       CHECK(*handle);
-
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       chainindex = offset2index(*handle, c->start_off);
-       end = offset2index(*handle, c->end_off);
-
-       if (chainindex + rulenum > end) {
-               errno = E2BIG;
-               return 0;
-       }
-
-       e = index2entry(*handle, chainindex + rulenum);
-
-       if ((*handle)->counter_map[chainindex + rulenum].maptype
-                       == COUNTER_MAP_NORMAL_MAP) {
-               (*handle)->counter_map[chainindex + rulenum].maptype
-                        = COUNTER_MAP_ZEROED;
-       }
-
-       set_changed(*handle);
-
-       return 1;
-}
-
-int 
-TC_SET_COUNTER(const IPT_CHAINLABEL chain,
-              unsigned int rulenum,
-              STRUCT_COUNTERS *counters,
-              TC_HANDLE_T *handle)
-{
-       STRUCT_ENTRY *e;
-       struct chain_cache *c;
-       unsigned int chainindex, end;
-
-       iptc_fn = TC_SET_COUNTER;
-       CHECK(*handle);
-
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       chainindex = offset2index(*handle, c->start_off);
-       end = offset2index(*handle, c->end_off);
-
-       if (chainindex + rulenum > end) {
-               errno = E2BIG;
-               return 0;
-       }
-
-       e = index2entry(*handle, chainindex + rulenum);
-
-       (*handle)->counter_map[chainindex + rulenum].maptype
-               = COUNTER_MAP_SET;
-
-       memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS));
-
-       set_changed(*handle);
-
-       return 1;
-}
-
-/* Creates a new chain. */
-/* To create a chain, create two rules: error node and unconditional
- * return. */
-int
-TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
-{
-       int ret;
-       struct chainstart {
-               STRUCT_ENTRY head;
-               struct ipt_error_target name;
-       } *newc1;
-       struct chainend {
-               STRUCT_ENTRY ret;
-               STRUCT_STANDARD_TARGET target;
-       } *newc2;
-       struct chain_head *chead;
-
-       iptc_fn = TC_CREATE_CHAIN;
-
-       /* find_label doesn't cover built-in targets: DROP, ACCEPT,
-           QUEUE, RETURN. */
-       if (find_label(chain, *handle)
-           || strcmp(chain, LABEL_DROP) == 0
-           || strcmp(chain, LABEL_ACCEPT) == 0
-           || strcmp(chain, LABEL_QUEUE) == 0
-           || strcmp(chain, LABEL_RETURN) == 0) {
-               errno = EEXIST;
-               return 0;
-       }
-
-       if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) {
-               errno = EINVAL;
-               return 0;
-       }
-
-       chead = chainh_alloc(*handle, chain);
-       if (!chead) {
-               errno = ENOMEM;
-               return 0;
-       }
-       
-       newc1 = ruleh_alloc(sizeof(*newc1));
-       if (!newc1) {
-               chainh_free(chead);
-               return 0;
-       }
-
-       newc2 = ruleh_alloc(sizeof(*newc2));
-       if (!newc2) {
-               chainh_free(chead);
-               ruleh_free(newc1);
-               return 0;
-       }
-
-       newc1->head.target_offset = sizeof(STRUCT_ENTRY);
-       newc1->head.next_offset
-               = sizeof(STRUCT_ENTRY)
-               + ALIGN(sizeof(struct ipt_error_target));
-       strcpy(newc1->name.t.u.user.name, ERROR_TARGET);
-       newc1->name.t.u.target_size = ALIGN(sizeof(struct ipt_error_target));
-       strcpy(newc1->name.error, chain);
-
-       newc2->ret.target_offset = sizeof(STRUCT_ENTRY);
-       newc2->ret.next_offset
-               = sizeof(STRUCT_ENTRY)
-               + ALIGN(sizeof(STRUCT_STANDARD_TARGET));
-       strcpy(newc2->target.target.u.user.name, STANDARD_TARGET);
-       newc->target.target.u.target_size
-               = ALIGN(sizeof(STRUCT_STANDARD_TARGET));
-       newc->target.verdict = RETURN;
-
-       list_prepend(newc1, &chead->rules);
-       list_append(newc2, &chead->rules);
-
-       return 1;
-}
-
-static int
-count_ref(STRUCT_ENTRY *e, unsigned int offset, unsigned int *ref)
-{
-       STRUCT_STANDARD_TARGET *t;
-
-       if (strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET) == 0) {
-               t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
-
-               if (t->verdict == offset)
-                       (*ref)++;
-       }
-
-       return 0;
-}
-
-/* Get the number of references to this chain. */
-int
-TC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain,
-                 TC_HANDLE_T *handle)
-{
-       struct chain_cache *c;
-
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       *ref = 0;
-       ENTRY_ITERATE((*handle)->entries.entrytable,
-                     (*handle)->entries.size,
-                     count_ref, c->start_off, ref);
-       return 1;
-}
-
-/* Deletes a chain. */
-int
-TC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
-{
-       unsigned int labelidx, labeloff;
-       unsigned int references;
-       struct chain_cache *c;
-       int ret;
-       STRUCT_ENTRY *start;
-
-       if (!TC_GET_REFERENCES(&references, chain, handle))
-               return 0;
-
-       iptc_fn = TC_DELETE_CHAIN;
-
-       if (TC_BUILTIN(chain, *handle)) {
-               errno = EINVAL;
-               return 0;
-       }
-
-       if (references > 0) {
-               errno = EMLINK;
-               return 0;
-       }
-
-       if (!(c = find_label(chain, *handle))) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       if (c->start_off != c->end_off) {
-               errno = ENOTEMPTY;
-               return 0;
-       }
-
-       /* Need label index: preceeds chain start */
-       labelidx = offset2index(*handle, c->start_off) - 1;
-       labeloff = index2offset(*handle, labelidx);
-
-       start = offset2entry(*handle, c->start_off);
-
-       ret = delete_rules(2,
-                          get_entry(*handle, labeloff)->next_offset
-                          + start->next_offset,
-                          labeloff, labelidx, handle);
-       return ret;
-}
-
-/* Renames a chain. */
-int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname,
-                   const IPT_CHAINLABEL newname,
-                   TC_HANDLE_T *handle)
-{
-       unsigned int labeloff, labelidx;
-       struct chain_cache *c;
-       struct ipt_error_target *t;
-
-       iptc_fn = TC_RENAME_CHAIN;
-
-       /* find_label doesn't cover built-in targets: DROP, ACCEPT,
-           QUEUE, RETURN. */
-       if (find_label(newname, *handle)
-           || strcmp(newname, LABEL_DROP) == 0
-           || strcmp(newname, LABEL_ACCEPT) == 0
-           || strcmp(newname, LABEL_QUEUE) == 0
-           || strcmp(newname, LABEL_RETURN) == 0) {
-               errno = EEXIST;
-               return 0;
-       }
-
-       if (!(c = find_label(oldname, *handle))
-           || TC_BUILTIN(oldname, *handle)) {
-               errno = ENOENT;
-               return 0;
-       }
-
-       if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) {
-               errno = EINVAL;
-               return 0;
-       }
-
-       /* Need label index: preceeds chain start */
-       labelidx = offset2index(*handle, c->start_off) - 1;
-       labeloff = index2offset(*handle, labelidx);
-
-       t = (struct ipt_error_target *)
-               GET_TARGET(get_entry(*handle, labeloff));
-
-       memset(t->error, 0, sizeof(t->error));
-       strcpy(t->error, newname);
-       set_changed(*handle);
-
-       return 1;
-}
-
-/* Sets the policy on a built-in chain. */
-int
-TC_SET_POLICY(const IPT_CHAINLABEL chain,
-             const IPT_CHAINLABEL policy,
-             STRUCT_COUNTERS *counters,
-             TC_HANDLE_T *handle)
-{
-       unsigned int hook;
-       unsigned int policyoff, ctrindex;
-       STRUCT_ENTRY *e;
-       STRUCT_STANDARD_TARGET *t;
-
-       iptc_fn = TC_SET_POLICY;
-       /* Figure out which chain. */
-       hook = TC_BUILTIN(chain, *handle);
-       if (hook == 0) {
-               errno = ENOENT;
-               return 0;
-       } else
-               hook--;
-
-       policyoff = get_chain_end(*handle, (*handle)->info.hook_entry[hook]);
-       if (policyoff != (*handle)->info.underflow[hook]) {
-               printf("ERROR: Policy for `%s' offset %u != underflow %u\n",
-                      chain, policyoff, (*handle)->info.underflow[hook]);
-               return 0;
-       }
-
-       e = get_entry(*handle, policyoff);
-       t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
-
-       if (strcmp(policy, LABEL_ACCEPT) == 0)
-               t->verdict = -NF_ACCEPT - 1;
-       else if (strcmp(policy, LABEL_DROP) == 0)
-               t->verdict = -NF_DROP - 1;
-       else {
-               errno = EINVAL;
-               return 0;
-       }
-
-       ctrindex = entry2index(*handle, e);
-
-       if (counters) {
-               /* set byte and packet counters */
-               memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS));
-
-               (*handle)->counter_map[ctrindex].maptype
-                       = COUNTER_MAP_SET;
-
-       } else {
-               (*handle)->counter_map[ctrindex]
-                       = ((struct counter_map){ COUNTER_MAP_NOMAP, 0 });
-       }
-
-       set_changed(*handle);
-
-       return 1;
-}
-
-/* Without this, on gcc 2.7.2.3, we get:
-   libiptc.c: In function `TC_COMMIT':
-   libiptc.c:833: fixed or forbidden register was spilled.
-   This may be due to a compiler bug or to impossible asm
-   statements or clauses.
-*/
-static void
-subtract_counters(STRUCT_COUNTERS *answer,
-                 const STRUCT_COUNTERS *a,
-                 const STRUCT_COUNTERS *b)
-{
-       answer->pcnt = a->pcnt - b->pcnt;
-       answer->bcnt = a->bcnt - b->bcnt;
-}
-
-int
-TC_COMMIT(TC_HANDLE_T *handle)
-{
-       /* Replace, then map back the counters. */
-       STRUCT_REPLACE *repl;
-       STRUCT_COUNTERS_INFO *newcounters;
-       unsigned int i;
-       size_t counterlen;
-
-       CHECK(*handle);
-
-       counterlen = sizeof(STRUCT_COUNTERS_INFO)
-                       + sizeof(STRUCT_COUNTERS) * (*handle)->new_number;
-
-#if 0
-       TC_DUMP_ENTRIES(*handle);
-#endif
-
-       /* Don't commit if nothing changed. */
-       if (!(*handle)->changed)
-               goto finished;
-
-       repl = malloc(sizeof(*repl) + (*handle)->entries.size);
-       if (!repl) {
-               errno = ENOMEM;
-               return 0;
-       }
-
-       /* These are the old counters we will get from kernel */
-       repl->counters = malloc(sizeof(STRUCT_COUNTERS)
-                               * (*handle)->info.num_entries);
-       if (!repl->counters) {
-               free(repl);
-               errno = ENOMEM;
-               return 0;
-       }
-
-       /* These are the counters we're going to put back, later. */
-       newcounters = malloc(counterlen);
-       if (!newcounters) {
-               free(repl->counters);
-               free(repl);
-               errno = ENOMEM;
-               return 0;
-       }
-
-       strcpy(repl->name, (*handle)->info.name);
-       repl->num_entries = (*handle)->new_number;
-       repl->size = (*handle)->entries.size;
-       memcpy(repl->hook_entry, (*handle)->info.hook_entry,
-              sizeof(repl->hook_entry));
-       memcpy(repl->underflow, (*handle)->info.underflow,
-              sizeof(repl->underflow));
-       repl->num_counters = (*handle)->info.num_entries;
-       repl->valid_hooks = (*handle)->info.valid_hooks;
-       memcpy(repl->entries, (*handle)->entries.entrytable,
-              (*handle)->entries.size);
-
-       if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl,
-                      sizeof(*repl) + (*handle)->entries.size) < 0) {
-               free(repl->counters);
-               free(repl);
-               free(newcounters);
-               return 0;
-       }
-
-       /* Put counters back. */
-       strcpy(newcounters->name, (*handle)->info.name);
-       newcounters->num_counters = (*handle)->new_number;
-       for (i = 0; i < (*handle)->new_number; i++) {
-               unsigned int mappos = (*handle)->counter_map[i].mappos;
-               switch ((*handle)->counter_map[i].maptype) {
-               case COUNTER_MAP_NOMAP:
-                       newcounters->counters[i]
-                               = ((STRUCT_COUNTERS){ 0, 0 });
-                       break;
-
-               case COUNTER_MAP_NORMAL_MAP:
-                       /* Original read: X.
-                        * Atomic read on replacement: X + Y.
-                        * Currently in kernel: Z.
-                        * Want in kernel: X + Y + Z.
-                        * => Add in X + Y
-                        * => Add in replacement read.
-                        */
-                       newcounters->counters[i] = repl->counters[mappos];
-                       break;
-
-               case COUNTER_MAP_ZEROED:
-                       /* Original read: X.
-                        * Atomic read on replacement: X + Y.
-                        * Currently in kernel: Z.
-                        * Want in kernel: Y + Z.
-                        * => Add in Y.
-                        * => Add in (replacement read - original read).
-                        */
-                       subtract_counters(&newcounters->counters[i],
-                                         &repl->counters[mappos],
-                                         &index2entry(*handle, i)->counters);
-                       break;
-
-               case COUNTER_MAP_SET:
-                       /* Want to set counter (iptables-restore) */
-
-                       memcpy(&newcounters->counters[i],
-                              &index2entry(*handle, i)->counters,
-                              sizeof(STRUCT_COUNTERS));
-
-                       break;
-               }
-       }
-
-#ifdef KERNEL_64_USERSPACE_32
-       {
-               /* Kernel will think that pointer should be 64-bits, and get
-                  padding.  So we accomodate here (assumption: alignment of
-                  `counters' is on 64-bit boundary). */
-               u_int64_t *kernptr = (u_int64_t *)&newcounters->counters;
-               if ((unsigned long)&newcounters->counters % 8 != 0) {
-                       fprintf(stderr,
-                               "counters alignment incorrect! Mail rusty!\n");
-                       abort();
-               }
-               *kernptr = newcounters->counters;
-       }
-#endif /* KERNEL_64_USERSPACE_32 */
-
-       if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS,
-                      newcounters, counterlen) < 0) {
-               free(repl->counters);
-               free(repl);
-               free(newcounters);
-               return 0;
-       }
-
-       free(repl->counters);
-       free(repl);
-       free(newcounters);
-
- finished:
-       TC_FREE(handle);
-       return 1;
-}
-
-/* Get raw socket. */
-int
-TC_GET_RAW_SOCKET()
-{
-       return sockfd;
-}
-
-/* Translates errno numbers into more human-readable form than strerror. */
-const char *
-TC_STRERROR(int err)
-{
-       unsigned int i;
-       struct table_struct {
-               void *fn;
-               int err;
-               const char *message;
-       } table [] =
-         { { TC_INIT, EPERM, "Permission denied (you must be root)" },
-           { TC_INIT, EINVAL, "Module is wrong version" },
-           { TC_INIT, ENOENT, 
-                   "Table does not exist (do you need to insmod?)" },
-           { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" },
-           { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" },
-           { TC_DELETE_CHAIN, EMLINK,
-             "Can't delete chain with references left" },
-           { TC_CREATE_CHAIN, EEXIST, "Chain already exists" },
-           { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" },
-           { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" },
-           { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" },
-           { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
-           { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" },
-           { TC_INSERT_ENTRY, ELOOP, "Loop found in table" },
-           { TC_INSERT_ENTRY, EINVAL, "Target problem" },
-           /* EINVAL for CHECK probably means bad interface. */
-           { TC_CHECK_PACKET, EINVAL,
-             "Bad arguments (does that interface exist?)" },
-           { TC_CHECK_PACKET, ENOSYS,
-             "Checking will most likely never get implemented" },
-           /* ENOENT for DELETE probably means no matching rule */
-           { TC_DELETE_ENTRY, ENOENT,
-             "Bad rule (does a matching rule exist in that chain?)" },
-           { TC_SET_POLICY, ENOENT,
-             "Bad built-in chain name" },
-           { TC_SET_POLICY, EINVAL,
-             "Bad policy name" },
-
-           { NULL, 0, "Incompatible with this kernel" },
-           { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
-           { NULL, ENOSYS, "Will be implemented real soon.  I promise ;)" },
-           { NULL, ENOMEM, "Memory allocation problem" },
-           { NULL, ENOENT, "No chain/target/match by that name" },
-         };
-
-       for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
-               if ((!table[i].fn || table[i].fn == iptc_fn)
-                   && table[i].err == err)
-                       return table[i].message;
-       }
-
-       return strerror(err);
-}