]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
forgot to add those two...
authorAndrás Kis-Szabó <kisza@sch.bme.hu>
Tue, 27 Feb 2001 09:59:48 +0000 (09:59 +0000)
committerHarald Welte <laforge@gnumonks.org>
Tue, 27 Feb 2001 09:59:48 +0000 (09:59 +0000)
ip6tables-restore.c [new file with mode: 0644]
ip6tables-save.c [new file with mode: 0644]

diff --git a/ip6tables-restore.c b/ip6tables-restore.c
new file mode 100644 (file)
index 0000000..9ebc577
--- /dev/null
@@ -0,0 +1,299 @@
+/* Code to restore the iptables state, from file by ip6tables-save. 
+ * Author:  Andras Kis-Szabo <kisza@sch.bme.hu>
+ *
+ * based on iptables-restore
+ * Authors:
+ *     Harald Welte <laforge@gnumonks.org>
+ *     Rusty Russell <rusty@linuxcare.com.au>
+ *
+ */
+
+#include <getopt.h>
+#include <sys/errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "ip6tables.h"
+#include "libiptc/libip6tc.h"
+
+#ifdef DEBUG
+#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
+#else
+#define DEBUGP(x, args...) 
+#endif
+
+extern int for_each_chain(int (*fn)(const ip6t_chainlabel, int, ip6tc_handle_t *), int verbose, int builtinstoo, ip6tc_handle_t *handle);
+extern int flush_entries(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
+extern int delete_chain(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
+
+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'},
+       { 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", name);
+               
+       exit(1);
+}
+
+ip6tc_handle_t create_handle(const char *tablename)
+{
+       ip6tc_handle_t handle;
+
+       handle = ip6tc_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 ip6t_counters *ctr)
+{
+       return (sscanf(string, "[%llu:%llu]", &ctr->pcnt, &ctr->bcnt) == 2);
+}
+
+int main(int argc, char *argv[])
+{
+       ip6tc_handle_t handle;
+       char buffer[10240];
+       unsigned int line = 0;
+       int c;
+       char curtable[IP6T_TABLE_MAXNAMELEN + 1];
+       char curchain[IP6T_FUNCTION_MAXNAMELEN + 1];
+       FILE *in;
+
+       program_name = "ip6tables-restore";
+       program_version = NETFILTER_VERSION;
+
+       while ((c = getopt_long(argc, argv, "bcvhn", options, NULL)) != -1) {
+               switch (c) {
+                       case 'b':
+                               binary = 1;
+                               break;
+                       case 'c':
+                               counters = 1;
+                               break;
+                       case 'h':
+                               print_usage("ip6tables-restore",
+                                           NETFILTER_VERSION);
+                               break;
+                       case 'n':
+                               noflush = 1;
+                               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;
+/*
+       handle = iptc_init("filter");
+       if (!handle)
+               exit_error(VERSION_PROBLEM,
+                          "can't initialize iptables-restore: %s",
+                          iptc_strerror(errno));
+
+       if (!clean_slate(&handle))
+               exit_error(OTHER_PROBLEM, "Deleting old chains: %s",
+                          iptc_strerror(errno));
+*/
+       /* Grab standard input. */
+       while (fgets(buffer, sizeof(buffer), in)) {
+               int ret;
+
+               line++;
+               if (buffer[0] == '\n') continue;
+               else if (buffer[0] == '#') {
+                       if (verbose) fputs(buffer, stdout);
+                       continue;
+               } else if (strcmp(buffer, "COMMIT\n") == 0) {
+                       DEBUGP("Calling commit\n");
+                       ret = ip6tc_commit(&handle);
+               } else if (buffer[0] == '*') {
+                       /* 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, IP6T_TABLE_MAXNAMELEN);
+
+                       handle = create_handle(table);
+                       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;
+
+               } else if (buffer[0] == ':') {
+                       /* 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);
+                       }
+                       strncpy(curchain, chain, IP6T_FUNCTION_MAXNAMELEN);
+
+                       /* why the f... does iptc_builtin not work here ? */
+                       /* FIXME: abort if chain creation fails --RR */
+//                     if (!iptc_builtin(curchain, &handle)) {
+                               DEBUGP("Creating new chain '%s'\n", curchain);
+                               if (!ip6tc_create_chain(curchain, &handle))
+                               DEBUGP("unable to create chain '%s':%s\n", curchain,
+                                       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 ip6t_counters count;
+
+                               if (counters) {
+                                       char *ctrs;
+                                       ctrs = strtok(NULL, " \t\n");
+
+                                       parse_counters(ctrs, &count);
+
+                               } else {
+                                       memset(&count, 0, 
+                                              sizeof(struct ip6t_counters));
+                               }
+
+                               DEBUGP("Setting policy of chain %s to %s\n",
+                                       chain, policy);
+
+                               if (!ip6tc_set_policy(chain, policy, &count,
+                                                    &handle))
+                                       exit_error(OTHER_PROBLEM,
+                                               "Can't set policy `%s'"
+                                               " on `%s' line %u: %s\n",
+                                               chain, policy, line,
+                                               ip6tc_strerror(errno));
+                       }
+
+                       ret = 1;
+
+               } else {
+                       char *newargv[1024];
+                       int i,a, argvsize;
+                       char *ptr = buffer;
+                       char *pcnt = NULL;
+                       char *bcnt = NULL;
+
+                       if (buffer[0] == '[') {
+                               ptr = strchr(buffer, ']');
+                               if (!ptr)
+                                       exit_error(PARAMETER_PROBLEM,
+                                                  "Bad line %u: need ]\n",
+                                                  line);
+                               pcnt = strtok(buffer+1, ":");
+                               bcnt = strtok(NULL, "]");
+                       } 
+
+                       newargv[0] = argv[0];
+                       newargv[1] = "-t";
+                       newargv[2] = (char *) &curtable;
+                       newargv[3] = "-A";
+                       newargv[4] = (char *) &curchain;
+                       argvsize = 5;
+
+                       if (counters && pcnt && bcnt) {
+                               newargv[5] = "--set-counters";
+                               newargv[6] = (char *) pcnt;
+                               newargv[7] = (char *) bcnt;
+                               argvsize = 8;
+                       }
+                               
+                       // strtok initcialize!
+                       if ( buffer[0]!='[' )
+                       {
+                               if (!(newargv[argvsize] = strtok(buffer, " \t\n")))
+                                       goto ImLaMeR;
+                                       //break;
+                               argvsize++;
+                       }
+
+                       /* strtok: a function only a coder could love */
+                       for (i = argvsize; i < sizeof(newargv)/sizeof(char *); 
+                                       i++) {
+                               if (!(newargv[i] = strtok(NULL, " \t\n")))
+                                       break;
+                               ptr = NULL;
+                       }
+ImLaMeR:               if (i == sizeof(newargv)/sizeof(char *)) {
+                               fprintf(stderr,
+                                       "%s: line %u too many arguments\n",
+                                       program_name, line);
+                               exit(1);
+                       }
+
+                       DEBUGP("===>calling do_command6(%u, argv, &%s, handle):\n",
+                                       i, curtable);
+
+                       for (a = 0; a <= i; a++)
+                               DEBUGP("argv[%u]: %s\n", a, newargv[a]);
+
+                       ret = do_command6(i, newargv, &newargv[2], &handle);
+               }
+               if (!ret) {
+                       fprintf(stderr, "%s: line %u failed\n",
+                                       program_name, line);
+                       exit(1);
+               }
+       }
+
+       return 0;
+}
diff --git a/ip6tables-save.c b/ip6tables-save.c
new file mode 100644 (file)
index 0000000..8957e13
--- /dev/null
@@ -0,0 +1,341 @@
+/* Code to save the ip6tables state, in human readable-form. */
+/* Author:  Andras Kis-Szabo <kisza@sch.bme.hu>
+ * Original code: iptables-save
+ * Authors: Paul 'Rusty' Russel <rusty@linuxcare.com.au> and
+ *         Harald Welte <laforge@gnumonks.org>
+ */
+#include <getopt.h>
+#include <sys/errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <time.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include "libiptc/libip6tc.h"
+#include "ip6tables.h"
+
+#ifndef IP6T_LIB_DIR
+#define IP6T_LIB_DIR "/usr/local/lib/iptables"
+#endif
+
+static int binary = 0, counters = 0;
+
+static struct option options[] = {
+       { "binary", 0, 0, 'b' },
+       { "counters", 0, 0, 'c' },
+       { "dump", 0, 0, 'd' },
+       { "table", 1, 0, 't' },
+       { 0 }
+};
+
+extern struct ip6tables_match *find_match(const char *name, enum ip6t_tryload tryload);
+extern struct ip6tables_target *find_target(const char *name, enum ip6t_tryload tryload);
+
+/* This assumes that mask is contiguous, and byte-bounded. */
+static void
+print_iface(char letter, const char *iface, const unsigned char *mask,
+           int invert)
+{
+       unsigned int i;
+
+       if (mask[0] == 0)
+               return;
+
+       printf("-%c %s", letter, invert ? "! " : "");
+
+       for (i = 0; i < IFNAMSIZ; i++) {
+               if (mask[i] != 0) {
+                       if (iface[i] != '\0')
+                               printf("%c", iface[i]);
+               } else {
+                       if (iface[i] != '\0')
+                               printf("+");
+                       break;
+               }
+       }
+
+       printf(" ");
+}
+
+/* These are hardcoded backups in ip6tables.c, so they are safe */
+struct pprot {
+       char *name;
+       u_int8_t num;
+};
+
+static const struct pprot chain_protos[] = {
+       { "tcp", IPPROTO_TCP },
+       { "udp", IPPROTO_UDP },
+       { "icmp", IPPROTO_ICMP },
+       { "esp", IPPROTO_ESP },
+       { "ah", IPPROTO_AH },
+};
+
+/* The ip6tables looks up the /etc/protocols. */
+static void print_proto(u_int16_t proto, int invert)
+{
+       if (proto) {
+               unsigned int i;
+               const char *invertstr = invert ? "! " : "";
+
+                struct protoent *pent = getprotobynumber(proto);
+                if (pent) {
+                       printf("-p %s%s ",
+                              invertstr, pent->p_name);
+                       return;
+               }
+
+               for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++)
+                       if (chain_protos[i].num == proto) {
+                               printf("-p %s%s ",
+                                      invertstr, chain_protos[i].name);
+                               return;
+                       }
+
+               printf("-p %s%u ", invertstr, proto);
+       }
+}
+
+static int print_match(const struct ip6t_entry_match *e,
+                       const struct ip6t_ip6 *ip)
+{
+       struct ip6tables_match *match
+               = find_match(e->u.user.name, TRY_LOAD);
+
+       if (match) {
+               printf("-m %s ", e->u.user.name);
+
+               /* some matches don't provide a save function */
+               if (match->save)
+                       match->save(ip, e);
+       } else {
+               if (e->u.match_size) {
+                       fprintf(stderr,
+                               "Can't find library for match `%s'\n",
+                               e->u.user.name);
+                       exit(1);
+               }
+       }
+       return 0;
+}
+
+/* print a given ip including mask if neccessary */
+static void print_ip(char *prefix, const struct in6_addr *ip, const struct in6_addr *mask, int invert)
+{
+       char buf[51];
+       int l = ipv6_prefix_length(mask);
+
+       if (!mask && !ip)
+               return;
+
+       printf("%s %s%s/",
+               prefix,
+               invert ? "! " : "",
+               inet_ntop(AF_INET6, ip, buf, sizeof buf));
+
+       if (l == -1)
+               printf("%s ", inet_ntop(AF_INET6, mask, buf, sizeof buf));
+       else
+               printf("%d ", l);
+       
+#if 0
+       if (mask != 0xffffffff) 
+               printf("/%u.%u.%u.%u ", IP_PARTS(mask));
+       else
+               printf(" ");
+#endif
+}
+
+/* We want this to be readable, so only print out neccessary fields.
+ * Because that's the kind of world I want to live in.  */
+static void print_rule(const struct ip6t_entry *e, 
+               ip6tc_handle_t *h, int counters)
+{
+       struct ip6t_entry_target *t;
+
+       /* print counters */
+       if (counters)
+               printf("[%llu:%llu] ", e->counters.pcnt, e->counters.bcnt);
+
+       /* Print IP part. */
+       print_ip("-s", &(e->ipv6.src), &(e->ipv6.smsk),
+                       e->ipv6.invflags & IP6T_INV_SRCIP);     
+
+       print_ip("-d", &(e->ipv6.dst), &(e->ipv6.dmsk),
+                       e->ipv6.invflags & IP6T_INV_DSTIP);
+
+       print_iface('i', e->ipv6.iniface, e->ipv6.iniface_mask,
+                   e->ipv6.invflags & IP6T_INV_VIA_IN);
+
+       print_iface('o', e->ipv6.outiface, e->ipv6.outiface_mask,
+                   e->ipv6.invflags & IP6T_INV_VIA_OUT);
+
+       print_proto(e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO);
+
+#if 0
+       // not definied in ipv6
+       // FIXME: linux/netfilter_ipv6/ip6_tables: IP6T_INV_FRAG why definied?
+       if (e->ipv6.flags & IPT_F_FRAG)
+               printf("%s-f ",
+                      e->ipv6.invflags & IP6T_INV_FRAG ? "! " : "");
+#endif
+
+       // TODO: i've got some problem with the code - under understanding ;)
+       // How can I set this?
+       if (e->ipv6.flags & IP6T_F_TOS)
+               printf("%s-? %d ",
+                      e->ipv6.invflags & IP6T_INV_TOS ? "! " : "", 
+                      e->ipv6.tos);
+
+       /* Print matchinfo part */
+       if (e->target_offset) {
+               IP6T_MATCH_ITERATE(e, print_match, &e->ipv6);
+       }
+
+       /* Print target name */ 
+       printf("-j %s ", ip6tc_get_target(e, h));
+
+       /* Print targinfo part */
+       t = ip6t_get_target((struct ip6t_entry *)e);
+       if (t->u.user.name[0]) {
+               struct ip6tables_target *target
+                       = find_target(t->u.user.name, TRY_LOAD);
+
+               if (target)
+                       target->save(&e->ipv6, t);
+               else {
+                       /* If some bits are non-zero, it implies we *need*
+                          to understand it */
+                       if (t->u.target_size) {
+                               fprintf(stderr,
+                                       "Can't find library for target `%s'\n",
+                                       t->u.user.name);
+                               exit(1);
+                       }
+               }
+       }
+       printf("\n");
+}
+
+/* Debugging prototype. */
+static int for_each_table(int (*func)(const char *tablename))
+{
+        int ret = 1;
+       FILE *procfile = NULL;
+       char tablename[IP6T_TABLE_MAXNAMELEN+1];
+
+       procfile = fopen("/proc/net/ip6_tables_names", "r");
+       if (!procfile)
+               return 0;
+
+       while (fgets(tablename, sizeof(tablename), procfile)) {
+               if (tablename[strlen(tablename) - 1] != '\n')
+                       exit_error(OTHER_PROBLEM, 
+                                  "Badly formed tablename `%s'\n",
+                                  tablename);
+               tablename[strlen(tablename) - 1] = '\0';
+               ret &= func(tablename);
+       }
+
+       return ret;
+}
+       
+
+static int do_output(const char *tablename)
+{
+       ip6tc_handle_t h;
+       const char *chain = NULL;
+
+       if (!tablename)
+               return for_each_table(&do_output);
+
+       h = ip6tc_init(tablename);
+       if (!h)
+               exit_error(OTHER_PROBLEM, "Can't initialize: %s\n",
+                          ip6tc_strerror(errno));
+
+       if (!binary) {
+               time_t now = time(NULL);
+
+               printf("# Generated by ip6tables-save v%s on %s",
+                      NETFILTER_VERSION, ctime(&now));
+               printf("*%s\n", tablename);
+
+               /* Dump out chain names */
+               for (chain = ip6tc_first_chain(&h);
+                    chain;
+                    chain = ip6tc_next_chain(&h)) {
+                       const struct ip6t_entry *e;
+
+                       printf(":%s ", chain);
+                       if (ip6tc_builtin(chain, h)) {
+                               struct ip6t_counters count;
+                               printf("%s ",
+                                      ip6tc_get_policy(chain, &count, &h));
+                               printf("[%llu:%llu]\n", count.pcnt, count.bcnt);
+                       } else {
+                               printf("- [0:0]\n");
+                       }
+
+                       /* Dump out rules */
+                       e = ip6tc_first_rule(chain, &h);
+                       while(e) {
+                               print_rule(e, &h, counters);
+                               e = ip6tc_next_rule(e, &h);
+                       }
+               }
+
+               now = time(NULL);
+               printf("COMMIT\n");
+               printf("# Completed on %s", ctime(&now));
+       } else {
+               /* Binary, huh?  OK. */
+               exit_error(OTHER_PROBLEM, "Binary NYI\n");
+       }
+
+       return 1;
+}
+
+/* Format:
+ * :Chain name POLICY packets bytes
+ * rule
+ */
+int main(int argc, char *argv[])
+{
+       const char *tablename = NULL;
+       int c;
+
+       program_name = "ip6tables-save";
+       program_version = NETFILTER_VERSION;
+
+       while ((c = getopt_long(argc, argv, "bc", options, NULL)) != -1) {
+               switch (c) {
+               case 'b':
+                       binary = 1;
+                       break;
+
+               case 'c':
+                       counters = 1;
+                       break;
+
+               case 't':
+                       /* Select specific table. */
+                       tablename = optarg;
+                       break;
+
+               case 'd':
+                       do_output(tablename);
+                       exit(0);
+               }
+       }
+
+       if (optind < argc) {
+               fprintf(stderr, "Unknown arguments found on commandline");
+               exit(1);
+       }
+
+       return !do_output(tablename);
+}