summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorAnton Danilov <littlesmilingcloud@gmail.com>2014-09-02 14:15:53 +0400
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2014-09-14 20:17:32 +0200
commit6d9ae2952a440b4ff28e86df6d18b53caa7ecd94 (patch)
treed250695fb21b2d77883a6b69d2fc295656b81f43 /extensions
parent1cc84d47766ad74be8609477d3496544848b75b1 (diff)
xtables: SET target: Add mapping of meta informations (skbinfo ipset extension)
This feature add support of mapping metainformation to packets like nftables maps or ipfw tables. Currently we can map firewall mark, tc priority and hardware NIC queue. Usage of this functionality allowed only from mangle table. We can map tc priority only in OUTPUT/FORWARD/POSTROUTING chains because it rewrite by route decision. If entry doesn't exist in the set nothing of fields changed. Example of classify by destination address: iptables -t mangle -A POSTROUTING -o eth0 -j SET --map-set DST2CLASS dst --map-prio Signed-off-by: Anton Danilov <littlesmilingcloud@gmail.com> Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libxt_SET.c193
-rw-r--r--extensions/libxt_SET.man21
2 files changed, 209 insertions, 5 deletions
diff --git a/extensions/libxt_SET.c b/extensions/libxt_SET.c
index a11db395..2a7640a0 100644
--- a/extensions/libxt_SET.c
+++ b/extensions/libxt_SET.c
@@ -5,7 +5,7 @@
*
* 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.
+ * published by the Free Software Foundation.
*/
/* Shared library add-on to iptables to add IP set mangling target. */
@@ -80,7 +80,7 @@ parse_target_v0(char **argv, int invert, unsigned int *flags,
get_set_byname(optarg, (struct xt_set_info *)info);
parse_dirs_v0(argv[optind], info);
optind++;
-
+
*flags = 1;
}
@@ -116,7 +116,7 @@ print_target_v0(const char *prefix, const struct xt_set_info_v0 *info)
printf(" %s %s", prefix, setname);
for (i = 0; i < IPSET_DIM_MAX; i++) {
if (!info->u.flags[i])
- break;
+ break;
printf("%s%s",
i == 0 ? " " : ",",
info->u.flags[i] & IPSET_SRC ? "src" : "dst");
@@ -125,7 +125,7 @@ print_target_v0(const char *prefix, const struct xt_set_info_v0 *info)
static void
set_target_print_v0(const void *ip, const struct xt_entry_target *target,
- int numeric)
+ int numeric)
{
const struct xt_set_info_target_v0 *info = (const void *)target->data;
@@ -158,6 +158,10 @@ set_target_init_v1(struct xt_entry_target *target)
#define SET_TARGET_DEL 0x2
#define SET_TARGET_EXIST 0x4
#define SET_TARGET_TIMEOUT 0x8
+#define SET_TARGET_MAP 0x10
+#define SET_TARGET_MAP_MARK 0x20
+#define SET_TARGET_MAP_PRIO 0x40
+#define SET_TARGET_MAP_QUEUE 0x80
static void
parse_target(char **argv, int invert, struct xt_set_info *info,
@@ -314,7 +318,7 @@ set_target_parse_v2(int c, char **argv, int invert, unsigned int *flags,
"or out of range 0-%u", UINT32_MAX - 1);
myinfo->timeout = timeout;
*flags |= SET_TARGET_TIMEOUT;
- break;
+ break;
}
return 1;
}
@@ -346,6 +350,170 @@ set_target_save_v2(const void *ip, const struct xt_entry_target *target)
print_target("--del-set", &info->del_set);
}
+
+/* Revision 3 */
+
+static void
+set_target_help_v3(void)
+{
+ printf("SET target options:\n"
+ " --add-set name flags [--exist] [--timeout n]\n"
+ " --del-set name flags\n"
+ " --map-set name flags"
+ " [--map-mark] [--map-prio] [--map-queue]\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_v3[] = {
+ {.name = "add-set", .has_arg = true, .val = '1'},
+ {.name = "del-set", .has_arg = true, .val = '2'},
+ {.name = "exist", .has_arg = false, .val = '3'},
+ {.name = "timeout", .has_arg = true, .val = '4'},
+ {.name = "map-set", .has_arg = true, .val = '5'},
+ {.name = "map-mark", .has_arg = false, .val = '6'},
+ {.name = "map-prio", .has_arg = false, .val = '7'},
+ {.name = "map-queue", .has_arg = false, .val = '8'},
+ XT_GETOPT_TABLEEND,
+};
+
+static void
+set_target_check_v3(unsigned int flags)
+{
+ if (!(flags & (SET_TARGET_ADD|SET_TARGET_DEL|SET_TARGET_MAP)))
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify either `--add-set' or "
+ "`--del-set' or `--map-set'");
+ if (!(flags & SET_TARGET_ADD)) {
+ if (flags & SET_TARGET_EXIST)
+ xtables_error(PARAMETER_PROBLEM,
+ "Flag `--exist' can be used with `--add-set' only");
+ if (flags & SET_TARGET_TIMEOUT)
+ xtables_error(PARAMETER_PROBLEM,
+ "Option `--timeout' can be used with `--add-set' only");
+ }
+ if (!(flags & SET_TARGET_MAP)) {
+ if (flags & SET_TARGET_MAP_MARK)
+ xtables_error(PARAMETER_PROBLEM,
+ "Flag `--map-mark' can be used with `--map-set' only");
+ if (flags & SET_TARGET_MAP_PRIO)
+ xtables_error(PARAMETER_PROBLEM,
+ "Flag `--map-prio' can be used with `--map-set' only");
+ if (flags & SET_TARGET_MAP_QUEUE)
+ xtables_error(PARAMETER_PROBLEM,
+ "Flag `--map-queue' can be used with `--map-set' only");
+ }
+ if ((flags & SET_TARGET_MAP) && !(flags & (SET_TARGET_MAP_MARK |
+ SET_TARGET_MAP_PRIO |
+ SET_TARGET_MAP_QUEUE)))
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify flags `--map-mark' or "
+ "'--map-prio` or `--map-queue'");
+}
+
+static void
+set_target_init_v3(struct xt_entry_target *target)
+{
+ struct xt_set_info_target_v3 *info =
+ (struct xt_set_info_target_v3 *) target->data;
+
+ info->add_set.index =
+ info->del_set.index =
+ info->map_set.index = IPSET_INVALID_ID;
+ info->timeout = UINT32_MAX;
+}
+
+static int
+set_target_parse_v3(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_set_info_target_v3 *myinfo =
+ (struct xt_set_info_target_v3 *) (*target)->data;
+ unsigned int timeout;
+
+ switch (c) {
+ case '1': /* --add-set <set> <flags> */
+ parse_target(argv, invert, &myinfo->add_set, "add-set");
+ *flags |= SET_TARGET_ADD;
+ break;
+ case '2': /* --del-set <set>[:<flags>] <flags> */
+ parse_target(argv, invert, &myinfo->del_set, "del-set");
+ *flags |= SET_TARGET_DEL;
+ break;
+ case '3':
+ myinfo->flags |= IPSET_FLAG_EXIST;
+ *flags |= SET_TARGET_EXIST;
+ break;
+ case '4':
+ if (!xtables_strtoui(optarg, NULL, &timeout, 0, UINT32_MAX - 1))
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid value for option --timeout "
+ "or out of range 0-%u", UINT32_MAX - 1);
+ myinfo->timeout = timeout;
+ *flags |= SET_TARGET_TIMEOUT;
+ break;
+ case '5': /* --map-set <set> <flags> */
+ parse_target(argv, invert, &myinfo->map_set, "map-set");
+ *flags |= SET_TARGET_MAP;
+ break;
+ case '6':
+ myinfo->flags |= IPSET_FLAG_MAP_SKBMARK;
+ *flags |= SET_TARGET_MAP_MARK;
+ break;
+ case '7':
+ myinfo->flags |= IPSET_FLAG_MAP_SKBPRIO;
+ *flags |= SET_TARGET_MAP_PRIO;
+ break;
+ case '8':
+ myinfo->flags |= IPSET_FLAG_MAP_SKBQUEUE;
+ *flags |= SET_TARGET_MAP_QUEUE;
+ break;
+ }
+ return 1;
+}
+
+static void
+set_target_print_v3(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_set_info_target_v3 *info = (const void *)target->data;
+
+ print_target("add-set", &info->add_set);
+ if (info->flags & IPSET_FLAG_EXIST)
+ printf(" exist");
+ if (info->timeout != UINT32_MAX)
+ printf(" timeout %u", info->timeout);
+ print_target("del-set", &info->del_set);
+ print_target("map-set", &info->map_set);
+ if (info->flags & IPSET_FLAG_MAP_SKBMARK)
+ printf(" map-mark");
+ if (info->flags & IPSET_FLAG_MAP_SKBPRIO)
+ printf(" map-prio");
+ if (info->flags & IPSET_FLAG_MAP_SKBQUEUE)
+ printf(" map-queue");
+}
+
+static void
+set_target_save_v3(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_set_info_target_v3 *info = (const void *)target->data;
+
+ print_target("--add-set", &info->add_set);
+ if (info->flags & IPSET_FLAG_EXIST)
+ printf(" --exist");
+ if (info->timeout != UINT32_MAX)
+ printf(" --timeout %u", info->timeout);
+ print_target("--del-set", &info->del_set);
+ print_target("--map-set", &info->map_set);
+ if (info->flags & IPSET_FLAG_MAP_SKBMARK)
+ printf(" --map-mark");
+ if (info->flags & IPSET_FLAG_MAP_SKBPRIO)
+ printf(" --map-prio");
+ if (info->flags & IPSET_FLAG_MAP_SKBQUEUE)
+ printf(" --map-queue");
+}
+
static struct xtables_target set_tg_reg[] = {
{
.name = "SET",
@@ -392,6 +560,21 @@ static struct xtables_target set_tg_reg[] = {
.save = set_target_save_v2,
.extra_opts = set_target_opts_v2,
},
+ {
+ .name = "SET",
+ .revision = 3,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_set_info_target_v3)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v3)),
+ .help = set_target_help_v3,
+ .init = set_target_init_v3,
+ .parse = set_target_parse_v3,
+ .final_check = set_target_check_v3,
+ .print = set_target_print_v3,
+ .save = set_target_save_v3,
+ .extra_opts = set_target_opts_v3,
+ },
};
void _init(void)
diff --git a/extensions/libxt_SET.man b/extensions/libxt_SET.man
index c35ba93d..78a9ae0f 100644
--- a/extensions/libxt_SET.man
+++ b/extensions/libxt_SET.man
@@ -6,6 +6,10 @@ add the address(es)/port(s) of the packet to the set
.TP
\fB\-\-del\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...]
delete the address(es)/port(s) of the packet from the set
+.TP
+\fB\-\-map\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...]
+[\-\-map\-mark] [\-\-map\-prio] [\-\-map\-queue]
+map packet properties (firewall mark, tc priority, hardware queue)
.IP
where \fIflag\fP(s) are
.BR "src"
@@ -20,6 +24,23 @@ one from the set definition
\fB\-\-exist\fP
when adding an entry if it already exists, reset the timeout value
to the specified one or to the default from the set definition
+.TP
+\fB\-\-map\-set\fP \fIset\-name\fP
+the set-name should be created with --skbinfo option
+\fB\-\-map\-mark\fP
+map firewall mark to packet by lookup of value in the set
+\fB\-\-map\-prio\fP
+map traffic control priority to packet by lookup of value in the set
+\fB\-\-map\-queue\fP
+map hardware NIC queue to packet by lookup of value in the set
+.IP
+The
+\fB\-\-map\-set\fP
+option can be used from the mangle table only. The
+\fB\-\-map\-prio\fP
+and
+\fB\-\-map\-queue\fP
+flags can be used in the OUTPUT, FORWARD and POSTROUTING chains.
.PP
Use of -j SET requires that ipset kernel support is provided, which, for
standard kernels, is the case since Linux 2.6.39.