From d40f1628c3717daebc437a398a285e371b5b6f7f Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 16 Jun 2010 12:45:33 +0200 Subject: libxt_set: new revision added libipt_set renamed to libxt_set and the support for the forthcoming ipset release added. I have tested backward (IPv4) and forward compatibility (IPv4/IPv6): ipset -N test iphash ipset -A test test-address iptables -N test-set iptables -A test-set -j LOG --log-prefix "match " iptables -A test-set -j DROP iptables -A OUTPUT -m set --match-set test dst -j test-set ping test-address --- extensions/libipt_SET.c | 164 -------------------------- extensions/libipt_SET.man | 18 --- extensions/libipt_set.c | 160 -------------------------- extensions/libipt_set.h | 119 ------------------- extensions/libipt_set.man | 23 ---- extensions/libxt_SET.c | 286 ++++++++++++++++++++++++++++++++++++++++++++++ extensions/libxt_SET.man | 18 +++ extensions/libxt_set.c | 250 ++++++++++++++++++++++++++++++++++++++++ extensions/libxt_set.h | 147 ++++++++++++++++++++++++ extensions/libxt_set.man | 23 ++++ 10 files changed, 724 insertions(+), 484 deletions(-) delete mode 100644 extensions/libipt_SET.c delete mode 100644 extensions/libipt_SET.man delete mode 100644 extensions/libipt_set.c delete mode 100644 extensions/libipt_set.h delete mode 100644 extensions/libipt_set.man create mode 100644 extensions/libxt_SET.c create mode 100644 extensions/libxt_SET.man create mode 100644 extensions/libxt_set.c create mode 100644 extensions/libxt_set.h create mode 100644 extensions/libxt_set.man (limited to 'extensions') 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 - * Patrick Schaaf - * Martin Josefsson - * Copyright (C) 2003-2004 Jozsef Kadlecsik - * - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#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 */ - parse_target(argv, invert, flags, - &myinfo->add_set, "add-set"); - break; - case '2': /* --del-set [:] */ - 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.man b/extensions/libipt_SET.man deleted file mode 100644 index ea80c2a1..00000000 --- a/extensions/libipt_SET.man +++ /dev/null @@ -1,18 +0,0 @@ -This modules adds and/or deletes entries from IP sets which can be defined -by ipset(8). -.TP -\fB\-\-add\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...] -add the address(es)/port(s) of the packet to the sets -.TP -\fB\-\-del\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...] -delete the address(es)/port(s) of the packet from the sets -.IP -where flags are -.BR "src" -and/or -.BR "dst" -specifications and there can be no more than six of them. -.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 -to be installed. 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 - * Patrick Schaaf - * Martin Josefsson - * Copyright (C) 2003-2004 Jozsef Kadlecsik - * - * 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 -#include -#include -#include -#include -#include -#include - -#include -#include -#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 [, */ - 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 -#include -#include -#include - -#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/libipt_set.man b/extensions/libipt_set.man deleted file mode 100644 index aca1bfce..00000000 --- a/extensions/libipt_set.man +++ /dev/null @@ -1,23 +0,0 @@ -This module matches IP sets which can be defined by ipset(8). -.TP -[\fB!\fP] \fB\-\-match\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP]... -where flags are the comma separated list of -.BR "src" -and/or -.BR "dst" -specifications and there can be no more than six of them. Hence the command -.IP - iptables \-A FORWARD \-m set \-\-match\-set test src,dst -.IP -will match packets, for which (if the set type is ipportmap) the source -address and destination port pair can be found in the specified set. If -the set type of the specified set is single dimension (for example ipmap), -then the command will match packets for which the source address can be -found in the specified set. -.PP -The option \fB\-\-match\-set\fR can be replaced by \fB\-\-set\fR if that does -not clash with an option of other extensions. -.PP -Use of -m set requires that ipset kernel support is provided. As standard -kernels do not ship this currently, the ipset or Xtables-addons package needs -to be installed. 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 + * Patrick Schaaf + * Martin Josefsson + * Copyright (C) 2003-2010 Jozsef Kadlecsik + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#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 */ + parse_target_v0(argv, invert, flags, + &myinfo->add_set, "add-set"); + break; + case '2': /* --del-set [:] */ + 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 */ + parse_target(argv, invert, flags, + &myinfo->add_set, "add-set"); + break; + case '2': /* --del-set [:] */ + 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/libxt_SET.man b/extensions/libxt_SET.man new file mode 100644 index 00000000..ea80c2a1 --- /dev/null +++ b/extensions/libxt_SET.man @@ -0,0 +1,18 @@ +This modules adds and/or deletes entries from IP sets which can be defined +by ipset(8). +.TP +\fB\-\-add\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...] +add the address(es)/port(s) of the packet to the sets +.TP +\fB\-\-del\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...] +delete the address(es)/port(s) of the packet from the sets +.IP +where flags are +.BR "src" +and/or +.BR "dst" +specifications and there can be no more than six of them. +.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 +to be installed. 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 + * Patrick Schaaf + * Martin Josefsson + * Copyright (C) 2003-2010 Jozsef Kadlecsik + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#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 [, */ + 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 [, */ + 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 +#include +#include +#include + +#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/libxt_set.man b/extensions/libxt_set.man new file mode 100644 index 00000000..aca1bfce --- /dev/null +++ b/extensions/libxt_set.man @@ -0,0 +1,23 @@ +This module matches IP sets which can be defined by ipset(8). +.TP +[\fB!\fP] \fB\-\-match\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP]... +where flags are the comma separated list of +.BR "src" +and/or +.BR "dst" +specifications and there can be no more than six of them. Hence the command +.IP + iptables \-A FORWARD \-m set \-\-match\-set test src,dst +.IP +will match packets, for which (if the set type is ipportmap) the source +address and destination port pair can be found in the specified set. If +the set type of the specified set is single dimension (for example ipmap), +then the command will match packets for which the source address can be +found in the specified set. +.PP +The option \fB\-\-match\-set\fR can be replaced by \fB\-\-set\fR if that does +not clash with an option of other extensions. +.PP +Use of -m set requires that ipset kernel support is provided. As standard +kernels do not ship this currently, the ipset or Xtables-addons package needs +to be installed. -- cgit v1.2.3 From dd2bbe0b614ad60fb2e267863471836aae424425 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 24 Jun 2010 21:13:47 +0200 Subject: libxt_hashlimit: always print burst value iptables -L lists the burst value, and so should iptables -S. I was certainly surprised to see it gone even when explicitly specifying --hashlimit-burst 5 on the command line. Signed-off-by: Jan Engelhardt --- extensions/libxt_hashlimit.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'extensions') 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)) { -- cgit v1.2.3 From 76f7a230e4182ab2b64a68c9d84437035d925f3b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 24 Jun 2010 21:23:44 +0200 Subject: libxt_conntrack: do print netmask References: http://bugzilla.netfilter.org/show_bug.cgi?id=659 Signed-off-by: Jan Engelhardt --- extensions/libxt_conntrack.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'extensions') 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)); } } -- cgit v1.2.3 From b1c768168ef1f79c4bdd02f6e681e6e1fbb8d533 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 2 Jul 2010 09:36:37 +0200 Subject: extensions: libxt_rateest: fix typo in the man page There were a few typos in some options in the rateest match section of the man page: --rateest1-bps should be --rateest-bps1 and so on. Signed-off-by: Luciano Coelho Signed-off-by: Patrick McHardy --- extensions/libxt_rateest.man | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'extensions') 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 -- cgit v1.2.3 From e4540fcb86c2d7f4cdf51c49872847a03a11b433 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 2 Jul 2010 09:57:09 +0200 Subject: extensions: libxt_quota.c: Support option negation The xt_quota_info flags should be set properly for the --quota option negation support. Signed-off-by: Samuel Ortiz Signed-off-by: Patrick McHardy --- extensions/libxt_quota.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'extensions') diff --git a/extensions/libxt_quota.c b/extensions/libxt_quota.c index 69d27460..bdfc92a8 100644 --- a/extensions/libxt_quota.c +++ b/extensions/libxt_quota.c @@ -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: -- cgit v1.2.3 From ce06c99ee107102a7168493b55970b53380ebbb6 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 2 Jul 2010 12:19:18 +0200 Subject: xt_quota: also document negation Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- extensions/libxt_quota.c | 2 +- extensions/libxt_quota.man | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'extensions') diff --git a/extensions/libxt_quota.c b/extensions/libxt_quota.c index bdfc92a8..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 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 -- cgit v1.2.3 From b4fa7222923bc10476b8753f358e871f461eb2db Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 15 Jul 2010 18:09:54 +0200 Subject: extensions: libxt_rateest: fix bps options for iptables-save The output generated by the libxt_rateest extension for bps matches was wrong and could not be restored properly. This patch fixes this problem by using the correct options in the right order when saving the table. Signed-off-by: Luciano Coelho Signed-off-by: Patrick McHardy --- extensions/libxt_rateest.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'extensions') 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 "); -- cgit v1.2.3