1d956798dSJozsef Kadlecsik /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> 2d956798dSJozsef Kadlecsik * Patrick Schaaf <bof@bof.de> 3d956798dSJozsef Kadlecsik * Martin Josefsson <gandalf@wlug.westbo.se> 4d956798dSJozsef Kadlecsik * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 5d956798dSJozsef Kadlecsik * 6d956798dSJozsef Kadlecsik * This program is free software; you can redistribute it and/or modify 7d956798dSJozsef Kadlecsik * it under the terms of the GNU General Public License version 2 as 8d956798dSJozsef Kadlecsik * published by the Free Software Foundation. 9d956798dSJozsef Kadlecsik */ 10d956798dSJozsef Kadlecsik 11d956798dSJozsef Kadlecsik /* Kernel module which implements the set match and SET target 12d956798dSJozsef Kadlecsik * for netfilter/iptables. */ 13d956798dSJozsef Kadlecsik 14d956798dSJozsef Kadlecsik #include <linux/module.h> 15d956798dSJozsef Kadlecsik #include <linux/skbuff.h> 16d956798dSJozsef Kadlecsik 17d956798dSJozsef Kadlecsik #include <linux/netfilter/x_tables.h> 18d956798dSJozsef Kadlecsik #include <linux/netfilter/xt_set.h> 19a73f89a6SJozsef Kadlecsik #include <linux/netfilter/ipset/ip_set_timeout.h> 20d956798dSJozsef Kadlecsik 21d956798dSJozsef Kadlecsik MODULE_LICENSE("GPL"); 22d956798dSJozsef Kadlecsik MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 23d956798dSJozsef Kadlecsik MODULE_DESCRIPTION("Xtables: IP set match and target module"); 24d956798dSJozsef Kadlecsik MODULE_ALIAS("xt_SET"); 25d956798dSJozsef Kadlecsik MODULE_ALIAS("ipt_set"); 26d956798dSJozsef Kadlecsik MODULE_ALIAS("ip6t_set"); 27d956798dSJozsef Kadlecsik MODULE_ALIAS("ipt_SET"); 28d956798dSJozsef Kadlecsik MODULE_ALIAS("ip6t_SET"); 29d956798dSJozsef Kadlecsik 30d956798dSJozsef Kadlecsik static inline int 31d956798dSJozsef Kadlecsik match_set(ip_set_id_t index, const struct sk_buff *skb, 32b66554cfSJozsef Kadlecsik const struct xt_action_param *par, 33ac8cc925SJozsef Kadlecsik const struct ip_set_adt_opt *opt, int inv) 34d956798dSJozsef Kadlecsik { 35b66554cfSJozsef Kadlecsik if (ip_set_test(index, skb, par, opt)) 36d956798dSJozsef Kadlecsik inv = !inv; 37d956798dSJozsef Kadlecsik return inv; 38d956798dSJozsef Kadlecsik } 39d956798dSJozsef Kadlecsik 40ac8cc925SJozsef Kadlecsik #define ADT_OPT(n, f, d, fs, cfs, t) \ 41ac8cc925SJozsef Kadlecsik const struct ip_set_adt_opt n = { \ 42ac8cc925SJozsef Kadlecsik .family = f, \ 43ac8cc925SJozsef Kadlecsik .dim = d, \ 44ac8cc925SJozsef Kadlecsik .flags = fs, \ 45ac8cc925SJozsef Kadlecsik .cmdflags = cfs, \ 46ac8cc925SJozsef Kadlecsik .timeout = t, \ 47ac8cc925SJozsef Kadlecsik } 48127f5591SJozsef Kadlecsik #define ADT_MOPT(n, f, d, fs, cfs, t) \ 49127f5591SJozsef Kadlecsik struct ip_set_adt_opt n = { \ 50127f5591SJozsef Kadlecsik .family = f, \ 51127f5591SJozsef Kadlecsik .dim = d, \ 52127f5591SJozsef Kadlecsik .flags = fs, \ 53127f5591SJozsef Kadlecsik .cmdflags = cfs, \ 54127f5591SJozsef Kadlecsik .timeout = t, \ 55127f5591SJozsef Kadlecsik } 56ac8cc925SJozsef Kadlecsik 57d956798dSJozsef Kadlecsik /* Revision 0 interface: backward compatible with netfilter/iptables */ 58d956798dSJozsef Kadlecsik 59d956798dSJozsef Kadlecsik static bool 60d956798dSJozsef Kadlecsik set_match_v0(const struct sk_buff *skb, struct xt_action_param *par) 61d956798dSJozsef Kadlecsik { 62d956798dSJozsef Kadlecsik const struct xt_set_info_match_v0 *info = par->matchinfo; 63ac8cc925SJozsef Kadlecsik ADT_OPT(opt, par->family, info->match_set.u.compat.dim, 64ac8cc925SJozsef Kadlecsik info->match_set.u.compat.flags, 0, UINT_MAX); 65d956798dSJozsef Kadlecsik 66b66554cfSJozsef Kadlecsik return match_set(info->match_set.index, skb, par, &opt, 67d956798dSJozsef Kadlecsik info->match_set.u.compat.flags & IPSET_INV_MATCH); 68d956798dSJozsef Kadlecsik } 69d956798dSJozsef Kadlecsik 70d956798dSJozsef Kadlecsik static void 71d956798dSJozsef Kadlecsik compat_flags(struct xt_set_info_v0 *info) 72d956798dSJozsef Kadlecsik { 73d956798dSJozsef Kadlecsik u_int8_t i; 74d956798dSJozsef Kadlecsik 75d956798dSJozsef Kadlecsik /* Fill out compatibility data according to enum ip_set_kopt */ 76d956798dSJozsef Kadlecsik info->u.compat.dim = IPSET_DIM_ZERO; 77d956798dSJozsef Kadlecsik if (info->u.flags[0] & IPSET_MATCH_INV) 78d956798dSJozsef Kadlecsik info->u.compat.flags |= IPSET_INV_MATCH; 79d956798dSJozsef Kadlecsik for (i = 0; i < IPSET_DIM_MAX-1 && info->u.flags[i]; i++) { 80d956798dSJozsef Kadlecsik info->u.compat.dim++; 81d956798dSJozsef Kadlecsik if (info->u.flags[i] & IPSET_SRC) 82d956798dSJozsef Kadlecsik info->u.compat.flags |= (1<<info->u.compat.dim); 83d956798dSJozsef Kadlecsik } 84d956798dSJozsef Kadlecsik } 85d956798dSJozsef Kadlecsik 86d956798dSJozsef Kadlecsik static int 87d956798dSJozsef Kadlecsik set_match_v0_checkentry(const struct xt_mtchk_param *par) 88d956798dSJozsef Kadlecsik { 89d956798dSJozsef Kadlecsik struct xt_set_info_match_v0 *info = par->matchinfo; 90d956798dSJozsef Kadlecsik ip_set_id_t index; 91d956798dSJozsef Kadlecsik 92d956798dSJozsef Kadlecsik index = ip_set_nfnl_get_byindex(info->match_set.index); 93d956798dSJozsef Kadlecsik 94d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) { 95d956798dSJozsef Kadlecsik pr_warning("Cannot find set indentified by id %u to match\n", 96d956798dSJozsef Kadlecsik info->match_set.index); 97d956798dSJozsef Kadlecsik return -ENOENT; 98d956798dSJozsef Kadlecsik } 99d956798dSJozsef Kadlecsik if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { 100d956798dSJozsef Kadlecsik pr_warning("Protocol error: set match dimension " 101d956798dSJozsef Kadlecsik "is over the limit!\n"); 102eafbd3fdSJozsef Kadlecsik ip_set_nfnl_put(info->match_set.index); 103d956798dSJozsef Kadlecsik return -ERANGE; 104d956798dSJozsef Kadlecsik } 105d956798dSJozsef Kadlecsik 106d956798dSJozsef Kadlecsik /* Fill out compatibility data */ 107d956798dSJozsef Kadlecsik compat_flags(&info->match_set); 108d956798dSJozsef Kadlecsik 109d956798dSJozsef Kadlecsik return 0; 110d956798dSJozsef Kadlecsik } 111d956798dSJozsef Kadlecsik 112d956798dSJozsef Kadlecsik static void 113d956798dSJozsef Kadlecsik set_match_v0_destroy(const struct xt_mtdtor_param *par) 114d956798dSJozsef Kadlecsik { 115d956798dSJozsef Kadlecsik struct xt_set_info_match_v0 *info = par->matchinfo; 116d956798dSJozsef Kadlecsik 117d956798dSJozsef Kadlecsik ip_set_nfnl_put(info->match_set.index); 118d956798dSJozsef Kadlecsik } 119d956798dSJozsef Kadlecsik 120d956798dSJozsef Kadlecsik static unsigned int 121d956798dSJozsef Kadlecsik set_target_v0(struct sk_buff *skb, const struct xt_action_param *par) 122d956798dSJozsef Kadlecsik { 123d956798dSJozsef Kadlecsik const struct xt_set_info_target_v0 *info = par->targinfo; 124ac8cc925SJozsef Kadlecsik ADT_OPT(add_opt, par->family, info->add_set.u.compat.dim, 125ac8cc925SJozsef Kadlecsik info->add_set.u.compat.flags, 0, UINT_MAX); 126ac8cc925SJozsef Kadlecsik ADT_OPT(del_opt, par->family, info->del_set.u.compat.dim, 127ac8cc925SJozsef Kadlecsik info->del_set.u.compat.flags, 0, UINT_MAX); 128d956798dSJozsef Kadlecsik 129d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) 130b66554cfSJozsef Kadlecsik ip_set_add(info->add_set.index, skb, par, &add_opt); 131d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) 132b66554cfSJozsef Kadlecsik ip_set_del(info->del_set.index, skb, par, &del_opt); 133d956798dSJozsef Kadlecsik 134d956798dSJozsef Kadlecsik return XT_CONTINUE; 135d956798dSJozsef Kadlecsik } 136d956798dSJozsef Kadlecsik 137d956798dSJozsef Kadlecsik static int 138d956798dSJozsef Kadlecsik set_target_v0_checkentry(const struct xt_tgchk_param *par) 139d956798dSJozsef Kadlecsik { 140d956798dSJozsef Kadlecsik struct xt_set_info_target_v0 *info = par->targinfo; 141d956798dSJozsef Kadlecsik ip_set_id_t index; 142d956798dSJozsef Kadlecsik 143d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) { 144d956798dSJozsef Kadlecsik index = ip_set_nfnl_get_byindex(info->add_set.index); 145d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) { 146d956798dSJozsef Kadlecsik pr_warning("Cannot find add_set index %u as target\n", 147d956798dSJozsef Kadlecsik info->add_set.index); 148d956798dSJozsef Kadlecsik return -ENOENT; 149d956798dSJozsef Kadlecsik } 150d956798dSJozsef Kadlecsik } 151d956798dSJozsef Kadlecsik 152d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) { 153d956798dSJozsef Kadlecsik index = ip_set_nfnl_get_byindex(info->del_set.index); 154d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) { 155d956798dSJozsef Kadlecsik pr_warning("Cannot find del_set index %u as target\n", 156d956798dSJozsef Kadlecsik info->del_set.index); 157eafbd3fdSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) 158eafbd3fdSJozsef Kadlecsik ip_set_nfnl_put(info->add_set.index); 159d956798dSJozsef Kadlecsik return -ENOENT; 160d956798dSJozsef Kadlecsik } 161d956798dSJozsef Kadlecsik } 162d956798dSJozsef Kadlecsik if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 || 163d956798dSJozsef Kadlecsik info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) { 164d956798dSJozsef Kadlecsik pr_warning("Protocol error: SET target dimension " 165d956798dSJozsef Kadlecsik "is over the limit!\n"); 166eafbd3fdSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) 167eafbd3fdSJozsef Kadlecsik ip_set_nfnl_put(info->add_set.index); 168eafbd3fdSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) 169eafbd3fdSJozsef Kadlecsik ip_set_nfnl_put(info->del_set.index); 170d956798dSJozsef Kadlecsik return -ERANGE; 171d956798dSJozsef Kadlecsik } 172d956798dSJozsef Kadlecsik 173d956798dSJozsef Kadlecsik /* Fill out compatibility data */ 174d956798dSJozsef Kadlecsik compat_flags(&info->add_set); 175d956798dSJozsef Kadlecsik compat_flags(&info->del_set); 176d956798dSJozsef Kadlecsik 177d956798dSJozsef Kadlecsik return 0; 178d956798dSJozsef Kadlecsik } 179d956798dSJozsef Kadlecsik 180d956798dSJozsef Kadlecsik static void 181d956798dSJozsef Kadlecsik set_target_v0_destroy(const struct xt_tgdtor_param *par) 182d956798dSJozsef Kadlecsik { 183d956798dSJozsef Kadlecsik const struct xt_set_info_target_v0 *info = par->targinfo; 184d956798dSJozsef Kadlecsik 185d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) 186d956798dSJozsef Kadlecsik ip_set_nfnl_put(info->add_set.index); 187d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) 188d956798dSJozsef Kadlecsik ip_set_nfnl_put(info->del_set.index); 189d956798dSJozsef Kadlecsik } 190d956798dSJozsef Kadlecsik 191ac8cc925SJozsef Kadlecsik /* Revision 1 match and target */ 192d956798dSJozsef Kadlecsik 193d956798dSJozsef Kadlecsik static bool 194ac8cc925SJozsef Kadlecsik set_match_v1(const struct sk_buff *skb, struct xt_action_param *par) 195d956798dSJozsef Kadlecsik { 196ac8cc925SJozsef Kadlecsik const struct xt_set_info_match_v1 *info = par->matchinfo; 197ac8cc925SJozsef Kadlecsik ADT_OPT(opt, par->family, info->match_set.dim, 198ac8cc925SJozsef Kadlecsik info->match_set.flags, 0, UINT_MAX); 199d956798dSJozsef Kadlecsik 200b66554cfSJozsef Kadlecsik return match_set(info->match_set.index, skb, par, &opt, 201d956798dSJozsef Kadlecsik info->match_set.flags & IPSET_INV_MATCH); 202d956798dSJozsef Kadlecsik } 203d956798dSJozsef Kadlecsik 204d956798dSJozsef Kadlecsik static int 205ac8cc925SJozsef Kadlecsik set_match_v1_checkentry(const struct xt_mtchk_param *par) 206d956798dSJozsef Kadlecsik { 207ac8cc925SJozsef Kadlecsik struct xt_set_info_match_v1 *info = par->matchinfo; 208d956798dSJozsef Kadlecsik ip_set_id_t index; 209d956798dSJozsef Kadlecsik 210d956798dSJozsef Kadlecsik index = ip_set_nfnl_get_byindex(info->match_set.index); 211d956798dSJozsef Kadlecsik 212d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) { 213d956798dSJozsef Kadlecsik pr_warning("Cannot find set indentified by id %u to match\n", 214d956798dSJozsef Kadlecsik info->match_set.index); 215d956798dSJozsef Kadlecsik return -ENOENT; 216d956798dSJozsef Kadlecsik } 217d956798dSJozsef Kadlecsik if (info->match_set.dim > IPSET_DIM_MAX) { 218d956798dSJozsef Kadlecsik pr_warning("Protocol error: set match dimension " 219d956798dSJozsef Kadlecsik "is over the limit!\n"); 220eafbd3fdSJozsef Kadlecsik ip_set_nfnl_put(info->match_set.index); 221d956798dSJozsef Kadlecsik return -ERANGE; 222d956798dSJozsef Kadlecsik } 223d956798dSJozsef Kadlecsik 224d956798dSJozsef Kadlecsik return 0; 225d956798dSJozsef Kadlecsik } 226d956798dSJozsef Kadlecsik 227d956798dSJozsef Kadlecsik static void 228ac8cc925SJozsef Kadlecsik set_match_v1_destroy(const struct xt_mtdtor_param *par) 229d956798dSJozsef Kadlecsik { 230ac8cc925SJozsef Kadlecsik struct xt_set_info_match_v1 *info = par->matchinfo; 231d956798dSJozsef Kadlecsik 232d956798dSJozsef Kadlecsik ip_set_nfnl_put(info->match_set.index); 233d956798dSJozsef Kadlecsik } 234d956798dSJozsef Kadlecsik 235d956798dSJozsef Kadlecsik static unsigned int 236ac8cc925SJozsef Kadlecsik set_target_v1(struct sk_buff *skb, const struct xt_action_param *par) 237d956798dSJozsef Kadlecsik { 238ac8cc925SJozsef Kadlecsik const struct xt_set_info_target_v1 *info = par->targinfo; 239ac8cc925SJozsef Kadlecsik ADT_OPT(add_opt, par->family, info->add_set.dim, 240ac8cc925SJozsef Kadlecsik info->add_set.flags, 0, UINT_MAX); 241ac8cc925SJozsef Kadlecsik ADT_OPT(del_opt, par->family, info->del_set.dim, 242ac8cc925SJozsef Kadlecsik info->del_set.flags, 0, UINT_MAX); 243d956798dSJozsef Kadlecsik 244d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) 245b66554cfSJozsef Kadlecsik ip_set_add(info->add_set.index, skb, par, &add_opt); 246d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) 247b66554cfSJozsef Kadlecsik ip_set_del(info->del_set.index, skb, par, &del_opt); 248d956798dSJozsef Kadlecsik 249d956798dSJozsef Kadlecsik return XT_CONTINUE; 250d956798dSJozsef Kadlecsik } 251d956798dSJozsef Kadlecsik 252d956798dSJozsef Kadlecsik static int 253ac8cc925SJozsef Kadlecsik set_target_v1_checkentry(const struct xt_tgchk_param *par) 254d956798dSJozsef Kadlecsik { 255ac8cc925SJozsef Kadlecsik const struct xt_set_info_target_v1 *info = par->targinfo; 256d956798dSJozsef Kadlecsik ip_set_id_t index; 257d956798dSJozsef Kadlecsik 258d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) { 259d956798dSJozsef Kadlecsik index = ip_set_nfnl_get_byindex(info->add_set.index); 260d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) { 261d956798dSJozsef Kadlecsik pr_warning("Cannot find add_set index %u as target\n", 262d956798dSJozsef Kadlecsik info->add_set.index); 263d956798dSJozsef Kadlecsik return -ENOENT; 264d956798dSJozsef Kadlecsik } 265d956798dSJozsef Kadlecsik } 266d956798dSJozsef Kadlecsik 267d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) { 268d956798dSJozsef Kadlecsik index = ip_set_nfnl_get_byindex(info->del_set.index); 269d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) { 270d956798dSJozsef Kadlecsik pr_warning("Cannot find del_set index %u as target\n", 271d956798dSJozsef Kadlecsik info->del_set.index); 272eafbd3fdSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) 273eafbd3fdSJozsef Kadlecsik ip_set_nfnl_put(info->add_set.index); 274d956798dSJozsef Kadlecsik return -ENOENT; 275d956798dSJozsef Kadlecsik } 276d956798dSJozsef Kadlecsik } 277d956798dSJozsef Kadlecsik if (info->add_set.dim > IPSET_DIM_MAX || 278eafbd3fdSJozsef Kadlecsik info->del_set.dim > IPSET_DIM_MAX) { 279d956798dSJozsef Kadlecsik pr_warning("Protocol error: SET target dimension " 280d956798dSJozsef Kadlecsik "is over the limit!\n"); 281eafbd3fdSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) 282eafbd3fdSJozsef Kadlecsik ip_set_nfnl_put(info->add_set.index); 283eafbd3fdSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) 284eafbd3fdSJozsef Kadlecsik ip_set_nfnl_put(info->del_set.index); 285d956798dSJozsef Kadlecsik return -ERANGE; 286d956798dSJozsef Kadlecsik } 287d956798dSJozsef Kadlecsik 288d956798dSJozsef Kadlecsik return 0; 289d956798dSJozsef Kadlecsik } 290d956798dSJozsef Kadlecsik 291d956798dSJozsef Kadlecsik static void 292ac8cc925SJozsef Kadlecsik set_target_v1_destroy(const struct xt_tgdtor_param *par) 293d956798dSJozsef Kadlecsik { 294ac8cc925SJozsef Kadlecsik const struct xt_set_info_target_v1 *info = par->targinfo; 295d956798dSJozsef Kadlecsik 296d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) 297d956798dSJozsef Kadlecsik ip_set_nfnl_put(info->add_set.index); 298d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) 299d956798dSJozsef Kadlecsik ip_set_nfnl_put(info->del_set.index); 300d956798dSJozsef Kadlecsik } 301d956798dSJozsef Kadlecsik 302ac8cc925SJozsef Kadlecsik /* Revision 2 target */ 303ac8cc925SJozsef Kadlecsik 304ac8cc925SJozsef Kadlecsik static unsigned int 305ac8cc925SJozsef Kadlecsik set_target_v2(struct sk_buff *skb, const struct xt_action_param *par) 306ac8cc925SJozsef Kadlecsik { 307ac8cc925SJozsef Kadlecsik const struct xt_set_info_target_v2 *info = par->targinfo; 308127f5591SJozsef Kadlecsik ADT_MOPT(add_opt, par->family, info->add_set.dim, 309ac8cc925SJozsef Kadlecsik info->add_set.flags, info->flags, info->timeout); 310ac8cc925SJozsef Kadlecsik ADT_OPT(del_opt, par->family, info->del_set.dim, 311ac8cc925SJozsef Kadlecsik info->del_set.flags, 0, UINT_MAX); 312ac8cc925SJozsef Kadlecsik 313127f5591SJozsef Kadlecsik /* Normalize to fit into jiffies */ 314a73f89a6SJozsef Kadlecsik if (add_opt.timeout != IPSET_NO_TIMEOUT && 315a73f89a6SJozsef Kadlecsik add_opt.timeout > UINT_MAX/MSEC_PER_SEC) 316127f5591SJozsef Kadlecsik add_opt.timeout = UINT_MAX/MSEC_PER_SEC; 317ac8cc925SJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) 318b66554cfSJozsef Kadlecsik ip_set_add(info->add_set.index, skb, par, &add_opt); 319ac8cc925SJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) 320b66554cfSJozsef Kadlecsik ip_set_del(info->del_set.index, skb, par, &del_opt); 321ac8cc925SJozsef Kadlecsik 322ac8cc925SJozsef Kadlecsik return XT_CONTINUE; 323ac8cc925SJozsef Kadlecsik } 324ac8cc925SJozsef Kadlecsik 325ac8cc925SJozsef Kadlecsik #define set_target_v2_checkentry set_target_v1_checkentry 326ac8cc925SJozsef Kadlecsik #define set_target_v2_destroy set_target_v1_destroy 327ac8cc925SJozsef Kadlecsik 328d956798dSJozsef Kadlecsik static struct xt_match set_matches[] __read_mostly = { 329d956798dSJozsef Kadlecsik { 330d956798dSJozsef Kadlecsik .name = "set", 331d956798dSJozsef Kadlecsik .family = NFPROTO_IPV4, 332d956798dSJozsef Kadlecsik .revision = 0, 333d956798dSJozsef Kadlecsik .match = set_match_v0, 334d956798dSJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v0), 335d956798dSJozsef Kadlecsik .checkentry = set_match_v0_checkentry, 336d956798dSJozsef Kadlecsik .destroy = set_match_v0_destroy, 337d956798dSJozsef Kadlecsik .me = THIS_MODULE 338d956798dSJozsef Kadlecsik }, 339d956798dSJozsef Kadlecsik { 340d956798dSJozsef Kadlecsik .name = "set", 341d956798dSJozsef Kadlecsik .family = NFPROTO_IPV4, 342d956798dSJozsef Kadlecsik .revision = 1, 343ac8cc925SJozsef Kadlecsik .match = set_match_v1, 344ac8cc925SJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v1), 345ac8cc925SJozsef Kadlecsik .checkentry = set_match_v1_checkentry, 346ac8cc925SJozsef Kadlecsik .destroy = set_match_v1_destroy, 347d956798dSJozsef Kadlecsik .me = THIS_MODULE 348d956798dSJozsef Kadlecsik }, 349d956798dSJozsef Kadlecsik { 350d956798dSJozsef Kadlecsik .name = "set", 351d956798dSJozsef Kadlecsik .family = NFPROTO_IPV6, 352d956798dSJozsef Kadlecsik .revision = 1, 353ac8cc925SJozsef Kadlecsik .match = set_match_v1, 354ac8cc925SJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v1), 355ac8cc925SJozsef Kadlecsik .checkentry = set_match_v1_checkentry, 356ac8cc925SJozsef Kadlecsik .destroy = set_match_v1_destroy, 357d956798dSJozsef Kadlecsik .me = THIS_MODULE 358d956798dSJozsef Kadlecsik }, 359d956798dSJozsef Kadlecsik }; 360d956798dSJozsef Kadlecsik 361d956798dSJozsef Kadlecsik static struct xt_target set_targets[] __read_mostly = { 362d956798dSJozsef Kadlecsik { 363d956798dSJozsef Kadlecsik .name = "SET", 364d956798dSJozsef Kadlecsik .revision = 0, 365d956798dSJozsef Kadlecsik .family = NFPROTO_IPV4, 366d956798dSJozsef Kadlecsik .target = set_target_v0, 367d956798dSJozsef Kadlecsik .targetsize = sizeof(struct xt_set_info_target_v0), 368d956798dSJozsef Kadlecsik .checkentry = set_target_v0_checkentry, 369d956798dSJozsef Kadlecsik .destroy = set_target_v0_destroy, 370d956798dSJozsef Kadlecsik .me = THIS_MODULE 371d956798dSJozsef Kadlecsik }, 372d956798dSJozsef Kadlecsik { 373d956798dSJozsef Kadlecsik .name = "SET", 374d956798dSJozsef Kadlecsik .revision = 1, 375d956798dSJozsef Kadlecsik .family = NFPROTO_IPV4, 376ac8cc925SJozsef Kadlecsik .target = set_target_v1, 377ac8cc925SJozsef Kadlecsik .targetsize = sizeof(struct xt_set_info_target_v1), 378ac8cc925SJozsef Kadlecsik .checkentry = set_target_v1_checkentry, 379ac8cc925SJozsef Kadlecsik .destroy = set_target_v1_destroy, 380d956798dSJozsef Kadlecsik .me = THIS_MODULE 381d956798dSJozsef Kadlecsik }, 382d956798dSJozsef Kadlecsik { 383d956798dSJozsef Kadlecsik .name = "SET", 384d956798dSJozsef Kadlecsik .revision = 1, 385d956798dSJozsef Kadlecsik .family = NFPROTO_IPV6, 386ac8cc925SJozsef Kadlecsik .target = set_target_v1, 387ac8cc925SJozsef Kadlecsik .targetsize = sizeof(struct xt_set_info_target_v1), 388ac8cc925SJozsef Kadlecsik .checkentry = set_target_v1_checkentry, 389ac8cc925SJozsef Kadlecsik .destroy = set_target_v1_destroy, 390ac8cc925SJozsef Kadlecsik .me = THIS_MODULE 391ac8cc925SJozsef Kadlecsik }, 392ac8cc925SJozsef Kadlecsik { 393ac8cc925SJozsef Kadlecsik .name = "SET", 394ac8cc925SJozsef Kadlecsik .revision = 2, 395ac8cc925SJozsef Kadlecsik .family = NFPROTO_IPV4, 396ac8cc925SJozsef Kadlecsik .target = set_target_v2, 397ac8cc925SJozsef Kadlecsik .targetsize = sizeof(struct xt_set_info_target_v2), 398ac8cc925SJozsef Kadlecsik .checkentry = set_target_v2_checkentry, 399ac8cc925SJozsef Kadlecsik .destroy = set_target_v2_destroy, 400ac8cc925SJozsef Kadlecsik .me = THIS_MODULE 401ac8cc925SJozsef Kadlecsik }, 402ac8cc925SJozsef Kadlecsik { 403ac8cc925SJozsef Kadlecsik .name = "SET", 404ac8cc925SJozsef Kadlecsik .revision = 2, 405ac8cc925SJozsef Kadlecsik .family = NFPROTO_IPV6, 406ac8cc925SJozsef Kadlecsik .target = set_target_v2, 407ac8cc925SJozsef Kadlecsik .targetsize = sizeof(struct xt_set_info_target_v2), 408ac8cc925SJozsef Kadlecsik .checkentry = set_target_v2_checkentry, 409ac8cc925SJozsef Kadlecsik .destroy = set_target_v2_destroy, 410d956798dSJozsef Kadlecsik .me = THIS_MODULE 411d956798dSJozsef Kadlecsik }, 412d956798dSJozsef Kadlecsik }; 413d956798dSJozsef Kadlecsik 414d956798dSJozsef Kadlecsik static int __init xt_set_init(void) 415d956798dSJozsef Kadlecsik { 416d956798dSJozsef Kadlecsik int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches)); 417d956798dSJozsef Kadlecsik 418d956798dSJozsef Kadlecsik if (!ret) { 419d956798dSJozsef Kadlecsik ret = xt_register_targets(set_targets, 420d956798dSJozsef Kadlecsik ARRAY_SIZE(set_targets)); 421d956798dSJozsef Kadlecsik if (ret) 422d956798dSJozsef Kadlecsik xt_unregister_matches(set_matches, 423d956798dSJozsef Kadlecsik ARRAY_SIZE(set_matches)); 424d956798dSJozsef Kadlecsik } 425d956798dSJozsef Kadlecsik return ret; 426d956798dSJozsef Kadlecsik } 427d956798dSJozsef Kadlecsik 428d956798dSJozsef Kadlecsik static void __exit xt_set_fini(void) 429d956798dSJozsef Kadlecsik { 430d956798dSJozsef Kadlecsik xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches)); 431d956798dSJozsef Kadlecsik xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets)); 432d956798dSJozsef Kadlecsik } 433d956798dSJozsef Kadlecsik 434d956798dSJozsef Kadlecsik module_init(xt_set_init); 435d956798dSJozsef Kadlecsik module_exit(xt_set_fini); 436