]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
Third stage to ipset-5
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Thu, 22 Apr 2010 14:50:57 +0000 (16:50 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Thu, 22 Apr 2010 14:50:57 +0000 (16:50 +0200)
Refresh existing files in src/ with the new content.

src/ipset.c
src/ipset_bitmap_ip.c
src/ipset_bitmap_ipmac.c
src/ipset_bitmap_port.c
src/ipset_hash_ip.c
src/ipset_hash_ipport.c
src/ipset_hash_ipportip.c
src/ipset_hash_ipportnet.c
src/ipset_hash_net.c
src/ipset_list_set.c
src/ipset_tree_ip.c

index 3b8e24857dbe4447e00034fedbe14ea51f6b63f9..d29042df6c62c269a74fb67ff7e42f4b898e5151 100644 (file)
 /* Copyright 2000-2002 Joakim Axelsson (gozem@linux.nu)
  *                     Patrick Schaaf (bof@bof.de)
- * Copyright 2003-2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+ * Copyright 2003-2010 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 version 2 as 
  * published by the Free Software Foundation.
  */
-
-#include <stdio.h>                     /* *printf, perror, sscanf, fdopen */
-#include <string.h>                    /* mem*, str* */
-#include <errno.h>                     /* errno, perror */
-#include <time.h>                      /* time, ctime */
-#include <netdb.h>                     /* gethostby*, getnetby*, getservby* */
-#include <stdlib.h>                    /* exit, malloc, free, strtol, getenv, mkstemp */
-#include <unistd.h>                    /* read, close, fork, exec*, unlink */
-#include <sys/types.h>                 /* open, wait, socket, *sockopt, umask */
-#include <sys/stat.h>                  /* open, umask */
-#include <sys/wait.h>                  /* wait */
-#include <sys/socket.h>                        /* socket, *sockopt, gethostby*, inet_* */
-#include <netinet/in.h>                        /* inet_* */
-#include <fcntl.h>                     /* open */
-#include <arpa/inet.h>                 /* htonl, inet_* */
+#include <ctype.h>                     /* isspace */
 #include <stdarg.h>                    /* va_* */
-#include <dlfcn.h>                     /* dlopen */
-
-#include "ipset.h"
-
-#ifndef PROC_SYS_MODPROBE
-#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
-#endif
-
-char program_name[] = "ipset";
-char program_version[] = IPSET_VERSION;
-static int protocol_version = 0;
-
-#define STREQ(a,b)     (strncmp(a,b,IP_SET_MAXNAMELEN) == 0)
-#define DONT_ALIGN     (protocol_version == IP_SET_PROTOCOL_UNALIGNED)
-#define ALIGNED(len)   IPSET_VALIGN(len, DONT_ALIGN)
-
-/* The list of loaded set types */
-static struct settype *all_settypes = NULL;
-
-/* Array of sets */
-struct set **set_list = NULL;
-ip_set_id_t max_sets = 0;
-
-/* Suppress output to stdout and stderr? */
-static int option_quiet = 0;
-
-/* Data for restore mode */
-static int restore = 0;
-void *restore_data = NULL;
-struct ip_set_restore *restore_set = NULL;
-size_t restore_offset = 0;
-socklen_t restore_size;
-unsigned restore_line = 0;
-unsigned warn_once = 0;
-
-#define TEMPFILE_PATTERN       "/ipsetXXXXXX"
-
-#ifdef IPSET_DEBUG
-int option_debug = 0;
-#endif
-
-#define OPTION_OFFSET 256
-static unsigned int global_option_offset = 0;
-
-/* Most of these command parsing functions are borrowed from iptables.c */
-
-static const char cmdflags[] = { ' ',                  /* CMD_NONE */ 
-       'N', 'X', 'F', 'E', 'W', 'L', 'S', 'R', 
-       'A', 'D', 'T', 'H', 'V',
-};
-
-/* Options */
-#define OPT_NONE               0x0000U
-#define OPT_NUMERIC            0x0001U         /* -n */
-#define OPT_SORTED             0x0002U         /* -s */
-#define OPT_QUIET              0x0004U         /* -q */
-#define OPT_DEBUG              0x0008U         /* -z */
-#define OPT_RESOLVE            0x0020U         /* -r */
-#define NUMBER_OF_OPT 5
-static const char optflags[] =
-    { 'n', 's', 'q', 'z', 'r' };
-
-static struct option opts_long[] = {
-       /* set operations */
-       {"create",  1, 0, 'N'},
-       {"destroy", 2, 0, 'X'},
-       {"flush",   2, 0, 'F'},
-       {"rename",  1, 0, 'E'},
-       {"swap",    1, 0, 'W'},
-       {"list",    2, 0, 'L'},
-
-       {"save",    2, 0, 'S'},
-       {"restore", 0, 0, 'R'},
-
-       /* ip in set operations */
-       {"add",     1, 0, 'A'},
-       {"del",     1, 0, 'D'},
-       {"test",    1, 0, 'T'},
-       
-       /* free options */
-       {"numeric", 0, 0, 'n'},
-       {"sorted",  0, 0, 's'},
-       {"quiet",   0, 0, 'q'},
-       {"resolve", 0, 0, 'r'},
-
-#ifdef IPSET_DEBUG
-       /* debug (if compiled with it) */
-       {"debug",   0, 0, 'z'},
-#endif
-
-       /* version and help */
-       {"version", 0, 0, 'V'},
-       {"help",    2, 0, 'H'},
-
-       /* end */
-       {NULL},
-};
-
-static char opts_short[] =
-    "-N:X::F::E:W:L::S::RA:D:T:nrsqzvVh::H::";
-
-/* Table of legal combinations of commands and options. If any of the
- * given commands make an option legal, that option is legal.
- * Key:
- *  +  compulsory
- *  x  illegal
- *     optional
- */
+#include <stdbool.h>                   /* bool */
+#include <stdio.h>                     /* fprintf, fgets */
+#include <stdlib.h>                    /* exit */
+#include <string.h>                    /* str* */
+
+#include <config.h>
+
+#include <libipset/parse.h>            /* ipset_parse_* */
+#include <libipset/session.h>          /* ipset_session_* */
+#include <libipset/types.h>            /* struct ipset_type */
+#include <libipset/ui.h>               /* core options, commands */
+#include <libipset/utils.h>            /* ipset_name_match */
+
+static char program_name[] = PACKAGE;
+static char program_version[] = PACKAGE_VERSION;
+
+static struct ipset_session *session = NULL;
+static uint32_t restore_line = 0;
+static bool interactive = false;
+static char cmdline[1024];
+static char *newargv[255];
+static int newargc = 0;
 
-static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = {
-       /*            -n   -s   -q   -z   -r */
-        /*CREATE*/  {'x', 'x', ' ', ' ', 'x'},
-        /*DESTROY*/ {'x', 'x', ' ', ' ', 'x'},
-        /*FLUSH*/   {'x', 'x', ' ', ' ', 'x'},
-        /*RENAME*/  {'x', 'x', ' ', ' ', 'x'},
-        /*SWAP*/    {'x', 'x', ' ', ' ', 'x'},
-        /*LIST*/    {' ', ' ', 'x', ' ', ' '},
-        /*SAVE*/    {'x', 'x', ' ', ' ', 'x'},
-        /*RESTORE*/ {'x', 'x', ' ', ' ', 'x'},
-        /*ADD*/     {'x', 'x', ' ', ' ', 'x'},
-        /*DEL*/     {'x', 'x', ' ', ' ', 'x'},
-        /*TEST*/    {'x', 'x', ' ', ' ', 'x'},
-        /*HELP*/    {'x', 'x', 'x', ' ', 'x'},
-        /*VERSION*/ {'x', 'x', 'x', ' ', 'x'},
+enum exittype {
+       NO_PROBLEM = 0,
+       OTHER_PROBLEM,
+       PARAMETER_PROBLEM,
+       VERSION_PROBLEM,
 };
-
-/* Main parser function */
-int parse_commandline(int argc, char *argv[]);
-
-static void exit_tryhelp(int status)
-{
-       fprintf(stderr,
-               "Try `%s -H' or '%s --help' for more information.\n",
-               program_name, program_name);
-       exit(status);
-}
-
-void exit_error(int status, const char *msg, ...)
-{
-       if (!option_quiet) {
-               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 (restore_line)
-                       fprintf(stderr, "Restore failed at line %u:\n", restore_line);
-               if (status == PARAMETER_PROBLEM)
-                       exit_tryhelp(status);
-               if (status == VERSION_PROBLEM)
-                       fprintf(stderr,
-                               "Perhaps %s or your kernel needs to be upgraded.\n",
-                               program_name);
-       }
-
-       exit(status);
-}
-
-static void ipset_printf(const char *msg, ...)
-{
-       if (!option_quiet) {
-               va_list args;
-
-               va_start(args, msg);
-               vfprintf(stdout, msg, args);
-               va_end(args);
-               fprintf(stdout, "\n");
-       }
-}
-
-static void generic_opt_check(int command, unsigned 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 = 1; j <= NUMBER_OF_CMD; j++) {
-                       if (command != j)
-                               continue;
-
-                       if (!(options & (1 << i))) {
-                               if (commands_v_options[j-1][i] == '+')
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "You need to supply the `-%c' "
-                                                  "option for this command\n",
-                                                  optflags[i]);
-                       } else {
-                               if (commands_v_options[j-1][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(unsigned int option)
-{
-       const char *ptr;
-       for (ptr = optflags; option > 1; option >>= 1, ptr++);
-
-       return *ptr;
-}
-
-static char cmd2char(int cmd)
-{
-       if (cmd <= CMD_NONE || cmd > NUMBER_OF_CMD)
-               return ' '; 
-
-       return cmdflags[cmd];
-}
-
-/* From iptables.c ... */
-static char *get_modprobe(void)
-{
-       int procfile;
-       char *ret;
-
-#define PROCFILE_BUFSIZ        1024
-       procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
-       if (procfile < 0)
-               return NULL;
-
-       ret = (char *) malloc(PROCFILE_BUFSIZ);
-       if (ret) {
-               memset(ret, 0, PROCFILE_BUFSIZ);
-               switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
-               case -1: goto fail;
-               case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
-               default: ; /* nothing */
-               }
-               if (ret[strlen(ret)-1]=='\n') 
-                       ret[strlen(ret)-1]=0;
-               close(procfile);
-               return ret;
-       }
- fail:
-       free(ret);
-       close(procfile);
-       return NULL;
-}
-
-static int ipset_insmod(const char *modname, const char *modprobe)
-{
-       char *buf = NULL;
-       char *argv[3];
-       struct stat junk;
-       int status;
-       
-       if (!stat(modprobe, &junk)) {
-               /* Try to read out of the kernel */
-               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);
-               
-               /* Should not reach */
-               exit(1);
-       case -1:
-               return -1;
-       
-       default: /* parent */
-               wait(&status);
-       }
-       
-       free(buf);
-       
-       if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
-               return 0;
-       return -1;
-}
-
-static int kernel_getsocket(void)
-{
-       int sockfd = -1;
-
-       sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
-       if (sockfd < 0)
-               exit_error(OTHER_PROBLEM,
-                          "You need to be root to perform this command.");
-
-       return sockfd;
-}
-
-static void kernel_error(unsigned cmd, int err)
-{
-       unsigned int i;
-       struct translate_error {
-               int err;
-               unsigned cmd;
-               const char *message;
-       } table[] =
-       { /* Generic error codes */
-         { EPERM, 0, "Missing capability" },
-         { EBADF, 0, "Invalid socket option" },
-         { EINVAL, 0, "Size mismatch for expected socket data" },
-         { ENOMEM, 0, "Not enough memory" },
-         { EFAULT, 0, "Failed to copy data" },
-         { EPROTO, 0, "ipset kernel/userspace version mismatch" },
-         { EBADMSG, 0, "Unknown command" },
-         /* Per command error codes */
-         /* Reserved ones for add/del/test to handle internally: 
-          *    EEXIST
-          */
-         { ENOENT, CMD_CREATE, "Unknown set type" },
-         { ENOENT, 0, "Unknown set" },
-         { EAGAIN, 0, "Sets are busy, try again later" },
-         { ERANGE, CMD_CREATE, "No free slot remained to add a new set" },
-         { ERANGE, 0, "IP/port/element is outside of the set or set is full" },
-         { ENOEXEC, CMD_CREATE, "Invalid parameters to create a set" },
-         { ENOEXEC, CMD_SWAP, "Sets with different types cannot be swapped" },
-         { EEXIST, CMD_CREATE, "Set already exists" },
-         { EEXIST, CMD_RENAME, "Set with new name already exists" },
-         { EEXIST, 0, "Set specified as element does not exist" },
-         { EBUSY, 0, "Set is in use, operation not permitted" },
-         };
-       for (i = 0; i < sizeof(table)/sizeof(struct translate_error); i++) {
-               if ((table[i].cmd == cmd || table[i].cmd == 0)
-                   && table[i].err == err)
-                       exit_error(err == EPROTO ? VERSION_PROBLEM
-                                                : OTHER_PROBLEM, 
-                                  table[i].message);
-       }
-       exit_error(OTHER_PROBLEM, "Error from kernel: %s", strerror(err));
-}
-
-static inline int wrapped_getsockopt(void *data, socklen_t *size)
-{
-       int res;
-       int sockfd = kernel_getsocket();
-
-       /* Send! */
-       res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-       if (res != 0 
-           && errno == ENOPROTOOPT 
-           && ipset_insmod("ip_set", "/sbin/modprobe") == 0)
-               res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-       DP("res=%d errno=%d", res, errno);
-       
-       return res;
-}
-
-static inline int wrapped_setsockopt(void *data, socklen_t size)
-{
-       int res;
-       int sockfd = kernel_getsocket();
-
-       /* Send! */
-       res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-       if (res != 0 
-           && errno == ENOPROTOOPT 
-           && ipset_insmod("ip_set", "/sbin/modprobe") == 0)
-               res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-       DP("res=%d errno=%d", res, errno);
-       
-       return res;
-}
-
-static void kernel_getfrom(unsigned cmd, void *data, socklen_t * size)
-{
-       int res = wrapped_getsockopt(data, size);
-
-       if (res != 0)
-               kernel_error(cmd, errno);
-}
-
-static int kernel_sendto_handleerrno(unsigned cmd,
-                                    void *data, socklen_t size)
-{
-       int res = wrapped_setsockopt(data, size);
-
-       if (res != 0) {
-               if (errno == EEXIST)
-                       return -1;
-               else
-                       kernel_error(cmd, errno);
-       }
-
-       return 0; /* all ok */
-}
-
-static void kernel_sendto(unsigned cmd, void *data, size_t size)
-{
-       int res = wrapped_setsockopt(data, size);
-
-       if (res != 0)
-               kernel_error(cmd, errno);
-}
-
-static int kernel_getfrom_handleerrno(unsigned cmd, void *data, socklen_t *size)
-{
-       int res = wrapped_getsockopt(data, size);
-
-       if (res != 0) {
-               if (errno == EAGAIN)
-                       return -1;
-               else
-                       kernel_error(cmd, errno);
-       }
-
-       return 0; /* all ok */
-}
-
-static void check_protocolversion(void)
-{
-       struct ip_set_req_version req_version;
-       socklen_t size = sizeof(struct ip_set_req_version);
-       int res;
-
-       if (protocol_version)
-               return;
-       
-       req_version.op = IP_SET_OP_VERSION;
-       res = wrapped_getsockopt(&req_version, &size);
-
-       if (res != 0)
-               exit_error(OTHER_PROBLEM,
-                          "Couldn't verify kernel module version!");
-
-       if (!(req_version.version == IP_SET_PROTOCOL_VERSION
-             || req_version.version == IP_SET_PROTOCOL_UNALIGNED))
-               exit_error(OTHER_PROBLEM,
-                          "Kernel ip_set module is of protocol version %u."
-                          "I'm of protocol version %u.\n"
-                          "Please upgrade your kernel and/or ipset(8) utillity.",
-                          req_version.version, IP_SET_PROTOCOL_VERSION);
-       protocol_version = req_version.version;
-}
-
-static void set_command(int *cmd, int newcmd)
-{
-       if (*cmd != CMD_NONE)
-               exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
-                          cmd2char(*cmd), cmd2char(newcmd));
-       *cmd = newcmd;
-}
-
-static void add_option(unsigned int *options, unsigned int option)
-{
-       if (*options & option)
-               exit_error(PARAMETER_PROBLEM,
-                          "multiple -%c flags not allowed",
-                          opt2char(option));
-       *options |= option;
-}
-
-void *ipset_malloc(size_t size)
-{
-       void *p;
-
-       if (size == 0)
-               return NULL;
-
-       if ((p = malloc(size)) == NULL) {
-               perror("ipset: not enough memory");
-               exit(1);
-       }
-       return p;
-}
-
-char *ipset_strdup(const char *s)
-{
-       char *p;
-
-       if ((p = strdup(s)) == NULL) {
-               perror("ipset: not enough memory");
-               exit(1);
-       }
-       return p;
-}
-
-void ipset_free(void *data)
-{
-       if (data == NULL)
-               return;
-
-       free(data);
-}
-
-static struct option *merge_options(struct option *oldopts,
-                                   const struct option *newopts,
-                                   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 = ipset_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;
-}
-
-static char *ip_tohost(const struct in_addr *addr)
-{
-       struct hostent *host;
-
-       if ((host = gethostbyaddr((char *) addr,
-                                 sizeof(struct in_addr),
-                                 AF_INET)) != NULL) {
-               DP("%s", host->h_name);
-               return (char *) host->h_name;
-       }
-
-       return (char *) NULL;
-}
-
-static char *ip_tonetwork(const struct in_addr *addr)
-{
-       struct netent *net;
-
-       if ((net = getnetbyaddr(ntohl(addr->s_addr), 
-                               AF_INET)) != NULL) {
-               DP("%s", net->n_name);
-               return (char *) net->n_name;
-       }
-
-       return (char *) NULL;
-}
-
-/* Return a string representation of an IP address.
- * Please notice that a pointer to static char* area is returned.
- */
-char *ip_tostring(ip_set_ip_t ip, unsigned options)
-{
-       struct in_addr addr;
-       addr.s_addr = htonl(ip);
-
-       if (!(options & OPT_NUMERIC)) {
-               char *name;
-               if ((name = ip_tohost(&addr)) != NULL ||
-                   (name = ip_tonetwork(&addr)) != NULL)
-                       return name;
-       }
-       
-       return inet_ntoa(addr);
-}
-
-char *ip_tostring_numeric(ip_set_ip_t ip)
-{
-       return ip_tostring(ip, OPT_NUMERIC);
-}
-
-/* Fills the 'ip' with the parsed ip or host in host byte order */
-void parse_ip(const char *str, ip_set_ip_t * ip)
-{
-       struct hostent *host;
-       struct in_addr addr;
-
-       DP("%s", str);
-       
-       if (inet_aton(str, &addr) != 0) {
-               *ip = ntohl(addr.s_addr);       /* We want host byte order */
-               return;
-       }
-
-       host = gethostbyname(str);
-       if (host != NULL) {
-               if (host->h_addrtype != AF_INET ||
-                   host->h_length != sizeof(struct in_addr))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "host/network `%s' not an internet name",
-                                  str);
-               if (host->h_addr_list[1] != 0)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "host/network `%s' resolves to serveral ip-addresses. "
-                                  "Please specify one.", str);
-
-               memcpy(&addr, host->h_addr_list[0], sizeof(struct in_addr));
-               *ip = ntohl(addr.s_addr);
-               return;
-       }
-
-       exit_error(PARAMETER_PROBLEM, "host/network `%s' not found", str);
-}
-
-/* Fills 'mask' with the parsed mask in host byte order */
-void parse_mask(const char *str, ip_set_ip_t * mask)
-{
-       struct in_addr addr;
-       int bits;
-
-       DP("%s", str);
-
-       if (str == NULL) {
-               /* no mask at all defaults to 32 bits */
-               *mask = 0xFFFFFFFF;
-               return;
-       }
-       if (strchr(str, '.') && inet_aton(str, &addr) != 0) {
-               *mask = ntohl(addr.s_addr);     /* We want host byte order */
-               return;
-       }
-       if (sscanf(str, "%d", &bits) != 1 || bits < 0 || bits > 32)
-               exit_error(PARAMETER_PROBLEM,
-                          "invalid mask `%s' specified", str);
-
-       DP("bits: %d", bits);
-
-       *mask = bits != 0 ? 0xFFFFFFFF << (32 - bits) : 0L;
-}
-
-/* Combines parse_ip and parse_mask */
-void
-parse_ipandmask(const char *str, ip_set_ip_t * ip, ip_set_ip_t * mask)
-{
-       char buf[256];
-       char *p;
-
-       strncpy(buf, str, sizeof(buf) - 1);
-       buf[255] = '\0';
-
-       if ((p = strrchr(buf, '/')) != NULL) {
-               *p = '\0';
-               parse_mask(p + 1, mask);
-       } else
-               parse_mask(NULL, mask);
-
-       /* if a null mask is given, the name is ignored, like in "any/0" */
-       if (*mask == 0U)
-               *ip = 0U;
-       else
-               parse_ip(buf, ip);
-
-       DP("%s ip: %08X (%s) mask: %08X",
-          str, *ip, ip_tostring_numeric(*ip), *mask);
-
-       /* Apply the netmask */
-       *ip &= *mask;
-
-       DP("%s ip: %08X (%s) mask: %08X",
-          str, *ip, ip_tostring_numeric(*ip), *mask);
-}
-
-/* Return a string representation of a port
- * Please notice that a pointer to static char* area is returned
- * and we assume TCP protocol.
- */
-char *port_tostring(ip_set_ip_t port, unsigned options)
-{
-       struct servent *service;
-       static char name[] = "65535";
-       
-       if (!(options & OPT_NUMERIC)) {
-               if ((service = getservbyport(htons(port), "tcp")))
-                       return service->s_name;
-       }
-       sprintf(name, "%u", port);
-       return name;
-}
-
-int
-string_to_number(const char *str, unsigned int min, unsigned int max,
-                ip_set_ip_t *port)
-{
-       unsigned long number;
-       char *end;
-
-       /* Handle hex, octal, etc. */
-       errno = 0;
-       number = strtoul(str, &end, 0);
-       if (*end == '\0' && end != str) {
-               /* we parsed a number, let's see if we want this */
-               if (errno != ERANGE && min <= number && number <= max) {
-                       *port = number;
-                       return 0;
-               }
-       }
-       return -1;
-}
-
-static int
-string_to_port(const char *str, ip_set_ip_t *port)
-{
-       struct servent *service;
-       
-       if ((service = getservbyname(str, "tcp")) != NULL) {
-               *port = ntohs((uint16_t) service->s_port);
-               return 0;
-       }
-       return -1;
-}
-
-/* Fills the 'ip' with the parsed port in host byte order */
-void parse_port(const char *str, ip_set_ip_t *port)
-{      
-       if ((string_to_number(str, 0, 65535, port) != 0)
-             && (string_to_port(str, port) != 0))
-               exit_error(PARAMETER_PROBLEM, 
-                          "Invalid TCP port `%s' specified", str);     
-}
-
-/* 
- * Settype functions
- */
-static struct settype *settype_find(const char *typename)
-{
-       struct settype *runner = all_settypes;
-
-       DP("%s", typename);
-
-       while (runner != NULL) {
-               if (STREQ(runner->typename, typename))
-                       return runner;
-
-               runner = runner->next;
-       }
-
-       return NULL;            /* not found */
-}
-
-static struct settype *settype_load(const char *typename)
-{
-       char path[sizeof(IPSET_LIB_DIR) + sizeof(IPSET_LIB_NAME) +
-                 strlen(typename)];
-       struct settype *settype;
-
-       /* do some search in list */
-       settype = settype_find(typename);
-       if (settype != NULL)
-               return settype; /* found */
-
-       /* Else we have to load it */
-       sprintf(path, IPSET_LIB_DIR IPSET_LIB_NAME, typename);
-
-       if (dlopen(path, RTLD_NOW)) {
-               /* Found library. */
-
-               settype = settype_find(typename);
-
-               if (settype != NULL)
-                       return settype;
-       }
-
-       /* Can't load the settype */
-       exit_error(PARAMETER_PROBLEM,
-                  "Couldn't load settype `%s':%s\n",
-                  typename, dlerror());
-
-       return NULL;            /* Never executed, but keep compilers happy */
-}
-
-static char *check_set_name(char *setname)
-{
-       if (strlen(setname) > IP_SET_MAXNAMELEN - 1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Setname '%s' too long, max %d characters.",
-                          setname, IP_SET_MAXNAMELEN - 1);
-
-       return setname;
-}
-
-static struct settype *check_set_typename(const char *typename)
-{
-       if (strlen(typename) > IP_SET_MAXNAMELEN - 1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Typename '%s' too long, max %d characters.",
-                          typename, IP_SET_MAXNAMELEN - 1);
-
-       return settype_load(typename);
-}
-
-#define MAX(a,b)       ((a) > (b) ? (a) : (b))
-
-/* Register a new set type */
-void settype_register(struct settype *settype)
-{
-       struct settype *chk;
-       size_t size;
-
-       DP("%s", settype->typename);
-
-       /* Check if this typename already exists */
-       chk = settype_find(settype->typename);
-
-       if (chk != NULL)
-               exit_error(OTHER_PROBLEM,
-                          "Set type '%s' already registered!\n",
-                          settype->typename);
-
-       /* Check version */
-       if (settype->protocol_version != IP_SET_PROTOCOL_VERSION)
-               exit_error(OTHER_PROBLEM,
-                          "Set type %s is of wrong protocol version %u!"
-                          " I'm of version %u.\n", settype->typename,
-                          settype->protocol_version,
-                          IP_SET_PROTOCOL_VERSION);
-
-       /* Initialize internal data */
-       settype->header = ipset_malloc(settype->header_size);
-       size = MAX(settype->create_size, settype->adt_size);
-       settype->data = ipset_malloc(size);
-
-       /* Insert first */
-       settype->next = all_settypes;
-       all_settypes = settype;
-
-       DP("%s registered", settype->typename);
-}
-
-/* Find set functions */
-struct set *set_find_byid(ip_set_id_t id)
-{
-       struct set *set = NULL;
-       ip_set_id_t i;
-       
-       for (i = 0; i < max_sets; i++)
-               if (set_list[i] && set_list[i]->id == id) {
-                       set = set_list[i];
-                       break;
-               }
-                       
-       if (set == NULL)
-               exit_error(PARAMETER_PROBLEM,
-                          "Set identified by id %u is not found", id);
-       return set;
-}
-
-struct set *set_find_byname(const char *name)
-{
-       struct set *set = NULL;
-       ip_set_id_t i;
-       
-       for (i = 0; i < max_sets; i++)
-               if (set_list[i] != NULL && STREQ(set_list[i]->name, name)) {
-                       set = set_list[i];
-                       break;
-               }
-       if (set == NULL)
-               exit_error(PARAMETER_PROBLEM,
-                          "Set %s is not found", name);
-       return set;
-}
-
-static ip_set_id_t set_find_free_index(const char *name)
-{
-       ip_set_id_t i, idx = IP_SET_INVALID_ID;
-
-       for (i = 0; i < max_sets; i++) {
-               if (idx == IP_SET_INVALID_ID
-                   && set_list[i] == NULL)
-                       idx = i;
-               if (set_list[i] != NULL && STREQ(set_list[i]->name, name))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Set %s is already defined, cannot be restored",
-                                  name);
-       }
-                       
-       if (idx == IP_SET_INVALID_ID)           
-               exit_error(PARAMETER_PROBLEM,
-                          "Set %s cannot be restored, "
-                          "max number of set %u reached",
-                          name, max_sets);
-
-       return idx;
-}
-
-/* 
- * Send create set order to kernel
- */
-static void set_create(const char *name, struct settype *settype)
-{
-       struct ip_set_req_create req_create;
-       size_t size;
-       void *data;
-
-       DP("%s %s", name, settype->typename);
-
-       req_create.op = IP_SET_OP_CREATE;
-       req_create.version = protocol_version;
-       strcpy(req_create.name, name);
-       strcpy(req_create.typename, settype->typename);
-
-       /* Final checks */
-       settype->create_final(settype->data, settype->flags);
-
-       /* Alloc memory for the data to send */
-       size = sizeof(struct ip_set_req_create) + settype->create_size;
-       data = ipset_malloc(size);
-
-       /* Add up ip_set_req_create and the settype data */
-       memcpy(data, &req_create, sizeof(struct ip_set_req_create));
-       memcpy(data + sizeof(struct ip_set_req_create),
-              settype->data, settype->create_size);
-
-       kernel_sendto(CMD_CREATE, data, size);
-       free(data);
-}
-
-static void set_restore_create(const char *name, struct settype *settype)
-{
-       struct set *set;
-       
-       DP("%s %s %zu %zu %u %u", name, settype->typename,
-          restore_offset, sizeof(struct ip_set_restore),
-          settype->create_size, restore_size);
-
-       /* Sanity checking */
-       if (restore_offset
-           + ALIGNED(sizeof(struct ip_set_restore))
-           + ALIGNED(settype->create_size) > restore_size)
-               exit_error(PARAMETER_PROBLEM,
-                          "Giving up, restore file is screwed up!");
-                          
-       /* Final checks */
-       settype->create_final(settype->data, settype->flags);
-
-       /* Fill out restore_data */
-       restore_set = (struct ip_set_restore *) 
-                       (restore_data + restore_offset);
-       strcpy(restore_set->name, name);
-       strcpy(restore_set->typename, settype->typename);
-       restore_set->index = set_find_free_index(name);
-       restore_set->header_size = settype->create_size;
-       restore_set->members_size = 0;
-
-       DP("name %s, restore index %u", restore_set->name, restore_set->index);
-       /* Add settype data */
-       
-       restore_offset += ALIGNED(sizeof(struct ip_set_restore));
-       memcpy(restore_data + restore_offset, settype->data, settype->create_size);
-
-       restore_offset += ALIGNED(settype->create_size);
-       DP("restore_offset: %zu", restore_offset);
-       
-       /* Add set to set_list */
-       set = ipset_malloc(sizeof(struct set));
-       strcpy(set->name, name);
-       set->settype = settype;
-       set->index = restore_set->index;
-       set_list[restore_set->index] = set;
-}
-
-/*
- * Send destroy/flush order to kernel for one or all sets
- */
-static void set_destroy(const char *name, unsigned op, unsigned cmd)
-{
-       struct ip_set_req_std req;
-
-       DP("%s %s", cmd == CMD_DESTROY ? "destroy" : "flush", name);
-
-       req.op = op;
-       req.version = protocol_version;
-       strcpy(req.name, name);
-
-       kernel_sendto(cmd, &req, sizeof(struct ip_set_req_std));
-}
-
-/*
- * Send rename/swap order to kernel
- */
-static void set_rename(const char *name, const char *newname,
-                      unsigned op, unsigned cmd)
-{
-       struct ip_set_req_create req;
-
-       DP("%s %s %s", cmd == CMD_RENAME ? "rename" : "swap",
-                      name, newname);
-
-       req.op = op;
-       req.version = protocol_version;
-       strcpy(req.name, name);
-       strcpy(req.typename, newname);
-
-       kernel_sendto(cmd, &req,
-                     sizeof(struct ip_set_req_create));
-}
-
-/*
- * Send MAX_SETS, LIST_SIZE and/or SAVE_SIZE orders to kernel
- */
-static size_t load_set_list(const char name[IP_SET_MAXNAMELEN],
-                           ip_set_id_t *idx,
-                           unsigned op, unsigned cmd)
-{
-       void *data = NULL;
-       struct ip_set_req_max_sets req_max_sets;
-       struct ip_set_name_list *name_list;
-       struct set *set;
-       ip_set_id_t i;
-       socklen_t size, req_size;
-       int repeated = 0, res = 0;
-
-       DP("%s %s", cmd == CMD_MAX_SETS ? "MAX_SETS"
-                   : cmd == CMD_LIST_SIZE ? "LIST_SIZE"
-                   : "SAVE_SIZE",
-                   name);
-       
-tryagain:
-       if (set_list) {
-               for (i = 0; i < max_sets; i++)
-                       if (set_list[i])
-                               free(set_list[i]);
-               free(set_list);
-               set_list = NULL;
-       }
-       /* Get max_sets */
-       req_max_sets.op = IP_SET_OP_MAX_SETS;
-       req_max_sets.version = protocol_version;
-       strcpy(req_max_sets.set.name, name);
-       size = sizeof(req_max_sets);
-       kernel_getfrom(CMD_MAX_SETS, &req_max_sets, &size);
-
-       DP("got MAX_SETS: sets %d, max_sets %d",
-          req_max_sets.sets, req_max_sets.max_sets);
-
-       max_sets = req_max_sets.max_sets;
-       set_list = ipset_malloc(max_sets * sizeof(struct set *));
-       memset(set_list, 0, max_sets * sizeof(struct set *));
-       *idx = req_max_sets.set.index;
-
-       if (req_max_sets.sets == 0)
-               /* No sets in kernel */
-               return 0;
-
-       /* Get setnames */
-       size = req_size = ALIGNED(sizeof(struct ip_set_req_setnames)) 
-                         + req_max_sets.sets * ALIGNED(sizeof(struct ip_set_name_list));
-       data = ipset_malloc(size);
-       ((struct ip_set_req_setnames *) data)->op = op;
-       ((struct ip_set_req_setnames *) data)->index = *idx;
-
-       res = kernel_getfrom_handleerrno(cmd, data, &size);
-
-       if (res != 0 || size != req_size) {
-               free(data);
-               if (repeated++ < LIST_TRIES)
-                       goto tryagain;
-               exit_error(OTHER_PROBLEM,
-                          "Tried to get sets from kernel %d times"
-                          " and failed. Please try again when the load on"
-                          " the sets has gone down.", LIST_TRIES);
-       }
-               
-       /* Load in setnames */
-       size = ALIGNED(sizeof(struct ip_set_req_setnames));                     
-       while (size + ALIGNED(sizeof(struct ip_set_name_list)) <= req_size) {
-               name_list = (struct ip_set_name_list *)
-                       (data + size);
-               set = ipset_malloc(sizeof(struct set));
-               strcpy(set->name, name_list->name);
-               set->index = name_list->index;
-               set->id = name_list->id;
-               set->settype = settype_load(name_list->typename);
-               set_list[name_list->index] = set;
-               DP("loaded %s, type %s, index %u",
-                  set->name, set->settype->typename, set->index);
-               size += ALIGNED(sizeof(struct ip_set_name_list));
-       }
-       /* Size to get set members  */
-       size = ((struct ip_set_req_setnames *)data)->size;
-       free(data);
-       
-       return size;
-}
-
-/*
- * Save operation
- */
-static size_t save_set(void *data, size_t offset, size_t len)
+
+static void __attribute__((format(printf,2,3)))
+exit_error(int status, const char *msg, ...)
 {
-       struct ip_set_save *set_save =
-               (struct ip_set_save *) (data + offset);
-       struct set *set;
-       struct settype *settype;
-       size_t used;
-       
-       DP("offset %zu (%zu/%u/%u), len %zu", offset,
-          sizeof(struct ip_set_save), 
-          set_save->header_size, set_save->members_size, 
-          len);
-       if (offset + ALIGNED(sizeof(struct ip_set_save)) > len
-           || offset + ALIGNED(sizeof(struct ip_set_save))
-              + set_save->header_size + set_save->members_size > len)
-               exit_error(OTHER_PROBLEM,
-                          "Save operation failed, try again later.");
+       bool quiet = !interactive
+                    && session
+                    && ipset_envopt_test(session, IPSET_ENV_QUIET);
 
-       DP("index: %u", set_save->index);
-       if (set_save->index == IP_SET_INVALID_ID) {
-               /* Marker */
-               return ALIGNED(sizeof(struct ip_set_save));
-       }
-       set = set_list[set_save->index];
-       if (!set)
-               exit_error(OTHER_PROBLEM,
-                          "Save set failed, try again later.");
-       settype = set->settype;
+       if (status && msg && !quiet) {
+               va_list args;
 
-       /* Init set header */
-       used = ALIGNED(sizeof(struct ip_set_save));
-       settype->initheader(set, data + offset + used);
+               fprintf(stderr, "%s v%s: ", program_name, program_version);
+               va_start(args, msg);
+               vfprintf(stderr, msg, args);
+               va_end(args);
+               fprintf(stderr, "\n");
 
-       /* Print create set */
-       settype->saveheader(set, OPT_NUMERIC);
+               if (status == PARAMETER_PROBLEM)
+                       fprintf(stderr,
+                               "Try `%s help' for more information.\n",
+                               program_name);
+       }
+       /* Ignore errors in interactive mode */
+       if (status && interactive) {
+               if (session)
+                       ipset_session_report_reset(session);
+               return;
+       }
 
-       /* Print add IPs */
-       used += set_save->header_size;
-       settype->saveips(set, data + offset + used,
-                        set_save->members_size, OPT_NUMERIC,
-                        DONT_ALIGN);
+       if (session)
+               ipset_session_fini(session);
 
-       return (used + set_save->members_size);
+       D("status: %u", status);
+       exit(status);
 }
 
-static int try_save_sets(const char name[IP_SET_MAXNAMELEN])
+static int
+handle_error(void)
 {
-       void *data = NULL;
-       socklen_t size, req_size = 0;
-       ip_set_id_t idx;
-       int res = 0;
-       time_t now = time(NULL);
-
-       /* Load set_list from kernel */
-       size = load_set_list(name, &idx,
-                            IP_SET_OP_SAVE_SIZE, CMD_SAVE);
-       
-       if (size) {
-               /* Get sets and print them */
-               /* Take into account marker */
-               req_size = (size += ALIGNED(sizeof(struct ip_set_save)));
-               data = ipset_malloc(size);
-               ((struct ip_set_req_list *) data)->op = IP_SET_OP_SAVE;
-               ((struct ip_set_req_list *) data)->index = idx;
-               res = kernel_getfrom_handleerrno(CMD_SAVE, data, &size);
+       if (ipset_session_warning(session)
+           && !ipset_envopt_test(session, IPSET_ENV_QUIET))
+               fprintf(stderr, "Warning: %s\n",
+                       ipset_session_warning(session));
+       if (ipset_session_error(session))
+               exit_error(OTHER_PROBLEM, "%s",
+                          ipset_session_error(session));
 
-               if (res != 0 || size != req_size) {
-                       DP("Try again: res: %i, size %u, req_size: %u",
-                          res, size, req_size);
-                       free(data);
-                       return -EAGAIN;
-               }
+       if (!interactive) {
+               ipset_session_fini(session);
+               exit(OTHER_PROBLEM);
        }
 
-       printf("# Generated by ipset %s on %s", IPSET_VERSION, ctime(&now));
-       size = 0;
-       while (size < req_size) {
-               DP("size: %u, req_size: %u", size, req_size);
-               size += save_set(data, size, req_size);
-       }
-       printf("COMMIT\n");
-       now = time(NULL);
-       printf("# Completed on %s", ctime(&now));
-       ipset_free(data);
-       return res;
+       ipset_session_report_reset(session);    
+       return -1;
 }
 
-/*
- * Performs a save to stdout
- */
-static void set_save(const char name[IP_SET_MAXNAMELEN])
+static void
+help(void)
 {
-       int i;
-
-       DP("%s", name);
-       for (i = 0; i < LIST_TRIES; i++)
-               if (try_save_sets(name) == 0)
-                       return;
+       enum ipset_cmd cmd;
+       const struct ipset_envopts *opt = ipset_envopts;
+       
+       printf("%s v%s\n\n"
+              "Usage: %s [options] COMMAND\n\nCommands:\n",
+              program_name, program_version, program_name);
 
-       if (errno == EAGAIN)
-               exit_error(OTHER_PROBLEM,
-                          "Tried to save sets from kernel %d times"
-                          " and failed. Please try again when the load on"
-                          " the sets has gone down.", LIST_TRIES);
-       else
-               kernel_error(CMD_SAVE, errno);
+       for (cmd = IPSET_CMD_NONE + 1; cmd < IPSET_CMD_MAX; cmd++) {
+               if (!ipset_commands[cmd-1].name[0])
+                       continue;
+               printf("%s %s\n",
+                      ipset_commands[cmd-1].name[0],
+                      ipset_commands[cmd-1].help);
+       }
+       printf("\nOptions:\n");
+       
+       while (opt->flag) {
+               if (opt->help)
+                       printf("%s %s\n", opt->name[0], opt->help);
+               opt++;
+       }
 }
 
-/*
- * Restore operation
- */
-
-/* global new argv and argc */
-static char *newargv[255];
-static int newargc = 0;
-
 /* Build faked argv from parsed line */
-static void build_argv(unsigned line, char *buffer) {
+static void
+build_argv(char *buffer)
+{
        char *ptr;
        int i;
 
        /* Reset */     
        for (i = 1; i < newargc; i++)
-               free(newargv[i]);
+               newargv[i] = NULL;
        newargc = 1;
 
        ptr = strtok(buffer, " \t\n");
-       newargv[newargc++] = ipset_strdup(ptr);
+       newargv[newargc++] = ptr;
        while ((ptr = strtok(NULL, " \t\n")) != NULL) {
                if ((newargc + 1) < (int)(sizeof(newargv)/sizeof(char *)))
-                       newargv[newargc++] = ipset_strdup(ptr);
+                       newargv[newargc++] = ptr;
                else
                        exit_error(PARAMETER_PROBLEM,
-                                  "Line %d is too long to restore\n", line);
+                                  "Line is too long to parse.");
        }
 }
 
-static FILE *create_tempfile(void)
-{
-       char buffer[1024], __tmpdir[] = "/tmp"; 
-       char *tmpdir = NULL;
-       char *filename;
-       int fd;
-       FILE *file;
-       
-       if (!(tmpdir = getenv("TMPDIR")) && !(tmpdir = getenv("TMP")))
-               tmpdir = __tmpdir;
-       filename = ipset_malloc(strlen(tmpdir) + strlen(TEMPFILE_PATTERN) + 1);
-       strcpy(filename, tmpdir);
-       strcat(filename, TEMPFILE_PATTERN);
-       
-       (void) umask(077);      /* Create with restrictive permissions */
-       fd = mkstemp(filename);
-       if (fd == -1)
-               exit_error(OTHER_PROBLEM, "Could not create temporary file.");
-       if (!(file = fdopen(fd, "r+")))
-               exit_error(OTHER_PROBLEM, "Could not open temporary file.");
-       if (unlink(filename) == -1)
-               exit_error(OTHER_PROBLEM, "Could not unlink temporary file.");
-       free(filename);
-
-       while (fgets(buffer, sizeof(buffer), stdin)) {
-               fputs(buffer, file);
-       }
-       fseek(file, 0L, SEEK_SET);
-
-       return file;
-}
+/* Main parser function, workhorse */
+int parse_commandline(int argc, char *argv[]);
 
 /*
- * Performs a restore from a file
+ * Performs a restore from stdin
  */
-static void set_restore(char *argv0)
+static int
+restore(char *argv0)
 {
-       char buffer[1024];      
-       char *ptr, *name = NULL;
-       char cmd = ' ';
-       int first_pass, i;
-       struct settype *settype = NULL;
-       struct ip_set_req_setnames *header;
-       ip_set_id_t idx;
-       FILE *in;
-       int res;
-       
-       /* Create and store stdin in temporary file */
-       in = create_tempfile();
-       
-       /* Load existing sets from kernel */
-       load_set_list(IPSET_TOKEN_ALL, &idx,
-                     IP_SET_OP_LIST_SIZE, CMD_RESTORE);
-       
-       restore_line = 0;
-       restore_size = ALIGNED(sizeof(struct ip_set_req_setnames)); /* header */
-       DP("restore_size: %u", restore_size);
-       /* First pass: calculate required amount of data */
-       while (fgets(buffer, sizeof(buffer), in)) {
-               restore_line++;
-
-               if (buffer[0] == '\n')
-                       continue;
-               else if (buffer[0] == '#')
-                       continue;
-               else if (strcmp(buffer, "COMMIT\n") == 0) {
-                       /* Enable restore mode */
-                       restore = 1;
-                       break;
-               }
-                       
-               /* -N, -A or -B */
-               ptr = strtok(buffer, " \t\n");
-               DP("ptr: %s", ptr);
-               if (ptr == NULL
-                   || ptr[0] != '-'
-                   || !(ptr[1] == 'N'
-                        || ptr[1] == 'A'
-                        || ptr[1] == 'B')
-                   || ptr[2] != '\0') {
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Line %u does not start as a valid restore command\n",
-                                  restore_line);
-               }
-               cmd = ptr[1];           
-               /* setname */
-               ptr = strtok(NULL, " \t\n");
-               DP("setname: %s", ptr);
-               if (ptr == NULL)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Missing set name in line %u\n",
-                                  restore_line);
-               DP("cmd %c", cmd);
-               switch (cmd) {
-               case 'N': {
-                       name = check_set_name(ptr);
-                       /* settype */
-                       ptr = strtok(NULL, " \t\n");
-                       if (ptr == NULL)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Missing settype in line %u\n",
-                                          restore_line);
-                       settype = check_set_typename(ptr);
-                       restore_size += ALIGNED(sizeof(struct ip_set_restore))
-                                       + ALIGNED(settype->create_size);
-                       DP("restore_size (N): %u", restore_size);
-                       break; 
-               }
-               case 'A': {
-                       if (name == NULL
-                           || strncmp(name, ptr, sizeof(name)) != 0)
-                               exit_error(PARAMETER_PROBLEM,
-                                          "Add IP to set %s in line %u without "
-                                          "preceding corresponding create set line\n",
-                                          ptr, restore_line);
-                       restore_size += ALIGNED(settype->adt_size);
-                       DP("restore_size (A): %u", restore_size);
-                       break;
-               }
-               default: {
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Unrecognized restore command in line %u\n",
-                                  restore_line);
-               }
-               } /* end of switch */
-       }                       
-       /* Sanity checking */
-       if (!restore)
-               exit_error(PARAMETER_PROBLEM,
-                          "Missing COMMIT line\n");
-       restore_size += ALIGNED(sizeof(struct ip_set_restore)); /* marker */
-       DP("restore_size: %u", restore_size);
-       restore_data = ipset_malloc(restore_size);
-       header = (struct ip_set_req_setnames *) restore_data;
-       header->op = IP_SET_OP_RESTORE; 
-       header->size = restore_size; 
-       restore_offset = ALIGNED(sizeof(struct ip_set_req_setnames));
-
-       /* Rewind to scan the file again */
-       fseek(in, 0L, SEEK_SET);
-       first_pass = restore_line;
-       restore_line = 0;
+       int ret = 0;
+       char *c;
        
        /* Initialize newargv/newargc */
-       newargv[newargc++] = ipset_strdup(argv0);
-       
-       /* Second pass: build up restore request */
-       while (fgets(buffer, sizeof(buffer), in)) {             
-               restore_line++;
+       newargc = 0;
+       newargv[newargc++] = argv0;
 
-               if (buffer[0] == '\n')
+       while (fgets(cmdline, sizeof(cmdline), stdin)) {
+               restore_line++;
+               c = cmdline;
+               while (isspace(c[0]))
+                       c++;
+               if (c[0] == '\0' || c[0] == '#')
                        continue;
-               else if (buffer[0] == '#')
+               else if (strcmp(c, "COMMIT\n") == 0) {
+                       ret = ipset_commit(session);
+                       if (ret < 0)
+                               handle_error();
                        continue;
-               else if (strcmp(buffer, "COMMIT\n") == 0)
-                       goto do_restore;
-               DP("restoring: %s", buffer);
+               }
                /* Build faked argv, argc */
-               build_argv(restore_line, buffer);
-               for (i = 0; i < newargc; i++)
-                       DP("argv[%u]: %s", i, newargv[i]);
+               build_argv(c);
                
-               /* Parse line */
-               parse_commandline(newargc, newargv);
-       }
-       exit_error(PARAMETER_PROBLEM,
-                  "Broken restore file\n");
-   do_restore:
-       if (restore_size == (restore_offset + ALIGNED(sizeof(struct ip_set_restore)))) {
-               /* No bindings */
-               struct ip_set_restore *marker = 
-                       (struct ip_set_restore *) (restore_data + restore_offset);
-
-               marker->index = IP_SET_INVALID_ID;
-               marker->header_size = marker->members_size = 0;
-               restore_offset += ALIGNED(sizeof(struct ip_set_restore));
-               DP("restore marker, restore_offset: %zu", restore_offset);
-       }
-       if (restore_size != restore_offset)
-               exit_error(PARAMETER_PROBLEM,
-                          "Giving up, restore file is screwed up!");
-       res = kernel_getfrom_handleerrno(CMD_RESTORE, restore_data, &restore_size);
-
-       if (res != 0) {
-               if (restore_size != sizeof(struct ip_set_req_setnames))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Communication with kernel failed (%u %u)!",
-                                  restore_size, sizeof(struct ip_set_req_setnames));
-               /* Check errors  */
-               header = (struct ip_set_req_setnames *) restore_data;
-               if (header->size != 0) 
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Committing restoring failed at line %u!",
-                                  header->size);
+               /* Execute line */
+               ret = parse_commandline(newargc, newargv);
+               if (ret < 0)
+                       handle_error();
        }
-}
-
-/*
- * Send ADT_GET order to kernel for a set
- */
-static struct set *set_adt_get(const char *name)
-{
-       struct ip_set_req_adt_get req_adt_get;
-       struct set *set;
-       socklen_t size;
-
-       DP("%s", name);
-
-       check_protocolversion();
-
-       req_adt_get.op = IP_SET_OP_ADT_GET;
-       req_adt_get.version = protocol_version;
-       strcpy(req_adt_get.set.name, name);
-       size = sizeof(struct ip_set_req_adt_get);
-
-       kernel_getfrom(CMD_ADT_GET, (void *) &req_adt_get, &size);
-
-       set = ipset_malloc(sizeof(struct set));
-       strcpy(set->name, name);
-       set->index = req_adt_get.set.index;     
-       set->settype = settype_load(req_adt_get.typename);
-
-       return set;
-}      
-
-/*
- * Send add/del/test order to kernel for a set
- */
-static int set_adtip(struct set *set, const char *adt, 
-                    unsigned op, unsigned cmd)
-{
-       struct ip_set_req_adt *req_adt;
-       size_t size;
-       void *data;
-       int res = 0;
-
-       DP("%s -> %s", set->name, adt);
-
-       /* Alloc memory for the data to send */
-       size = ALIGNED(sizeof(struct ip_set_req_adt)) + set->settype->adt_size ;
-       DP("alloc size %zu", size);
-       data = ipset_malloc(size);
-
-       /* Fill out the request */
-       req_adt = (struct ip_set_req_adt *) data;
-       req_adt->op = op;
-       req_adt->index = set->index;
-       memcpy(data + ALIGNED(sizeof(struct ip_set_req_adt)),
-              set->settype->data, set->settype->adt_size);
-       
-       if (kernel_sendto_handleerrno(cmd, data, size) == -1)
-               switch (op) {
-               case IP_SET_OP_ADD_IP:
-                       exit_error(OTHER_PROBLEM, "%s is already in set %s.",
-                                  adt, set->name);
-                       break;
-               case IP_SET_OP_DEL_IP:
-                       exit_error(OTHER_PROBLEM, "%s is not in set %s.",
-                                  adt, set->name);
-                       break;
-               case IP_SET_OP_TEST_IP:
-                       ipset_printf("%s is in set %s.", adt, set->name);
-                       res = 0;
-                       break;
-               default:
-                       break;
-               }
-       else
-               switch (op) {
-               case IP_SET_OP_TEST_IP:
-                       ipset_printf("%s is NOT in set %s.", adt, set->name);
-                       res = 1;
-                       break;
-               default:
-                       break;
-               }
-       free(data);
-
-       return res;
-}
+       /* implicit "COMMIT" at EOF */
+       ret = ipset_commit(session);
+       if (ret < 0)
+               handle_error();
 
-static void set_restore_add(struct set *set, const char *adt UNUSED)
-{
-       DP("%s %s", set->name, adt);
-       /* Sanity checking */
-       if (restore_offset + ALIGNED(set->settype->adt_size) > restore_size)
-               exit_error(PARAMETER_PROBLEM,
-                          "Giving up, restore file is screwed up!");
-                          
-       memcpy(restore_data + restore_offset,
-              set->settype->data, set->settype->adt_size);
-       restore_set->members_size += ALIGNED(set->settype->adt_size);
-       restore_offset += ALIGNED(set->settype->adt_size);
-
-       DP("restore_offset: %zu", restore_offset);
-}
-
-/*
- * Print operation
- */
-
-/* Help function to set_list() */
-static size_t print_set(void *data, unsigned options)
-{
-       struct ip_set_list *setlist = data;
-       struct set *set = set_list[setlist->index];
-       struct settype *settype = set->settype;
-       size_t offset;
-
-       /* Pretty print the set */
-       DP("header size: %u, members size: %u",
-          setlist->header_size, setlist->members_size);
-       printf("Name: %s\n", set->name);
-       printf("Type: %s\n", settype->typename);
-       printf("References: %d\n", setlist->ref);
-
-       /* Init header */
-       offset = ALIGNED(sizeof(struct ip_set_list));
-       settype->initheader(set, data + offset);
-
-       /* Pretty print the type header */
-       printf("Header:");
-       settype->printheader(set, options);
-
-       /* Pretty print all IPs */
-       printf("Members:\n");
-       offset += setlist->header_size;
-       DP("Aligned: %u, offset: %zu, members_size %u\n", !DONT_ALIGN, offset,
-          setlist->members_size);
-       if (options & OPT_SORTED)
-               settype->printips_sorted(set, data + offset,
-                                        setlist->members_size, options,
-                                        DONT_ALIGN);
-       else
-               settype->printips(set, data + offset,
-                                 setlist->members_size, options,
-                                 DONT_ALIGN);
-
-       printf("\n");           /* One newline between sets */
-       
-       return (offset + setlist->members_size);
+       return ret;
 }
 
-static int try_list_sets(const char name[IP_SET_MAXNAMELEN],
-                        unsigned options)
-{
-       void *data = NULL;
-       ip_set_id_t idx;
-       socklen_t size, req_size;
-       int res = 0;
-
-       /* Default is numeric listing */
-       if (!(options & (OPT_RESOLVE|OPT_NUMERIC)))
-               options |= OPT_NUMERIC;
-
-       DP("%s", name);
-       /* Load set_list from kernel */
-       size = req_size = load_set_list(name, &idx,
-                                       IP_SET_OP_LIST_SIZE, CMD_LIST);
-
-       if (size) {
-               /* Get sets and print them */
-               data = ipset_malloc(size);
-               ((struct ip_set_req_list *) data)->op = IP_SET_OP_LIST;
-               ((struct ip_set_req_list *) data)->index = idx;
-               res = kernel_getfrom_handleerrno(CMD_LIST, data, &size);
-               DP("get_lists getsockopt() res=%d errno=%d", res, errno);
-
-               if (res != 0 || size != req_size) {
-                       free(data);
-                       return -EAGAIN;
+static int
+call_parser(int argc, char *argv[],  const struct ipset_arg *args)
+{
+       int i = 1, ret = 0;
+       const struct ipset_arg *arg;
+       
+       /* Currently CREATE and ADD may have got additional arguments */
+       if (!args)
+               goto done;
+       for (arg = args; arg->opt; arg++) {
+               for (i = 1; i < argc; ) {
+                       D("argc: %u, i: %u", argc, i);
+                       if (!(ipset_name_match(argv[i], arg->name))) {
+                               i++;
+                               continue;
+                       }
+                       /* Shift off matched option */
+                       D("match %s", arg->name[0]);
+                       ipset_shift_argv(&argc, argv, i);
+                       D("argc: %u, i: %u", argc, i);
+                       switch (arg->has_arg) {
+                       case IPSET_MANDATORY_ARG:
+                               if (i + 1 > argc) {
+                                       exit_error(PARAMETER_PROBLEM,
+                                                  "Missing mandatory argument of option `%s'",
+                                                  arg->name[0]);
+                                       return 1;
+                               }
+                               /* Fall through */
+                       case IPSET_OPTIONAL_ARG:
+                               if (i + 1 <= argc) {
+                                       ret = arg->parse(session, arg->opt,
+                                                        argv[i]);
+                                       if (ret < 0)
+                                               return ret;
+                                       ipset_shift_argv(&argc, argv, i);
+                               }
+                               break;
+                       default:
+                               ret = ipset_data_set(ipset_session_data(session),
+                                                    arg->opt, arg->name[0]);
+                               if (ret < 0)
+                                       return ret;
+                       }
                }
-               size = 0;
        }
-       while (size != req_size)
-               size += print_set(data + size, options);
-
-       ipset_free(data);
-       return res;
+done:
+       if (i < argc) {
+               exit_error(PARAMETER_PROBLEM, "Unknown argument: `%s'",
+                          argv[i]);
+               return 1;
+       }
+       return ret;
 }
 
-/* Print a set or all sets
- * All sets: name = NULL
- */
-static void list_sets(const char name[IP_SET_MAXNAMELEN], unsigned options)
+static void
+check_mandatory(const struct ipset_type *type, int cmd)
 {
-       int i;
-
-       DP("%s", name);
-       for (i = 0; i < LIST_TRIES; i++)
-               if (try_list_sets(name, options) == 0)
-                       return;
-
-       if (errno == EAGAIN)
-               exit_error(OTHER_PROBLEM,
-                          "Tried to list sets from kernel %d times"
-                          " and failed. Please try again when the load on"
-                          " the sets has gone down.", LIST_TRIES);
-       else
-               kernel_error(CMD_LIST, errno);
-}
+       uint64_t flags = ipset_data_flags(ipset_session_data(session));
+       uint64_t mandatory = type->mandatory[cmd];
+       const struct ipset_arg *arg = type->args[cmd];
 
-/* Prints help
- * If settype is non null help for that type is printed as well
- */
-static void set_help(const struct settype *settype)
-{
-       printf("%s v%s\n\n"
-              "Usage: %s -N new-set settype [options]\n"
-              "       %s -[XFLSH] [set] [options]\n"
-              "       %s -[EW] from-set to-set\n"
-              "       %s -[ADT] set IP\n"
-              "       %s -R\n"
-              "       %s -v\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);
+       /* Range can be expressed by ip/cidr */
+       if (flags & IPSET_FLAG(IPSET_OPT_CIDR))
+               flags |= IPSET_FLAG(IPSET_OPT_IP_TO);
 
-       printf("Commands:\n"
-              "Either long or short options are allowed.\n"
-              "  --create  -N setname settype <options>\n"
-              "                    Create a new set\n"
-              "  --destroy -X [setname]\n"
-              "                    Destroy a set or all sets\n"
-              "  --flush   -F [setname]\n"
-              "                    Flush a set or all sets\n"
-              "  --rename  -E from-set to-set\n"
-              "                    Rename from-set to to-set\n"
-              "  --swap    -W from-set to-set\n"
-              "                    Swap the content of two existing sets\n"
-              "  --list    -L [setname] [options]\n"
-              "                    List the IPs in a set or all sets\n"
-              "  --save    -S [setname]\n"
-              "                    Save the set or all sets to stdout\n"
-              "  --restore -R [option]\n"
-              "                    Restores a saved state\n"
-              "  --add     -A setname IP\n"
-              "                    Add an IP to a set\n"
-              "  --del     -D setname IP\n"
-              "                    Deletes an IP from a set\n"
-              "  --test    -T setname IP \n"
-              "                    Tests if an IP exists in a set.\n"
-              "  --help    -H [settype]\n"
-              "                    Prints this help, and settype specific help\n"
-              "  --version -V\n"
-              "                    Prints version information\n\n"
-              "Options:\n"
-              "  --sorted     -s   Numeric sort of the IPs in -L\n"
-              "  --numeric    -n   Numeric output of addresses in a -L (default)\n"
-              "  --resolve    -r   Try to resolve addresses in a -L\n"
-              "  --quiet      -q   Suppress any output to stdout and stderr.\n");
-#ifdef IPSET_DEBUG
-       printf("  --debug      -z   Enable debugging\n\n");
-#else
-       printf("\n");
-#endif
+       mandatory &= ~flags;
+       if (!mandatory)
+               return;
 
-       if (settype != NULL) {
-               printf("Type '%s' specific:\n", settype->typename);
-               settype->usage();
-       }
+       for (; arg->opt; arg++)
+               if (mandatory & IPSET_FLAG(arg->opt))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Mandatory option `%s' is missing",
+                                  arg->name[0]);
 }
 
-static int find_cmd(int option)
+static const struct ipset_type *
+type_find(const char *name)
 {
-       int i;
+       const struct ipset_type *t = ipset_types();
        
-       for (i = 1; i <= NUMBER_OF_CMD; i++)
-               if (cmdflags[i] == option)
-                       return i;
-                       
-       return CMD_NONE;
+       while (t) {
+               if (STREQ(t->name, name) || STREQ(t->alias, name))
+                       return t;
+               t = t->next;
+       }
+       return NULL;
 }
 
-static int parse_adt_cmdline(int command,
-                            const char *name,
-                            char *adt,
-                            struct set **set,
-                            struct settype **settype)
+static inline int cmd2cmd(int cmd)
 {
-       int res = 0;
-
-       *set = restore ? set_find_byname(name) : set_adt_get(name);
-                                       
-       /* Reset space for adt data */
-       *settype = (*set)->settype;
-       memset((*settype)->data, 0, (*settype)->adt_size);
-
-       res = (*settype)->adt_parser(command, adt, (*settype)->data);
-
-       return res;
+       switch(cmd) {
+       case IPSET_CMD_ADD:
+               return IPSET_ADD;
+       case IPSET_CMD_DEL:
+               return IPSET_DEL;
+       case IPSET_CMD_TEST:
+               return IPSET_TEST;
+       case IPSET_CMD_CREATE:
+               return IPSET_CREATE;
+       default:
+               return 0;
+       }
 }
 
-/* Main worker function */
-int parse_commandline(int argc, char *argv[])
-{
-       int res = 0;
-       int command = CMD_NONE;
-       unsigned options = 0;
-       int c;
-       
-       char *name = NULL;              /* All except -H, -R */
-       char *newname = NULL;           /* -E, -W */
-       char *adt = NULL;               /* -A, -D, -T */
-       struct set *set = NULL;         /* -A, -D, -T */
-       struct settype *settype = NULL; /* -N, -H */
-       char all_sets[] = IPSET_TOKEN_ALL;
-       
-       struct option *opts = opts_long;
-
-       /* Suppress error messages: we may add new options if we
-          demand-load a protocol. */
-       opterr = 0;
-       /* Reset optind to 0 for restore */
-       optind = 0;
-       
-       while ((c = getopt_long(argc, argv, opts_short, opts, NULL)) != -1) {
-
-               DP("commandline parsed: opt %c (%s)", c, argv[optind]);
-
-               switch (c) {
-                       /*
-                        * Command selection
-                        */
-               case 'h':
-               case 'H':{      /* Help: -H [typename [options]] */
-                               check_protocolversion();
-                               set_command(&command, CMD_HELP);
-                               
-                               if (optarg)
-                                       settype = check_set_typename(optarg);
-                               else if (optind < argc
-                                        && argv[optind][0] != '-')
-                                       settype = check_set_typename(argv[optind++]);
-                               
-                               break;
-                       }
-
-               case 'V':
-               case 'v': {     /* Version */
-                               printf("%s v%s, protocol version %u.\n",
-                                      program_name, program_version,
-                                      IP_SET_PROTOCOL_VERSION);
-                               check_protocolversion();
-                               printf("Kernel module protocol version %u.\n",
-                                      protocol_version);
-                               exit(0);
+/* Workhorse */
+int
+parse_commandline(int argc, char *argv[])
+{
+       int ret = 0;
+       enum ipset_cmd cmd = IPSET_CMD_NONE;
+       int i = 0, j;
+       char *arg0 = NULL, *arg1 = NULL, *c;
+       const struct ipset_envopts *opt;
+       const struct ipset_commands *command;
+       const struct ipset_type *type;
+
+       /* Initialize session */
+       if (session == NULL) {
+               session = ipset_session_init(printf);
+               if (session == NULL)
+                       exit_error(OTHER_PROBLEM,
+                                  "Cannot initialize ipset session, aborting.");
+       }
+
+       /* Commandline parsing, somewhat similar to that of 'ip' */
+
+       /* First: parse core options */
+       for (opt = ipset_envopts; opt->flag ; opt++) {
+               for (i = 1; i < argc; ) {
+                       if (!ipset_name_match(argv[i], opt->name)) {
+                               i++;
+                               continue;
                        }
-
-               case 'N':{      /* Create: -N name typename options */
-                               set_command(&command, CMD_CREATE);
-
-                               name = check_set_name(optarg);
-                               
-                               /* Protect reserved names */
-                               if (name[0] == ':')
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "setname might not start with colon",
-                                                  cmd2char(CMD_CREATE));
-                               
-                               if (optind < argc
-                                   && argv[optind][0] != '-')
-                                       settype = check_set_typename(argv[optind++]);
-                               else
+                       /* Shift off matched option */
+                       ipset_shift_argv(&argc, argv, i);
+                       switch (opt->has_arg) {
+                       case IPSET_MANDATORY_ARG:
+                               if (i + 1 > argc)
                                        exit_error(PARAMETER_PROBLEM,
-                                                  "-%c requires setname and settype",
-                                                  cmd2char(CMD_CREATE));
-
-                               DP("merge options");
-                               /* Merge the create options */
-                               opts = merge_options(opts,
-                                            settype->create_opts,
-                                            &settype->option_offset);
-
-                               /* Reset space for create data */
-                               memset(settype->data, 0, settype->create_size);
-
-                               /* Zero the flags */
-                               settype->flags = 0;
-
-                               DP("call create_init");
-                               /* Call the settype create_init */
-                               settype->create_init(settype->data);
-
+                                                  "Missing mandatory argument to option %s",
+                                                  opt->name[0]);
+                               /* Fall through */
+                       case IPSET_OPTIONAL_ARG:
+                               if (i + 1 <= argc) {
+                                       ret = opt->parse(session, opt->flag,
+                                                        argv[i]);
+                                       if (ret < 0)
+                                               return handle_error();
+                                       ipset_shift_argv(&argc, argv, i);
+                               }
                                break;
-                       }
-
-               case 'X':       /* Destroy */
-               case 'F':       /* Flush */
-               case 'L':       /* List */
-               case 'S':{      /* Save */
-                               set_command(&command, find_cmd(c));
-
-                               if (optarg)
-                                       name = check_set_name(optarg);
-                               else if (optind < argc
-                                          && argv[optind][0] != '-')
-                                       name = check_set_name(argv[optind++]);
-                               else
-                                       name = all_sets;
-
+                       default:
+                               ret = opt->parse(session, opt->flag, argv[i]);
+                               if (ret < 0)
+                                       return handle_error();
                                break;
                        }
+               }
+       }
 
-               case 'R':{      /* Restore */
-                               set_command(&command, find_cmd(c));
-
-                               break;
+       /* Second: parse command */
+       for (j = IPSET_CMD_NONE + 1; j < IPSET_CMD_MAX; j++) {
+               command = &ipset_commands[j - 1];
+               if (!command->name[0])
+                       continue;
+               for (i = 1; i < argc; ) {
+                       if (!ipset_name_match(argv[i], command->name)) {
+                               i++;
+                               continue;
                        }
-
-               case 'E':       /* Rename */
-               case 'W':{      /* Swap */
-                               set_command(&command, find_cmd(c));
-                               name = check_set_name(optarg);
-
-                               if (optind < argc
-                                   && argv[optind][0] != '-')
-                                       newname = check_set_name(argv[optind++]);
-                               else
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "-%c requires a setname "
-                                                  "and the new name for that set",
-                                                  cmd2char(CMD_RENAME));
-
-                               break;
+                       if (cmd != IPSET_CMD_NONE)
+                               exit_error(PARAMETER_PROBLEM,
+                                          "Commands `%s' and `%s'"
+                                          "cannot be specified together.",
+                                          ipset_commands[cmd - 1].name[0],
+                                          command->name[0]);
+                       if (restore_line != 0
+                           && (j == IPSET_CMD_RESTORE
+                               || j == IPSET_CMD_VERSION
+                               || j == IPSET_CMD_HELP))
+                               exit_error(PARAMETER_PROBLEM,
+                                          "Command `%s' is invalid in restore mode.",
+                                          command->name[0]);
+                       if (interactive && j == IPSET_CMD_RESTORE) {
+                               printf("Restore command ignored in interactive mode\n");
+                               return 0;
                        }
 
-               case 'A':       /* Add IP */
-               case 'D':       /* Del IP */
-               case 'T':{      /* Test IP */
-                               set_command(&command, find_cmd(c));
-
-                               name = check_set_name(optarg);
-
-                               /* IP */
-                               if (optind < argc
-                                   && argv[optind][0] != '-')
-                                       adt = argv[optind++];
-                               else
-                                       exit_error(PARAMETER_PROBLEM,
-                                                  "-%c requires setname and IP",
-                                                  c);
-
-                               res = parse_adt_cmdline(command, name, adt,
-                                                       &set, &settype);
-
-                               if (!res)
+                       /* Shift off matched command arg */
+                       ipset_shift_argv(&argc, argv, i);
+                       cmd = j;
+                       switch (command->has_arg) {
+                       case IPSET_MANDATORY_ARG:
+                       case IPSET_MANDATORY_ARG2:
+                               if (i + 1 > argc)
                                        exit_error(PARAMETER_PROBLEM,
-                                                  "Unknown arg `%s'",
-                                                  argv[optind - 1]);
-
-                               res = 0;
+                                                  "Missing mandatory argument to command %s",
+                                                  command->name[0]);
+                               /* Fall through */
+                       case IPSET_OPTIONAL_ARG:
+                               arg0 = argv[i];
+                               if (i + 1 <= argc)
+                                       /* Shift off first arg */
+                                       ipset_shift_argv(&argc, argv, i);
+                               break;
+                       default:
                                break;
                        }
-
-                       /* options */
-
-               case 'n':
-                       add_option(&options, OPT_NUMERIC);
-                       break;
-
-               case 'r':
-                       if (!(options & OPT_NUMERIC))
-                               add_option(&options, OPT_RESOLVE);
-                       break;
-
-               case 's':
-                       add_option(&options, OPT_SORTED);
-                       break;
-
-               case 'q':
-                       add_option(&options, OPT_QUIET);
-                       option_quiet = 1;
-                       break;
-
-#ifdef IPSET_DEBUG
-               case 'z':       /* debug */
-                       add_option(&options, OPT_DEBUG);
-                       option_debug = 1;
-                       break;
-#endif
-
-               case 1: /* non option */
-                       printf("Bad argument `%s'\n", optarg);
-                       exit_tryhelp(PARAMETER_PROBLEM);
-                       break;  /*always good */
-
-               default:{
-                               DP("default");
-
-                               switch (command) {
-                               case CMD_CREATE:
-                                       res = settype->create_parse(
-                                                       c - settype->option_offset,
-                                                       argv,
-                                                       settype->data,
-                                                       &settype->flags);
-                                       break;
-
-                               default:
-                                       res = 0;        /* failed */
-                               }       /* switch (command) */
-
-
-                               if (!res)
+                       if (command->has_arg == IPSET_MANDATORY_ARG2) {
+                               if (i + 1 > argc)
                                        exit_error(PARAMETER_PROBLEM,
-                                                  "Unknown arg `%s'",
-                                                  argv[optind - 1]);
-                               
-                               res = 0;
+                                                  "Missing second mandatory argument to command %s",
+                                                  command->name[0]);
+                               arg1 = argv[i];
+                               /* Shift off second arg */
+                               ipset_shift_argv(&argc, argv, i);
                        }
+               }
+       }
 
-                       DP("next arg");
-               }       /* switch */
-
-       }       /* while( getopt_long() ) */
-
-
-       if (optind < argc)
-               exit_error(PARAMETER_PROBLEM,
-                          "unknown arguments found on commandline");
-       if (command == CMD_NONE)
-               exit_error(PARAMETER_PROBLEM, "no command specified");
-
-       /* Check options */
-       generic_opt_check(command, options);
-
-       DP("cmd: %c", cmd2char(command));
-       
-       check_protocolversion();
-
-       switch (command) {
-       case CMD_CREATE:
-               DP("CMD_CREATE");
-               if (restore)
-                       set_restore_create(name, settype);
-               else
-                       set_create(name, settype);
-               break;
-
-       case CMD_DESTROY:
-               set_destroy(name, IP_SET_OP_DESTROY, CMD_DESTROY);
-               break;
-
-       case CMD_FLUSH:
-               set_destroy(name, IP_SET_OP_FLUSH, CMD_FLUSH);
-               break;
-
-       case CMD_RENAME:
-               set_rename(name, newname, IP_SET_OP_RENAME, CMD_RENAME);
-               break;
-
-       case CMD_SWAP:
-               set_rename(name, newname, IP_SET_OP_SWAP, CMD_SWAP);
-               break;
-
-       case CMD_LIST:
-               list_sets(name, options);
-               break;
-
-       case CMD_SAVE:
-               set_save(name);
-               break;
-
-       case CMD_RESTORE:
-               set_restore(argv[0]);
+       /* Third: catch interactive mode, handle help, version */
+       switch (cmd) {
+       case IPSET_CMD_NONE:
+               if (interactive) {
+                       printf("No command specified\n");
+                       return 0;
+               }
+               if (argc > 1 && STREQ(argv[1], "-")) {
+                       interactive = true;
+                       printf("%s> ", program_name);
+                       /* Initialize newargv/newargc */
+                       newargv[newargc++] = program_name;
+                       while (fgets(cmdline, sizeof(cmdline), stdin)) {
+                               c = cmdline;
+                               while (isspace(c[0]))
+                                       c++;
+                               if (c[0] == '\0' || c[0] == '#')
+                                       continue;
+                               /* Build fake argv, argc */
+                               build_argv(c);
+                               /* Execute line: ignore errors */
+                               parse_commandline(newargc, newargv);
+                               printf("%s> ", program_name);
+                       }
+                       exit_error(NO_PROBLEM, NULL);
+               }
+               exit_error(PARAMETER_PROBLEM, "No command specified.");
+       case IPSET_CMD_VERSION:
+               printf("%s v%s.\n", program_name, program_version);
+               if (interactive)
+                       return 0;
+               exit_error(NO_PROBLEM, NULL);
+       case IPSET_CMD_HELP:
+               help();
+
+               if (interactive
+                   || !ipset_envopt_test(session, IPSET_ENV_QUIET)) {
+                       if (arg0) {
+                               /* Type-specific help, without kernel checking */
+                               type = type_find(arg0);
+                               if (!type)
+                                       exit_error(PARAMETER_PROBLEM,
+                                                  "Unknown settype: `%s'", arg0);
+                               printf("\n%s type specific options:\n\n%s",
+                                      type->name, type->usage);
+                               if (type->family == AF_UNSPEC)
+                                       printf("\nType %s is family neutral.\n",
+                                              type->name);
+                               else if (type->family == AF_INET46)
+                                       printf("\nType %s supports INET and INET6.\n",
+                                              type->name);
+                               else
+                                       printf("\nType %s supports family %s only.\n",
+                                              type->name,
+                                              type->family == AF_INET ? "INET" : "INET6");
+                       } else {
+                               printf("\nSupported set types:\n");
+                               type = ipset_types();
+                               while (type) {
+                                       printf("    %s\n", type->name);
+                                       type = type->next;
+                               }
+                       } 
+               }
+               if (interactive)
+                       return 0;
+               exit_error(NO_PROBLEM, NULL);
+       default:
                break;
-
-       case CMD_ADD:
-               if (restore)
-                       set_restore_add(set, adt);
-               else
-                       set_adtip(set, adt, IP_SET_OP_ADD_IP, CMD_ADD);
+       }
+       
+       /* Forth: parse command args and issue the command */
+       switch (cmd) {
+       case IPSET_CMD_CREATE:
+               /* Args: setname typename [type specific options] */
+               ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
+               if (ret < 0)
+                       return handle_error();
+
+               ret = ipset_parse_typename(session, IPSET_OPT_TYPENAME, arg1);
+               if (ret < 0)
+                       return handle_error();
+
+               type = ipset_type_get(session, cmd);
+               if (type == NULL)
+                       return handle_error();
+
+               /* Parse create options */
+               ret = call_parser(argc, argv, type->args[IPSET_CREATE]);
+               if (ret < 0)
+                       return handle_error();
+               else if (ret)
+                       return ret;
+               
+               /* Check mandatory options */
+               check_mandatory(type, IPSET_CREATE);
+               
                break;
-
-       case CMD_DEL:
-               set_adtip(set, adt, IP_SET_OP_DEL_IP, CMD_DEL);
+       case IPSET_CMD_DESTROY:
+       case IPSET_CMD_FLUSH:
+       case IPSET_CMD_LIST:
+       case IPSET_CMD_SAVE:
+               /* Args: [setname] */
+               if (arg0) {
+                       ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
+                       if (ret < 0)
+                               return handle_error();
+               }
                break;
 
-       case CMD_TEST:
-               res = set_adtip(set, adt, IP_SET_OP_TEST_IP, CMD_TEST);
+       case IPSET_CMD_RENAME:
+       case IPSET_CMD_SWAP:
+               /* Args: from-setname to-setname */
+               ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
+               if (ret < 0)
+                       return handle_error();
+               ret = ipset_parse_name(session, IPSET_OPT_SETNAME2, arg1);
+               if (ret < 0)
+                       return handle_error();
                break;
 
-       case CMD_HELP:
-               set_help(settype);
+       case IPSET_CMD_RESTORE:
+               /* Restore mode */
+               return restore(argv[0]);
+       case IPSET_CMD_ADD:
+       case IPSET_CMD_DEL:
+       case IPSET_CMD_TEST:
+               D("ADT: setname %s", arg0);
+               /* Args: setname ip [options] */
+               ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
+               if (ret < 0)
+                       return handle_error();
+
+               type = ipset_type_get(session, cmd);
+               if (type == NULL)
+                       return handle_error();
+               
+               ret = ipset_parse_elem(session, type->last_elem_optional, arg1);
+               if (ret < 0)
+                       return handle_error();
+               
+               /* Parse additional ADT options */
+               ret = call_parser(argc, argv, type->args[cmd2cmd(cmd)]);
+               if (ret < 0)
+                       return handle_error();
+               else if (ret)
+                       return ret;
+               
+               /* Check mandatory options */
+               check_mandatory(type, cmd2cmd(cmd));
+               
                break;
-
        default:
-               /* Will never happen */
-               break; /* Keep the compiler happy */
+               break;
+       }
 
-       }       /* switch( command ) */
+       ret = ipset_cmd(session, cmd, restore_line);
+       D("ret %d", ret);
+       /* Special case for TEST and non-quiet mode */
+       if (cmd == IPSET_CMD_TEST && ipset_session_warning(session)) {
+               if (!ipset_envopt_test(session, IPSET_ENV_QUIET))
+                       fprintf(stderr, "%s\n", ipset_session_warning(session));
+               ipset_session_report_reset(session);
+       }
+       if (ret < 0)
+               handle_error();
 
-       return res;
+       return ret;
 }
 
-
-int main(int argc, char *argv[])
-{      
+int
+main(int argc, char *argv[])
+{
        return parse_commandline(argc, argv);
-
 }
index 87b8e698198dd2be86cb96ea2b7732ba3ea3471a..471cc969cce91618aeee18953c35a266bd71a945 100644 (file)
-/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
- *                     Patrick Schaaf (bof@bof.de)
- *                     Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+/* Copyright 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation.
  */
-
-#include <stdio.h>                     /* *printf */
-#include <string.h>                    /* mem* */
-
-#include "ipset.h"
-
-#include <linux/netfilter_ipv4/ip_set_ipmap.h>
-
-#define BUFLEN 30;
-
-#define OPT_CREATE_FROM    0x01U
-#define OPT_CREATE_TO      0x02U
-#define OPT_CREATE_NETWORK 0x04U
-#define OPT_CREATE_NETMASK 0x08U
-
-#define OPT_ADDDEL_IP      0x01U
-
-/* Initialize the create. */
-static void
-ipmap_create_init(void *data)
-{
-       struct ip_set_req_ipmap_create *mydata = data;
-
-       DP("create INIT");
-       mydata->netmask = 0xFFFFFFFF;
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-ipmap_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
-{
-       struct ip_set_req_ipmap_create *mydata = data;
-       unsigned int bits;
-
-       DP("create_parse");
-
-       switch (c) {
-       case '1':
-               parse_ip(optarg, &mydata->from);
-
-               *flags |= OPT_CREATE_FROM;
-
-               DP("--from %x (%s)", mydata->from,
-                  ip_tostring_numeric(mydata->from));
-
-               break;
-
-       case '2':
-               parse_ip(optarg, &mydata->to);
-
-               *flags |= OPT_CREATE_TO;
-
-               DP("--to %x (%s)", mydata->to,
-                  ip_tostring_numeric(mydata->to));
-
-               break;
-
-       case '3':
-               parse_ipandmask(optarg, &mydata->from, &mydata->to);
-
-               /* Make to the last of from + mask */
-               if (mydata->to)
-                       mydata->to = mydata->from | ~(mydata->to);
-               else {
-                       mydata->from = 0x00000000;
-                       mydata->to = 0xFFFFFFFF;
-               }
-               *flags |= OPT_CREATE_NETWORK;
-
-               DP("--network from %x (%s)", 
-                  mydata->from, ip_tostring_numeric(mydata->from));
-               DP("--network to %x (%s)", 
-                  mydata->to, ip_tostring_numeric(mydata->to));
-
-               break;
-
-       case '4':
-               if (string_to_number(optarg, 0, 32, &bits))
-                       exit_error(PARAMETER_PROBLEM, 
-                                 "Invalid netmask `%s' specified", optarg);
-               
-               if (bits != 0)
-                       mydata->netmask = 0xFFFFFFFF << (32 - bits);
-
-               *flags |= OPT_CREATE_NETMASK;
-
-               DP("--netmask %x", mydata->netmask);
-               
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; exit if not ok. */
-static void
-ipmap_create_final(void *data, unsigned int flags)
-{
-       struct ip_set_req_ipmap_create *mydata = data;
-       ip_set_ip_t range;
-
-       if (flags == 0)
-               exit_error(PARAMETER_PROBLEM,
-                          "Need to specify --from and --to, or --network\n");
-
-       if (flags & OPT_CREATE_NETWORK) {
-               /* --network */
-               if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --from or --to with --network\n");
-       } else {
-               /* --from --to */
-               if ((flags & OPT_CREATE_FROM) == 0
-                   || (flags & OPT_CREATE_TO) == 0)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Need to specify both --from and --to\n");
-       }
-
-       DP("from : %x to: %x diff: %x", 
-          mydata->from, mydata->to,
-          mydata->to - mydata->from);
-
-       if (mydata->from > mydata->to)
-               exit_error(PARAMETER_PROBLEM,
-                          "From can't be lower than to.\n");
-
-       if (flags & OPT_CREATE_NETMASK) {
-               unsigned int mask_bits, netmask_bits;
-               ip_set_ip_t mask;
-
-               if ((mydata->from & mydata->netmask) != mydata->from)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "%s is not a network address according to netmask %d\n",
-                                  ip_tostring_numeric(mydata->from),
-                                  mask_to_bits(mydata->netmask));
-               
-               mask = range_to_mask(mydata->from, mydata->to, &mask_bits);
-               if (!mask
-                   && (mydata->from || mydata->to != 0xFFFFFFFF)) {
-                       exit_error(PARAMETER_PROBLEM,
-                                  "You have to define a full network with --from"
-                                  " and --to if you specify the --network option\n");
-               }
-               netmask_bits = mask_to_bits(mydata->netmask);
-               if (netmask_bits <= mask_bits) {
-                       exit_error(PARAMETER_PROBLEM,
-                                  "%d netmask specifies larger or equal netblock than the network itself\n");
-               }
-               range = (1<<(netmask_bits - mask_bits)) - 1;
-       } else {
-               range = mydata->to - mydata->from;
-       }
-       if (range > MAX_RANGE)
-               exit_error(PARAMETER_PROBLEM,
-                          "Range too large. Max is %d IPs in range\n",
-                          MAX_RANGE+1);
-}
-
-/* Create commandline options */
-static const struct option create_opts[] = {
-       {.name = "from",        .has_arg = required_argument,   .val = '1'},
-       {.name = "to",          .has_arg = required_argument,   .val = '2'},
-       {.name = "network",     .has_arg = required_argument,   .val = '3'},
-       {.name = "netmask",     .has_arg = required_argument,   .val = '4'},
-       {NULL},
+#include <libipset/data.h>                     /* IPSET_OPT_* */
+#include <libipset/parse.h>                    /* parser functions */
+#include <libipset/print.h>                    /* printing functions */
+#include <libipset/types.h>                    /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg bitmap_ip_create_args[] = {
+       { .name = { "range", "--range", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_netrange,        .print = ipset_print_ip,
+       },
+       { .name = { "netmask", "--netmask", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_NETMASK,
+         .parse = ipset_parse_netmask,         .print = ipset_print_number,
+       },
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       /* Backward compatibility */
+       { .name = { "--from", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_single_ip,
+       },
+       { .name = { "--to", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP_TO,
+         .parse = ipset_parse_single_ip,
+       },
+       { .name = { "--network", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_net,
+       },
+       { },
+}; 
+
+static const struct ipset_arg bitmap_ip_add_args[] = {
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const char bitmap_ip_usage[] =
+"create SETNAME bitmap:ip range IP/CIDR|FROM-TO\n"
+"               [netmask CIDR] [timeout VALUE]\n"
+"add    SETNAME IP|IP/CIDR|FROM-TO [timeout VALUE]\n"
+"del    SETNAME IP|IP/CIDR|FROM-TO\n"
+"test   SETNAME IP\n";
+
+struct ipset_type ipset_bitmap_ip0 = {
+       .name = "bitmap:ip",
+       .alias = "ipmap",
+       .revision = 0,
+       .family = AF_INET,
+       .dimension = IPSET_DIM_ONE,
+       .elem = { 
+               [IPSET_DIM_ONE] = { 
+                       .parse = ipset_parse_ip,
+                       .print = ipset_print_ip,
+                       .opt = IPSET_OPT_IP
+               },
+       },
+       .args = {
+               [IPSET_CREATE] = bitmap_ip_create_args,
+               [IPSET_ADD] = bitmap_ip_add_args,
+       },
+       .mandatory = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
+       },
+       .full = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO)
+                       | IPSET_FLAG(IPSET_OPT_NETMASK)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
+       },
+
+       .usage = bitmap_ip_usage,
 };
-
-/* Add, del, test parser */
-static ip_set_ip_t
-ipmap_adt_parser(int cmd UNUSED, const char *arg, void *data)
-{
-       struct ip_set_req_ipmap *mydata = data;
-
-       DP("ipmap: %p %p", arg, data);
-
-       parse_ip(arg, &mydata->ip);
-       DP("%s", ip_tostring_numeric(mydata->ip));
-
-       return 1;       
-}
-
-/*
- * Print and save
- */
-
-static void
-ipmap_initheader(struct set *set, const void *data)
-{
-       const struct ip_set_req_ipmap_create *header = data;
-       struct ip_set_ipmap *map = set->settype->header;
-               
-       memset(map, 0, sizeof(struct ip_set_ipmap));
-       map->first_ip = header->from;
-       map->last_ip = header->to;
-       map->netmask = header->netmask;
-
-       if (map->netmask == 0xFFFFFFFF) {
-               map->hosts = 1;
-               map->sizeid = map->last_ip - map->first_ip + 1;
-       } else {
-               unsigned int mask_bits, netmask_bits;
-               ip_set_ip_t mask;
-       
-               mask = range_to_mask(header->from, header->to, &mask_bits);
-               netmask_bits = mask_to_bits(header->netmask);
-
-               DP("bits: %d %d", mask_bits, netmask_bits);
-               map->hosts = 2 << (32 - netmask_bits - 1);
-               map->sizeid = 2 << (netmask_bits - mask_bits - 1);
-       }
-
-       DP("%d %d", map->hosts, map->sizeid );
-}
-
-static void
-ipmap_printheader(struct set *set, unsigned options)
-{
-       struct ip_set_ipmap *mysetdata = set->settype->header;
-
-       printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
-       printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
-       if (mysetdata->netmask == 0xFFFFFFFF)
-               printf("\n");
-       else
-               printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
-}
-
-static inline void
-__ipmap_printips_sorted(struct set *set, void *data,
-                       u_int32_t len UNUSED, unsigned options)
-{
-       struct ip_set_ipmap *mysetdata = set->settype->header;
-       ip_set_ip_t id;
-
-       for (id = 0; id < mysetdata->sizeid; id++)
-               if (test_bit(id, data))
-                       printf("%s\n",
-                              ip_tostring(mysetdata->first_ip
-                                          + id * mysetdata->hosts,
-                                          options));
-}
-
-static void
-ipmap_printips_sorted(struct set *set, void *data,
-                     u_int32_t len, unsigned options,
-                     char dont_align)
-{
-       ip_set_ip_t *ip;
-       size_t offset = 0;
-       
-       if (dont_align)
-               return __ipmap_printips_sorted(set, data, len, options);
-       
-       while (offset < len) {
-               DP("offset: %zu, len %u\n", offset, len);
-               ip = data + offset;
-               printf("%s\n", ip_tostring(*ip, options));
-               offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
-       }
-}
-
-static void
-ipmap_saveheader(struct set *set, unsigned options)
-{
-       struct ip_set_ipmap *mysetdata = set->settype->header;
-
-       printf("-N %s %s --from %s",
-              set->name, set->settype->typename,
-              ip_tostring(mysetdata->first_ip, options));
-       printf(" --to %s",
-              ip_tostring(mysetdata->last_ip, options));
-       if (mysetdata->netmask == 0xFFFFFFFF)
-               printf("\n");
-       else
-               printf(" --netmask %d\n",
-                      mask_to_bits(mysetdata->netmask));
-}
-
-static inline void
-__ipmap_saveips(struct set *set, void *data, u_int32_t len UNUSED,
-               unsigned options)
-{
-       struct ip_set_ipmap *mysetdata = set->settype->header;
-       ip_set_ip_t id;
-
-       DP("%s", set->name);
-       for (id = 0; id < mysetdata->sizeid; id++)
-               if (test_bit(id, data))
-                       printf("-A %s %s\n",
-                              set->name,
-                              ip_tostring(mysetdata->first_ip 
-                                          + id * mysetdata->hosts,
-                                          options));
-}
-
-static void
-ipmap_saveips(struct set *set, void *data, u_int32_t len,
-             unsigned options, char dont_align)
-{
-       ip_set_ip_t *ip;
-       size_t offset = 0;
-       
-       if (dont_align)
-               return __ipmap_saveips(set, data, len, options);
-       
-       while (offset < len) {
-               ip = data + offset;
-               printf("-A %s %s\n", set->name, ip_tostring(*ip, options));
-               offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
-       }
-}
-
-static void
-ipmap_usage(void)
-{
-       printf
-           ("-N set ipmap --from IP --to IP [--netmask CIDR-netmask]\n"
-            "-N set ipmap --network IP/mask [--netmask CIDR-netmask]\n"
-            "-A set IP\n"
-            "-D set IP\n"
-            "-T set IP\n");
-}
-
-static struct settype settype_ipmap = {
-       .typename = SETTYPE_NAME,
-       .protocol_version = IP_SET_PROTOCOL_VERSION,
-
-       /* Create */
-       .create_size = sizeof(struct ip_set_req_ipmap_create),
-       .create_init = ipmap_create_init,
-       .create_parse = ipmap_create_parse,
-       .create_final = ipmap_create_final,
-       .create_opts = create_opts,
-
-       /* Add/del/test */
-       .adt_size = sizeof(struct ip_set_req_ipmap),
-       .adt_parser = ipmap_adt_parser,
-
-       /* Printing */
-       .header_size = sizeof(struct ip_set_ipmap),
-       .initheader = ipmap_initheader,
-       .printheader = ipmap_printheader,
-       .printips = ipmap_printips_sorted,
-       .printips_sorted = ipmap_printips_sorted,
-       .saveheader = ipmap_saveheader,
-       .saveips = ipmap_saveips,
-       
-       .usage = ipmap_usage,
-};
-
-CONSTRUCTOR(ipmap)
-{
-       settype_register(&settype_ipmap);
-
-}
index fb97caef9405bb5a8ca0ca47931336d71a946d3d..4985fc48ac23c2505d5f19cf40335baadcdd8d83 100644 (file)
-/* Copyright 2000, 2001, 2002 Joakim Axelsson (gozem@linux.nu)
- *                            Patrick Schaaf (bof@bof.de)
- *                            Martin Josefsson (gandalf@wlug.westbo.se)
+/* Copyright 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation.
  */
-
-
-#include <stdio.h>                     /* *printf */
-#include <stdlib.h>                    /* mem* */
-#include <string.h>                    /* str* */
-#include <net/ethernet.h>              /* ETH_ALEN */
-
-#include "ipset.h"
-
-#include <linux/netfilter_ipv4/ip_set_macipmap.h>
-
-#define BUFLEN 30;
-
-#define OPT_CREATE_FROM    0x01U
-#define OPT_CREATE_TO      0x02U
-#define OPT_CREATE_NETWORK 0x04U
-#define OPT_CREATE_MATCHUNSET  0x08U
-
-#define OPT_ADDDEL_IP      0x01U
-#define OPT_ADDDEL_MAC     0x02U
-
-/* Initialize the create. */
-static void
-macipmap_create_init(void *data UNUSED)
-{
-       DP("create INIT");
-       /* Nothing */
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-macipmap_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
-{
-       struct ip_set_req_macipmap_create *mydata = data;
-
-       DP("create_parse");
-
-       switch (c) {
-       case '1':
-               parse_ip(optarg, &mydata->from);
-
-               *flags |= OPT_CREATE_FROM;
-
-               DP("--from %x (%s)", mydata->from,
-                  ip_tostring_numeric(mydata->from));
-
-               break;
-
-       case '2':
-               parse_ip(optarg, &mydata->to);
-
-               *flags |= OPT_CREATE_TO;
-
-               DP("--to %x (%s)", mydata->to,
-                  ip_tostring_numeric(mydata->to));
-
-               break;
-
-       case '3':
-               parse_ipandmask(optarg, &mydata->from, &mydata->to);
-
-               /* Make to the last of from + mask */
-               mydata->to = mydata->from | (~mydata->to);
-
-               *flags |= OPT_CREATE_NETWORK;
-
-               DP("--network from %x (%s)", 
-                  mydata->from, ip_tostring_numeric(mydata->from));
-               DP("--network to %x (%s)", 
-                  mydata->to, ip_tostring_numeric(mydata->to));
-
-               break;
-
-       case '4':
-               mydata->flags |= IPSET_MACIP_MATCHUNSET;
-
-               *flags |= OPT_CREATE_MATCHUNSET;
-
-               DP("--matchunset");
-
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; exit if not ok. */
-static void
-macipmap_create_final(void *data, unsigned int flags)
-{
-       struct ip_set_req_macipmap_create *mydata = data;
-
-       if (flags == 0)
-               exit_error(PARAMETER_PROBLEM,
-                          "Need to specify --from and --to, or --network\n");
-
-       if (flags & OPT_CREATE_NETWORK) {
-               /* --network */
-               if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --from or --to with --network\n");
-       } else {
-               /* --from --to */
-               if ((flags & OPT_CREATE_FROM) == 0
-                   || (flags & OPT_CREATE_TO) == 0)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Need to specify both --from and --to\n");
-       }
-
-
-       DP("from : %x to: %x  diff: %d  match unset: %d", mydata->from,
-          mydata->to, mydata->to - mydata->from,
-          flags & OPT_CREATE_MATCHUNSET);
-
-       if (mydata->from > mydata->to)
-               exit_error(PARAMETER_PROBLEM,
-                          "From can't be lower than to.\n");
-
-       if (mydata->to - mydata->from > MAX_RANGE)
-               exit_error(PARAMETER_PROBLEM,
-                          "Range too large. Max is %d IPs in range\n",
-                          MAX_RANGE+1);
-}
-
-/* Create commandline options */
-static const struct option create_opts[] = {
-       {.name = "from",        .has_arg = required_argument,   .val = '1'},
-       {.name = "to",          .has_arg = required_argument,   .val = '2'},
-       {.name = "network",     .has_arg = required_argument,   .val = '3'},
-       {.name = "matchunset",  .has_arg = no_argument,         .val = '4'},
-       {NULL},
+#include <libipset/data.h>                     /* IPSET_OPT_* */
+#include <libipset/parse.h>                    /* parser functions */
+#include <libipset/print.h>                    /* printing functions */
+#include <libipset/types.h>                    /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg bitmap_ipmac_create_args[] = {
+       { .name = { "range", "--range", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_netrange,        .print = ipset_print_ip,
+       },
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       /* Backward compatibility */
+       { .name = { "--from", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_single_ip,
+       },
+       { .name = { "--to", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP_TO,
+         .parse = ipset_parse_single_ip,
+       },
+       { .name = { "--network", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_net,
+       },
+       { },
+}; 
+
+static const struct ipset_arg bitmap_ipmac_add_args[] = {
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const char bitmap_ipmac_usage[] =
+"create SETNAME bitmap:ip,mac range IP/CIDR|FROM-TO\n"
+"               [matchunset] [timeout VALUE]\n"
+"add    SETNAME IP[,MAC] [timeout VALUE]\n"
+"del    SETNAME IP[,MAC]\n"
+"test   SETNAME IP[,MAC]\n";
+
+struct ipset_type ipset_bitmap_ipmac0 = {
+       .name = "bitmap:ip,mac",
+       .alias = "macipmap",
+       .revision = 0,
+       .family = AF_INET,
+       .dimension = IPSET_DIM_TWO,
+       .last_elem_optional = true,
+       .elem = { 
+               [IPSET_DIM_ONE] = { 
+                       .parse = ipset_parse_single_ip,
+                       .print = ipset_print_ip,
+                       .opt = IPSET_OPT_IP
+               },
+               [IPSET_DIM_TWO] = { 
+                       .parse = ipset_parse_ether,
+                       .print = ipset_print_ether,
+                       .opt = IPSET_OPT_ETHER
+               },
+       },
+       .args = {
+               [IPSET_CREATE] = bitmap_ipmac_create_args,
+               [IPSET_ADD] = bitmap_ipmac_add_args,
+       },
+       .mandatory = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
+       },
+       .full = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_ETHER)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_ETHER),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_ETHER),
+       },
+
+       .usage = bitmap_ipmac_usage,
 };
-
-static void
-parse_mac(const char *mac, unsigned char *ethernet)
-{
-       unsigned int i = 0;
-
-       if (strlen(mac) != ETH_ALEN * 3 - 1)
-               exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
-
-       for (i = 0; i < ETH_ALEN; i++) {
-               long number;
-               char *end;
-
-               number = strtol(mac + i * 3, &end, 16);
-
-               if (end == mac + i * 3 + 2 && number >= 0 && number <= 255)
-                       ethernet[i] = number;
-               else
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Bad mac address `%s'", mac);
-       }
-}
-
-/* Add, del, test parser */
-static ip_set_ip_t
-macipmap_adt_parser(int cmd UNUSED, const char *arg, void *data)
-{
-       struct ip_set_req_macipmap *mydata = data;
-       char *saved = ipset_strdup(arg);
-       char *ptr, *tmp = saved;
-
-       DP("macipmap: %p %p", arg, data);
-
-       ptr = strsep(&tmp, ",");
-       if (!tmp) {
-               tmp = saved;
-               ptr = strsep(&tmp, ":%");       
-               if (tmp && ++warn_once == 1)
-                       fprintf(stderr, "Warning: please use ',' separator token between ip,mac.\n"
-                                       "Next release won't support old separator tokens.\n");
-       }
-       parse_ip(ptr, &mydata->ip);
-
-       if (tmp)
-               parse_mac(tmp, mydata->ethernet);
-       else
-               memset(mydata->ethernet, 0, ETH_ALEN);  
-
-       free(saved);
-
-       return 1;       
-}
-
-/*
- * Print and save
- */
-
-static void
-macipmap_initheader(struct set *set, const void *data)
-{
-       const struct ip_set_req_macipmap_create *header = data;
-       struct ip_set_macipmap *map = set->settype->header;
-
-       memset(map, 0, sizeof(struct ip_set_macipmap));
-       map->first_ip = header->from;
-       map->last_ip = header->to;
-       map->flags = header->flags;
-}
-
-static void
-macipmap_printheader(struct set *set, unsigned options)
-{
-       struct ip_set_macipmap *mysetdata = set->settype->header;
-
-       printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
-       printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
-
-       if (mysetdata->flags & IPSET_MACIP_MATCHUNSET)
-               printf(" matchunset");
-       printf("\n");
-}
-
-static void
-print_mac(unsigned char macaddress[ETH_ALEN])
-{
-       unsigned int i;
-
-       printf("%02X", macaddress[0]);
-       for (i = 1; i < ETH_ALEN; i++)
-               printf(":%02X", macaddress[i]);
-}
-
-static inline void
-__macipmap_printips_sorted(struct set *set, void *data,
-                          u_int32_t len UNUSED, unsigned options)
-{
-       struct ip_set_macipmap *mysetdata = set->settype->header;
-       struct ip_set_macip *table = data;
-       u_int32_t addr = mysetdata->first_ip;
-
-       while (addr <= mysetdata->last_ip) {
-               if (table[addr - mysetdata->first_ip].match) {
-                       printf("%s,", ip_tostring(addr, options));
-                       print_mac(table[addr - mysetdata->first_ip].
-                                 ethernet);
-                       printf("\n");
-               }
-               addr++;
-       }
-}
-
-static void
-macipmap_printips_sorted(struct set *set, void *data,
-                        u_int32_t len, unsigned options,
-                        char dont_align)
-{
-       struct ip_set_req_macipmap *d;
-       size_t offset = 0;
-       
-       if (dont_align)
-               return __macipmap_printips_sorted(set, data, len, options);
-       
-       while (offset < len) {
-               d = data + offset;
-               printf("%s,", ip_tostring(d->ip, options));
-               print_mac(d->ethernet);
-               printf("\n");
-               offset += IPSET_ALIGN(sizeof(struct ip_set_req_macipmap));
-       }
-}
-
-static void
-macipmap_saveheader(struct set *set, unsigned options)
-{
-       struct ip_set_macipmap *mysetdata = set->settype->header;
-
-       printf("-N %s %s --from %s",
-              set->name, set->settype->typename,
-              ip_tostring(mysetdata->first_ip, options));
-       printf(" --to %s", ip_tostring(mysetdata->last_ip, options));
-
-       if (mysetdata->flags & IPSET_MACIP_MATCHUNSET)
-               printf(" --matchunset");
-       printf("\n");
-}
-
-static inline void
-__macipmap_saveips(struct set *set, void *data,
-                  u_int32_t len UNUSED, unsigned options)
-{
-       struct ip_set_macipmap *mysetdata = set->settype->header;
-       struct ip_set_macip *table = data;
-       u_int32_t addr = mysetdata->first_ip;
-
-       while (addr <= mysetdata->last_ip) {
-               if (table[addr - mysetdata->first_ip].match) {
-                       printf("-A %s %s,",
-                              set->name, ip_tostring(addr, options));
-                       print_mac(table[addr - mysetdata->first_ip].
-                                 ethernet);
-                       printf("\n");
-               }
-               addr++;
-       }
-}
-
-static void
-macipmap_saveips(struct set *set, void *data,
-                u_int32_t len, unsigned options,
-                char dont_align)
-{
-       struct ip_set_req_macipmap *d;
-       size_t offset = 0;
-       
-       if (dont_align)
-               return __macipmap_saveips(set, data, len, options);
-       
-       while (offset < len) {
-               d = data + offset;
-               printf("-A %s %s,", set->name, ip_tostring(d->ip, options));
-               print_mac(d->ethernet);
-               printf("\n");
-               offset += IPSET_ALIGN(sizeof(struct ip_set_req_macipmap));
-       }
-}
-
-static void
-macipmap_usage(void)
-{
-       printf
-           ("-N set macipmap --from IP --to IP [--matchunset]\n"
-            "-N set macipmap --network IP/mask [--matchunset]\n"
-            "-A set IP[,MAC]\n"
-            "-D set IP[,MAC]\n"
-            "-T set IP[,MAC]\n");
-}
-
-static struct settype settype_macipmap = {
-       .typename = SETTYPE_NAME,
-       .protocol_version = IP_SET_PROTOCOL_VERSION,
-
-       /* Create */
-       .create_size = sizeof(struct ip_set_req_macipmap_create),
-       .create_init = macipmap_create_init,
-       .create_parse = macipmap_create_parse,
-       .create_final = macipmap_create_final,
-       .create_opts = create_opts,
-
-       /* Add/del/test */
-       .adt_size = sizeof(struct ip_set_req_macipmap),
-       .adt_parser = macipmap_adt_parser,
-
-       /* Printing */
-       .header_size = sizeof(struct ip_set_macipmap),
-       .initheader = macipmap_initheader,
-       .printheader = macipmap_printheader,
-       .printips = macipmap_printips_sorted,
-       .printips_sorted = macipmap_printips_sorted,
-       .saveheader = macipmap_saveheader,
-       .saveips = macipmap_saveips,
-
-       .usage = macipmap_usage,
-};
-
-CONSTRUCTOR(macipmap)
-{
-       settype_register(&settype_macipmap);
-
-}
index a1065ae6759301549f44cab75caf7ac76c6a4049..11566ce5e3e432f54a0d9926b170c54e60d56eb4 100644 (file)
-/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+/* Copyright 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation.
  */
-
-
-#include <stdio.h>                     /* *printf */
-#include <string.h>                    /* mem* */
-
-#include "ipset.h"
-
-#include <linux/netfilter_ipv4/ip_set_portmap.h>
-
-#define BUFLEN 30;
-
-#define OPT_CREATE_FROM    0x01U
-#define OPT_CREATE_TO      0x02U
-
-#define OPT_ADDDEL_PORT      0x01U
-
-/* Initialize the create. */
-static void
-portmap_create_init(void *data UNUSED)
-{
-       DP("create INIT");
-       /* Nothing */
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-portmap_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
-{
-       struct ip_set_req_portmap_create *mydata = data;
-
-       DP("create_parse");
-
-       switch (c) {
-       case '1':
-               parse_port(optarg, &mydata->from);
-
-               *flags |= OPT_CREATE_FROM;
-
-               DP("--from %x (%s)", mydata->from,
-                  port_tostring(mydata->from, 0));
-
-               break;
-
-       case '2':
-               parse_port(optarg, &mydata->to);
-
-               *flags |= OPT_CREATE_TO;
-
-               DP("--to %x (%s)", mydata->to,
-                  port_tostring(mydata->to, 0));
-
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; exit if not ok. */
-static void
-portmap_create_final(void *data, unsigned int flags)
-{
-       struct ip_set_req_portmap_create *mydata = data;
-
-       if (flags == 0) {
-               exit_error(PARAMETER_PROBLEM,
-                          "Need to specify --from and --to\n");
-       } else {
-               /* --from --to */
-               if ((flags & OPT_CREATE_FROM) == 0
-                   || (flags & OPT_CREATE_TO) == 0)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Need to specify both --from and --to\n");
-       }
-
-       DP("from : %x to: %x  diff: %d", mydata->from, mydata->to,
-          mydata->to - mydata->from);
-
-       if (mydata->from > mydata->to)
-               exit_error(PARAMETER_PROBLEM,
-                          "From can't be lower than to.\n");
-
-       if (mydata->to - mydata->from > MAX_RANGE)
-               exit_error(PARAMETER_PROBLEM,
-                          "Range too large. Max is %d ports in range\n",
-                          MAX_RANGE+1);
-}
-
-/* Create commandline options */
-static const struct option create_opts[] = {
-       {.name = "from",        .has_arg = required_argument,   .val = '1'},
-       {.name = "to",          .has_arg = required_argument,   .val = '2'},
-       {NULL},
+#include <libipset/data.h>                     /* IPSET_OPT_* */
+#include <libipset/parse.h>                    /* parser functions */
+#include <libipset/print.h>                    /* printing functions */
+#include <libipset/types.h>                    /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg bitmap_port_create_args[] = {
+       { .name = { "range", "--range", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PORT,
+         .parse = ipset_parse_port,            .print = ipset_print_port,
+       },
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       /* Backward compatibility */
+       { .name = { "--from", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PORT,
+         .parse = ipset_parse_single_port,
+       },
+       { .name = { "--to", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PORT_TO,
+         .parse = ipset_parse_single_port,
+       },
+       { },
+}; 
+
+static const struct ipset_arg bitmap_port_add_args[] = {
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const char bitmap_port_usage[] =
+"create SETNAME bitmap:port range FROM-TO\n"
+"               [timeout VALUE]\n"
+"add    SETNAME PORT|FROM-TO [timeout VALUE]\n"
+"del    SETNAME PORT|FROM-TO\n"
+"test   SETNAME PORT\n";
+
+struct ipset_type ipset_bitmap_port0 = {
+       .name = "bitmap:port",
+       .alias = "portmap",
+       .revision = 0,
+       .family = AF_UNSPEC,
+       .dimension = IPSET_DIM_ONE,
+       .elem = { 
+               [IPSET_DIM_ONE] = { 
+                       .parse = ipset_parse_port,
+                       .print = ipset_print_port,
+                       .opt = IPSET_OPT_PORT
+               },
+       },
+       .args = {
+               [IPSET_CREATE] = bitmap_port_create_args,
+               [IPSET_ADD] = bitmap_port_add_args,
+       },
+       .mandatory = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PORT_TO),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_PORT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_PORT),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_PORT),
+       },
+       .full = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PORT_TO)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PORT_TO)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_PORT_TO),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_PORT),
+       },
+
+       .usage = bitmap_port_usage,
 };
-
-/* Add, del, test parser */
-static ip_set_ip_t
-portmap_adt_parser(int cmd UNUSED, const char *arg, void *data)
-{
-       struct ip_set_req_portmap *mydata = data;
-
-       parse_port(arg, &mydata->ip);
-       DP("%s", port_tostring(mydata->ip, 0));
-
-       return 1;       
-}
-
-/*
- * Print and save
- */
-
-static void
-portmap_initheader(struct set *set, const void *data)
-{
-       const struct ip_set_req_portmap_create *header = data;
-       struct ip_set_portmap *map = set->settype->header;
-
-       memset(map, 0, sizeof(struct ip_set_portmap));
-       map->first_ip = header->from;
-       map->last_ip = header->to;
-}
-
-static void
-portmap_printheader(struct set *set, unsigned options)
-{
-       struct ip_set_portmap *mysetdata = set->settype->header;
-
-       printf(" from: %s", port_tostring(mysetdata->first_ip, options));
-       printf(" to: %s\n", port_tostring(mysetdata->last_ip, options));
-}
-
-static inline void
-__portmap_printips_sorted(struct set *set, void *data,
-                         u_int32_t len UNUSED, unsigned options)
-{
-       struct ip_set_portmap *mysetdata = set->settype->header;
-       ip_set_ip_t addr = mysetdata->first_ip;
-
-       DP("%u -- %u", mysetdata->first_ip, mysetdata->last_ip);
-       while (addr <= mysetdata->last_ip) {
-               if (test_bit(addr - mysetdata->first_ip, data))
-                       printf("%s\n", port_tostring(addr, options));
-               addr++;
-       }
-}
-
-static void
-portmap_printips_sorted(struct set *set, void *data,
-                       u_int32_t len, unsigned options,
-                       char dont_align)
-{
-       ip_set_ip_t *ip;
-       size_t offset = 0;
-       
-       if (dont_align)
-               return __portmap_printips_sorted(set, data, len, options);
-       
-       while (offset < len) {
-               ip = data + offset;
-               printf("%s\n", port_tostring(*ip, options));
-               offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
-       }
-}
-
-static void
-portmap_saveheader(struct set *set, unsigned options)
-{
-       struct ip_set_portmap *mysetdata = set->settype->header;
-
-       printf("-N %s %s --from %s", 
-              set->name,
-              set->settype->typename,
-              port_tostring(mysetdata->first_ip, options));
-       printf(" --to %s\n", 
-              port_tostring(mysetdata->last_ip, options));
-}
-
-static inline void
-__portmap_saveips(struct set *set, void *data,
-                 u_int32_t len UNUSED, unsigned options)
-{
-       struct ip_set_portmap *mysetdata = set->settype->header;
-       ip_set_ip_t addr = mysetdata->first_ip;
-
-       while (addr <= mysetdata->last_ip) {
-               DP("addr: %lu, last_ip %lu", (long unsigned)addr, (long unsigned)mysetdata->last_ip);
-               if (test_bit(addr - mysetdata->first_ip, data))
-                       printf("-A %s %s\n",
-                              set->name,
-                              port_tostring(addr, options));
-               addr++;
-       }
-}
-
-static void
-portmap_saveips(struct set *set, void *data,
-               u_int32_t len, unsigned options,
-               char dont_align)
-{
-       ip_set_ip_t *ip;
-       size_t offset = 0;
-       
-       if (dont_align)
-               return __portmap_saveips(set, data, len, options);
-       
-       while (offset < len) {
-               ip = data + offset;
-               printf("-A %s %s\n", set->name, port_tostring(*ip, options));
-               offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
-       }
-}
-
-static void
-portmap_usage(void)
-{
-       printf
-           ("-N set portmap --from PORT --to PORT\n"
-            "-A set PORT\n"
-            "-D set PORT\n"
-            "-T set PORT\n");
-}
-
-static struct settype settype_portmap = {
-       .typename = SETTYPE_NAME,
-       .protocol_version = IP_SET_PROTOCOL_VERSION,
-
-       /* Create */
-       .create_size = sizeof(struct ip_set_req_portmap_create),
-       .create_init = portmap_create_init,
-       .create_parse = portmap_create_parse,
-       .create_final = portmap_create_final,
-       .create_opts = create_opts,
-
-       /* Add/del/test */
-       .adt_size = sizeof(struct ip_set_req_portmap),
-       .adt_parser = portmap_adt_parser,
-
-       /* Printing */
-       .header_size = sizeof(struct ip_set_portmap),
-       .initheader = portmap_initheader,
-       .printheader = portmap_printheader,
-       .printips = portmap_printips_sorted,
-       .printips_sorted = portmap_printips_sorted,
-       .saveheader = portmap_saveheader,
-       .saveips = portmap_saveips,
-       
-       .usage = portmap_usage,
-};
-
-CONSTRUCTOR(portmap)
-{
-       settype_register(&settype_portmap);
-
-}
index 0bc5bd186d5dc42e5304a7e9383b6c9146be8d31..212cb2224f184694d8569165c74ada2ebee3de7d 100644 (file)
-/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+/* Copyright 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation.
  */
-
-#include <limits.h>                    /* UINT_MAX */
-#include <stdio.h>                     /* *printf */
-#include <string.h>                    /* mem* */
-
-#include "ipset.h"
-
-#include <linux/netfilter_ipv4/ip_set_iphash.h>
-
-#define BUFLEN 30;
-
-#define OPT_CREATE_HASHSIZE    0x01U
-#define OPT_CREATE_PROBES      0x02U
-#define OPT_CREATE_RESIZE      0x04U
-#define OPT_CREATE_NETMASK     0x08U
-
-/* Initialize the create. */
-static void
-iphash_create_init(void *data)
-{
-       struct ip_set_req_iphash_create *mydata = data;
-
-       DP("create INIT");
-
-       /* Default create parameters */ 
-       mydata->hashsize = 1024;
-       mydata->probes = 8;
-       mydata->resize = 50;
-       
-       mydata->netmask = 0xFFFFFFFF;
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-iphash_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
-{
-       struct ip_set_req_iphash_create *mydata =
-           (struct ip_set_req_iphash_create *) data;
-       unsigned int bits;
-       ip_set_ip_t value;
-
-       DP("create_parse");
-
-       switch (c) {
-       case '1':
-
-               if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
-                       exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
-
-               *flags |= OPT_CREATE_HASHSIZE;
-
-               DP("--hashsize %u", mydata->hashsize);
-               
-               break;
-
-       case '2':
-
-               if (string_to_number(optarg, 1, 65535, &value))
-                       exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
-
-               mydata->probes = value;
-               *flags |= OPT_CREATE_PROBES;
-
-               DP("--probes %u", mydata->probes);
-               
-               break;
-
-       case '3':
-
-               if (string_to_number(optarg, 0, 65535, &value))
-                       exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
-
-               mydata->resize = value;
-               *flags |= OPT_CREATE_RESIZE;
-
-               DP("--resize %u", mydata->resize);
-               
-               break;
-
-       case '4':
-
-               if (string_to_number(optarg, 0, 32, &bits))
-                       exit_error(PARAMETER_PROBLEM, 
-                                 "Invalid netmask `%s' specified", optarg);
-               
-               if (bits != 0)
-                       mydata->netmask = 0xFFFFFFFF << (32 - bits);
-
-               *flags |= OPT_CREATE_NETMASK;
-
-               DP("--netmask %x", mydata->netmask);
-               
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; exit if not ok. */
-static void
-iphash_create_final(void *data UNUSED, unsigned int flags UNUSED)
-{
-}
-
-/* Create commandline options */
-static const struct option create_opts[] = {
-       {.name = "hashsize",    .has_arg = required_argument,   .val = '1'},
-       {.name = "probes",      .has_arg = required_argument,   .val = '2'},
-       {.name = "resize",      .has_arg = required_argument,   .val = '3'},
-       {.name = "netmask",     .has_arg = required_argument,   .val = '4'},
-       {NULL},
-};
-
-/* Add, del, test parser */
-static ip_set_ip_t
-iphash_adt_parser(int cmd UNUSED, const char *arg, void *data)
-{
-       struct ip_set_req_iphash *mydata = data;
-
-       parse_ip(arg, &mydata->ip);
-       if (!mydata->ip)
-               exit_error(PARAMETER_PROBLEM,
-                          "Zero valued IP address `%s' specified", arg);
-
-       return mydata->ip;      
+#include <libipset/data.h>                     /* IPSET_OPT_* */
+#include <libipset/parse.h>                    /* parser functions */
+#include <libipset/print.h>                    /* printing functions */
+#include <libipset/types.h>                    /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg hash_ip_create_args[] = {
+       { .name = { "hashsize", "--hashsize", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_HASHSIZE,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "maxelem", "--maxleme", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "probes", "--probes", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
+         .parse = ipset_parse_uint8,           .print = ipset_print_number,
+       },
+       { .name = { "resize", "--resize", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_RESIZE,
+         .parse = ipset_parse_uint8,           .print = ipset_print_number,
+       },
+       { .name = { "netmask", "--netmask", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_NETMASK,
+         .parse = ipset_parse_netmask,         .print = ipset_print_number,
+       },
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
 };
 
-/*
- * Print and save
- */
-
-static void
-iphash_initheader(struct set *set, const void *data)
-{
-       const struct ip_set_req_iphash_create *header = data;
-       struct ip_set_iphash *map = set->settype->header;
-
-       memset(map, 0, sizeof(struct ip_set_iphash));
-       map->hashsize = header->hashsize;
-       map->probes = header->probes;
-       map->resize = header->resize;
-       map->netmask = header->netmask;
-}
-
-static unsigned int
-mask_to_bits(ip_set_ip_t mask)
-{
-       unsigned int bits = 32;
-       ip_set_ip_t maskaddr;
-       
-       if (mask == 0xFFFFFFFF)
-               return bits;
-       
-       maskaddr = 0xFFFFFFFE;
-       while (--bits > 0 && maskaddr != mask)
-               maskaddr <<= 1;
-       
-       return bits;
-}
-
-static void
-iphash_printheader(struct set *set, unsigned options UNUSED)
-{
-       struct ip_set_iphash *mysetdata = set->settype->header;
-
-       printf(" hashsize: %u", mysetdata->hashsize);
-       printf(" probes: %u", mysetdata->probes);
-       printf(" resize: %u", mysetdata->resize);
-       if (mysetdata->netmask == 0xFFFFFFFF)
-               printf("\n");
-       else
-               printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
-}
-
-static void
-iphash_printips(struct set *set UNUSED, void *data, u_int32_t len,
-               unsigned options, char dont_align)
-{
-       size_t offset = 0;
-       ip_set_ip_t *ip;
-
-       while (offset < len) {
-               ip = data + offset;
-               printf("%s\n", ip_tostring(*ip, options));
-               offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
-       }
-}
-
-static void
-iphash_saveheader(struct set *set, unsigned options UNUSED)
-{
-       struct ip_set_iphash *mysetdata = set->settype->header;
-
-       printf("-N %s %s --hashsize %u --probes %u --resize %u",
-              set->name, set->settype->typename,
-              mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
-       if (mysetdata->netmask == 0xFFFFFFFF)
-               printf("\n");
-       else
-               printf(" --netmask %d\n", mask_to_bits(mysetdata->netmask));
-}
-
-/* Print save for an IP */
-static void
-iphash_saveips(struct set *set UNUSED, void *data, u_int32_t len,
-              unsigned options, char dont_align)
-{
-       size_t offset = 0;
-       ip_set_ip_t *ip;
-
-       while (offset < len) {
-               ip = data + offset;
-               printf("-A %s %s\n", set->name, ip_tostring(*ip, options));
-               offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
-       }
-}
-
-static void
-iphash_usage(void)
-{
-       printf
-           ("-N set iphash [--hashsize hashsize] [--probes probes ]\n"
-            "              [--resize resize] [--netmask CIDR-netmask]\n"
-            "-A set IP\n"
-            "-D set IP\n"
-            "-T set IP\n");
-}
-
-static struct settype settype_iphash = {
-       .typename = SETTYPE_NAME,
-       .protocol_version = IP_SET_PROTOCOL_VERSION,
-
-       /* Create */
-       .create_size = sizeof(struct ip_set_req_iphash_create),
-       .create_init = iphash_create_init,
-       .create_parse = iphash_create_parse,
-       .create_final = iphash_create_final,
-       .create_opts = create_opts,
-
-       /* Add/del/test */
-       .adt_size = sizeof(struct ip_set_req_iphash),
-       .adt_parser = iphash_adt_parser,
-
-       /* Printing */
-       .header_size = sizeof(struct ip_set_iphash),
-       .initheader = iphash_initheader,
-       .printheader = iphash_printheader,
-       .printips = iphash_printips,
-       .printips_sorted = iphash_printips,
-       .saveheader = iphash_saveheader,
-       .saveips = iphash_saveips,
-       
-       .usage = iphash_usage,
+static const struct ipset_arg hash_ip_add_args[] = {
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const char hash_ip_usage[] =
+"create SETNAME hash:ip\n"
+"               [hashsize VALUE] [maxelem VALUE]\n"
+"               [probes VALUE] [resize VALUE]\n"
+"               [netmask CIDR] [timeout VALUE]\n"
+"add    SETNAME IP|IP/CIDR|FROM-TO [timeout VALUE]\n"
+"del    SETNAME IP|IP/CIDR|FROM-TO\n"
+"test   SETNAME IP\n";
+
+struct ipset_type ipset_hash_ip0 = {
+       .name = "hash:ip",
+       .alias = "iphash",
+       .revision = 0,
+       .family = AF_INET46,
+       .dimension = IPSET_DIM_ONE,
+       .elem = { 
+               [IPSET_DIM_ONE] = { 
+                       .parse = ipset_parse_ip,
+                       .print = ipset_print_ip,
+                       .opt = IPSET_OPT_IP
+               },
+       },
+       .args = {
+               [IPSET_CREATE] = hash_ip_create_args,
+               [IPSET_ADD] = hash_ip_add_args,
+       },
+       .mandatory = {
+               [IPSET_CREATE] = 0,
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
+       },
+       .full = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
+                       | IPSET_FLAG(IPSET_OPT_MAXELEM)
+                       | IPSET_FLAG(IPSET_OPT_PROBES)
+                       | IPSET_FLAG(IPSET_OPT_RESIZE)
+                       | IPSET_FLAG(IPSET_OPT_NETMASK)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
+       },
+
+       .usage = hash_ip_usage,
 };
-
-CONSTRUCTOR(iphash)
-{
-       settype_register(&settype_iphash);
-
-}
index 9249b2a925f79f1e81061a0f6f421b3a26abc5af..a8cc7ad92d121e296acd01f57d2a8a1ed4baa262 100644 (file)
-/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+/* Copyright 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation.
  */
-
-#include <limits.h>                    /* UINT_MAX */
-#include <stdio.h>                     /* *printf */
-#include <string.h>                    /* mem*, str* */
-
-#include "ipset.h"
-
-#include <linux/netfilter_ipv4/ip_set_ipporthash.h>
-
-#define OPT_CREATE_HASHSIZE    0x01U
-#define OPT_CREATE_PROBES      0x02U
-#define OPT_CREATE_RESIZE      0x04U
-#define OPT_CREATE_NETWORK     0x08U
-#define OPT_CREATE_FROM                0x10U
-#define OPT_CREATE_TO          0x20U
-
-/* Initialize the create. */
-static void
-ipporthash_create_init(void *data)
-{
-       struct ip_set_req_ipporthash_create *mydata = data;
-
-       DP("create INIT");
-
-       /* Default create parameters */ 
-       mydata->hashsize = 1024;
-       mydata->probes = 8;
-       mydata->resize = 50;
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-ipporthash_create_parse(int c, char *argv[] UNUSED, void *data,
-                       unsigned *flags)
-{
-       struct ip_set_req_ipporthash_create *mydata = data;
-       ip_set_ip_t value;
-
-       DP("create_parse");
-
-       switch (c) {
-       case '1':
-
-               if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
-                       exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
-
-               *flags |= OPT_CREATE_HASHSIZE;
-
-               DP("--hashsize %u", mydata->hashsize);
-               
-               break;
-
-       case '2':
-
-               if (string_to_number(optarg, 1, 65535, &value))
-                       exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
-
-               mydata->probes = value;
-               *flags |= OPT_CREATE_PROBES;
-
-               DP("--probes %u", mydata->probes);
-               
-               break;
-
-       case '3':
-
-               if (string_to_number(optarg, 0, 65535, &value))
-                       exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
-
-               mydata->resize = value;
-               *flags |= OPT_CREATE_RESIZE;
-
-               DP("--resize %u", mydata->resize);
-               
-               break;
-
-       case '4':
-               parse_ip(optarg, &mydata->from);
-
-               *flags |= OPT_CREATE_FROM;
-
-               DP("--from %x (%s)", mydata->from,
-                  ip_tostring_numeric(mydata->from));
-
-               break;
-
-       case '5':
-               parse_ip(optarg, &mydata->to);
-
-               *flags |= OPT_CREATE_TO;
-
-               DP("--to %x (%s)", mydata->to,
-                  ip_tostring_numeric(mydata->to));
-
-               break;
-
-       case '6':
-               parse_ipandmask(optarg, &mydata->from, &mydata->to);
-
-               /* Make to the last of from + mask */
-               if (mydata->to)
-                       mydata->to = mydata->from | ~(mydata->to);
-               else {
-                       mydata->from = 0x00000000;
-                       mydata->to = 0xFFFFFFFF;
-               }
-               *flags |= OPT_CREATE_NETWORK;
-
-               DP("--network from %x (%s)", 
-                  mydata->from, ip_tostring_numeric(mydata->from));
-               DP("--network to %x (%s)", 
-                  mydata->to, ip_tostring_numeric(mydata->to));
-
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; exit if not ok. */
-static void
-ipporthash_create_final(void *data, unsigned int flags)
-{
-       struct ip_set_req_ipporthash_create *mydata = data;
-
-#ifdef IPSET_DEBUG
-       DP("hashsize %u probes %u resize %u",
-          mydata->hashsize, mydata->probes, mydata->resize);
-#endif
-
-       if (flags & OPT_CREATE_NETWORK) {
-               /* --network */
-               if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --from or --to with --network\n");
-       } else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
-               /* --from --to */
-               if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Need to specify both --from and --to\n");
-       } else {
-               exit_error(PARAMETER_PROBLEM,
-                          "Need to specify --from and --to, or --network\n");
-
-       }
-
-       DP("from : %x to: %x diff: %x", 
-          mydata->from, mydata->to,
-          mydata->to - mydata->from);
-
-       if (mydata->from > mydata->to)
-               exit_error(PARAMETER_PROBLEM,
-                          "From can't be higher than to.\n");
-
-       if (mydata->to - mydata->from > MAX_RANGE)
-               exit_error(PARAMETER_PROBLEM,
-                          "Range too large. Max is %d IPs in range\n",
-                          MAX_RANGE+1);
-}
-
-/* Create commandline options */
-static const struct option create_opts[] = {
-       {.name = "hashsize",    .has_arg = required_argument,   .val = '1'},
-       {.name = "probes",      .has_arg = required_argument,   .val = '2'},
-       {.name = "resize",      .has_arg = required_argument,   .val = '3'},
-       {.name = "from",        .has_arg = required_argument,   .val = '4'},
-       {.name = "to",          .has_arg = required_argument,   .val = '5'},
-       {.name = "network",     .has_arg = required_argument,   .val = '6'},
-       {NULL},
-};
-
-/* Add, del, test parser */
-static ip_set_ip_t
-ipporthash_adt_parser(int cmd UNUSED, const char *arg, void *data)
-{
-       struct ip_set_req_ipporthash *mydata = data;
-       char *saved = ipset_strdup(arg);
-       char *ptr, *tmp = saved;
-
-       DP("ipporthash: %p %p", arg, data);
-
-       if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
-               fprintf(stderr, "Warning: please use ',' separator token between ip,port.\n"
-                               "Next release won't support old separator tokens.\n");
-
-       ptr = strsep(&tmp, ":%,");
-       parse_ip(ptr, &mydata->ip);
-
-       if (tmp)
-               parse_port(tmp, &mydata->port);
-       else
-               exit_error(PARAMETER_PROBLEM,
-                          "IP address and port must be specified: ip,port");
-
-       if (!(mydata->ip || mydata->port))
-               exit_error(PARAMETER_PROBLEM,
-                         "Zero valued IP address and port `%s' specified", arg);
-       ipset_free(saved);
-       return 1;       
+#include <libipset/data.h>                     /* IPSET_OPT_* */
+#include <libipset/parse.h>                    /* parser functions */
+#include <libipset/print.h>                    /* printing functions */
+#include <libipset/types.h>                    /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg hash_ipport_create_args[] = {
+       { .name = { "range", "--range", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_netrange,        .print = ipset_print_ip,
+       },
+       { .name = { "hashsize", "--hashsize", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_HASHSIZE,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "maxelem", "--maxleme", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "probes", "--probes", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
+         .parse = ipset_parse_uint8,           .print = ipset_print_number,
+       },
+       { .name = { "resize", "--resize", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_RESIZE,
+         .parse = ipset_parse_uint8,           .print = ipset_print_number,
+       },
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       /* Backward compatibility */
+       { .name = { "--from", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_single_ip,
+       },
+       { .name = { "--to", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP_TO,
+         .parse = ipset_parse_single_ip,
+       },
+       { .name = { "--network", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_net,
+       },
+       { },
+}; 
+
+static const struct ipset_arg hash_ipport_add_args[] = {
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const char hash_ipport_usage[] =
+"create SETNAME hash:ip,port range IP/CIDR|FROM-TO\n"
+"              [family inet|inet6]\n"
+"               [hashsize VALUE] [maxelem VALUE]\n"
+"               [probes VALUE] [resize VALUE]\n"
+"               [timeout VALUE]\n"
+"add    SETNAME IP,PORT [timeout VALUE]\n"
+"del    SETNAME IP,PORT\n"
+"test   SETNAME IP,PORT\n";
+
+struct ipset_type ipset_hash_ipport0 = {
+       .name = "hash:ip,port",
+       .alias = "ipporthash",
+       .revision = 0,
+       .family = AF_INET46,
+       .dimension = IPSET_DIM_TWO,
+       .elem = { 
+               [IPSET_DIM_ONE] = { 
+                       .parse = ipset_parse_single_ip,
+                       .print = ipset_print_ip,
+                       .opt = IPSET_OPT_IP
+               },
+               [IPSET_DIM_TWO] = { 
+                       .parse = ipset_parse_single_port,
+                       .print = ipset_print_port,
+                       .opt = IPSET_OPT_PORT
+               },
+       },
+       .args = {
+               [IPSET_CREATE] = hash_ipport_create_args,
+               [IPSET_ADD] = hash_ipport_add_args,
+       },
+       .mandatory = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT),
+       },
+       .full = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO)
+                       | IPSET_FLAG(IPSET_OPT_HASHSIZE)
+                       | IPSET_FLAG(IPSET_OPT_MAXELEM)
+                       | IPSET_FLAG(IPSET_OPT_PROBES)
+                       | IPSET_FLAG(IPSET_OPT_RESIZE)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT),
+       },
+
+       .usage = hash_ipport_usage,
 };
-
-/*
- * Print and save
- */
-
-static void
-ipporthash_initheader(struct set *set, const void *data)
-{
-       const struct ip_set_req_ipporthash_create *header = data;
-       struct ip_set_ipporthash *map = set->settype->header;
-
-       memset(map, 0, sizeof(struct ip_set_ipporthash));
-       map->hashsize = header->hashsize;
-       map->probes = header->probes;
-       map->resize = header->resize;
-       map->first_ip = header->from;
-       map->last_ip = header->to;
-}
-
-static void
-ipporthash_printheader(struct set *set, unsigned options)
-{
-       struct ip_set_ipporthash *mysetdata = set->settype->header;
-
-       printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
-       printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
-       printf(" hashsize: %u", mysetdata->hashsize);
-       printf(" probes: %u", mysetdata->probes);
-       printf(" resize: %u\n", mysetdata->resize);
-}
-
-static void
-ipporthash_printips(struct set *set, void *data, u_int32_t len,
-                   unsigned options, char dont_align)
-{
-       struct ip_set_ipporthash *mysetdata = set->settype->header;
-       size_t offset = 0;
-       ip_set_ip_t *ipptr, ip;
-       uint16_t port;
-
-       while (offset < len) {
-               ipptr = data + offset;
-               ip = (*ipptr>>16) + mysetdata->first_ip;
-               port = (uint16_t) *ipptr;
-               printf("%s,%s\n", 
-                      ip_tostring(ip, options),
-                      port_tostring(port, options));
-               offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
-       }
-}
-
-static void
-ipporthash_saveheader(struct set *set, unsigned options)
-{
-       struct ip_set_ipporthash *mysetdata = set->settype->header;
-
-       printf("-N %s %s --from %s",
-              set->name, set->settype->typename,
-              ip_tostring(mysetdata->first_ip, options));
-       printf(" --to %s",
-              ip_tostring(mysetdata->last_ip, options));
-       printf(" --hashsize %u --probes %u --resize %u\n",
-              mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
-}
-
-/* Print save for an IP */
-static void
-ipporthash_saveips(struct set *set, void *data, u_int32_t len,
-                  unsigned options, char dont_align)
-{
-       struct ip_set_ipporthash *mysetdata = set->settype->header;
-       size_t offset = 0;
-       ip_set_ip_t *ipptr, ip;
-       uint16_t port;
-
-       while (offset < len) {
-               ipptr = data + offset;
-               ip = (*ipptr>>16) + mysetdata->first_ip;
-               port = (uint16_t) *ipptr;
-               printf("-A %s %s,%s\n", set->name, 
-                      ip_tostring(ip, options),
-                      port_tostring(port, options));
-               offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
-       }
-}
-
-static void
-ipporthash_usage(void)
-{
-       printf
-           ("-N set ipporthash --from IP --to IP\n"
-            "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
-            "-N set ipporthash --network IP/mask\n"
-            "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
-            "-A set IP,port\n"
-            "-D set IP,port\n"
-            "-T set IP,port\n");
-}
-
-static struct settype settype_ipporthash = {
-       .typename = SETTYPE_NAME,
-       .protocol_version = IP_SET_PROTOCOL_VERSION,
-
-       /* Create */
-       .create_size = sizeof(struct ip_set_req_ipporthash_create),
-       .create_init = ipporthash_create_init,
-       .create_parse = ipporthash_create_parse,
-       .create_final = ipporthash_create_final,
-       .create_opts = create_opts,
-
-       /* Add/del/test */
-       .adt_size = sizeof(struct ip_set_req_ipporthash),
-       .adt_parser = ipporthash_adt_parser,
-
-       /* Printing */
-       .header_size = sizeof(struct ip_set_ipporthash),
-       .initheader = ipporthash_initheader,
-       .printheader = ipporthash_printheader,
-       .printips = ipporthash_printips,
-       .printips_sorted = ipporthash_printips,
-       .saveheader = ipporthash_saveheader,
-       .saveips = ipporthash_saveips,
-       
-       .usage = ipporthash_usage,
-};
-
-CONSTRUCTOR(ipporthash)
-{
-       settype_register(&settype_ipporthash);
-
-}
index 49861bfbc4ccc0f8ca63cd573d8cd94ff1108475..71ed3c523396ae5d37b39905514e5d42cb98f8a3 100644 (file)
-/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+/* Copyright 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation.
  */
-
-#include <limits.h>                    /* UINT_MAX */
-#include <stdio.h>                     /* *printf */
-#include <string.h>                    /* mem*, str* */
-
-#include "ipset.h"
-
-#include <linux/netfilter_ipv4/ip_set_ipportiphash.h>
-
-#define OPT_CREATE_HASHSIZE    0x01U
-#define OPT_CREATE_PROBES      0x02U
-#define OPT_CREATE_RESIZE      0x04U
-#define OPT_CREATE_NETWORK     0x08U
-#define OPT_CREATE_FROM                0x10U
-#define OPT_CREATE_TO          0x20U
-
-/* Initialize the create. */
-static void
-ipportiphash_create_init(void *data)
-{
-       struct ip_set_req_ipportiphash_create *mydata = data;
-
-       DP("create INIT");
-
-       /* Default create parameters */ 
-       mydata->hashsize = 1024;
-       mydata->probes = 8;
-       mydata->resize = 50;
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-ipportiphash_create_parse(int c, char *argv[] UNUSED, void *data,
-                         unsigned *flags)
-{
-       struct ip_set_req_ipportiphash_create *mydata = data;
-       ip_set_ip_t value;
-
-       DP("create_parse");
-
-       switch (c) {
-       case '1':
-
-               if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
-                       exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
-
-               *flags |= OPT_CREATE_HASHSIZE;
-
-               DP("--hashsize %u", mydata->hashsize);
-               
-               break;
-
-       case '2':
-
-               if (string_to_number(optarg, 1, 65535, &value))
-                       exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
-
-               mydata->probes = value;
-               *flags |= OPT_CREATE_PROBES;
-
-               DP("--probes %u", mydata->probes);
-               
-               break;
-
-       case '3':
-
-               if (string_to_number(optarg, 0, 65535, &value))
-                       exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
-
-               mydata->resize = value;
-               *flags |= OPT_CREATE_RESIZE;
-
-               DP("--resize %u", mydata->resize);
-               
-               break;
-
-       case '4':
-               parse_ip(optarg, &mydata->from);
-
-               *flags |= OPT_CREATE_FROM;
-
-               DP("--from %x (%s)", mydata->from,
-                  ip_tostring_numeric(mydata->from));
-
-               break;
-
-       case '5':
-               parse_ip(optarg, &mydata->to);
-
-               *flags |= OPT_CREATE_TO;
-
-               DP("--to %x (%s)", mydata->to,
-                  ip_tostring_numeric(mydata->to));
-
-               break;
-
-       case '6':
-               parse_ipandmask(optarg, &mydata->from, &mydata->to);
-
-               /* Make to the last of from + mask */
-               if (mydata->to)
-                       mydata->to = mydata->from | ~(mydata->to);
-               else {
-                       mydata->from = 0x00000000;
-                       mydata->to = 0xFFFFFFFF;
-               }
-               *flags |= OPT_CREATE_NETWORK;
-
-               DP("--network from %x (%s)", 
-                  mydata->from, ip_tostring_numeric(mydata->from));
-               DP("--network to %x (%s)", 
-                  mydata->to, ip_tostring_numeric(mydata->to));
-
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; exit if not ok. */
-static void
-ipportiphash_create_final(void *data, unsigned int flags)
-{
-       struct ip_set_req_ipportiphash_create *mydata = data;
-
-#ifdef IPSET_DEBUG
-       DP("hashsize %u probes %u resize %u",
-          mydata->hashsize, mydata->probes, mydata->resize);
-#endif
-
-       if (flags & OPT_CREATE_NETWORK) {
-               /* --network */
-               if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --from or --to with --network\n");
-       } else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
-               /* --from --to */
-               if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Need to specify both --from and --to\n");
-       } else {
-               exit_error(PARAMETER_PROBLEM,
-                          "Need to specify --from and --to, or --network\n");
-
-       }
-
-       DP("from : %x to: %x diff: %x", 
-          mydata->from, mydata->to,
-          mydata->to - mydata->from);
-
-       if (mydata->from > mydata->to)
-               exit_error(PARAMETER_PROBLEM,
-                          "From can't be higher than to.\n");
-
-       if (mydata->to - mydata->from > MAX_RANGE)
-               exit_error(PARAMETER_PROBLEM,
-                          "Range too large. Max is %d IPs in range\n",
-                          MAX_RANGE+1);
-}
-
-/* Create commandline options */
-static const struct option create_opts[] = {
-       {.name = "hashsize",    .has_arg = required_argument,   .val = '1'},
-       {.name = "probes",      .has_arg = required_argument,   .val = '2'},
-       {.name = "resize",      .has_arg = required_argument,   .val = '3'},
-       {.name = "from",        .has_arg = required_argument,   .val = '4'},
-       {.name = "to",          .has_arg = required_argument,   .val = '5'},
-       {.name = "network",     .has_arg = required_argument,   .val = '6'},
-       {NULL},
-};
-
-/* Add, del, test parser */
-static ip_set_ip_t
-ipportiphash_adt_parser(int cmd UNUSED, const char *arg, void *data)
-{
-       struct ip_set_req_ipportiphash *mydata = data;
-       char *saved = ipset_strdup(arg);
-       char *ptr, *tmp = saved;
-
-       DP("ipportiphash: %p %p", arg, data);
-
-       if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
-               fprintf(stderr, "Warning: please use ',' separator token between ip,port,ip.\n"
-                               "Next release won't support old separator tokens.\n");
-
-       ptr = strsep(&tmp, ":%,");
-       parse_ip(ptr, &mydata->ip);
-
-       if (!tmp)
-               exit_error(PARAMETER_PROBLEM,
-                          "IP address, port and IP address must be specified: ip,port,ip");
-
-       ptr = strsep(&tmp, ":%,");
-       parse_port(ptr, &mydata->port);
-       if (tmp)
-               parse_ip(tmp, &mydata->ip1);
-       else
-               exit_error(PARAMETER_PROBLEM,
-                          "IP address, port and IP address must be specified: ip,port,ip");
-       if (!(mydata->ip || mydata->port || mydata->ip1))
-               exit_error(PARAMETER_PROBLEM,
-                         "Zero valued IP address, port and IP address `%s' specified", arg);
-       ipset_free(saved);
-       return 1;       
+#include <libipset/data.h>                     /* IPSET_OPT_* */
+#include <libipset/parse.h>                    /* parser functions */
+#include <libipset/print.h>                    /* printing functions */
+#include <libipset/types.h>                    /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg hash_ipportip_create_args[] = {
+       { .name = { "range", "--range", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_netrange,        .print = ipset_print_ip,
+       },
+       { .name = { "hashsize", "--hashsize", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_HASHSIZE,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "maxelem", "--maxleme", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "probes", "--probes", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
+         .parse = ipset_parse_uint8,           .print = ipset_print_number,
+       },
+       { .name = { "resize", "--resize", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_RESIZE,
+         .parse = ipset_parse_uint8,           .print = ipset_print_number,
+       },
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       /* Backward compatibility */
+       { .name = { "--from", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_single_ip,
+       },
+       { .name = { "--to", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP_TO,
+         .parse = ipset_parse_single_ip,
+       },
+       { .name = { "--network", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_net,
+       },
+       { },
+}; 
+
+static const struct ipset_arg hash_ipportip_add_args[] = {
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const char hash_ipportip_usage[] =
+"create SETNAME hash:ip,port,ip range IP/CIDR|FROM-TO\n"
+"              [family inet|inet6]\n"
+"               [hashsize VALUE] [maxelem VALUE]\n"
+"               [probes VALUE] [resize VALUE]\n"
+"               [timeout VALUE]\n"
+"add    SETNAME IP,PORT,IP [timeout VALUE]\n"
+"del    SETNAME IP,PORT,IP\n"
+"test   SETNAME IP,PORT,IP\n";
+
+struct ipset_type ipset_hash_ipportip0 = {
+       .name = "hash:ip,port,ip",
+       .alias = "ipportiphash",
+       .revision = 0,
+       .family = AF_INET46,
+       .dimension = IPSET_DIM_THREE,
+       .elem = { 
+               [IPSET_DIM_ONE] = { 
+                       .parse = ipset_parse_single_ip,
+                       .print = ipset_print_ip,
+                       .opt = IPSET_OPT_IP
+               },
+               [IPSET_DIM_TWO] = { 
+                       .parse = ipset_parse_single_port,
+                       .print = ipset_print_port,
+                       .opt = IPSET_OPT_PORT
+               },
+               [IPSET_DIM_THREE] = { 
+                       .parse = ipset_parse_single_ip,
+                       .print = ipset_print_ip,
+                       .opt = IPSET_OPT_IP2
+               },
+       },
+       .args = {
+               [IPSET_CREATE] = hash_ipportip_create_args,
+               [IPSET_ADD] = hash_ipportip_add_args,
+       },
+       .mandatory = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2),
+       },
+       .full = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO)
+                       | IPSET_FLAG(IPSET_OPT_HASHSIZE)
+                       | IPSET_FLAG(IPSET_OPT_MAXELEM)
+                       | IPSET_FLAG(IPSET_OPT_PROBES)
+                       | IPSET_FLAG(IPSET_OPT_RESIZE)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2),
+       },
+
+       .usage = hash_ipportip_usage,
 };
-
-/*
- * Print and save
- */
-
-static void
-ipportiphash_initheader(struct set *set, const void *data)
-{
-       const struct ip_set_req_ipportiphash_create *header = data;
-       struct ip_set_ipportiphash *map = set->settype->header;
-
-       memset(map, 0, sizeof(struct ip_set_ipportiphash));
-       map->hashsize = header->hashsize;
-       map->probes = header->probes;
-       map->resize = header->resize;
-       map->first_ip = header->from;
-       map->last_ip = header->to;
-}
-
-static void
-ipportiphash_printheader(struct set *set, unsigned options)
-{
-       struct ip_set_ipportiphash *mysetdata = set->settype->header;
-
-       printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
-       printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
-       printf(" hashsize: %u", mysetdata->hashsize);
-       printf(" probes: %u", mysetdata->probes);
-       printf(" resize: %u\n", mysetdata->resize);
-}
-
-static void
-ipportiphash_printips(struct set *set, void *data, u_int32_t len,
-                     unsigned options, char dont_align)
-{
-       struct ip_set_ipportiphash *mysetdata = set->settype->header;
-       size_t offset = 0;
-       struct ipportip *ipptr;
-       ip_set_ip_t ip;
-       uint16_t port;
-
-       while (offset < len) {
-               ipptr = data + offset;
-               ip = (ipptr->ip>>16) + mysetdata->first_ip;
-               port = (uint16_t) ipptr->ip;
-               printf("%s,%s,", 
-                      ip_tostring(ip, options),
-                      port_tostring(port, options));
-               printf("%s\n", 
-                      ip_tostring(ipptr->ip1, options));
-               offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align);
-       }
-}
-
-static void
-ipportiphash_saveheader(struct set *set, unsigned options)
-{
-       struct ip_set_ipportiphash *mysetdata = set->settype->header;
-
-       printf("-N %s %s --from %s",
-              set->name, set->settype->typename,
-              ip_tostring(mysetdata->first_ip, options));
-       printf(" --to %s",
-              ip_tostring(mysetdata->last_ip, options));
-       printf(" --hashsize %u --probes %u --resize %u\n",
-              mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
-}
-
-/* Print save for an IP */
-static void
-ipportiphash_saveips(struct set *set, void *data, u_int32_t len,
-                    unsigned options, char dont_align)
-{
-       struct ip_set_ipportiphash *mysetdata = set->settype->header;
-       size_t offset = 0;
-       struct ipportip *ipptr;
-       ip_set_ip_t ip;
-       uint16_t port;
-
-       while (offset < len) {
-               ipptr = data + offset;
-               ip = (ipptr->ip>>16) + mysetdata->first_ip;
-               port = (uint16_t) ipptr->ip;
-               printf("-A %s %s,%s,", set->name, 
-                      ip_tostring(ip, options),
-                      port_tostring(port, options));
-               printf("%s\n",
-                      ip_tostring(ipptr->ip1, options));
-               offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align);
-       }
-}
-
-static void
-ipportiphash_usage(void)
-{
-       printf
-           ("-N set ipportiphash --from IP --to IP\n"
-            "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
-            "-N set ipportiphash --network IP/mask\n"
-            "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
-            "-A set IP,port,IP\n"
-            "-D set IP,port,IP\n"
-            "-T set IP,port,IP\n");
-}
-
-static struct settype settype_ipportiphash = {
-       .typename = SETTYPE_NAME,
-       .protocol_version = IP_SET_PROTOCOL_VERSION,
-
-       /* Create */
-       .create_size = sizeof(struct ip_set_req_ipportiphash_create),
-       .create_init = ipportiphash_create_init,
-       .create_parse = ipportiphash_create_parse,
-       .create_final = ipportiphash_create_final,
-       .create_opts = create_opts,
-
-       /* Add/del/test */
-       .adt_size = sizeof(struct ip_set_req_ipportiphash),
-       .adt_parser = ipportiphash_adt_parser,
-
-       /* Printing */
-       .header_size = sizeof(struct ip_set_ipportiphash),
-       .initheader = ipportiphash_initheader,
-       .printheader = ipportiphash_printheader,
-       .printips = ipportiphash_printips,
-       .printips_sorted = ipportiphash_printips,
-       .saveheader = ipportiphash_saveheader,
-       .saveips = ipportiphash_saveips,
-       
-       .usage = ipportiphash_usage,
-};
-
-CONSTRUCTOR(ipportiphash)
-{
-       settype_register(&settype_ipportiphash);
-
-}
index 3a60bf1a9b50484ef1f9e329650cf6be72171376..769304dec62463c820ee1dafcfab34eeefd74409 100644 (file)
-/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+/* Copyright 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation.
  */
-
-#include <limits.h>                    /* UINT_MAX */
-#include <stdio.h>                     /* *printf */
-#include <string.h>                    /* mem*, str* */
-
-#include "ipset.h"
-
-#include <linux/netfilter_ipv4/ip_set_ipportnethash.h>
-
-#define OPT_CREATE_HASHSIZE    0x01U
-#define OPT_CREATE_PROBES      0x02U
-#define OPT_CREATE_RESIZE      0x04U
-#define OPT_CREATE_NETWORK     0x08U
-#define OPT_CREATE_FROM                0x10U
-#define OPT_CREATE_TO          0x20U
-
-/* Initialize the create. */
-static void
-ipportnethash_create_init(void *data)
-{
-       struct ip_set_req_ipportnethash_create *mydata = data;
-
-       DP("create INIT");
-
-       /* Default create parameters */ 
-       mydata->hashsize = 1024;
-       mydata->probes = 8;
-       mydata->resize = 50;
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-ipportnethash_create_parse(int c, char *argv[] UNUSED, void *data,
-                          unsigned *flags)
-{
-       struct ip_set_req_ipportnethash_create *mydata = data;
-       ip_set_ip_t value;
-
-       DP("create_parse");
-
-       switch (c) {
-       case '1':
-
-               if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
-                       exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
-
-               *flags |= OPT_CREATE_HASHSIZE;
-
-               DP("--hashsize %u", mydata->hashsize);
-               
-               break;
-
-       case '2':
-
-               if (string_to_number(optarg, 1, 65535, &value))
-                       exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
-
-               mydata->probes = value;
-               *flags |= OPT_CREATE_PROBES;
-
-               DP("--probes %u", mydata->probes);
-               
-               break;
-
-       case '3':
-
-               if (string_to_number(optarg, 0, 65535, &value))
-                       exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
-
-               mydata->resize = value;
-               *flags |= OPT_CREATE_RESIZE;
-
-               DP("--resize %u", mydata->resize);
-               
-               break;
-
-       case '4':
-               parse_ip(optarg, &mydata->from);
-
-               *flags |= OPT_CREATE_FROM;
-
-               DP("--from %x (%s)", mydata->from,
-                  ip_tostring_numeric(mydata->from));
-
-               break;
-
-       case '5':
-               parse_ip(optarg, &mydata->to);
-
-               *flags |= OPT_CREATE_TO;
-
-               DP("--to %x (%s)", mydata->to,
-                  ip_tostring_numeric(mydata->to));
-
-               break;
-
-       case '6':
-               parse_ipandmask(optarg, &mydata->from, &mydata->to);
-
-               /* Make to the last of from + mask */
-               if (mydata->to)
-                       mydata->to = mydata->from | ~(mydata->to);
-               else {
-                       mydata->from = 0x00000000;
-                       mydata->to = 0xFFFFFFFF;
-               }
-               *flags |= OPT_CREATE_NETWORK;
-
-               DP("--network from %x (%s)", 
-                  mydata->from, ip_tostring_numeric(mydata->from));
-               DP("--network to %x (%s)", 
-                  mydata->to, ip_tostring_numeric(mydata->to));
-
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; exit if not ok. */
-static void
-ipportnethash_create_final(void *data, unsigned int flags)
-{
-       struct ip_set_req_ipportnethash_create *mydata = data;
-
-#ifdef IPSET_DEBUG
-       DP("hashsize %u probes %u resize %u",
-          mydata->hashsize, mydata->probes, mydata->resize);
-#endif
-
-       if (flags & OPT_CREATE_NETWORK) {
-               /* --network */
-               if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --from or --to with --network\n");
-       } else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
-               /* --from --to */
-               if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Need to specify both --from and --to\n");
-       } else {
-               exit_error(PARAMETER_PROBLEM,
-                          "Need to specify --from and --to, or --network\n");
-
-       }
-
-       DP("from : %x to: %x diff: %x", 
-          mydata->from, mydata->to,
-          mydata->to - mydata->from);
-
-       if (mydata->from > mydata->to)
-               exit_error(PARAMETER_PROBLEM,
-                          "From can't be higher than to.\n");
-
-       if (mydata->to - mydata->from > MAX_RANGE)
-               exit_error(PARAMETER_PROBLEM,
-                          "Range too large. Max is %d IPs in range\n",
-                          MAX_RANGE+1);
-}
-
-/* Create commandline options */
-static const struct option create_opts[] = {
-       {.name = "hashsize",    .has_arg = required_argument,   .val = '1'},
-       {.name = "probes",      .has_arg = required_argument,   .val = '2'},
-       {.name = "resize",      .has_arg = required_argument,   .val = '3'},
-       {.name = "from",        .has_arg = required_argument,   .val = '4'},
-       {.name = "to",          .has_arg = required_argument,   .val = '5'},
-       {.name = "network",     .has_arg = required_argument,   .val = '6'},
-       {NULL},
+#include <libipset/data.h>                     /* IPSET_OPT_* */
+#include <libipset/parse.h>                    /* parser functions */
+#include <libipset/print.h>                    /* printing functions */
+#include <libipset/types.h>                    /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg hash_ipportnet_create_args[] = {
+       { .name = { "range", "--range", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_netrange,        .print = ipset_print_ip,
+       },
+       { .name = { "hashsize", "--hashsize", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_HASHSIZE,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "maxelem", "--maxleme", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "probes", "--probes", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
+         .parse = ipset_parse_uint8,           .print = ipset_print_number,
+       },
+       { .name = { "resize", "--resize", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_RESIZE,
+         .parse = ipset_parse_uint8,           .print = ipset_print_number,
+       },
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       /* Backward compatibility */
+       { .name = { "--from", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_single_ip,
+       },
+       { .name = { "--to", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP_TO,
+         .parse = ipset_parse_single_ip,
+       },
+       { .name = { "--network", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
+         .parse = ipset_parse_net,
+       },
+       { },
+}; 
+
+static const struct ipset_arg hash_ipportnet_add_args[] = {
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const char hash_ipportnet_usage[] =
+"create SETNAME hash:ip,port,net range IP/CIDR|FROM-TO\n"
+"              [family inet|inet6]\n"
+"               [hashsize VALUE] [maxelem VALUE]\n"
+"               [probes VALUE] [resize VALUE]\n"
+"               [timeout VALUE]\n"
+"add    SETNAME IP,PORT,IP/CIDR [timeout VALUE]\n"
+"del    SETNAME IP,PORT,IP/CIDR\n"
+"test   SETNAME IP,PORT,IP/CIDR\n";
+
+struct ipset_type ipset_hash_ipportnet0 = {
+       .name = "hash:ip,port,net",
+       .alias = "ipportnethash",
+       .revision = 0,
+       .family = AF_INET46,
+       .dimension = IPSET_DIM_THREE,
+       .elem = { 
+               [IPSET_DIM_ONE] = { 
+                       .parse = ipset_parse_single_ip,
+                       .print = ipset_print_ip,
+                       .opt = IPSET_OPT_IP
+               },
+               [IPSET_DIM_TWO] = { 
+                       .parse = ipset_parse_single_port,
+                       .print = ipset_print_port,
+                       .opt = IPSET_OPT_PORT
+               },
+               [IPSET_DIM_THREE] = { 
+                       .parse = ipset_parse_net,
+                       .print = ipset_print_ip,
+                       .opt = IPSET_OPT_IP2
+               },
+       },
+       .args = {
+               [IPSET_CREATE] = hash_ipportnet_create_args,
+               [IPSET_ADD] = hash_ipportnet_add_args,
+       },
+       .mandatory = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2)
+                       | IPSET_FLAG(IPSET_OPT_CIDR2),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2)
+                       | IPSET_FLAG(IPSET_OPT_CIDR2),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2)
+                       | IPSET_FLAG(IPSET_OPT_CIDR2),
+       },
+       .full = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO)
+                       | IPSET_FLAG(IPSET_OPT_HASHSIZE)
+                       | IPSET_FLAG(IPSET_OPT_MAXELEM)
+                       | IPSET_FLAG(IPSET_OPT_PROBES)
+                       | IPSET_FLAG(IPSET_OPT_RESIZE)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2)
+                       | IPSET_FLAG(IPSET_OPT_CIDR2)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2)
+                       | IPSET_FLAG(IPSET_OPT_CIDR2),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_PORT)
+                       | IPSET_FLAG(IPSET_OPT_IP2)
+                       | IPSET_FLAG(IPSET_OPT_CIDR2),
+       },
+
+       .usage = hash_ipportnet_usage,
 };
-
-/* Add, del, test parser */
-static ip_set_ip_t
-ipportnethash_adt_parser(int cmd, const char *arg, void *data)
-{
-       struct ip_set_req_ipportnethash *mydata = data;
-       char *saved = ipset_strdup(arg);
-       char *ptr, *tmp = saved;
-       ip_set_ip_t cidr;
-
-       DP("ipportnethash: %p %p", arg, data);
-
-       if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
-               fprintf(stderr, "Warning: please use ',' separator token between ip,port,net.\n"
-                               "Next release won't support old separator tokens.\n");
-
-       ptr = strsep(&tmp, ":%,");
-       parse_ip(ptr, &mydata->ip);
-       if (!tmp)
-               exit_error(PARAMETER_PROBLEM,
-                          "IP address, port and network address must be specified: ip,port,net");
-
-       ptr = strsep(&tmp, ":%,");
-       parse_port(ptr, &mydata->port);
-       if (!tmp)
-               exit_error(PARAMETER_PROBLEM,
-                          "IP address, port and network address must be specified: ip,port,net");
-
-       ptr = strsep(&tmp, "/");
-       if (tmp == NULL)
-               if (cmd == CMD_TEST)
-                       cidr = 32;
-               else
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Missing /cidr from `%s'", arg);
-       else
-               if (string_to_number(tmp, 1, 31, &cidr))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Out of range cidr `%s' specified", arg);
-       
-       mydata->cidr = cidr;
-
-       parse_ip(ptr, &mydata->ip1);
-       ipset_free(saved);
-       return 1;       
-};
-
-/*
- * Print and save
- */
-
-static void
-ipportnethash_initheader(struct set *set, const void *data)
-{
-       const struct ip_set_req_ipportnethash_create *header = data;
-       struct ip_set_ipportnethash *map = set->settype->header;
-
-       memset(map, 0, sizeof(struct ip_set_ipportnethash));
-       map->hashsize = header->hashsize;
-       map->probes = header->probes;
-       map->resize = header->resize;
-       map->first_ip = header->from;
-       map->last_ip = header->to;
-}
-
-static void
-ipportnethash_printheader(struct set *set, unsigned options)
-{
-       struct ip_set_ipportnethash *mysetdata = set->settype->header;
-
-       printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
-       printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
-       printf(" hashsize: %u", mysetdata->hashsize);
-       printf(" probes: %u", mysetdata->probes);
-       printf(" resize: %u\n", mysetdata->resize);
-}
-
-static char buf[20];
-
-static char *
-unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED)
-{
-       int i, j = 3;
-       unsigned char a, b;
-
-       ip = htonl(ip); 
-       for (i = 3; i >= 0; i--)
-               if (((unsigned char *)&ip)[i] != 0) {
-                       j = i;
-                       break;
-               }
-                       
-       a = ((unsigned char *)&ip)[j];
-       if (a <= 128) {
-               a = (a - 1) * 2;
-               b = 7;
-       } else if (a <= 192) {
-               a = (a - 129) * 4;
-               b = 6;
-       } else if (a <= 224) {
-               a = (a - 193) * 8;
-               b = 5;
-       } else if (a <= 240) {
-               a = (a - 225) * 16;
-               b = 4;
-       } else if (a <= 248) {
-               a = (a - 241) * 32;
-               b = 3;
-       } else if (a <= 252) {
-               a = (a - 249) * 64;
-               b = 2;
-       } else if (a <= 254) {
-               a = (a - 253) * 128;
-               b = 1;
-       } else {
-               a = b = 0;
-       }
-       ((unsigned char *)&ip)[j] = a;
-       b += j * 8;
-       
-       sprintf(buf, "%u.%u.%u.%u/%u",
-               ((unsigned char *)&ip)[0],
-               ((unsigned char *)&ip)[1],
-               ((unsigned char *)&ip)[2],
-               ((unsigned char *)&ip)[3],
-               b);
-
-       DP("%s %s", ip_tostring(ntohl(ip), 0), buf);
-       return buf;
-}
-
-static void
-ipportnethash_printips(struct set *set, void *data, u_int32_t len,
-                      unsigned options, char dont_align)
-{
-       struct ip_set_ipportnethash *mysetdata = set->settype->header;
-       size_t offset = 0;
-       struct ipportip *ipptr;
-       ip_set_ip_t ip;
-       uint16_t port;
-
-       while (offset < len) {
-               ipptr = data + offset;
-               ip = (ipptr->ip>>16) + mysetdata->first_ip;
-               port = (uint16_t) ipptr->ip;
-               printf("%s,%s,", 
-                      ip_tostring(ip, options),
-                      port_tostring(port, options));
-               printf("%s\n", 
-                      unpack_ip_tostring(ipptr->ip1, options));
-               offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align);
-       }
-}
-
-static void
-ipportnethash_saveheader(struct set *set, unsigned options)
-{
-       struct ip_set_ipportnethash *mysetdata = set->settype->header;
-
-       printf("-N %s %s --from %s",
-              set->name, set->settype->typename,
-              ip_tostring(mysetdata->first_ip, options));
-       printf(" --to %s",
-              ip_tostring(mysetdata->last_ip, options));
-       printf(" --hashsize %u --probes %u --resize %u\n",
-              mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
-}
-
-/* Print save for an IP */
-static void
-ipportnethash_saveips(struct set *set, void *data, u_int32_t len,
-                     unsigned options, char dont_align)
-{
-       struct ip_set_ipportnethash *mysetdata = set->settype->header;
-       size_t offset = 0;
-       struct ipportip *ipptr;
-       ip_set_ip_t ip;
-       uint16_t port;
-
-       while (offset < len) {
-               ipptr = data + offset;
-               ip = (ipptr->ip>>16) + mysetdata->first_ip;
-               port = (uint16_t) ipptr->ip;
-               printf("-A %s %s,%s,", set->name, 
-                      ip_tostring(ip, options),
-                      port_tostring(port, options));
-               printf("%s\n",
-                      unpack_ip_tostring(ipptr->ip, options));
-               offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align);
-       }
-}
-
-static void
-ipportnethash_usage(void)
-{
-       printf
-           ("-N set ipportnethash --from IP --to IP\n"
-            "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
-            "-N set ipportnethash --network IP/mask\n"
-            "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
-            "-A set IP,port,IP/net\n"
-            "-D set IP,port,IP/net\n"
-            "-T set IP,port,IP[/net]\n");
-}
-
-static struct settype settype_ipportnethash = {
-       .typename = SETTYPE_NAME,
-       .protocol_version = IP_SET_PROTOCOL_VERSION,
-
-       /* Create */
-       .create_size = sizeof(struct ip_set_req_ipportnethash_create),
-       .create_init = ipportnethash_create_init,
-       .create_parse = ipportnethash_create_parse,
-       .create_final = ipportnethash_create_final,
-       .create_opts = create_opts,
-
-       /* Add/del/test */
-       .adt_size = sizeof(struct ip_set_req_ipportnethash),
-       .adt_parser = ipportnethash_adt_parser,
-
-       /* Printing */
-       .header_size = sizeof(struct ip_set_ipportnethash),
-       .initheader = ipportnethash_initheader,
-       .printheader = ipportnethash_printheader,
-       .printips = ipportnethash_printips,
-       .printips_sorted = ipportnethash_printips,
-       .saveheader = ipportnethash_saveheader,
-       .saveips = ipportnethash_saveips,
-       
-       .usage = ipportnethash_usage,
-};
-
-CONSTRUCTOR(ipportnethash)
-{
-       settype_register(&settype_ipportnethash);
-
-}
index c7891cf645e88bb877c176dc36db17c7bfc17fa9..1d70900c89195b1313ebf012136467d05a63e337 100644 (file)
-/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+/* Copyright 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation.
  */
-
-#include <limits.h>                    /* UINT_MAX */
-#include <stdio.h>                     /* *printf */
-#include <string.h>                    /* mem*, str* */
-
-#include "ipset.h"
-
-#include <linux/netfilter_ipv4/ip_set_nethash.h>
-
-#define BUFLEN 30;
-
-#define OPT_CREATE_HASHSIZE    0x01U
-#define OPT_CREATE_PROBES      0x02U
-#define OPT_CREATE_RESIZE      0x04U
-
-/* Initialize the create. */
-static void
-nethash_create_init(void *data)
-{
-       struct ip_set_req_nethash_create *mydata = data;
-
-       DP("create INIT");
-
-       /* Default create parameters */ 
-       mydata->hashsize = 1024;
-       mydata->probes = 4;
-       mydata->resize = 50;
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-nethash_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
-{
-       struct ip_set_req_nethash_create *mydata = data;
-       ip_set_ip_t value;
-
-       DP("create_parse");
-
-       switch (c) {
-       case '1':
-
-               if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
-                       exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
-
-               *flags |= OPT_CREATE_HASHSIZE;
-
-               DP("--hashsize %u", mydata->hashsize);
-               
-               break;
-
-       case '2':
-
-               if (string_to_number(optarg, 1, 65535, &value))
-                       exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
-
-               mydata->probes = value;
-               *flags |= OPT_CREATE_PROBES;
-
-               DP("--probes %u", mydata->probes);
-               
-               break;
-
-       case '3':
-
-               if (string_to_number(optarg, 0, 65535, &value))
-                       exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
-
-               mydata->resize = value;
-               *flags |= OPT_CREATE_RESIZE;
-
-               DP("--resize %u", mydata->resize);
-               
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; exit if not ok. */
-static void
-nethash_create_final(void *data UNUSED, unsigned int flags UNUSED)
-{
-}
-
-/* Create commandline options */
-static const struct option create_opts[] = {
-       {.name = "hashsize",    .has_arg = required_argument,   .val = '1'},
-       {.name = "probes",      .has_arg = required_argument,   .val = '2'},
-       {.name = "resize",      .has_arg = required_argument,   .val = '3'},
-       {NULL},
-};
-
-/* Add, del, test parser */
-static ip_set_ip_t
-nethash_adt_parser(int cmd, const char *arg, void *data)
-{
-       struct ip_set_req_nethash *mydata = data;
-       char *saved = ipset_strdup(arg);
-       char *ptr, *tmp = saved;
-       ip_set_ip_t cidr;
-
-       ptr = strsep(&tmp, "/");
-       
-       if (tmp == NULL) {
-               if (cmd == CMD_TEST)
-                       cidr = 32;
-               else
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Missing cidr from `%s'", arg);
-       } else
-               if (string_to_number(tmp, 1, 31, &cidr))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Out of range cidr `%s' specified", arg);
-       
-       mydata->cidr = cidr;
-       parse_ip(ptr, &mydata->ip);
-#if 0
-       if (!mydata->ip)
-               exit_error(PARAMETER_PROBLEM,
-                         "Zero valued IP address `%s' specified", ptr);
-#endif
-       ipset_free(saved);
-
-       return 1;       
+#include <libipset/data.h>                     /* IPSET_OPT_* */
+#include <libipset/parse.h>                    /* parser functions */
+#include <libipset/print.h>                    /* printing functions */
+#include <libipset/types.h>                    /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg hash_net_create_args[] = {
+       { .name = { "hashsize", "--hashsize", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_HASHSIZE,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "maxelem", "--maxleme", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "probes", "--probes", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
+         .parse = ipset_parse_uint8,           .print = ipset_print_number,
+       },
+       { .name = { "resize", "--resize", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_RESIZE,
+         .parse = ipset_parse_uint8,           .print = ipset_print_number,
+       },
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const struct ipset_arg hash_net_add_args[] = {
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const char hash_net_usage[] =
+"create SETNAME hash:net\n"
+"              [family inet|inet6]\n"
+"               [hashsize VALUE] [maxelem VALUE]\n"
+"               [probes VALUE] [resize VALUE]\n"
+"               [timeout VALUE]\n"
+"add    SETNAME IP/CIDR [timeout VALUE]\n"
+"del    SETNAME IP/CIDR\n"
+"test   SETNAME IP/CIDR\n";
+
+struct ipset_type ipset_hash_net0 = {
+       .name = "hash:net",
+       .alias = "nethash",
+       .revision = 0,
+       .family = AF_INET46,
+       .dimension = IPSET_DIM_ONE,
+       .elem = { 
+               [IPSET_DIM_ONE] = { 
+                       .parse = ipset_parse_net,
+                       .print = ipset_print_ip,
+                       .opt = IPSET_OPT_IP
+               },
+       },
+       .args = {
+               [IPSET_CREATE] = hash_net_create_args,
+               [IPSET_ADD] = hash_net_add_args,
+       },
+       .mandatory = {
+               [IPSET_CREATE] = 0,
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_CIDR),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_CIDR),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_CIDR),
+       },
+       .full = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
+                       | IPSET_FLAG(IPSET_OPT_MAXELEM)
+                       | IPSET_FLAG(IPSET_OPT_PROBES)
+                       | IPSET_FLAG(IPSET_OPT_RESIZE)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_CIDR)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_CIDR),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_CIDR),
+       },
+
+       .usage = hash_net_usage,
 };
-
-/*
- * Print and save
- */
-
-static void
-nethash_initheader(struct set *set, const void *data)
-{
-       const struct ip_set_req_nethash_create *header = data;
-       struct ip_set_nethash *map = set->settype->header;
-
-       memset(map, 0, sizeof(struct ip_set_nethash));
-       map->hashsize = header->hashsize;
-       map->probes = header->probes;
-       map->resize = header->resize;
-}
-
-static void
-nethash_printheader(struct set *set, unsigned options UNUSED)
-{
-       struct ip_set_nethash *mysetdata = set->settype->header;
-
-       printf(" hashsize: %u", mysetdata->hashsize);
-       printf(" probes: %u", mysetdata->probes);
-       printf(" resize: %u\n", mysetdata->resize);
-}
-
-static char buf[20];
-
-static char *
-unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED)
-{
-       int i, j = 3;
-       unsigned char a, b;
-
-       ip = htonl(ip); 
-       for (i = 3; i >= 0; i--)
-               if (((unsigned char *)&ip)[i] != 0) {
-                       j = i;
-                       break;
-               }
-                       
-       a = ((unsigned char *)&ip)[j];
-       if (a <= 128) {
-               a = (a - 1) * 2;
-               b = 7;
-       } else if (a <= 192) {
-               a = (a - 129) * 4;
-               b = 6;
-       } else if (a <= 224) {
-               a = (a - 193) * 8;
-               b = 5;
-       } else if (a <= 240) {
-               a = (a - 225) * 16;
-               b = 4;
-       } else if (a <= 248) {
-               a = (a - 241) * 32;
-               b = 3;
-       } else if (a <= 252) {
-               a = (a - 249) * 64;
-               b = 2;
-       } else if (a <= 254) {
-               a = (a - 253) * 128;
-               b = 1;
-       } else {
-               a = b = 0;
-       }
-       ((unsigned char *)&ip)[j] = a;
-       b += j * 8;
-       
-       sprintf(buf, "%u.%u.%u.%u/%u",
-               ((unsigned char *)&ip)[0],
-               ((unsigned char *)&ip)[1],
-               ((unsigned char *)&ip)[2],
-               ((unsigned char *)&ip)[3],
-               b);
-
-       DP("%s %s", ip_tostring(ntohl(ip), 0), buf);
-       return buf;
-}
-
-static void
-nethash_printips(struct set *set UNUSED, void *data, u_int32_t len,
-                unsigned options, char dont_align)
-{
-       size_t offset = 0;
-       ip_set_ip_t *ip;
-
-       while (offset < len) {
-               ip = data + offset;
-               printf("%s\n", unpack_ip_tostring(*ip, options));
-               offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
-       }
-}
-
-static void
-nethash_saveheader(struct set *set, unsigned options UNUSED)
-{
-       struct ip_set_nethash *mysetdata = set->settype->header;
-
-       printf("-N %s %s --hashsize %u --probes %u --resize %u\n",
-              set->name, set->settype->typename,
-              mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
-}
-
-/* Print save for an IP */
-static void
-nethash_saveips(struct set *set UNUSED, void *data, u_int32_t len,
-               unsigned options, char dont_align)
-{
-       size_t offset = 0;
-       ip_set_ip_t *ip;
-
-       while (offset < len) {
-               ip = data + offset;
-               printf("-A %s %s\n", set->name,
-                      unpack_ip_tostring(*ip, options));
-               offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
-       }
-}
-
-static void
-nethash_usage(void)
-{
-       printf
-           ("-N set nethash [--hashsize hashsize] [--probes probes ]\n"
-            "               [--resize resize]\n"
-            "-A set IP/cidr\n"
-            "-D set IP/cidr\n"
-            "-T set IP/cidr\n");
-}
-
-static struct settype settype_nethash = {
-       .typename = SETTYPE_NAME,
-       .protocol_version = IP_SET_PROTOCOL_VERSION,
-
-       /* Create */
-       .create_size = sizeof(struct ip_set_req_nethash_create),
-       .create_init = nethash_create_init,
-       .create_parse = nethash_create_parse,
-       .create_final = nethash_create_final,
-       .create_opts = create_opts,
-
-       /* Add/del/test */
-       .adt_size = sizeof(struct ip_set_req_nethash),
-       .adt_parser = nethash_adt_parser,
-
-       /* Printing */
-       .header_size = sizeof(struct ip_set_nethash),
-       .initheader = nethash_initheader,
-       .printheader = nethash_printheader,
-       .printips = nethash_printips,
-       .printips_sorted = nethash_printips,
-       .saveheader = nethash_saveheader,
-       .saveips = nethash_saveips,
-       
-       .usage = nethash_usage,
-};
-
-CONSTRUCTOR(nethash)
-{
-       settype_register(&settype_nethash);
-
-}
index de16c442ec8e17fe800f3ba5e1188ab7a846fe64..11b2523c3c87bbaeb3f47a631ecf2223ae397062 100644 (file)
-/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+/* Copyright 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation.
  */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <linux/netfilter_ipv4/ip_set_setlist.h>
-#include "ipset.h"
-
-/* Initialize the create. */
-static void
-setlist_create_init(void *data)
-{
-       struct ip_set_req_setlist_create *mydata = data;
-       
-       mydata->size = 8;
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-setlist_create_parse(int c, char *argv[] UNUSED, void *data,
-                    unsigned *flags UNUSED)
-{
-       struct ip_set_req_setlist_create *mydata = data;
-       unsigned int size;
-       
-       switch (c) {
-       case '1':
-               if (string_to_number(optarg, 1, 255, &size))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Invalid size '%s specified: must be "
-                                  "between 1-255", optarg);
-               mydata->size = size;
-               break;
-       default:
-               return 0;
-       }
-       return 1;
-}
-
-/* Final check; exit if not ok. */
-static void
-setlist_create_final(void *data UNUSED, unsigned int flags UNUSED)
-{
-}
-
-/* Create commandline options */
-static const struct option create_opts[] = {
-       {.name = "size",        .has_arg = required_argument,   .val = '1'},
-       {NULL},
+#include <libipset/data.h>                     /* IPSET_OPT_* */
+#include <libipset/parse.h>                    /* parser functions */
+#include <libipset/print.h>                    /* printing functions */
+#include <libipset/types.h>                    /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg list_set_create_args[] = {
+       { .name = { "size", "--size", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
+         .parse = ipset_parse_uint32,          .print = ipset_print_ip,
+       },
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const struct ipset_arg list_set_add_args[] = {
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const char list_set_usage[] =
+"create SETNAME list:set\n"
+"               [size VALUE] [timeout VALUE]\n"
+"add    SETNAME NAME[,before|after,NAME] [timeout VALUE]\n"
+"del    SETNAME NAME\n"
+"test   SETNAME NAME\n";
+
+struct ipset_type ipset_list_set0 = {
+       .name = "list:set",
+       .alias = "setlist",
+       .revision = 0,
+       .family = AF_UNSPEC,
+       .dimension = IPSET_DIM_ONE,
+       .elem = { 
+               [IPSET_DIM_ONE] = { 
+                       .parse = ipset_parse_name,
+                       .print = ipset_print_name,
+                       .opt = IPSET_OPT_NAME
+               },
+       },
+       .args = {
+               [IPSET_CREATE] = list_set_create_args,
+               [IPSET_ADD] = list_set_add_args,
+       },
+       .mandatory = {
+               [IPSET_CREATE] = 0,
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_NAME),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_NAME),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_NAME),
+       },
+       .full = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_SIZE)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_NAME)
+                       | IPSET_FLAG(IPSET_OPT_BEFORE)
+                       | IPSET_FLAG(IPSET_OPT_NAMEREF)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_NAME),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_NAME),
+       },
+
+       .usage = list_set_usage,
 };
-
-static void
-check_setname(const char *name)
-{
-       if (strlen(name) > IP_SET_MAXNAMELEN - 1)
-               exit_error(PARAMETER_PROBLEM,
-                       "Setname %s is longer than %d characters.",
-                       name, IP_SET_MAXNAMELEN - 1);
-}
-
-/* Add, del, test parser */
-static ip_set_ip_t
-setlist_adt_parser(int cmd UNUSED, const char *arg, void *data)
-{
-       struct ip_set_req_setlist *mydata = data;
-       char *saved = ipset_strdup(arg);
-       char *ptr, *tmp = saved;
-       
-       DP("setlist: %p %p", arg, data);
-
-       ptr = strsep(&tmp, ",");
-       check_setname(ptr);
-       strcpy(mydata->name, ptr);
-       
-       if (!tmp) {
-               mydata->before = 0;
-               mydata->ref[0] = '\0';
-               return 1;
-       }
-       
-       ptr = strsep(&tmp, ",");
-       
-       if (tmp == NULL || !(strcmp(ptr, "before") == 0 || strcmp(ptr, "after") == 0))
-               exit_error(PARAMETER_PROBLEM,
-                       "Syntax error, you must specify elements as setname,[before|after],setname");
-
-       check_setname(tmp);
-       strcpy(mydata->ref, tmp);
-       mydata->before = !strcmp(ptr, "before");
-
-       free(saved);
-
-       return 1;       
-}
-
-/*
- * Print and save
- */
-
-static void
-setlist_initheader(struct set *set, const void *data)
-{
-       const struct ip_set_req_setlist_create *header = data;
-       struct ip_set_setlist *map = set->settype->header;
-               
-       memset(map, 0, sizeof(struct ip_set_setlist));
-       map->size = header->size;
-}
-
-static void
-setlist_printheader(struct set *set, unsigned options UNUSED)
-{
-       struct ip_set_setlist *mysetdata = set->settype->header;
-
-       printf(" size: %u\n", mysetdata->size);
-}
-
-static void
-setlist_printips_sorted(struct set *set, void *data,
-                       u_int32_t len UNUSED, unsigned options UNUSED,
-                       char dont_align)
-{
-       struct ip_set_setlist *mysetdata = set->settype->header;
-       int i, asize;
-       ip_set_id_t *id;
-       struct set *elem;
-
-       asize = IPSET_VALIGN(sizeof(ip_set_id_t), dont_align);
-       for (i = 0; i < mysetdata->size; i++ ) {
-               DP("Try %u", i);
-               id = (ip_set_id_t *)(data + i * asize);
-               DP("Try %u, check", i);
-               if (*id == IP_SET_INVALID_ID)
-                       return;
-               elem = set_find_byid(*id);
-               printf("%s\n", elem->name);
-       }
-}
-
-static void
-setlist_saveheader(struct set *set, unsigned options UNUSED)
-{
-       struct ip_set_setlist *mysetdata = set->settype->header;
-
-       printf("-N %s %s --size %u\n",
-              set->name, set->settype->typename,
-              mysetdata->size);
-}
-
-static void
-setlist_saveips(struct set *set, void *data,
-               u_int32_t len UNUSED, unsigned options UNUSED, char dont_align)
-{
-       struct ip_set_setlist *mysetdata = set->settype->header;
-       int i, asize;
-       ip_set_id_t *id;
-       struct set *elem;
-
-       asize = IPSET_VALIGN(sizeof(ip_set_id_t), dont_align);
-       for (i = 0; i < mysetdata->size; i++ ) {
-               id = (ip_set_id_t *)(data + i * asize);
-               if (*id == IP_SET_INVALID_ID)
-                       return;
-               elem = set_find_byid(*id);
-               printf("-A %s %s\n", set->name, elem->name);
-       }
-}
-
-static void
-setlist_usage(void)
-{
-       printf
-           ("-N set setlist --size size\n"
-            "-A set setname[,before|after,setname]\n"
-            "-D set setname\n"
-            "-T set setname\n");
-}
-
-static struct settype settype_setlist = {
-       .typename = SETTYPE_NAME,
-       .protocol_version = IP_SET_PROTOCOL_VERSION,
-
-       /* Create */
-       .create_size = sizeof(struct ip_set_req_setlist_create),
-       .create_init = setlist_create_init,
-       .create_parse = setlist_create_parse,
-       .create_final = setlist_create_final,
-       .create_opts = create_opts,
-
-       /* Add/del/test */
-       .adt_size = sizeof(struct ip_set_req_setlist),
-       .adt_parser = setlist_adt_parser,
-
-       /* Printing */
-       .header_size = sizeof(struct ip_set_setlist),
-       .initheader = setlist_initheader,
-       .printheader = setlist_printheader,
-       .printips = setlist_printips_sorted,
-       .printips_sorted = setlist_printips_sorted,
-       .saveheader = setlist_saveheader,
-       .saveips = setlist_saveips,
-       
-       .usage = setlist_usage,
-};
-
-CONSTRUCTOR(setlist)
-{
-       settype_register(&settype_setlist);
-
-}
index 508e67ae4820512c9c25e4cef25a0949c691a8bc..7f7d842d2d0bacec78a3dddc1737a415e4d2fa39 100644 (file)
-/* Copyright 2005 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
+/* Copyright 2007-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation.
  */
-
-#include <limits.h>                    /* UINT_MAX */
-#include <stdio.h>                     /* *printf */
-#include <string.h>                    /* mem* */
-
-#include "ipset.h"
-
-#include <linux/netfilter_ipv4/ip_set_iptree.h>
-
-#define BUFLEN 30;
-
-#define OPT_CREATE_TIMEOUT    0x01U
-
-/* Initialize the create. */
-static void
-iptree_create_init(void *data)
-{
-       struct ip_set_req_iptree_create *mydata = data;
-
-       DP("create INIT");
-       mydata->timeout = 0;
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-iptree_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
-{
-       struct ip_set_req_iptree_create *mydata = data;
-
-       DP("create_parse");
-
-       switch (c) {
-       case '1':
-               string_to_number(optarg, 0, UINT_MAX, &mydata->timeout);
-
-               *flags |= OPT_CREATE_TIMEOUT;
-
-               DP("--timeout %u", mydata->timeout);
-
-               break;
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; exit if not ok. */
-static void
-iptree_create_final(void *data UNUSED, unsigned int flags UNUSED)
-{
-}
-
-/* Create commandline options */
-static const struct option create_opts[] = {
-       {.name = "timeout",     .has_arg = required_argument,   .val = '1'},
-       {NULL},
-};
-
-/* Add, del, test parser */
-static ip_set_ip_t
-iptree_adt_parser(int cmd UNUSED, const char *arg, void *data)
-{
-       struct ip_set_req_iptree *mydata = data;
-       char *saved = ipset_strdup(arg);
-       char *ptr, *tmp = saved;
-
-       DP("iptree: %p %p", arg, data);
-
-       if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
-               fprintf(stderr, "Warning: please use ',' separator token between ip,timeout.\n"
-                               "Next release won't support old separator tokens.\n");
-
-       ptr = strsep(&tmp, ":%,");
-       parse_ip(ptr, &mydata->ip);
-
-       if (tmp)
-               string_to_number(tmp, 0, UINT_MAX, &mydata->timeout);
-       else
-               mydata->timeout = 0;    
-
-       ipset_free(saved);
-       return 1;       
-}
-
-/*
- * Print and save
- */
-
-static void
-iptree_initheader(struct set *set, const void *data)
-{
-       const struct ip_set_req_iptree_create *header = data;
-       struct ip_set_iptree *map = set->settype->header;
-               
-       map->timeout = header->timeout;
-}
-
-static void
-iptree_printheader(struct set *set, unsigned options UNUSED)
-{
-       struct ip_set_iptree *mysetdata = set->settype->header;
-
-       if (mysetdata->timeout)
-               printf(" timeout: %u", mysetdata->timeout);
-       printf("\n");
-}
-
-static void
-iptree_printips_sorted(struct set *set, void *data, u_int32_t len,
-                      unsigned options, char dont_align)
-{
-       struct ip_set_iptree *mysetdata = set->settype->header;
-       struct ip_set_req_iptree *req;
-       size_t offset = 0;
-
-       while (len >= offset + sizeof(struct ip_set_req_iptree)) {
-               req = (struct ip_set_req_iptree *)(data + offset);
-               if (mysetdata->timeout)
-                       printf("%s,%u\n", ip_tostring(req->ip, options),
-                                         req->timeout);
-               else
-                       printf("%s\n", ip_tostring(req->ip, options));
-               offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptree), dont_align);
-       }
-}
-
-static void
-iptree_saveheader(struct set *set, unsigned options UNUSED)
-{
-       struct ip_set_iptree *mysetdata = set->settype->header;
-
-       if (mysetdata->timeout)
-               printf("-N %s %s --timeout %u\n",
-                      set->name, set->settype->typename,
-                      mysetdata->timeout);
-       else
-               printf("-N %s %s\n",
-                      set->name, set->settype->typename);
-}
-
-static void
-iptree_saveips(struct set *set, void *data, u_int32_t len,
-              unsigned options, char dont_align)
-{
-       struct ip_set_iptree *mysetdata = set->settype->header;
-       struct ip_set_req_iptree *req;
-       size_t offset = 0;
-
-       DP("%s", set->name);
-
-       while (len >= offset + sizeof(struct ip_set_req_iptree)) {
-               req = (struct ip_set_req_iptree *)(data + offset);
-               if (mysetdata->timeout)
-                       printf("-A %s %s,%u\n",
-                               set->name, 
-                               ip_tostring(req->ip, options),
-                               req->timeout);
-               else
-                       printf("-A %s %s\n", 
-                               set->name,
-                               ip_tostring(req->ip, options));
-               offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptree), dont_align);
-       }
-}
-
-static void
-iptree_usage(void)
-{
-       printf
-           ("-N set iptree [--timeout value]\n"
-            "-A set IP[,timeout]\n"
-            "-D set IP\n"
-            "-T set IP\n");
-}
-
-static struct settype settype_iptree = {
-       .typename = SETTYPE_NAME,
-       .protocol_version = IP_SET_PROTOCOL_VERSION,
-
-       /* Create */
-       .create_size = sizeof(struct ip_set_req_iptree_create),
-       .create_init = iptree_create_init,
-       .create_parse = iptree_create_parse,
-       .create_final = iptree_create_final,
-       .create_opts = create_opts,
-
-       /* Add/del/test */
-       .adt_size = sizeof(struct ip_set_req_iptree),
-       .adt_parser = iptree_adt_parser,
-
-       /* Printing */
-       .header_size = sizeof(struct ip_set_iptree),
-       .initheader = iptree_initheader,
-       .printheader = iptree_printheader,
-       .printips = iptree_printips_sorted,     /* We only have sorted version */
-       .printips_sorted = iptree_printips_sorted,
-       .saveheader = iptree_saveheader,
-       .saveips = iptree_saveips,
-       
-       .usage = iptree_usage,
+#include <libipset/data.h>                     /* IPSET_OPT_* */
+#include <libipset/parse.h>                    /* parser functions */
+#include <libipset/print.h>                    /* printing functions */
+#include <libipset/types.h>                    /* prototypes */
+
+/* Parse commandline arguments */
+static const struct ipset_arg tree_ip_create_args[] = {
+       { .name = { "gc", "--gc", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_GC,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const struct ipset_arg tree_ip_add_args[] = {
+       { .name = { "timeout", "--timeout", NULL },
+         .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
+         .parse = ipset_parse_uint32,          .print = ipset_print_number,
+       },
+       { },
+}; 
+
+static const char tree_ip_usage[] =
+"create SETNAME tree:ip\n"
+"               [gc VALUE] [timeout VALUE]\n"
+"add    SETNAME IP|IP/CIDR|FROM-TO [timeout VALUE]\n"
+"del    SETNAME IP|IP/CIDR|FROM-TO\n"
+"test   SETNAME IP\n";
+
+struct ipset_type ipset_tree_ip0 = {
+       .name = "tree:ip",
+       .alias = "iptree",
+       .revision = 0,
+       .family = AF_INET,
+       .dimension = IPSET_DIM_ONE,
+       .elem = { 
+               [IPSET_DIM_ONE] = { 
+                       .parse = ipset_parse_ip,
+                       .print = ipset_print_ip,
+                       .opt = IPSET_OPT_IP
+               },
+       },
+       .args = {
+               [IPSET_CREATE] = tree_ip_create_args,
+               [IPSET_ADD] = tree_ip_add_args,
+       },
+       .mandatory = {
+               [IPSET_CREATE] = 0,
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
+       },
+       .full = {
+               [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_GC)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO)
+                       | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+               [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+                       | IPSET_FLAG(IPSET_OPT_IP_TO),
+               [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
+       },
+
+       .usage = tree_ip_usage,
 };
-
-CONSTRUCTOR(iptree)
-{
-       settype_register(&settype_iptree);
-
-}