diff options
author | Patrick McHardy <kaber@trash.net> | 2010-07-15 18:15:03 +0200 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-07-15 18:15:03 +0200 |
commit | b14f160c11196aeb99000611207bd353c7ae2cb9 (patch) | |
tree | 250e1e5386a24e41f2d1cf83089876549c9135d2 /extensions | |
parent | 0bcda81f5f6d121084131fb944e2940f614cc98c (diff) | |
parent | b4fa7222923bc10476b8753f358e871f461eb2db (diff) |
Merge branch 'master' into iptables-next
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/libipt_SET.c | 164 | ||||
-rw-r--r-- | extensions/libipt_set.c | 160 | ||||
-rw-r--r-- | extensions/libipt_set.h | 119 | ||||
-rw-r--r-- | extensions/libxt_SET.c | 286 | ||||
-rw-r--r-- | extensions/libxt_SET.man (renamed from extensions/libipt_SET.man) | 0 | ||||
-rw-r--r-- | extensions/libxt_conntrack.c | 16 | ||||
-rw-r--r-- | extensions/libxt_hashlimit.c | 6 | ||||
-rw-r--r-- | extensions/libxt_quota.c | 6 | ||||
-rw-r--r-- | extensions/libxt_quota.man | 3 | ||||
-rw-r--r-- | extensions/libxt_rateest.c | 6 | ||||
-rw-r--r-- | extensions/libxt_rateest.man | 8 | ||||
-rw-r--r-- | extensions/libxt_set.c | 250 | ||||
-rw-r--r-- | extensions/libxt_set.h | 147 | ||||
-rw-r--r-- | extensions/libxt_set.man (renamed from extensions/libipt_set.man) | 0 |
14 files changed, 711 insertions, 460 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_conntrack.c b/extensions/libxt_conntrack.c index e8225e6d..5557d3ea 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -842,9 +842,13 @@ conntrack_dump_addr(const union nf_inet_addr *addr, return; } if (numeric) - printf("%s ", xtables_ipaddr_to_numeric(&addr->in)); + printf("%s%s ", + xtables_ipaddr_to_numeric(&addr->in), + xtables_ipmask_to_numeric(&mask->in)); else - printf("%s ", xtables_ipaddr_to_anyname(&addr->in)); + printf("%s%s ", + xtables_ipaddr_to_anyname(&addr->in), + xtables_ipmask_to_numeric(&mask->in)); } else if (family == NFPROTO_IPV6) { if (!numeric && addr->ip6[0] == 0 && addr->ip6[1] == 0 && addr->ip6[2] == 0 && addr->ip6[3] == 0) { @@ -852,9 +856,13 @@ conntrack_dump_addr(const union nf_inet_addr *addr, return; } if (numeric) - printf("%s ", xtables_ip6addr_to_numeric(&addr->in6)); + printf("%s%s ", + xtables_ip6addr_to_numeric(&addr->in6), + xtables_ip6mask_to_numeric(&mask->in6)); else - printf("%s ", xtables_ip6addr_to_anyname(&addr->in6)); + printf("%s%s ", + xtables_ip6addr_to_anyname(&addr->in6), + xtables_ip6mask_to_numeric(&mask->in6)); } } diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c index a8fe588f..7442dfcf 100644 --- a/extensions/libxt_hashlimit.c +++ b/extensions/libxt_hashlimit.c @@ -591,8 +591,7 @@ static void hashlimit_save(const void *ip, const struct xt_entry_match *match) const struct xt_hashlimit_info *r = (const void *)match->data; fputs("--hashlimit ", stdout); print_rate(r->cfg.avg); - if (r->cfg.burst != XT_HASHLIMIT_BURST) - printf("--hashlimit-burst %u ", r->cfg.burst); + printf("--hashlimit-burst %u ", r->cfg.burst); fputs("--hashlimit-mode ", stdout); print_mode(r->cfg.mode, ','); @@ -617,8 +616,7 @@ hashlimit_mt_save(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) else fputs("--hashlimit-upto ", stdout); print_rate(info->cfg.avg); - if (info->cfg.burst != XT_HASHLIMIT_BURST) - printf("--hashlimit-burst %u ", info->cfg.burst); + printf("--hashlimit-burst %u ", info->cfg.burst); if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT | XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) { diff --git a/extensions/libxt_quota.c b/extensions/libxt_quota.c index 69d27460..ac7c686e 100644 --- a/extensions/libxt_quota.c +++ b/extensions/libxt_quota.c @@ -19,7 +19,7 @@ static const struct option quota_opts[] = { static void quota_help(void) { printf("quota match options:\n" - " --quota quota quota (bytes)\n"); + "[!] --quota quota quota (bytes)\n"); } static void @@ -65,6 +65,10 @@ quota_parse(int c, char **argv, int invert, unsigned int *flags, if (!parse_quota(optarg, &info->quota)) xtables_error(PARAMETER_PROBLEM, "bad quota: '%s'", optarg); + + if (invert) + info->flags |= XT_QUOTA_INVERT; + break; default: diff --git a/extensions/libxt_quota.man b/extensions/libxt_quota.man index f8bf77b5..8d9e18b8 100644 --- a/extensions/libxt_quota.man +++ b/extensions/libxt_quota.man @@ -1,6 +1,5 @@ Implements network quotas by decrementing a byte counter with each packet. .TP -\fB\-\-quota\fP \fIbytes\fP +[\fB!\fP] \fB\-\-quota\fP \fIbytes\fP The quota in bytes. -.P diff --git a/extensions/libxt_rateest.c b/extensions/libxt_rateest.c index 62100f4b..ad0884e7 100644 --- a/extensions/libxt_rateest.c +++ b/extensions/libxt_rateest.c @@ -419,9 +419,11 @@ rateest_save(const void *ip, const struct xt_entry_match *match) } else { printf("--rateest %s ", info->name1); if (info->flags & XT_RATEEST_MATCH_BPS) { - printf("--rateest-bps "); - rateest_print_mode(info, "--rateest-"); + printf("--rateest-bps1 "); + rateest_print_rate(info->bps1, 0); + printf("--rateest-bps2 "); rateest_print_rate(info->bps2, 0); + rateest_print_mode(info, "--rateest-"); } if (info->flags & XT_RATEEST_MATCH_PPS) { printf("--rateest-pps "); diff --git a/extensions/libxt_rateest.man b/extensions/libxt_rateest.man index 24c0673b..de064af3 100644 --- a/extensions/libxt_rateest.man +++ b/extensions/libxt_rateest.man @@ -11,14 +11,14 @@ Name of the second rate estimator (if difference is to be calculated). \fB\-\-rateest\-delta\fP Compare difference(s) to given rate(s) .TP -\fB\-\-rateest1\-bps\fP \fIvalue\fP +\fB\-\-rateest\-bps1\fP \fIvalue\fP .TP -\fB\-\-rateest2\-bps\fP \fIvalue\fP +\fB\-\-rateest\-bps2\fP \fIvalue\fP Compare bytes per second. .TP -\fB\-\-rateest1\-pps\fP \fIvalue\fP +\fB\-\-rateest\-pps1\fP \fIvalue\fP .TP -\fB\-\-rateest2\-pps\fP \fIvalue\fP +\fB\-\-rateest\-pps2\fP \fIvalue\fP Compare packets per second. .TP [\fB!\fP] \fB\-\-rateest\-lt\fP 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 |