]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
SET target revision 2 added
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Sun, 17 Apr 2011 09:38:18 +0000 (11:38 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Sun, 17 Apr 2011 09:38:18 +0000 (11:38 +0200)
The new revision of the SET target supports the following new operations

- specifying the timeout value of the entry to be added
- flag to instruct the kernel that if the entry already
  exists then reset the timeout value to the specified one (or
  to the default from the set definition)

extensions/libxt_SET.c
extensions/libxt_SET.man
extensions/libxt_set.c
include/linux/netfilter/xt_set.h

index 2f915bcd6a6ab4cc744177272813138b89202172..51c0cec6e0a1e568e38e8ecfc3285fa2d8682a17 100644 (file)
 #include <linux/netfilter/xt_set.h>
 #include "libxt_set.h"
 
+/* Revision 0 */
+
 static void
-set_target_help(void)
+set_target_help_v0(void)
 {
        printf("SET target options:\n"
               " --add-set name flags\n"
@@ -32,14 +34,14 @@ set_target_help(void)
               "                'src' and 'dst' specifications.\n");
 }
 
-static const struct option set_target_opts[] = {
+static const struct option set_target_opts_v0[] = {
        {.name = "add-set", .has_arg = true, .val = '1'},
        {.name = "del-set", .has_arg = true, .val = '2'},
        XT_GETOPT_TABLEEND,
 };
 
 static void
-set_target_check(unsigned int flags)
+set_target_check_v0(unsigned int flags)
 {
        if (!flags)
                xtables_error(PARAMETER_PROBLEM,
@@ -144,20 +146,29 @@ set_target_save_v0(const void *ip, const struct xt_entry_target *target)
        print_target_v0("--del-set", &info->del_set);
 }
 
+/* Revision 1 */
+
+#define set_target_help_v1     set_target_help_v0
+
 static void
-set_target_init(struct xt_entry_target *target)
+set_target_init_v1(struct xt_entry_target *target)
 {
-       struct xt_set_info_target *info =
-               (struct xt_set_info_target *) target->data;
+       struct xt_set_info_target_v1 *info =
+               (struct xt_set_info_target_v1 *) target->data;
 
        info->add_set.index =
        info->del_set.index = IPSET_INVALID_ID;
 
 }
 
+#define SET_TARGET_ADD         0x1
+#define SET_TARGET_DEL         0x2
+#define SET_TARGET_EXIST       0x4
+#define SET_TARGET_TIMEOUT     0x8
+
 static void
-parse_target(char **argv, int invert, unsigned int *flags,
-            struct xt_set_info *info, const char *what)
+parse_target(char **argv, int invert, struct xt_set_info *info,
+            const char *what)
 {
        if (info->dim)
                xtables_error(PARAMETER_PROBLEM,
@@ -180,30 +191,30 @@ parse_target(char **argv, int invert, unsigned int *flags,
        get_set_byname(optarg, info);
        parse_dirs(argv[optind], info);
        optind++;
-       
-       *flags = 1;
 }
 
 static int
-set_target_parse(int c, char **argv, int invert, unsigned int *flags,
-                const void *entry, struct xt_entry_target **target)
+set_target_parse_v1(int c, char **argv, int invert, unsigned int *flags,
+                   const void *entry, struct xt_entry_target **target)
 {
-       struct xt_set_info_target *myinfo =
-               (struct xt_set_info_target *) (*target)->data;
+       struct xt_set_info_target_v1 *myinfo =
+               (struct xt_set_info_target_v1 *) (*target)->data;
 
        switch (c) {
        case '1':               /* --add-set <set> <flags> */
-               parse_target(argv, invert, flags,
-                            &myinfo->add_set, "add-set");
+               parse_target(argv, invert, &myinfo->add_set, "add-set");
+               *flags |= SET_TARGET_ADD;
                break;
        case '2':               /* --del-set <set>[:<flags>] <flags> */
-               parse_target(argv, invert, flags,
-                            &myinfo->del_set, "del-set");
+               parse_target(argv, invert, &myinfo->del_set, "del-set");
+               *flags |= SET_TARGET_DEL;
                break;
        }
        return 1;
 }
 
+#define set_target_check_v1    set_target_check_v0
+
 static void
 print_target(const char *prefix, const struct xt_set_info *info)
 {
@@ -222,21 +233,132 @@ print_target(const char *prefix, const struct xt_set_info *info)
 }
 
 static void
-set_target_print(const void *ip, const struct xt_entry_target *target,
-                 int numeric)
+set_target_print_v1(const void *ip, const struct xt_entry_target *target,
+                   int numeric)
+{
+       const struct xt_set_info_target_v1 *info = (const void *)target->data;
+
+       print_target("add-set", &info->add_set);
+       print_target("del-set", &info->del_set);
+}
+
+static void
+set_target_save_v1(const void *ip, const struct xt_entry_target *target)
+{
+       const struct xt_set_info_target_v1 *info = (const void *)target->data;
+
+       print_target("--add-set", &info->add_set);
+       print_target("--del-set", &info->del_set);
+}
+
+#define set_target_opts_v1     set_target_opts_v0
+
+/* Revision 2 */
+
+static void
+set_target_help_v2(void)
+{
+       printf("SET target options:\n"
+              " --add-set name flags [--exist] [--timeout n]\n"
+              " --del-set name flags\n"
+              "                add/del src/dst IP/port from/to named sets,\n"
+              "                where flags are the comma separated list of\n"
+              "                'src' and 'dst' specifications.\n");
+}
+
+static const struct option set_target_opts_v2[] = {
+       {.name = "add-set", .has_arg = true,  .val = '1'},
+       {.name = "del-set", .has_arg = true,  .val = '2'},
+       {.name = "exist",   .has_arg = false, .val = '3'},
+       {.name = "timeout", .has_arg = true,  .val = '4'},
+       XT_GETOPT_TABLEEND,
+};
+
+static void
+set_target_check_v2(unsigned int flags)
+{
+       if (!(flags & (SET_TARGET_ADD|SET_TARGET_DEL)))
+               xtables_error(PARAMETER_PROBLEM,
+                          "You must specify either `--add-set' or `--del-set'");
+       if (!(flags & SET_TARGET_ADD)) {
+               if (flags & SET_TARGET_EXIST)
+                       xtables_error(PARAMETER_PROBLEM,
+                               "Flag `--exist' can be used with `--add-set' only");
+               if (flags & SET_TARGET_TIMEOUT)
+                       xtables_error(PARAMETER_PROBLEM,
+                               "Option `--timeout' can be used with `--add-set' only");
+       }
+}
+
+
+static void
+set_target_init_v2(struct xt_entry_target *target)
 {
-       const struct xt_set_info_target *info = (const void *)target->data;
+       struct xt_set_info_target_v2 *info =
+               (struct xt_set_info_target_v2 *) target->data;
+
+       info->add_set.index =
+       info->del_set.index = IPSET_INVALID_ID;
+       info->timeout = UINT32_MAX;
+}
+
+static int
+set_target_parse_v2(int c, char **argv, int invert, unsigned int *flags,
+                   const void *entry, struct xt_entry_target **target)
+{
+       struct xt_set_info_target_v2 *myinfo =
+               (struct xt_set_info_target_v2 *) (*target)->data;
+       unsigned int timeout;
+
+       switch (c) {
+       case '1':               /* --add-set <set> <flags> */
+               parse_target(argv, invert, &myinfo->add_set, "add-set");
+               *flags |= SET_TARGET_ADD;
+               break;
+       case '2':               /* --del-set <set>[:<flags>] <flags> */
+               parse_target(argv, invert, &myinfo->del_set, "del-set");
+               *flags |= SET_TARGET_DEL;
+               break;
+       case '3':
+               myinfo->flags |= IPSET_FLAG_EXIST;
+               *flags |= SET_TARGET_EXIST;
+               break;
+       case '4':
+               if (!xtables_strtoui(optarg, NULL, &timeout, 0, UINT32_MAX - 1))
+                       xtables_error(PARAMETER_PROBLEM,
+                                     "Invalid value for option --timeout "
+                                     "or out of range 0-%u", UINT32_MAX - 1);
+               myinfo->timeout = timeout;
+               *flags |= SET_TARGET_TIMEOUT;
+               break;  
+       }
+       return 1;
+}
+
+static void
+set_target_print_v2(const void *ip, const struct xt_entry_target *target,
+                   int numeric)
+{
+       const struct xt_set_info_target_v2 *info = (const void *)target->data;
 
        print_target("add-set", &info->add_set);
+       if (info->flags & IPSET_FLAG_EXIST)
+               printf(" exist");
+       if (info->timeout != UINT32_MAX)
+               printf(" timeout %u", info->timeout);
        print_target("del-set", &info->del_set);
 }
 
 static void
-set_target_save(const void *ip, const struct xt_entry_target *target)
+set_target_save_v2(const void *ip, const struct xt_entry_target *target)
 {
-       const struct xt_set_info_target *info = (const void *)target->data;
+       const struct xt_set_info_target_v2 *info = (const void *)target->data;
 
        print_target("--add-set", &info->add_set);
+       if (info->flags & IPSET_FLAG_EXIST)
+               printf(" --exist");
+       if (info->timeout != UINT32_MAX)
+               printf(" --timeout %u", info->timeout);
        print_target("--del-set", &info->del_set);
 }
 
@@ -248,28 +370,43 @@ static struct xtables_target set_tg_reg[] = {
                .family         = NFPROTO_IPV4,
                .size           = XT_ALIGN(sizeof(struct xt_set_info_target_v0)),
                .userspacesize  = XT_ALIGN(sizeof(struct xt_set_info_target_v0)),
-               .help           = set_target_help,
+               .help           = set_target_help_v0,
                .init           = set_target_init_v0,
                .parse          = set_target_parse_v0,
-               .final_check    = set_target_check,
+               .final_check    = set_target_check_v0,
                .print          = set_target_print_v0,
                .save           = set_target_save_v0,
-               .extra_opts     = set_target_opts,
+               .extra_opts     = set_target_opts_v0,
        },
        {
                .name           = "SET",
                .revision       = 1,
                .version        = XTABLES_VERSION,
                .family         = NFPROTO_UNSPEC,
-               .size           = XT_ALIGN(sizeof(struct xt_set_info_target)),
-               .userspacesize  = XT_ALIGN(sizeof(struct xt_set_info_target)),
-               .help           = set_target_help,
-               .init           = set_target_init,
-               .parse          = set_target_parse,
-               .final_check    = set_target_check,
-               .print          = set_target_print,
-               .save           = set_target_save,
-               .extra_opts     = set_target_opts,
+               .size           = XT_ALIGN(sizeof(struct xt_set_info_target_v1)),
+               .userspacesize  = XT_ALIGN(sizeof(struct xt_set_info_target_v1)),
+               .help           = set_target_help_v1,
+               .init           = set_target_init_v1,
+               .parse          = set_target_parse_v1,
+               .final_check    = set_target_check_v1,
+               .print          = set_target_print_v1,
+               .save           = set_target_save_v1,
+               .extra_opts     = set_target_opts_v1,
+       },
+       {
+               .name           = "SET",
+               .revision       = 2,
+               .version        = XTABLES_VERSION,
+               .family         = NFPROTO_UNSPEC,
+               .size           = XT_ALIGN(sizeof(struct xt_set_info_target_v2)),
+               .userspacesize  = XT_ALIGN(sizeof(struct xt_set_info_target_v2)),
+               .help           = set_target_help_v2,
+               .init           = set_target_init_v2,
+               .parse          = set_target_parse_v2,
+               .final_check    = set_target_check_v2,
+               .print          = set_target_print_v2,
+               .save           = set_target_save_v2,
+               .extra_opts     = set_target_opts_v2,
        },
 };
 
index ea80c2a1f321ae2ceb2599b73b491ca3a51ce661..739be41467ca847a7e78a70d17ee5c20047f8b97 100644 (file)
@@ -12,6 +12,14 @@ where flags are
 and/or
 .BR "dst"
 specifications and there can be no more than six of them.
+.TP
+\fB\-\-timeout\fP \fIvalue\fP
+when adding entry, the timeout value to use instead of the default
+one from the set definition
+.TP
+\fB\-\-exist\fP
+when adding entry if it already exists, reset the timeout value
+to the specified one or to the default from the set definition
 .PP
 Use of -j SET requires that ipset kernel support is provided. As standard
 kernels do not ship this currently, the ipset or Xtables-addons package needs
index 78bf7c10a0181cd856a96955ff72249fc004e769..da722c738ddf8a1cb45b6495bcca2a7f1859149f 100644 (file)
 #include <linux/netfilter/xt_set.h>
 #include "libxt_set.h"
 
+/* Revision 0 */
+
 static void
-set_help(void)
+set_help_v0(void)
 {
        printf("set match options:\n"
               " [!] --match-set name flags\n"
@@ -32,14 +34,14 @@ set_help(void)
               "                 'src' and 'dst' specifications.\n");
 }
 
-static const struct option set_opts[] = {
+static const struct option set_opts_v0[] = {
        {.name = "match-set", .has_arg = true, .val = '1'},
        {.name = "set",       .has_arg = true, .val = '2'},
        XT_GETOPT_TABLEEND,
 };
 
 static void
-set_check(unsigned int flags)
+set_check_v0(unsigned int flags)
 {
        if (!flags)
                xtables_error(PARAMETER_PROBLEM,
@@ -127,12 +129,18 @@ set_save_v0(const void *ip, const struct xt_entry_match *match)
        print_match_v0("--match-set", &info->match_set);
 }
 
+/* Revision 1 */
+
+#define set_help_v1    set_help_v0
+#define set_opts_v1    set_opts_v0
+#define set_check_v1   set_check_v0
+
 static int
-set_parse(int c, char **argv, int invert, unsigned int *flags,
-         const void *entry, struct xt_entry_match **match)
+set_parse_v1(int c, char **argv, int invert, unsigned int *flags,
+            const void *entry, struct xt_entry_match **match)
 {
-       struct xt_set_info_match *myinfo = 
-               (struct xt_set_info_match *) (*match)->data;
+       struct xt_set_info_match_v1 *myinfo = 
+               (struct xt_set_info_match_v1 *) (*match)->data;
        struct xt_set_info *info = &myinfo->match_set;
 
        switch (c) {
@@ -191,17 +199,17 @@ print_match(const char *prefix, const struct xt_set_info *info)
 
 /* Prints out the matchinfo. */
 static void
-set_print(const void *ip, const struct xt_entry_match *match, int numeric)
+set_print_v1(const void *ip, const struct xt_entry_match *match, int numeric)
 {
-       const struct xt_set_info_match *info = (const void *)match->data;
+       const struct xt_set_info_match_v1 *info = (const void *)match->data;
 
        print_match("match-set", &info->match_set);
 }
 
 static void
-set_save(const void *ip, const struct xt_entry_match *match)
+set_save_v1(const void *ip, const struct xt_entry_match *match)
 {
-       const struct xt_set_info_match *info = (const void *)match->data;
+       const struct xt_set_info_match_v1 *info = (const void *)match->data;
 
        print_match("--match-set", &info->match_set);
 }
@@ -214,26 +222,26 @@ static struct xtables_match set_mt_reg[] = {
                .family         = NFPROTO_IPV4,
                .size           = XT_ALIGN(sizeof(struct xt_set_info_match_v0)),
                .userspacesize  = XT_ALIGN(sizeof(struct xt_set_info_match_v0)),
-               .help           = set_help,
+               .help           = set_help_v0,
                .parse          = set_parse_v0,
-               .final_check    = set_check,
+               .final_check    = set_check_v0,
                .print          = set_print_v0,
                .save           = set_save_v0,
-               .extra_opts     = set_opts,
+               .extra_opts     = set_opts_v0,
        },
        {
                .name           = "set",
                .revision       = 1,
                .version        = XTABLES_VERSION,
                .family         = NFPROTO_UNSPEC,
-               .size           = XT_ALIGN(sizeof(struct xt_set_info_match)),
-               .userspacesize  = XT_ALIGN(sizeof(struct xt_set_info_match)),
-               .help           = set_help,
-               .parse          = set_parse,
-               .final_check    = set_check,
-               .print          = set_print,
-               .save           = set_save,
-               .extra_opts     = set_opts,
+               .size           = XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
+               .userspacesize  = XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
+               .help           = set_help_v1,
+               .parse          = set_parse_v1,
+               .final_check    = set_check_v1,
+               .print          = set_print_v1,
+               .save           = set_save_v1,
+               .extra_opts     = set_opts_v1,
        },
 };
 
index 3ad313785eade32ba7f4106da1a8e97b60037974..4379ce9fcfa112661dbf45c7a944d6205a075e79 100644 (file)
@@ -89,7 +89,7 @@ struct xt_set_info_target_v0 {
        struct xt_set_info_v0 del_set;
 };
 
-/* Revision 1: current interface to netfilter/iptables */
+/* Revision 1 match and target */
 
 struct xt_set_info {
        ip_set_id_t index;
@@ -98,13 +98,27 @@ struct xt_set_info {
 };
 
 /* match and target infos */
-struct xt_set_info_match {
+struct xt_set_info_match_v1 {
        struct xt_set_info match_set;
 };
 
-struct xt_set_info_target {
+struct xt_set_info_target_v1 {
        struct xt_set_info add_set;
        struct xt_set_info del_set;
 };
 
+/* Revision 2 target */
+
+enum ipset_cmd_flags {
+       IPSET_FLAG_BIT_EXIST    = 0,
+       IPSET_FLAG_EXIST        = (1 << IPSET_FLAG_BIT_EXIST),
+};
+
+struct xt_set_info_target_v2 {
+       struct xt_set_info add_set;
+       struct xt_set_info del_set;
+       u_int32_t flags;
+       u_int32_t timeout;
+};
+
 #endif /*_XT_SET_H*/