0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/module.h>
0013 #include <linux/skbuff.h>
0014
0015 #include <linux/netfilter/x_tables.h>
0016 #include <linux/netfilter/ipset/ip_set.h>
0017 #include <uapi/linux/netfilter/xt_set.h>
0018
0019 MODULE_LICENSE("GPL");
0020 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
0021 MODULE_DESCRIPTION("Xtables: IP set match and target module");
0022 MODULE_ALIAS("xt_SET");
0023 MODULE_ALIAS("ipt_set");
0024 MODULE_ALIAS("ip6t_set");
0025 MODULE_ALIAS("ipt_SET");
0026 MODULE_ALIAS("ip6t_SET");
0027
0028 static inline int
0029 match_set(ip_set_id_t index, const struct sk_buff *skb,
0030 const struct xt_action_param *par,
0031 struct ip_set_adt_opt *opt, int inv)
0032 {
0033 if (ip_set_test(index, skb, par, opt))
0034 inv = !inv;
0035 return inv;
0036 }
0037
0038 #define ADT_OPT(n, f, d, fs, cfs, t, p, b, po, bo) \
0039 struct ip_set_adt_opt n = { \
0040 .family = f, \
0041 .dim = d, \
0042 .flags = fs, \
0043 .cmdflags = cfs, \
0044 .ext.timeout = t, \
0045 .ext.packets = p, \
0046 .ext.bytes = b, \
0047 .ext.packets_op = po, \
0048 .ext.bytes_op = bo, \
0049 }
0050
0051
0052
0053 static bool
0054 set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
0055 {
0056 const struct xt_set_info_match_v0 *info = par->matchinfo;
0057
0058 ADT_OPT(opt, xt_family(par), info->match_set.u.compat.dim,
0059 info->match_set.u.compat.flags, 0, UINT_MAX,
0060 0, 0, 0, 0);
0061
0062 return match_set(info->match_set.index, skb, par, &opt,
0063 info->match_set.u.compat.flags & IPSET_INV_MATCH);
0064 }
0065
0066 static void
0067 compat_flags(struct xt_set_info_v0 *info)
0068 {
0069 u_int8_t i;
0070
0071
0072 info->u.compat.dim = IPSET_DIM_ZERO;
0073 if (info->u.flags[0] & IPSET_MATCH_INV)
0074 info->u.compat.flags |= IPSET_INV_MATCH;
0075 for (i = 0; i < IPSET_DIM_MAX - 1 && info->u.flags[i]; i++) {
0076 info->u.compat.dim++;
0077 if (info->u.flags[i] & IPSET_SRC)
0078 info->u.compat.flags |= (1 << info->u.compat.dim);
0079 }
0080 }
0081
0082 static int
0083 set_match_v0_checkentry(const struct xt_mtchk_param *par)
0084 {
0085 struct xt_set_info_match_v0 *info = par->matchinfo;
0086 ip_set_id_t index;
0087
0088 index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
0089
0090 if (index == IPSET_INVALID_ID) {
0091 pr_info_ratelimited("Cannot find set identified by id %u to match\n",
0092 info->match_set.index);
0093 return -ENOENT;
0094 }
0095 if (info->match_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
0096 pr_info_ratelimited("set match dimension is over the limit!\n");
0097 ip_set_nfnl_put(par->net, info->match_set.index);
0098 return -ERANGE;
0099 }
0100
0101
0102 compat_flags(&info->match_set);
0103
0104 return 0;
0105 }
0106
0107 static void
0108 set_match_v0_destroy(const struct xt_mtdtor_param *par)
0109 {
0110 struct xt_set_info_match_v0 *info = par->matchinfo;
0111
0112 ip_set_nfnl_put(par->net, info->match_set.index);
0113 }
0114
0115
0116
0117 static bool
0118 set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
0119 {
0120 const struct xt_set_info_match_v1 *info = par->matchinfo;
0121
0122 ADT_OPT(opt, xt_family(par), info->match_set.dim,
0123 info->match_set.flags, 0, UINT_MAX,
0124 0, 0, 0, 0);
0125
0126 if (opt.flags & IPSET_RETURN_NOMATCH)
0127 opt.cmdflags |= IPSET_FLAG_RETURN_NOMATCH;
0128
0129 return match_set(info->match_set.index, skb, par, &opt,
0130 info->match_set.flags & IPSET_INV_MATCH);
0131 }
0132
0133 static int
0134 set_match_v1_checkentry(const struct xt_mtchk_param *par)
0135 {
0136 struct xt_set_info_match_v1 *info = par->matchinfo;
0137 ip_set_id_t index;
0138
0139 index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
0140
0141 if (index == IPSET_INVALID_ID) {
0142 pr_info_ratelimited("Cannot find set identified by id %u to match\n",
0143 info->match_set.index);
0144 return -ENOENT;
0145 }
0146 if (info->match_set.dim > IPSET_DIM_MAX) {
0147 pr_info_ratelimited("set match dimension is over the limit!\n");
0148 ip_set_nfnl_put(par->net, info->match_set.index);
0149 return -ERANGE;
0150 }
0151
0152 return 0;
0153 }
0154
0155 static void
0156 set_match_v1_destroy(const struct xt_mtdtor_param *par)
0157 {
0158 struct xt_set_info_match_v1 *info = par->matchinfo;
0159
0160 ip_set_nfnl_put(par->net, info->match_set.index);
0161 }
0162
0163
0164
0165 static bool
0166 set_match_v3(const struct sk_buff *skb, struct xt_action_param *par)
0167 {
0168 const struct xt_set_info_match_v3 *info = par->matchinfo;
0169
0170 ADT_OPT(opt, xt_family(par), info->match_set.dim,
0171 info->match_set.flags, info->flags, UINT_MAX,
0172 info->packets.value, info->bytes.value,
0173 info->packets.op, info->bytes.op);
0174
0175 if (info->packets.op != IPSET_COUNTER_NONE ||
0176 info->bytes.op != IPSET_COUNTER_NONE)
0177 opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
0178
0179 return match_set(info->match_set.index, skb, par, &opt,
0180 info->match_set.flags & IPSET_INV_MATCH);
0181 }
0182
0183 #define set_match_v3_checkentry set_match_v1_checkentry
0184 #define set_match_v3_destroy set_match_v1_destroy
0185
0186
0187
0188 static bool
0189 set_match_v4(const struct sk_buff *skb, struct xt_action_param *par)
0190 {
0191 const struct xt_set_info_match_v4 *info = par->matchinfo;
0192
0193 ADT_OPT(opt, xt_family(par), info->match_set.dim,
0194 info->match_set.flags, info->flags, UINT_MAX,
0195 info->packets.value, info->bytes.value,
0196 info->packets.op, info->bytes.op);
0197
0198 if (info->packets.op != IPSET_COUNTER_NONE ||
0199 info->bytes.op != IPSET_COUNTER_NONE)
0200 opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
0201
0202 return match_set(info->match_set.index, skb, par, &opt,
0203 info->match_set.flags & IPSET_INV_MATCH);
0204 }
0205
0206 #define set_match_v4_checkentry set_match_v1_checkentry
0207 #define set_match_v4_destroy set_match_v1_destroy
0208
0209
0210
0211 static unsigned int
0212 set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
0213 {
0214 const struct xt_set_info_target_v0 *info = par->targinfo;
0215
0216 ADT_OPT(add_opt, xt_family(par), info->add_set.u.compat.dim,
0217 info->add_set.u.compat.flags, 0, UINT_MAX,
0218 0, 0, 0, 0);
0219 ADT_OPT(del_opt, xt_family(par), info->del_set.u.compat.dim,
0220 info->del_set.u.compat.flags, 0, UINT_MAX,
0221 0, 0, 0, 0);
0222
0223 if (info->add_set.index != IPSET_INVALID_ID)
0224 ip_set_add(info->add_set.index, skb, par, &add_opt);
0225 if (info->del_set.index != IPSET_INVALID_ID)
0226 ip_set_del(info->del_set.index, skb, par, &del_opt);
0227
0228 return XT_CONTINUE;
0229 }
0230
0231 static int
0232 set_target_v0_checkentry(const struct xt_tgchk_param *par)
0233 {
0234 struct xt_set_info_target_v0 *info = par->targinfo;
0235 ip_set_id_t index;
0236
0237 if (info->add_set.index != IPSET_INVALID_ID) {
0238 index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
0239 if (index == IPSET_INVALID_ID) {
0240 pr_info_ratelimited("Cannot find add_set index %u as target\n",
0241 info->add_set.index);
0242 return -ENOENT;
0243 }
0244 }
0245
0246 if (info->del_set.index != IPSET_INVALID_ID) {
0247 index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
0248 if (index == IPSET_INVALID_ID) {
0249 pr_info_ratelimited("Cannot find del_set index %u as target\n",
0250 info->del_set.index);
0251 if (info->add_set.index != IPSET_INVALID_ID)
0252 ip_set_nfnl_put(par->net, info->add_set.index);
0253 return -ENOENT;
0254 }
0255 }
0256 if (info->add_set.u.flags[IPSET_DIM_MAX - 1] != 0 ||
0257 info->del_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
0258 pr_info_ratelimited("SET target dimension over the limit!\n");
0259 if (info->add_set.index != IPSET_INVALID_ID)
0260 ip_set_nfnl_put(par->net, info->add_set.index);
0261 if (info->del_set.index != IPSET_INVALID_ID)
0262 ip_set_nfnl_put(par->net, info->del_set.index);
0263 return -ERANGE;
0264 }
0265
0266
0267 compat_flags(&info->add_set);
0268 compat_flags(&info->del_set);
0269
0270 return 0;
0271 }
0272
0273 static void
0274 set_target_v0_destroy(const struct xt_tgdtor_param *par)
0275 {
0276 const struct xt_set_info_target_v0 *info = par->targinfo;
0277
0278 if (info->add_set.index != IPSET_INVALID_ID)
0279 ip_set_nfnl_put(par->net, info->add_set.index);
0280 if (info->del_set.index != IPSET_INVALID_ID)
0281 ip_set_nfnl_put(par->net, info->del_set.index);
0282 }
0283
0284
0285
0286 static unsigned int
0287 set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
0288 {
0289 const struct xt_set_info_target_v1 *info = par->targinfo;
0290
0291 ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
0292 info->add_set.flags, 0, UINT_MAX,
0293 0, 0, 0, 0);
0294 ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
0295 info->del_set.flags, 0, UINT_MAX,
0296 0, 0, 0, 0);
0297
0298 if (info->add_set.index != IPSET_INVALID_ID)
0299 ip_set_add(info->add_set.index, skb, par, &add_opt);
0300 if (info->del_set.index != IPSET_INVALID_ID)
0301 ip_set_del(info->del_set.index, skb, par, &del_opt);
0302
0303 return XT_CONTINUE;
0304 }
0305
0306 static int
0307 set_target_v1_checkentry(const struct xt_tgchk_param *par)
0308 {
0309 const struct xt_set_info_target_v1 *info = par->targinfo;
0310 ip_set_id_t index;
0311
0312 if (info->add_set.index != IPSET_INVALID_ID) {
0313 index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
0314 if (index == IPSET_INVALID_ID) {
0315 pr_info_ratelimited("Cannot find add_set index %u as target\n",
0316 info->add_set.index);
0317 return -ENOENT;
0318 }
0319 }
0320
0321 if (info->del_set.index != IPSET_INVALID_ID) {
0322 index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
0323 if (index == IPSET_INVALID_ID) {
0324 pr_info_ratelimited("Cannot find del_set index %u as target\n",
0325 info->del_set.index);
0326 if (info->add_set.index != IPSET_INVALID_ID)
0327 ip_set_nfnl_put(par->net, info->add_set.index);
0328 return -ENOENT;
0329 }
0330 }
0331 if (info->add_set.dim > IPSET_DIM_MAX ||
0332 info->del_set.dim > IPSET_DIM_MAX) {
0333 pr_info_ratelimited("SET target dimension over the limit!\n");
0334 if (info->add_set.index != IPSET_INVALID_ID)
0335 ip_set_nfnl_put(par->net, info->add_set.index);
0336 if (info->del_set.index != IPSET_INVALID_ID)
0337 ip_set_nfnl_put(par->net, info->del_set.index);
0338 return -ERANGE;
0339 }
0340
0341 return 0;
0342 }
0343
0344 static void
0345 set_target_v1_destroy(const struct xt_tgdtor_param *par)
0346 {
0347 const struct xt_set_info_target_v1 *info = par->targinfo;
0348
0349 if (info->add_set.index != IPSET_INVALID_ID)
0350 ip_set_nfnl_put(par->net, info->add_set.index);
0351 if (info->del_set.index != IPSET_INVALID_ID)
0352 ip_set_nfnl_put(par->net, info->del_set.index);
0353 }
0354
0355
0356
0357 static unsigned int
0358 set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
0359 {
0360 const struct xt_set_info_target_v2 *info = par->targinfo;
0361
0362 ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
0363 info->add_set.flags, info->flags, info->timeout,
0364 0, 0, 0, 0);
0365 ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
0366 info->del_set.flags, 0, UINT_MAX,
0367 0, 0, 0, 0);
0368
0369
0370 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
0371 add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
0372 add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
0373 if (info->add_set.index != IPSET_INVALID_ID)
0374 ip_set_add(info->add_set.index, skb, par, &add_opt);
0375 if (info->del_set.index != IPSET_INVALID_ID)
0376 ip_set_del(info->del_set.index, skb, par, &del_opt);
0377
0378 return XT_CONTINUE;
0379 }
0380
0381 #define set_target_v2_checkentry set_target_v1_checkentry
0382 #define set_target_v2_destroy set_target_v1_destroy
0383
0384
0385
0386 #define MOPT(opt, member) ((opt).ext.skbinfo.member)
0387
0388 static unsigned int
0389 set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
0390 {
0391 const struct xt_set_info_target_v3 *info = par->targinfo;
0392 int ret;
0393
0394 ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
0395 info->add_set.flags, info->flags, info->timeout,
0396 0, 0, 0, 0);
0397 ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
0398 info->del_set.flags, 0, UINT_MAX,
0399 0, 0, 0, 0);
0400 ADT_OPT(map_opt, xt_family(par), info->map_set.dim,
0401 info->map_set.flags, 0, UINT_MAX,
0402 0, 0, 0, 0);
0403
0404
0405 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
0406 add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
0407 add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
0408 if (info->add_set.index != IPSET_INVALID_ID)
0409 ip_set_add(info->add_set.index, skb, par, &add_opt);
0410 if (info->del_set.index != IPSET_INVALID_ID)
0411 ip_set_del(info->del_set.index, skb, par, &del_opt);
0412 if (info->map_set.index != IPSET_INVALID_ID) {
0413 map_opt.cmdflags |= info->flags & (IPSET_FLAG_MAP_SKBMARK |
0414 IPSET_FLAG_MAP_SKBPRIO |
0415 IPSET_FLAG_MAP_SKBQUEUE);
0416 ret = match_set(info->map_set.index, skb, par, &map_opt,
0417 info->map_set.flags & IPSET_INV_MATCH);
0418 if (!ret)
0419 return XT_CONTINUE;
0420 if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
0421 skb->mark = (skb->mark & ~MOPT(map_opt,skbmarkmask))
0422 ^ MOPT(map_opt, skbmark);
0423 if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO)
0424 skb->priority = MOPT(map_opt, skbprio);
0425 if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) &&
0426 skb->dev &&
0427 skb->dev->real_num_tx_queues > MOPT(map_opt, skbqueue))
0428 skb_set_queue_mapping(skb, MOPT(map_opt, skbqueue));
0429 }
0430 return XT_CONTINUE;
0431 }
0432
0433 static int
0434 set_target_v3_checkentry(const struct xt_tgchk_param *par)
0435 {
0436 const struct xt_set_info_target_v3 *info = par->targinfo;
0437 ip_set_id_t index;
0438 int ret = 0;
0439
0440 if (info->add_set.index != IPSET_INVALID_ID) {
0441 index = ip_set_nfnl_get_byindex(par->net,
0442 info->add_set.index);
0443 if (index == IPSET_INVALID_ID) {
0444 pr_info_ratelimited("Cannot find add_set index %u as target\n",
0445 info->add_set.index);
0446 return -ENOENT;
0447 }
0448 }
0449
0450 if (info->del_set.index != IPSET_INVALID_ID) {
0451 index = ip_set_nfnl_get_byindex(par->net,
0452 info->del_set.index);
0453 if (index == IPSET_INVALID_ID) {
0454 pr_info_ratelimited("Cannot find del_set index %u as target\n",
0455 info->del_set.index);
0456 ret = -ENOENT;
0457 goto cleanup_add;
0458 }
0459 }
0460
0461 if (info->map_set.index != IPSET_INVALID_ID) {
0462 if (strncmp(par->table, "mangle", 7)) {
0463 pr_info_ratelimited("--map-set only usable from mangle table\n");
0464 ret = -EINVAL;
0465 goto cleanup_del;
0466 }
0467 if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
0468 (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) &&
0469 (par->hook_mask & ~(1 << NF_INET_FORWARD |
0470 1 << NF_INET_LOCAL_OUT |
0471 1 << NF_INET_POST_ROUTING))) {
0472 pr_info_ratelimited("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");
0473 ret = -EINVAL;
0474 goto cleanup_del;
0475 }
0476 index = ip_set_nfnl_get_byindex(par->net,
0477 info->map_set.index);
0478 if (index == IPSET_INVALID_ID) {
0479 pr_info_ratelimited("Cannot find map_set index %u as target\n",
0480 info->map_set.index);
0481 ret = -ENOENT;
0482 goto cleanup_del;
0483 }
0484 }
0485
0486 if (info->add_set.dim > IPSET_DIM_MAX ||
0487 info->del_set.dim > IPSET_DIM_MAX ||
0488 info->map_set.dim > IPSET_DIM_MAX) {
0489 pr_info_ratelimited("SET target dimension over the limit!\n");
0490 ret = -ERANGE;
0491 goto cleanup_mark;
0492 }
0493
0494 return 0;
0495 cleanup_mark:
0496 if (info->map_set.index != IPSET_INVALID_ID)
0497 ip_set_nfnl_put(par->net, info->map_set.index);
0498 cleanup_del:
0499 if (info->del_set.index != IPSET_INVALID_ID)
0500 ip_set_nfnl_put(par->net, info->del_set.index);
0501 cleanup_add:
0502 if (info->add_set.index != IPSET_INVALID_ID)
0503 ip_set_nfnl_put(par->net, info->add_set.index);
0504 return ret;
0505 }
0506
0507 static void
0508 set_target_v3_destroy(const struct xt_tgdtor_param *par)
0509 {
0510 const struct xt_set_info_target_v3 *info = par->targinfo;
0511
0512 if (info->add_set.index != IPSET_INVALID_ID)
0513 ip_set_nfnl_put(par->net, info->add_set.index);
0514 if (info->del_set.index != IPSET_INVALID_ID)
0515 ip_set_nfnl_put(par->net, info->del_set.index);
0516 if (info->map_set.index != IPSET_INVALID_ID)
0517 ip_set_nfnl_put(par->net, info->map_set.index);
0518 }
0519
0520 static struct xt_match set_matches[] __read_mostly = {
0521 {
0522 .name = "set",
0523 .family = NFPROTO_IPV4,
0524 .revision = 0,
0525 .match = set_match_v0,
0526 .matchsize = sizeof(struct xt_set_info_match_v0),
0527 .checkentry = set_match_v0_checkentry,
0528 .destroy = set_match_v0_destroy,
0529 .me = THIS_MODULE
0530 },
0531 {
0532 .name = "set",
0533 .family = NFPROTO_IPV4,
0534 .revision = 1,
0535 .match = set_match_v1,
0536 .matchsize = sizeof(struct xt_set_info_match_v1),
0537 .checkentry = set_match_v1_checkentry,
0538 .destroy = set_match_v1_destroy,
0539 .me = THIS_MODULE
0540 },
0541 {
0542 .name = "set",
0543 .family = NFPROTO_IPV6,
0544 .revision = 1,
0545 .match = set_match_v1,
0546 .matchsize = sizeof(struct xt_set_info_match_v1),
0547 .checkentry = set_match_v1_checkentry,
0548 .destroy = set_match_v1_destroy,
0549 .me = THIS_MODULE
0550 },
0551
0552 {
0553 .name = "set",
0554 .family = NFPROTO_IPV4,
0555 .revision = 2,
0556 .match = set_match_v1,
0557 .matchsize = sizeof(struct xt_set_info_match_v1),
0558 .checkentry = set_match_v1_checkentry,
0559 .destroy = set_match_v1_destroy,
0560 .me = THIS_MODULE
0561 },
0562 {
0563 .name = "set",
0564 .family = NFPROTO_IPV6,
0565 .revision = 2,
0566 .match = set_match_v1,
0567 .matchsize = sizeof(struct xt_set_info_match_v1),
0568 .checkentry = set_match_v1_checkentry,
0569 .destroy = set_match_v1_destroy,
0570 .me = THIS_MODULE
0571 },
0572
0573 {
0574 .name = "set",
0575 .family = NFPROTO_IPV4,
0576 .revision = 3,
0577 .match = set_match_v3,
0578 .matchsize = sizeof(struct xt_set_info_match_v3),
0579 .checkentry = set_match_v3_checkentry,
0580 .destroy = set_match_v3_destroy,
0581 .me = THIS_MODULE
0582 },
0583 {
0584 .name = "set",
0585 .family = NFPROTO_IPV6,
0586 .revision = 3,
0587 .match = set_match_v3,
0588 .matchsize = sizeof(struct xt_set_info_match_v3),
0589 .checkentry = set_match_v3_checkentry,
0590 .destroy = set_match_v3_destroy,
0591 .me = THIS_MODULE
0592 },
0593
0594 {
0595 .name = "set",
0596 .family = NFPROTO_IPV4,
0597 .revision = 4,
0598 .match = set_match_v4,
0599 .matchsize = sizeof(struct xt_set_info_match_v4),
0600 .checkentry = set_match_v4_checkentry,
0601 .destroy = set_match_v4_destroy,
0602 .me = THIS_MODULE
0603 },
0604 {
0605 .name = "set",
0606 .family = NFPROTO_IPV6,
0607 .revision = 4,
0608 .match = set_match_v4,
0609 .matchsize = sizeof(struct xt_set_info_match_v4),
0610 .checkentry = set_match_v4_checkentry,
0611 .destroy = set_match_v4_destroy,
0612 .me = THIS_MODULE
0613 },
0614 };
0615
0616 static struct xt_target set_targets[] __read_mostly = {
0617 {
0618 .name = "SET",
0619 .revision = 0,
0620 .family = NFPROTO_IPV4,
0621 .target = set_target_v0,
0622 .targetsize = sizeof(struct xt_set_info_target_v0),
0623 .checkentry = set_target_v0_checkentry,
0624 .destroy = set_target_v0_destroy,
0625 .me = THIS_MODULE
0626 },
0627 {
0628 .name = "SET",
0629 .revision = 1,
0630 .family = NFPROTO_IPV4,
0631 .target = set_target_v1,
0632 .targetsize = sizeof(struct xt_set_info_target_v1),
0633 .checkentry = set_target_v1_checkentry,
0634 .destroy = set_target_v1_destroy,
0635 .me = THIS_MODULE
0636 },
0637 {
0638 .name = "SET",
0639 .revision = 1,
0640 .family = NFPROTO_IPV6,
0641 .target = set_target_v1,
0642 .targetsize = sizeof(struct xt_set_info_target_v1),
0643 .checkentry = set_target_v1_checkentry,
0644 .destroy = set_target_v1_destroy,
0645 .me = THIS_MODULE
0646 },
0647
0648 {
0649 .name = "SET",
0650 .revision = 2,
0651 .family = NFPROTO_IPV4,
0652 .target = set_target_v2,
0653 .targetsize = sizeof(struct xt_set_info_target_v2),
0654 .checkentry = set_target_v2_checkentry,
0655 .destroy = set_target_v2_destroy,
0656 .me = THIS_MODULE
0657 },
0658 {
0659 .name = "SET",
0660 .revision = 2,
0661 .family = NFPROTO_IPV6,
0662 .target = set_target_v2,
0663 .targetsize = sizeof(struct xt_set_info_target_v2),
0664 .checkentry = set_target_v2_checkentry,
0665 .destroy = set_target_v2_destroy,
0666 .me = THIS_MODULE
0667 },
0668
0669 {
0670 .name = "SET",
0671 .revision = 3,
0672 .family = NFPROTO_IPV4,
0673 .target = set_target_v3,
0674 .targetsize = sizeof(struct xt_set_info_target_v3),
0675 .checkentry = set_target_v3_checkentry,
0676 .destroy = set_target_v3_destroy,
0677 .me = THIS_MODULE
0678 },
0679 {
0680 .name = "SET",
0681 .revision = 3,
0682 .family = NFPROTO_IPV6,
0683 .target = set_target_v3,
0684 .targetsize = sizeof(struct xt_set_info_target_v3),
0685 .checkentry = set_target_v3_checkentry,
0686 .destroy = set_target_v3_destroy,
0687 .me = THIS_MODULE
0688 },
0689 };
0690
0691 static int __init xt_set_init(void)
0692 {
0693 int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches));
0694
0695 if (!ret) {
0696 ret = xt_register_targets(set_targets,
0697 ARRAY_SIZE(set_targets));
0698 if (ret)
0699 xt_unregister_matches(set_matches,
0700 ARRAY_SIZE(set_matches));
0701 }
0702 return ret;
0703 }
0704
0705 static void __exit xt_set_fini(void)
0706 {
0707 xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches));
0708 xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets));
0709 }
0710
0711 module_init(xt_set_init);
0712 module_exit(xt_set_fini);