summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-06-25 14:50:53 +0200
committerPatrick McHardy <kaber@trash.net>2010-06-25 14:50:53 +0200
commit78514bc3a9b1b724c9fc904941c5854644865673 (patch)
tree699d5858891356952376a37077ea3f5f3355eb8a /extensions
parente6d0d94139e826f7b5d8446ce174155c04963b07 (diff)
parentd40f1628c3717daebc437a398a285e371b5b6f7f (diff)
Merge branch 'master' of vishnu.netfilter.org:/data/git/iptables
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libipt_SET.c164
-rw-r--r--extensions/libipt_set.c160
-rw-r--r--extensions/libipt_set.h119
-rw-r--r--extensions/libxt_SET.c286
-rw-r--r--extensions/libxt_SET.man (renamed from extensions/libipt_SET.man)0
-rw-r--r--extensions/libxt_set.c250
-rw-r--r--extensions/libxt_set.h147
-rw-r--r--extensions/libxt_set.man (renamed from extensions/libipt_set.man)0
8 files changed, 683 insertions, 443 deletions
diff --git a/extensions/libipt_SET.c b/extensions/libipt_SET.c
deleted file mode 100644
index 18cf7d48..00000000
--- a/extensions/libipt_SET.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
- * Patrick Schaaf <bof@bof.de>
- * Martin Josefsson <gandalf@wlug.westbo.se>
- * Copyright (C) 2003-2004 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.
- */
-
-/* Shared library add-on to iptables to add IP set mangling target. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-
-#include <xtables.h>
-#include <linux/netfilter_ipv4/ip_set.h>
-#include <linux/netfilter_ipv4/ipt_set.h>
-#include "libipt_set.h"
-
-static void SET_help(void)
-{
- printf("SET target options:\n"
- " --add-set name flags\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_opts[] = {
- { .name = "add-set", .has_arg = true, .val = '1'},
- { .name = "del-set", .has_arg = true, .val = '2'},
- { .name = NULL }
-};
-
-static void SET_init(struct xt_entry_target *target)
-{
- struct ipt_set_info_target *info =
- (struct ipt_set_info_target *) target->data;
-
- memset(info, 0, sizeof(struct ipt_set_info_target));
- info->add_set.index =
- info->del_set.index = IP_SET_INVALID_ID;
-
-}
-
-static void
-parse_target(char **argv, int invert, unsigned int *flags,
- struct ipt_set_info *info, const char *what)
-{
- if (info->flags[0])
- xtables_error(PARAMETER_PROBLEM,
- "--%s can be specified only once", what);
-
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --%s", what);
-
- if (!argv[optind]
- || argv[optind][0] == '-' || argv[optind][0] == '!')
- xtables_error(PARAMETER_PROBLEM,
- "--%s requires two args.", what);
-
- if (strlen(optarg) > IP_SET_MAXNAMELEN - 1)
- xtables_error(PARAMETER_PROBLEM,
- "setname `%s' too long, max %d characters.",
- optarg, IP_SET_MAXNAMELEN - 1);
-
- get_set_byname(optarg, info);
- parse_bindings(argv[optind], info);
- optind++;
-
- *flags = 1;
-}
-
-static int SET_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct ipt_set_info_target *myinfo =
- (struct ipt_set_info_target *) (*target)->data;
-
- switch (c) {
- case '1': /* --add-set <set> <flags> */
- parse_target(argv, invert, flags,
- &myinfo->add_set, "add-set");
- break;
- case '2': /* --del-set <set>[:<flags>] <flags> */
- parse_target(argv, invert, flags,
- &myinfo->del_set, "del-set");
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static void SET_check(unsigned int flags)
-{
- if (!flags)
- xtables_error(PARAMETER_PROBLEM,
- "You must specify either `--add-set' or `--del-set'");
-}
-
-static void
-print_target(const char *prefix, const struct ipt_set_info *info)
-{
- int i;
- char setname[IP_SET_MAXNAMELEN];
-
- if (info->index == IP_SET_INVALID_ID)
- return;
- get_set_byid(setname, info->index);
- printf("%s %s", prefix, setname);
- for (i = 0; i < IP_SET_MAX_BINDINGS; i++) {
- if (!info->flags[i])
- break;
- printf("%s%s",
- i == 0 ? " " : ",",
- info->flags[i] & IPSET_SRC ? "src" : "dst");
- }
- printf(" ");
-}
-
-static void SET_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- const struct ipt_set_info_target *info = (const void *)target->data;
-
- print_target("add-set", &info->add_set);
- print_target("del-set", &info->del_set);
-}
-
-static void SET_save(const void *ip, const struct xt_entry_target *target)
-{
- const struct ipt_set_info_target *info = (const void *)target->data;
-
- print_target("--add-set", &info->add_set);
- print_target("--del-set", &info->del_set);
-}
-
-static struct xtables_target set_tg_reg = {
- .name = "SET",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct ipt_set_info_target)),
- .userspacesize = XT_ALIGN(sizeof(struct ipt_set_info_target)),
- .help = SET_help,
- .init = SET_init,
- .parse = SET_parse,
- .final_check = SET_check,
- .print = SET_print,
- .save = SET_save,
- .extra_opts = SET_opts,
-};
-
-void _init(void)
-{
- xtables_register_target(&set_tg_reg);
-}
diff --git a/extensions/libipt_set.c b/extensions/libipt_set.c
deleted file mode 100644
index 9f7a97c9..00000000
--- a/extensions/libipt_set.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
- * Patrick Schaaf <bof@bof.de>
- * Martin Josefsson <gandalf@wlug.westbo.se>
- * Copyright (C) 2003-2004 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.
- */
-
-/* Shared library add-on to iptables to add IP set matching. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include <xtables.h>
-#include <linux/netfilter_ipv4/ipt_set.h>
-#include "libipt_set.h"
-
-static void set_help(void)
-{
- printf("set match options:\n"
- " [!] --match-set name flags\n"
- " 'name' is the set name from to match,\n"
- " 'flags' are the comma separated list of\n"
- " 'src' and 'dst' specifications.\n");
-}
-
-static const struct option set_opts[] = {
- { .name = "match-set", .has_arg = true, .val = '1'},
- { .name = "set", .has_arg = true, .val = '2'},
- { .name = NULL }
-};
-
-static void set_init(struct xt_entry_match *match)
-{
- struct ipt_set_info_match *info =
- (struct ipt_set_info_match *) match->data;
-
-
- memset(info, 0, sizeof(struct ipt_set_info_match));
-
-}
-
-static int set_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- struct ipt_set_info_match *myinfo =
- (struct ipt_set_info_match *) (*match)->data;
- struct ipt_set_info *info = &myinfo->match_set;
-
- switch (c) {
- case '2':
-#if 0
- fprintf(stderr,
- "--set option deprecated, please use --match-set\n");
-#endif
- case '1': /* --match-set <set> <flag>[,<flag> */
- if (info->flags[0])
- xtables_error(PARAMETER_PROBLEM,
- "--match-set can be specified only once");
-
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- if (invert)
- info->flags[0] |= IPSET_MATCH_INV;
-
- if (!argv[optind]
- || argv[optind][0] == '-'
- || argv[optind][0] == '!')
- xtables_error(PARAMETER_PROBLEM,
- "--match-set requires two args.");
-
- if (strlen(optarg) > IP_SET_MAXNAMELEN - 1)
- xtables_error(PARAMETER_PROBLEM,
- "setname `%s' too long, max %d characters.",
- optarg, IP_SET_MAXNAMELEN - 1);
-
- get_set_byname(optarg, info);
- parse_bindings(argv[optind], info);
- DEBUGP("parse: set index %u\n", info->index);
- optind++;
-
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void set_check(unsigned int flags)
-{
- if (!flags)
- xtables_error(PARAMETER_PROBLEM,
- "You must specify `--match-set' with proper arguments");
- DEBUGP("final check OK\n");
-}
-
-static void
-print_match(const char *prefix, const struct ipt_set_info *info)
-{
- int i;
- char setname[IP_SET_MAXNAMELEN];
-
- get_set_byid(setname, info->index);
- printf("%s%s %s",
- (info->flags[0] & IPSET_MATCH_INV) ? "! " : "",
- prefix,
- setname);
- for (i = 0; i < IP_SET_MAX_BINDINGS; i++) {
- if (!info->flags[i])
- break;
- printf("%s%s",
- i == 0 ? " " : ",",
- info->flags[i] & IPSET_SRC ? "src" : "dst");
- }
- printf(" ");
-}
-
-/* Prints out the matchinfo. */
-static void set_print(const void *ip, const struct xt_entry_match *match,
- int numeric)
-{
- const struct ipt_set_info_match *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)
-{
- const struct ipt_set_info_match *info = (const void *)match->data;
-
- print_match("--match-set", &info->match_set);
-}
-
-static struct xtables_match set_mt_reg = {
- .name = "set",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct ipt_set_info_match)),
- .userspacesize = XT_ALIGN(sizeof(struct ipt_set_info_match)),
- .help = set_help,
- .init = set_init,
- .parse = set_parse,
- .final_check = set_check,
- .print = set_print,
- .save = set_save,
- .extra_opts = set_opts,
-};
-
-void _init(void)
-{
- xtables_register_match(&set_mt_reg);
-}
diff --git a/extensions/libipt_set.h b/extensions/libipt_set.h
deleted file mode 100644
index 0e9b0b54..00000000
--- a/extensions/libipt_set.h
+++ /dev/null
@@ -1,119 +0,0 @@
-#ifndef _LIBIPT_SET_H
-#define _LIBIPT_SET_H
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-
-#ifdef DEBUG
-#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
-static void
-parse_bindings(const char *opt_arg, struct ipt_set_info *info)
-{
- char *saved = strdup(opt_arg);
- char *ptr, *tmp = saved;
- int i = 0;
-
- while (i < (IP_SET_MAX_BINDINGS - 1) && tmp != NULL) {
- ptr = strsep(&tmp, ",");
- if (strncmp(ptr, "src", 3) == 0)
- info->flags[i++] |= IPSET_SRC;
- else if (strncmp(ptr, "dst", 3) == 0)
- info->flags[i++] |= IPSET_DST;
- else
- xtables_error(PARAMETER_PROBLEM,
- "You must spefify (the comma separated list of) 'src' or 'dst'.");
- }
-
- if (tmp)
- xtables_error(PARAMETER_PROBLEM,
- "Can't follow bindings deeper than %i.",
- IP_SET_MAX_BINDINGS - 1);
-
- free(saved);
-}
-
-static int get_version(unsigned *version)
-{
- int res, sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
- struct ip_set_req_version req_version;
- socklen_t size = sizeof(req_version);
-
- if (sockfd < 0)
- xtables_error(OTHER_PROBLEM,
- "Can't open socket to ipset.\n");
-
- req_version.op = IP_SET_OP_VERSION;
- res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size);
- if (res != 0)
- xtables_error(OTHER_PROBLEM,
- "Kernel module ip_set is not loaded in.\n");
-
- *version = req_version.version;
-
- return sockfd;
-}
-
-static void get_set_byname(const char *setname, struct ipt_set_info *info)
-{
- struct ip_set_req_get_set req;
- socklen_t size = sizeof(struct ip_set_req_get_set);
- int res, sockfd;
-
- sockfd = get_version(&req.version);
- req.op = IP_SET_OP_GET_BYNAME;
- strncpy(req.set.name, setname, IP_SET_MAXNAMELEN);
- req.set.name[IP_SET_MAXNAMELEN - 1] = '\0';
- res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req, &size);
- close(sockfd);
-
- if (res != 0)
- xtables_error(OTHER_PROBLEM,
- "Problem when communicating with ipset, errno=%d.\n",
- errno);
- if (size != sizeof(struct ip_set_req_get_set))
- xtables_error(OTHER_PROBLEM,
- "Incorrect return size from kernel during ipset lookup, "
- "(want %zu, got %zu)\n",
- sizeof(struct ip_set_req_get_set), (size_t)size);
- if (req.set.index == IP_SET_INVALID_ID)
- xtables_error(PARAMETER_PROBLEM,
- "Set %s doesn't exist.\n", setname);
-
- info->index = req.set.index;
-}
-
-static void get_set_byid(char * setname, ip_set_id_t idx)
-{
- struct ip_set_req_get_set req;
- socklen_t size = sizeof(struct ip_set_req_get_set);
- int res, sockfd;
-
- sockfd = get_version(&req.version);
- req.op = IP_SET_OP_GET_BYINDEX;
- req.set.index = idx;
- res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req, &size);
- close(sockfd);
-
- if (res != 0)
- xtables_error(OTHER_PROBLEM,
- "Problem when communicating with ipset, errno=%d.\n",
- errno);
- if (size != sizeof(struct ip_set_req_get_set))
- xtables_error(OTHER_PROBLEM,
- "Incorrect return size from kernel during ipset lookup, "
- "(want %zu, got %zu)\n",
- sizeof(struct ip_set_req_get_set), (size_t)size);
- if (req.set.name[0] == '\0')
- xtables_error(PARAMETER_PROBLEM,
- "Set id %i in kernel doesn't exist.\n", idx);
-
- strncpy(setname, req.set.name, IP_SET_MAXNAMELEN);
-}
-
-#endif /*_LIBIPT_SET_H*/
diff --git a/extensions/libxt_SET.c b/extensions/libxt_SET.c
new file mode 100644
index 00000000..f6386a9e
--- /dev/null
+++ b/extensions/libxt_SET.c
@@ -0,0 +1,286 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Martin Josefsson <gandalf@wlug.westbo.se>
+ * Copyright (C) 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.
+ */
+
+/* Shared library add-on to iptables to add IP set mangling target. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_set.h>
+#include "libxt_set.h"
+
+static void
+set_target_help(void)
+{
+ printf("SET target options:\n"
+ " --add-set name flags\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[] = {
+ { .name = "add-set", .has_arg = true, .val = '1'},
+ { .name = "del-set", .has_arg = true, .val = '2'},
+ { .name = NULL }
+};
+
+static void
+set_target_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify either `--add-set' or `--del-set'");
+}
+
+static void
+set_target_init_v0(struct xt_entry_target *target)
+{
+ struct xt_set_info_target_v0 *info =
+ (struct xt_set_info_target_v0 *) target->data;
+
+ info->add_set.index =
+ info->del_set.index = IPSET_INVALID_ID;
+
+}
+
+static void
+parse_target_v0(char **argv, int invert, unsigned int *flags,
+ struct xt_set_info_v0 *info, const char *what)
+{
+ if (info->u.flags[0])
+ xtables_error(PARAMETER_PROBLEM,
+ "--%s can be specified only once", what);
+
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --%s", what);
+
+ if (!argv[optind]
+ || argv[optind][0] == '-' || argv[optind][0] == '!')
+ xtables_error(PARAMETER_PROBLEM,
+ "--%s requires two args.", what);
+
+ if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "setname `%s' too long, max %d characters.",
+ optarg, IPSET_MAXNAMELEN - 1);
+
+ get_set_byname(optarg, (struct xt_set_info *)info);
+ parse_dirs_v0(argv[optind], info);
+ optind++;
+
+ *flags = 1;
+}
+
+static int
+set_target_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_set_info_target_v0 *myinfo =
+ (struct xt_set_info_target_v0 *) (*target)->data;
+
+ switch (c) {
+ case '1': /* --add-set <set> <flags> */
+ parse_target_v0(argv, invert, flags,
+ &myinfo->add_set, "add-set");
+ break;
+ case '2': /* --del-set <set>[:<flags>] <flags> */
+ parse_target_v0(argv, invert, flags,
+ &myinfo->del_set, "del-set");
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void
+print_target_v0(const char *prefix, const struct xt_set_info_v0 *info)
+{
+ int i;
+ char setname[IPSET_MAXNAMELEN];
+
+ if (info->index == IPSET_INVALID_ID)
+ return;
+ get_set_byid(setname, info->index);
+ printf("%s %s", prefix, setname);
+ for (i = 0; i < IPSET_DIM_MAX; i++) {
+ if (!info->u.flags[i])
+ break;
+ printf("%s%s",
+ i == 0 ? " " : ",",
+ info->u.flags[i] & IPSET_SRC ? "src" : "dst");
+ }
+ printf(" ");
+}
+
+static void
+set_target_print_v0(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_set_info_target_v0 *info = (const void *)target->data;
+
+ print_target_v0("add-set", &info->add_set);
+ print_target_v0("del-set", &info->del_set);
+}
+
+static void
+set_target_save_v0(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_set_info_target_v0 *info = (const void *)target->data;
+
+ print_target_v0("--add-set", &info->add_set);
+ print_target_v0("--del-set", &info->del_set);
+}
+
+static void
+set_target_init(struct xt_entry_target *target)
+{
+ struct xt_set_info_target *info =
+ (struct xt_set_info_target *) target->data;
+
+ info->add_set.index =
+ info->del_set.index = IPSET_INVALID_ID;
+
+}
+
+static void
+parse_target(char **argv, int invert, unsigned int *flags,
+ struct xt_set_info *info, const char *what)
+{
+ if (info->dim)
+ xtables_error(PARAMETER_PROBLEM,
+ "--%s can be specified only once", what);
+
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --%s", what);
+
+ if (!argv[optind]
+ || argv[optind][0] == '-' || argv[optind][0] == '!')
+ xtables_error(PARAMETER_PROBLEM,
+ "--%s requires two args.", what);
+
+ if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "setname `%s' too long, max %d characters.",
+ optarg, IPSET_MAXNAMELEN - 1);
+
+ 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)
+{
+ struct xt_set_info_target *myinfo =
+ (struct xt_set_info_target *) (*target)->data;
+
+ switch (c) {
+ case '1': /* --add-set <set> <flags> */
+ parse_target(argv, invert, flags,
+ &myinfo->add_set, "add-set");
+ break;
+ case '2': /* --del-set <set>[:<flags>] <flags> */
+ parse_target(argv, invert, flags,
+ &myinfo->del_set, "del-set");
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void
+print_target(const char *prefix, const struct xt_set_info *info)
+{
+ int i;
+ char setname[IPSET_MAXNAMELEN];
+
+ if (info->index == IPSET_INVALID_ID)
+ return;
+ get_set_byid(setname, info->index);
+ printf("%s %s", prefix, setname);
+ for (i = 1; i <= IPSET_DIM_MAX; i++) {
+ printf("%s%s",
+ i == 1 ? " " : ",",
+ info->flags & (1 << i) ? "src" : "dst");
+ }
+ printf(" ");
+}
+
+static void
+set_target_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_set_info_target *info = (const void *)target->data;
+
+ print_target("add-set", &info->add_set);
+ print_target("del-set", &info->del_set);
+}
+
+static void
+set_target_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_set_info_target *info = (const void *)target->data;
+
+ print_target("--add-set", &info->add_set);
+ print_target("--del-set", &info->del_set);
+}
+
+static struct xtables_target set_tg_reg[] = {
+ {
+ .name = "SET",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .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,
+ .init = set_target_init_v0,
+ .parse = set_target_parse_v0,
+ .final_check = set_target_check,
+ .print = set_target_print_v0,
+ .save = set_target_save_v0,
+ .extra_opts = set_target_opts,
+ },
+ {
+ .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,
+ },
+};
+
+void _init(void)
+{
+ xtables_register_targets(set_tg_reg, ARRAY_SIZE(set_tg_reg));
+}
diff --git a/extensions/libipt_SET.man b/extensions/libxt_SET.man
index ea80c2a1..ea80c2a1 100644
--- a/extensions/libipt_SET.man
+++ b/extensions/libxt_SET.man
diff --git a/extensions/libxt_set.c b/extensions/libxt_set.c
new file mode 100644
index 00000000..75fa3c27
--- /dev/null
+++ b/extensions/libxt_set.c
@@ -0,0 +1,250 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Martin Josefsson <gandalf@wlug.westbo.se>
+ * Copyright (C) 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.
+ */
+
+/* Shared library add-on to iptables to add IP set matching. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_set.h>
+#include "libxt_set.h"
+
+static void
+set_help(void)
+{
+ printf("set match options:\n"
+ " [!] --match-set name flags\n"
+ " 'name' is the set name from to match,\n"
+ " 'flags' are the comma separated list of\n"
+ " 'src' and 'dst' specifications.\n");
+}
+
+static const struct option set_opts[] = {
+ { .name = "match-set", .has_arg = true, .val = '1'},
+ { .name = "set", .has_arg = true, .val = '2'},
+ { .name = NULL }
+};
+
+static void
+set_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify `--match-set' with proper arguments");
+}
+
+static int
+set_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_set_info_match_v0 *myinfo =
+ (struct xt_set_info_match_v0 *) (*match)->data;
+ struct xt_set_info_v0 *info = &myinfo->match_set;
+
+ switch (c) {
+ case '2':
+ fprintf(stderr,
+ "--set option deprecated, please use --match-set\n");
+ case '1': /* --match-set <set> <flag>[,<flag> */
+ if (info->u.flags[0])
+ xtables_error(PARAMETER_PROBLEM,
+ "--match-set can be specified only once");
+
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ info->u.flags[0] |= IPSET_MATCH_INV;
+
+ if (!argv[optind]
+ || argv[optind][0] == '-'
+ || argv[optind][0] == '!')
+ xtables_error(PARAMETER_PROBLEM,
+ "--match-set requires two args.");
+
+ if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "setname `%s' too long, max %d characters.",
+ optarg, IPSET_MAXNAMELEN - 1);
+
+ get_set_byname(optarg, (struct xt_set_info *)info);
+ parse_dirs_v0(argv[optind], info);
+ DEBUGP("parse: set index %u\n", info->index);
+ optind++;
+
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+print_match_v0(const char *prefix, const struct xt_set_info_v0 *info)
+{
+ int i;
+ char setname[IPSET_MAXNAMELEN];
+
+ get_set_byid(setname, info->index);
+ printf("%s%s %s",
+ (info->u.flags[0] & IPSET_MATCH_INV) ? "! " : "",
+ prefix,
+ setname);
+ for (i = 0; i < IPSET_DIM_MAX; i++) {
+ if (!info->u.flags[i])
+ break;
+ printf("%s%s",
+ i == 0 ? " " : ",",
+ info->u.flags[i] & IPSET_SRC ? "src" : "dst");
+ }
+ printf(" ");
+}
+
+/* Prints out the matchinfo. */
+static void
+set_print_v0(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_set_info_match_v0 *info = (const void *)match->data;
+
+ print_match_v0("match-set", &info->match_set);
+}
+
+static void
+set_save_v0(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_set_info_match_v0 *info = (const void *)match->data;
+
+ print_match_v0("--match-set", &info->match_set);
+}
+
+static int
+set_parse(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 *info = &myinfo->match_set;
+
+ switch (c) {
+ case '2':
+ fprintf(stderr,
+ "--set option deprecated, please use --match-set\n");
+ case '1': /* --match-set <set> <flag>[,<flag> */
+ if (info->dim)
+ xtables_error(PARAMETER_PROBLEM,
+ "--match-set can be specified only once");
+
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ info->flags |= IPSET_INV_MATCH;
+
+ if (!argv[optind]
+ || argv[optind][0] == '-'
+ || argv[optind][0] == '!')
+ xtables_error(PARAMETER_PROBLEM,
+ "--match-set requires two args.");
+
+ if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "setname `%s' too long, max %d characters.",
+ optarg, IPSET_MAXNAMELEN - 1);
+
+ get_set_byname(optarg, info);
+ parse_dirs(argv[optind], info);
+ DEBUGP("parse: set index %u\n", info->index);
+ optind++;
+
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+print_match(const char *prefix, const struct xt_set_info *info)
+{
+ int i;
+ char setname[IPSET_MAXNAMELEN];
+
+ get_set_byid(setname, info->index);
+ printf("%s%s %s",
+ (info->flags & IPSET_INV_MATCH) ? "! " : "",
+ prefix,
+ setname);
+ for (i = 1; i <= info->dim; i++) {
+ printf("%s%s",
+ i == 1 ? " " : ",",
+ info->flags & (1 << i) ? "src" : "dst");
+ }
+ printf(" ");
+}
+
+/* Prints out the matchinfo. */
+static void
+set_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_set_info_match *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)
+{
+ const struct xt_set_info_match *info = (const void *)match->data;
+
+ print_match("--match-set", &info->match_set);
+}
+
+static struct xtables_match set_mt_reg[] = {
+ {
+ .name = "set",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .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,
+ .parse = set_parse_v0,
+ .final_check = set_check,
+ .print = set_print_v0,
+ .save = set_save_v0,
+ .extra_opts = set_opts,
+ },
+ {
+ .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,
+ },
+};
+
+void _init(void)
+{
+ xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg));
+}
diff --git a/extensions/libxt_set.h b/extensions/libxt_set.h
new file mode 100644
index 00000000..6b936911
--- /dev/null
+++ b/extensions/libxt_set.h
@@ -0,0 +1,147 @@
+#ifndef _LIBXT_SET_H
+#define _LIBXT_SET_H
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#ifdef DEBUG
+#define DEBUGP(x, args...) fprintf(stderr, x , ## args)
+#else
+#define DEBUGP(x, args...)
+#endif
+
+static int
+get_version(unsigned *version)
+{
+ int res, sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ struct ip_set_req_version req_version;
+ socklen_t size = sizeof(req_version);
+
+ if (sockfd < 0)
+ xtables_error(OTHER_PROBLEM,
+ "Can't open socket to ipset.\n");
+
+ req_version.op = IP_SET_OP_VERSION;
+ res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size);
+ if (res != 0)
+ xtables_error(OTHER_PROBLEM,
+ "Kernel module xt_set is not loaded in.\n");
+
+ *version = req_version.version;
+
+ return sockfd;
+}
+
+static void
+get_set_byid(char *setname, ip_set_id_t idx)
+{
+ struct ip_set_req_get_set req;
+ socklen_t size = sizeof(struct ip_set_req_get_set);
+ int res, sockfd;
+
+ sockfd = get_version(&req.version);
+ req.op = IP_SET_OP_GET_BYINDEX;
+ req.set.index = idx;
+ res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req, &size);
+ close(sockfd);
+
+ if (res != 0)
+ xtables_error(OTHER_PROBLEM,
+ "Problem when communicating with ipset, errno=%d.\n",
+ errno);
+ if (size != sizeof(struct ip_set_req_get_set))
+ xtables_error(OTHER_PROBLEM,
+ "Incorrect return size from kernel during ipset lookup, "
+ "(want %zu, got %zu)\n",
+ sizeof(struct ip_set_req_get_set), (size_t)size);
+ if (req.set.name[0] == '\0')
+ xtables_error(PARAMETER_PROBLEM,
+ "Set with index %i in kernel doesn't exist.\n", idx);
+
+ strncpy(setname, req.set.name, IPSET_MAXNAMELEN);
+}
+
+static void
+get_set_byname(const char *setname, struct xt_set_info *info)
+{
+ struct ip_set_req_get_set req;
+ socklen_t size = sizeof(struct ip_set_req_get_set);
+ int res, sockfd;
+
+ sockfd = get_version(&req.version);
+ req.op = IP_SET_OP_GET_BYNAME;
+ strncpy(req.set.name, setname, IPSET_MAXNAMELEN);
+ req.set.name[IPSET_MAXNAMELEN - 1] = '\0';
+ res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req, &size);
+ close(sockfd);
+
+ if (res != 0)
+ xtables_error(OTHER_PROBLEM,
+ "Problem when communicating with ipset, errno=%d.\n",
+ errno);
+ if (size != sizeof(struct ip_set_req_get_set))
+ xtables_error(OTHER_PROBLEM,
+ "Incorrect return size from kernel during ipset lookup, "
+ "(want %zu, got %zu)\n",
+ sizeof(struct ip_set_req_get_set), (size_t)size);
+ if (req.set.index == IPSET_INVALID_ID)
+ xtables_error(PARAMETER_PROBLEM,
+ "Set %s doesn't exist.\n", setname);
+
+ info->index = req.set.index;
+}
+
+static void
+parse_dirs_v0(const char *opt_arg, struct xt_set_info_v0 *info)
+{
+ char *saved = strdup(opt_arg);
+ char *ptr, *tmp = saved;
+ int i = 0;
+
+ while (i < (IPSET_DIM_MAX - 1) && tmp != NULL) {
+ ptr = strsep(&tmp, ",");
+ if (strncmp(ptr, "src", 3) == 0)
+ info->u.flags[i++] |= IPSET_SRC;
+ else if (strncmp(ptr, "dst", 3) == 0)
+ info->u.flags[i++] |= IPSET_DST;
+ else
+ xtables_error(PARAMETER_PROBLEM,
+ "You must spefify (the comma separated list of) 'src' or 'dst'.");
+ }
+
+ if (tmp)
+ xtables_error(PARAMETER_PROBLEM,
+ "Can't be more src/dst options than %i.",
+ IPSET_DIM_MAX - 1);
+
+ free(saved);
+}
+
+static void
+parse_dirs(const char *opt_arg, struct xt_set_info *info)
+{
+ char *saved = strdup(opt_arg);
+ char *ptr, *tmp = saved;
+ int i = 0;
+
+ while (i < (IPSET_DIM_MAX - 1) && tmp != NULL) {
+ info->dim++;
+ ptr = strsep(&tmp, ",");
+ if (strncmp(ptr, "src", 3) == 0)
+ info->flags |= (1 << info->dim);
+ else if (strncmp(ptr, "dst", 3) != 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "You must spefify (the comma separated list of) 'src' or 'dst'.");
+ }
+
+ if (tmp)
+ xtables_error(PARAMETER_PROBLEM,
+ "Can't be more src/dst options than %i.",
+ IPSET_DIM_MAX - 1);
+
+ free(saved);
+}
+
+#endif /*_LIBXT_SET_H*/
diff --git a/extensions/libipt_set.man b/extensions/libxt_set.man
index aca1bfce..aca1bfce 100644
--- a/extensions/libipt_set.man
+++ b/extensions/libxt_set.man