123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746 |
- /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
- * Patrick Schaaf <bof@bof.de>
- * Martin Josefsson <gandalf@wlug.westbo.se>
- * Copyright (C) 2003-2013 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.
- */
- /* Kernel module which implements the set match and SET target
- * for netfilter/iptables.
- */
- #include <linux/module.h>
- #include <linux/skbuff.h>
- #include <linux/netfilter/x_tables.h>
- #include <linux/netfilter/ipset/ip_set.h>
- #include <linux/netfilter/ipset/ip_set_timeout.h>
- #include <uapi/linux/netfilter/xt_set.h>
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
- MODULE_DESCRIPTION("Xtables: IP set match and target module");
- MODULE_ALIAS("xt_SET");
- MODULE_ALIAS("ipt_set");
- MODULE_ALIAS("ip6t_set");
- MODULE_ALIAS("ipt_SET");
- MODULE_ALIAS("ip6t_SET");
- static inline int
- match_set(ip_set_id_t index, const struct sk_buff *skb,
- const struct xt_action_param *par,
- struct ip_set_adt_opt *opt, int inv)
- {
- if (ip_set_test(index, skb, par, opt))
- inv = !inv;
- return inv;
- }
- #define ADT_OPT(n, f, d, fs, cfs, t) \
- struct ip_set_adt_opt n = { \
- .family = f, \
- .dim = d, \
- .flags = fs, \
- .cmdflags = cfs, \
- .ext.timeout = t, \
- }
- /* Revision 0 interface: backward compatible with netfilter/iptables */
- static bool
- set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
- {
- const struct xt_set_info_match_v0 *info = par->matchinfo;
- ADT_OPT(opt, par->family, info->match_set.u.compat.dim,
- info->match_set.u.compat.flags, 0, UINT_MAX);
- return match_set(info->match_set.index, skb, par, &opt,
- info->match_set.u.compat.flags & IPSET_INV_MATCH);
- }
- static void
- compat_flags(struct xt_set_info_v0 *info)
- {
- u_int8_t i;
- /* Fill out compatibility data according to enum ip_set_kopt */
- info->u.compat.dim = IPSET_DIM_ZERO;
- if (info->u.flags[0] & IPSET_MATCH_INV)
- info->u.compat.flags |= IPSET_INV_MATCH;
- for (i = 0; i < IPSET_DIM_MAX - 1 && info->u.flags[i]; i++) {
- info->u.compat.dim++;
- if (info->u.flags[i] & IPSET_SRC)
- info->u.compat.flags |= (1 << info->u.compat.dim);
- }
- }
- static int
- set_match_v0_checkentry(const struct xt_mtchk_param *par)
- {
- struct xt_set_info_match_v0 *info = par->matchinfo;
- ip_set_id_t index;
- index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
- if (index == IPSET_INVALID_ID) {
- pr_warn("Cannot find set identified by id %u to match\n",
- info->match_set.index);
- return -ENOENT;
- }
- if (info->match_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
- pr_warn("Protocol error: set match dimension is over the limit!\n");
- ip_set_nfnl_put(par->net, info->match_set.index);
- return -ERANGE;
- }
- /* Fill out compatibility data */
- compat_flags(&info->match_set);
- return 0;
- }
- static void
- set_match_v0_destroy(const struct xt_mtdtor_param *par)
- {
- struct xt_set_info_match_v0 *info = par->matchinfo;
- ip_set_nfnl_put(par->net, info->match_set.index);
- }
- /* Revision 1 match */
- static bool
- set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
- {
- const struct xt_set_info_match_v1 *info = par->matchinfo;
- ADT_OPT(opt, par->family, info->match_set.dim,
- info->match_set.flags, 0, UINT_MAX);
- if (opt.flags & IPSET_RETURN_NOMATCH)
- opt.cmdflags |= IPSET_FLAG_RETURN_NOMATCH;
- return match_set(info->match_set.index, skb, par, &opt,
- info->match_set.flags & IPSET_INV_MATCH);
- }
- static int
- set_match_v1_checkentry(const struct xt_mtchk_param *par)
- {
- struct xt_set_info_match_v1 *info = par->matchinfo;
- ip_set_id_t index;
- index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
- if (index == IPSET_INVALID_ID) {
- pr_warn("Cannot find set identified by id %u to match\n",
- info->match_set.index);
- return -ENOENT;
- }
- if (info->match_set.dim > IPSET_DIM_MAX) {
- pr_warn("Protocol error: set match dimension is over the limit!\n");
- ip_set_nfnl_put(par->net, info->match_set.index);
- return -ERANGE;
- }
- return 0;
- }
- static void
- set_match_v1_destroy(const struct xt_mtdtor_param *par)
- {
- struct xt_set_info_match_v1 *info = par->matchinfo;
- ip_set_nfnl_put(par->net, info->match_set.index);
- }
- /* Revision 3 match */
- static bool
- match_counter0(u64 counter, const struct ip_set_counter_match0 *info)
- {
- switch (info->op) {
- case IPSET_COUNTER_NONE:
- return true;
- case IPSET_COUNTER_EQ:
- return counter == info->value;
- case IPSET_COUNTER_NE:
- return counter != info->value;
- case IPSET_COUNTER_LT:
- return counter < info->value;
- case IPSET_COUNTER_GT:
- return counter > info->value;
- }
- return false;
- }
- static bool
- set_match_v3(const struct sk_buff *skb, struct xt_action_param *par)
- {
- const struct xt_set_info_match_v3 *info = par->matchinfo;
- int ret;
- ADT_OPT(opt, par->family, info->match_set.dim,
- info->match_set.flags, info->flags, UINT_MAX);
- if (info->packets.op != IPSET_COUNTER_NONE ||
- info->bytes.op != IPSET_COUNTER_NONE)
- opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
- ret = match_set(info->match_set.index, skb, par, &opt,
- info->match_set.flags & IPSET_INV_MATCH);
- if (!(ret && opt.cmdflags & IPSET_FLAG_MATCH_COUNTERS))
- return ret;
- if (!match_counter0(opt.ext.packets, &info->packets))
- return false;
- return match_counter0(opt.ext.bytes, &info->bytes);
- }
- #define set_match_v3_checkentry set_match_v1_checkentry
- #define set_match_v3_destroy set_match_v1_destroy
- /* Revision 4 match */
- static bool
- match_counter(u64 counter, const struct ip_set_counter_match *info)
- {
- switch (info->op) {
- case IPSET_COUNTER_NONE:
- return true;
- case IPSET_COUNTER_EQ:
- return counter == info->value;
- case IPSET_COUNTER_NE:
- return counter != info->value;
- case IPSET_COUNTER_LT:
- return counter < info->value;
- case IPSET_COUNTER_GT:
- return counter > info->value;
- }
- return false;
- }
- static bool
- set_match_v4(const struct sk_buff *skb, struct xt_action_param *par)
- {
- const struct xt_set_info_match_v4 *info = par->matchinfo;
- int ret;
- ADT_OPT(opt, par->family, info->match_set.dim,
- info->match_set.flags, info->flags, UINT_MAX);
- if (info->packets.op != IPSET_COUNTER_NONE ||
- info->bytes.op != IPSET_COUNTER_NONE)
- opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
- ret = match_set(info->match_set.index, skb, par, &opt,
- info->match_set.flags & IPSET_INV_MATCH);
- if (!(ret && opt.cmdflags & IPSET_FLAG_MATCH_COUNTERS))
- return ret;
- if (!match_counter(opt.ext.packets, &info->packets))
- return false;
- return match_counter(opt.ext.bytes, &info->bytes);
- }
- #define set_match_v4_checkentry set_match_v1_checkentry
- #define set_match_v4_destroy set_match_v1_destroy
- /* Revision 0 interface: backward compatible with netfilter/iptables */
- static unsigned int
- set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
- {
- const struct xt_set_info_target_v0 *info = par->targinfo;
- ADT_OPT(add_opt, par->family, info->add_set.u.compat.dim,
- info->add_set.u.compat.flags, 0, UINT_MAX);
- ADT_OPT(del_opt, par->family, info->del_set.u.compat.dim,
- info->del_set.u.compat.flags, 0, UINT_MAX);
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_add(info->add_set.index, skb, par, &add_opt);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_del(info->del_set.index, skb, par, &del_opt);
- return XT_CONTINUE;
- }
- static int
- set_target_v0_checkentry(const struct xt_tgchk_param *par)
- {
- struct xt_set_info_target_v0 *info = par->targinfo;
- ip_set_id_t index;
- if (info->add_set.index != IPSET_INVALID_ID) {
- index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
- if (index == IPSET_INVALID_ID) {
- pr_warn("Cannot find add_set index %u as target\n",
- info->add_set.index);
- return -ENOENT;
- }
- }
- if (info->del_set.index != IPSET_INVALID_ID) {
- index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
- if (index == IPSET_INVALID_ID) {
- pr_warn("Cannot find del_set index %u as target\n",
- info->del_set.index);
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->add_set.index);
- return -ENOENT;
- }
- }
- if (info->add_set.u.flags[IPSET_DIM_MAX - 1] != 0 ||
- info->del_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
- pr_warn("Protocol error: SET target dimension is over the limit!\n");
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->add_set.index);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->del_set.index);
- return -ERANGE;
- }
- /* Fill out compatibility data */
- compat_flags(&info->add_set);
- compat_flags(&info->del_set);
- return 0;
- }
- static void
- set_target_v0_destroy(const struct xt_tgdtor_param *par)
- {
- const struct xt_set_info_target_v0 *info = par->targinfo;
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->add_set.index);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->del_set.index);
- }
- /* Revision 1 target */
- static unsigned int
- set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
- {
- const struct xt_set_info_target_v1 *info = par->targinfo;
- ADT_OPT(add_opt, par->family, info->add_set.dim,
- info->add_set.flags, 0, UINT_MAX);
- ADT_OPT(del_opt, par->family, info->del_set.dim,
- info->del_set.flags, 0, UINT_MAX);
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_add(info->add_set.index, skb, par, &add_opt);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_del(info->del_set.index, skb, par, &del_opt);
- return XT_CONTINUE;
- }
- static int
- set_target_v1_checkentry(const struct xt_tgchk_param *par)
- {
- const struct xt_set_info_target_v1 *info = par->targinfo;
- ip_set_id_t index;
- if (info->add_set.index != IPSET_INVALID_ID) {
- index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
- if (index == IPSET_INVALID_ID) {
- pr_warn("Cannot find add_set index %u as target\n",
- info->add_set.index);
- return -ENOENT;
- }
- }
- if (info->del_set.index != IPSET_INVALID_ID) {
- index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
- if (index == IPSET_INVALID_ID) {
- pr_warn("Cannot find del_set index %u as target\n",
- info->del_set.index);
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->add_set.index);
- return -ENOENT;
- }
- }
- if (info->add_set.dim > IPSET_DIM_MAX ||
- info->del_set.dim > IPSET_DIM_MAX) {
- pr_warn("Protocol error: SET target dimension is over the limit!\n");
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->add_set.index);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->del_set.index);
- return -ERANGE;
- }
- return 0;
- }
- static void
- set_target_v1_destroy(const struct xt_tgdtor_param *par)
- {
- const struct xt_set_info_target_v1 *info = par->targinfo;
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->add_set.index);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->del_set.index);
- }
- /* Revision 2 target */
- static unsigned int
- set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
- {
- const struct xt_set_info_target_v2 *info = par->targinfo;
- ADT_OPT(add_opt, par->family, info->add_set.dim,
- info->add_set.flags, info->flags, info->timeout);
- ADT_OPT(del_opt, par->family, info->del_set.dim,
- info->del_set.flags, 0, UINT_MAX);
- /* Normalize to fit into jiffies */
- if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
- add_opt.ext.timeout > UINT_MAX / MSEC_PER_SEC)
- add_opt.ext.timeout = UINT_MAX / MSEC_PER_SEC;
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_add(info->add_set.index, skb, par, &add_opt);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_del(info->del_set.index, skb, par, &del_opt);
- return XT_CONTINUE;
- }
- #define set_target_v2_checkentry set_target_v1_checkentry
- #define set_target_v2_destroy set_target_v1_destroy
- /* Revision 3 target */
- static unsigned int
- set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
- {
- const struct xt_set_info_target_v3 *info = par->targinfo;
- int ret;
- ADT_OPT(add_opt, par->family, info->add_set.dim,
- info->add_set.flags, info->flags, info->timeout);
- ADT_OPT(del_opt, par->family, info->del_set.dim,
- info->del_set.flags, 0, UINT_MAX);
- ADT_OPT(map_opt, par->family, info->map_set.dim,
- info->map_set.flags, 0, UINT_MAX);
- /* Normalize to fit into jiffies */
- if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
- add_opt.ext.timeout > UINT_MAX / MSEC_PER_SEC)
- add_opt.ext.timeout = UINT_MAX / MSEC_PER_SEC;
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_add(info->add_set.index, skb, par, &add_opt);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_del(info->del_set.index, skb, par, &del_opt);
- if (info->map_set.index != IPSET_INVALID_ID) {
- map_opt.cmdflags |= info->flags & (IPSET_FLAG_MAP_SKBMARK |
- IPSET_FLAG_MAP_SKBPRIO |
- IPSET_FLAG_MAP_SKBQUEUE);
- ret = match_set(info->map_set.index, skb, par, &map_opt,
- info->map_set.flags & IPSET_INV_MATCH);
- if (!ret)
- return XT_CONTINUE;
- if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
- skb->mark = (skb->mark & ~(map_opt.ext.skbmarkmask))
- ^ (map_opt.ext.skbmark);
- if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO)
- skb->priority = map_opt.ext.skbprio;
- if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) &&
- skb->dev &&
- skb->dev->real_num_tx_queues > map_opt.ext.skbqueue)
- skb_set_queue_mapping(skb, map_opt.ext.skbqueue);
- }
- return XT_CONTINUE;
- }
- static int
- set_target_v3_checkentry(const struct xt_tgchk_param *par)
- {
- const struct xt_set_info_target_v3 *info = par->targinfo;
- ip_set_id_t index;
- if (info->add_set.index != IPSET_INVALID_ID) {
- index = ip_set_nfnl_get_byindex(par->net,
- info->add_set.index);
- if (index == IPSET_INVALID_ID) {
- pr_warn("Cannot find add_set index %u as target\n",
- info->add_set.index);
- return -ENOENT;
- }
- }
- if (info->del_set.index != IPSET_INVALID_ID) {
- index = ip_set_nfnl_get_byindex(par->net,
- info->del_set.index);
- if (index == IPSET_INVALID_ID) {
- pr_warn("Cannot find del_set index %u as target\n",
- info->del_set.index);
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net,
- info->add_set.index);
- return -ENOENT;
- }
- }
- if (info->map_set.index != IPSET_INVALID_ID) {
- if (strncmp(par->table, "mangle", 7)) {
- pr_warn("--map-set only usable from mangle table\n");
- return -EINVAL;
- }
- if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
- (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) &&
- !(par->hook_mask & (1 << NF_INET_FORWARD |
- 1 << NF_INET_LOCAL_OUT |
- 1 << NF_INET_POST_ROUTING))) {
- pr_warn("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");
- return -EINVAL;
- }
- index = ip_set_nfnl_get_byindex(par->net,
- info->map_set.index);
- if (index == IPSET_INVALID_ID) {
- pr_warn("Cannot find map_set index %u as target\n",
- info->map_set.index);
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net,
- info->add_set.index);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net,
- info->del_set.index);
- return -ENOENT;
- }
- }
- if (info->add_set.dim > IPSET_DIM_MAX ||
- info->del_set.dim > IPSET_DIM_MAX ||
- info->map_set.dim > IPSET_DIM_MAX) {
- pr_warn("Protocol error: SET target dimension is over the limit!\n");
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->add_set.index);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->del_set.index);
- if (info->map_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->map_set.index);
- return -ERANGE;
- }
- return 0;
- }
- static void
- set_target_v3_destroy(const struct xt_tgdtor_param *par)
- {
- const struct xt_set_info_target_v3 *info = par->targinfo;
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->add_set.index);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->del_set.index);
- if (info->map_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(par->net, info->map_set.index);
- }
- static struct xt_match set_matches[] __read_mostly = {
- {
- .name = "set",
- .family = NFPROTO_IPV4,
- .revision = 0,
- .match = set_match_v0,
- .matchsize = sizeof(struct xt_set_info_match_v0),
- .checkentry = set_match_v0_checkentry,
- .destroy = set_match_v0_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "set",
- .family = NFPROTO_IPV4,
- .revision = 1,
- .match = set_match_v1,
- .matchsize = sizeof(struct xt_set_info_match_v1),
- .checkentry = set_match_v1_checkentry,
- .destroy = set_match_v1_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "set",
- .family = NFPROTO_IPV6,
- .revision = 1,
- .match = set_match_v1,
- .matchsize = sizeof(struct xt_set_info_match_v1),
- .checkentry = set_match_v1_checkentry,
- .destroy = set_match_v1_destroy,
- .me = THIS_MODULE
- },
- /* --return-nomatch flag support */
- {
- .name = "set",
- .family = NFPROTO_IPV4,
- .revision = 2,
- .match = set_match_v1,
- .matchsize = sizeof(struct xt_set_info_match_v1),
- .checkentry = set_match_v1_checkentry,
- .destroy = set_match_v1_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "set",
- .family = NFPROTO_IPV6,
- .revision = 2,
- .match = set_match_v1,
- .matchsize = sizeof(struct xt_set_info_match_v1),
- .checkentry = set_match_v1_checkentry,
- .destroy = set_match_v1_destroy,
- .me = THIS_MODULE
- },
- /* counters support: update, match */
- {
- .name = "set",
- .family = NFPROTO_IPV4,
- .revision = 3,
- .match = set_match_v3,
- .matchsize = sizeof(struct xt_set_info_match_v3),
- .checkentry = set_match_v3_checkentry,
- .destroy = set_match_v3_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "set",
- .family = NFPROTO_IPV6,
- .revision = 3,
- .match = set_match_v3,
- .matchsize = sizeof(struct xt_set_info_match_v3),
- .checkentry = set_match_v3_checkentry,
- .destroy = set_match_v3_destroy,
- .me = THIS_MODULE
- },
- /* new revision for counters support: update, match */
- {
- .name = "set",
- .family = NFPROTO_IPV4,
- .revision = 4,
- .match = set_match_v4,
- .matchsize = sizeof(struct xt_set_info_match_v4),
- .checkentry = set_match_v4_checkentry,
- .destroy = set_match_v4_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "set",
- .family = NFPROTO_IPV6,
- .revision = 4,
- .match = set_match_v4,
- .matchsize = sizeof(struct xt_set_info_match_v4),
- .checkentry = set_match_v4_checkentry,
- .destroy = set_match_v4_destroy,
- .me = THIS_MODULE
- },
- };
- static struct xt_target set_targets[] __read_mostly = {
- {
- .name = "SET",
- .revision = 0,
- .family = NFPROTO_IPV4,
- .target = set_target_v0,
- .targetsize = sizeof(struct xt_set_info_target_v0),
- .checkentry = set_target_v0_checkentry,
- .destroy = set_target_v0_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "SET",
- .revision = 1,
- .family = NFPROTO_IPV4,
- .target = set_target_v1,
- .targetsize = sizeof(struct xt_set_info_target_v1),
- .checkentry = set_target_v1_checkentry,
- .destroy = set_target_v1_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "SET",
- .revision = 1,
- .family = NFPROTO_IPV6,
- .target = set_target_v1,
- .targetsize = sizeof(struct xt_set_info_target_v1),
- .checkentry = set_target_v1_checkentry,
- .destroy = set_target_v1_destroy,
- .me = THIS_MODULE
- },
- /* --timeout and --exist flags support */
- {
- .name = "SET",
- .revision = 2,
- .family = NFPROTO_IPV4,
- .target = set_target_v2,
- .targetsize = sizeof(struct xt_set_info_target_v2),
- .checkentry = set_target_v2_checkentry,
- .destroy = set_target_v2_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "SET",
- .revision = 2,
- .family = NFPROTO_IPV6,
- .target = set_target_v2,
- .targetsize = sizeof(struct xt_set_info_target_v2),
- .checkentry = set_target_v2_checkentry,
- .destroy = set_target_v2_destroy,
- .me = THIS_MODULE
- },
- /* --map-set support */
- {
- .name = "SET",
- .revision = 3,
- .family = NFPROTO_IPV4,
- .target = set_target_v3,
- .targetsize = sizeof(struct xt_set_info_target_v3),
- .checkentry = set_target_v3_checkentry,
- .destroy = set_target_v3_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "SET",
- .revision = 3,
- .family = NFPROTO_IPV6,
- .target = set_target_v3,
- .targetsize = sizeof(struct xt_set_info_target_v3),
- .checkentry = set_target_v3_checkentry,
- .destroy = set_target_v3_destroy,
- .me = THIS_MODULE
- },
- };
- static int __init xt_set_init(void)
- {
- int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches));
- if (!ret) {
- ret = xt_register_targets(set_targets,
- ARRAY_SIZE(set_targets));
- if (ret)
- xt_unregister_matches(set_matches,
- ARRAY_SIZE(set_matches));
- }
- return ret;
- }
- static void __exit xt_set_fini(void)
- {
- xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches));
- xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets));
- }
- module_init(xt_set_init);
- module_exit(xt_set_fini);
|