root/net/netfilter/xt_set.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. match_set
  2. set_match_v0
  3. compat_flags
  4. set_match_v0_checkentry
  5. set_match_v0_destroy
  6. set_match_v1
  7. set_match_v1_checkentry
  8. set_match_v1_destroy
  9. set_match_v3
  10. set_match_v4
  11. set_target_v0
  12. set_target_v0_checkentry
  13. set_target_v0_destroy
  14. set_target_v1
  15. set_target_v1_checkentry
  16. set_target_v1_destroy
  17. set_target_v2
  18. set_target_v3
  19. set_target_v3_checkentry
  20. set_target_v3_destroy
  21. xt_set_init
  22. xt_set_fini

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
   3  *                         Patrick Schaaf <bof@bof.de>
   4  *                         Martin Josefsson <gandalf@wlug.westbo.se>
   5  * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@netfilter.org>
   6  */
   7 
   8 /* Kernel module which implements the set match and SET target
   9  * for netfilter/iptables.
  10  */
  11 
  12 #include <linux/module.h>
  13 #include <linux/skbuff.h>
  14 
  15 #include <linux/netfilter/x_tables.h>
  16 #include <linux/netfilter/ipset/ip_set.h>
  17 #include <uapi/linux/netfilter/xt_set.h>
  18 
  19 MODULE_LICENSE("GPL");
  20 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
  21 MODULE_DESCRIPTION("Xtables: IP set match and target module");
  22 MODULE_ALIAS("xt_SET");
  23 MODULE_ALIAS("ipt_set");
  24 MODULE_ALIAS("ip6t_set");
  25 MODULE_ALIAS("ipt_SET");
  26 MODULE_ALIAS("ip6t_SET");
  27 
  28 static inline int
  29 match_set(ip_set_id_t index, const struct sk_buff *skb,
  30           const struct xt_action_param *par,
  31           struct ip_set_adt_opt *opt, int inv)
  32 {
  33         if (ip_set_test(index, skb, par, opt))
  34                 inv = !inv;
  35         return inv;
  36 }
  37 
  38 #define ADT_OPT(n, f, d, fs, cfs, t, p, b, po, bo)      \
  39 struct ip_set_adt_opt n = {                             \
  40         .family = f,                                    \
  41         .dim = d,                                       \
  42         .flags = fs,                                    \
  43         .cmdflags = cfs,                                \
  44         .ext.timeout = t,                               \
  45         .ext.packets = p,                               \
  46         .ext.bytes = b,                                 \
  47         .ext.packets_op = po,                           \
  48         .ext.bytes_op = bo,                             \
  49 }
  50 
  51 /* Revision 0 interface: backward compatible with netfilter/iptables */
  52 
  53 static bool
  54 set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
  55 {
  56         const struct xt_set_info_match_v0 *info = par->matchinfo;
  57 
  58         ADT_OPT(opt, xt_family(par), info->match_set.u.compat.dim,
  59                 info->match_set.u.compat.flags, 0, UINT_MAX,
  60                 0, 0, 0, 0);
  61 
  62         return match_set(info->match_set.index, skb, par, &opt,
  63                          info->match_set.u.compat.flags & IPSET_INV_MATCH);
  64 }
  65 
  66 static void
  67 compat_flags(struct xt_set_info_v0 *info)
  68 {
  69         u_int8_t i;
  70 
  71         /* Fill out compatibility data according to enum ip_set_kopt */
  72         info->u.compat.dim = IPSET_DIM_ZERO;
  73         if (info->u.flags[0] & IPSET_MATCH_INV)
  74                 info->u.compat.flags |= IPSET_INV_MATCH;
  75         for (i = 0; i < IPSET_DIM_MAX - 1 && info->u.flags[i]; i++) {
  76                 info->u.compat.dim++;
  77                 if (info->u.flags[i] & IPSET_SRC)
  78                         info->u.compat.flags |= (1 << info->u.compat.dim);
  79         }
  80 }
  81 
  82 static int
  83 set_match_v0_checkentry(const struct xt_mtchk_param *par)
  84 {
  85         struct xt_set_info_match_v0 *info = par->matchinfo;
  86         ip_set_id_t index;
  87 
  88         index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
  89 
  90         if (index == IPSET_INVALID_ID) {
  91                 pr_info_ratelimited("Cannot find set identified by id %u to match\n",
  92                                     info->match_set.index);
  93                 return -ENOENT;
  94         }
  95         if (info->match_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
  96                 pr_info_ratelimited("set match dimension is over the limit!\n");
  97                 ip_set_nfnl_put(par->net, info->match_set.index);
  98                 return -ERANGE;
  99         }
 100 
 101         /* Fill out compatibility data */
 102         compat_flags(&info->match_set);
 103 
 104         return 0;
 105 }
 106 
 107 static void
 108 set_match_v0_destroy(const struct xt_mtdtor_param *par)
 109 {
 110         struct xt_set_info_match_v0 *info = par->matchinfo;
 111 
 112         ip_set_nfnl_put(par->net, info->match_set.index);
 113 }
 114 
 115 /* Revision 1 match */
 116 
 117 static bool
 118 set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
 119 {
 120         const struct xt_set_info_match_v1 *info = par->matchinfo;
 121 
 122         ADT_OPT(opt, xt_family(par), info->match_set.dim,
 123                 info->match_set.flags, 0, UINT_MAX,
 124                 0, 0, 0, 0);
 125 
 126         if (opt.flags & IPSET_RETURN_NOMATCH)
 127                 opt.cmdflags |= IPSET_FLAG_RETURN_NOMATCH;
 128 
 129         return match_set(info->match_set.index, skb, par, &opt,
 130                          info->match_set.flags & IPSET_INV_MATCH);
 131 }
 132 
 133 static int
 134 set_match_v1_checkentry(const struct xt_mtchk_param *par)
 135 {
 136         struct xt_set_info_match_v1 *info = par->matchinfo;
 137         ip_set_id_t index;
 138 
 139         index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
 140 
 141         if (index == IPSET_INVALID_ID) {
 142                 pr_info_ratelimited("Cannot find set identified by id %u to match\n",
 143                                     info->match_set.index);
 144                 return -ENOENT;
 145         }
 146         if (info->match_set.dim > IPSET_DIM_MAX) {
 147                 pr_info_ratelimited("set match dimension is over the limit!\n");
 148                 ip_set_nfnl_put(par->net, info->match_set.index);
 149                 return -ERANGE;
 150         }
 151 
 152         return 0;
 153 }
 154 
 155 static void
 156 set_match_v1_destroy(const struct xt_mtdtor_param *par)
 157 {
 158         struct xt_set_info_match_v1 *info = par->matchinfo;
 159 
 160         ip_set_nfnl_put(par->net, info->match_set.index);
 161 }
 162 
 163 /* Revision 3 match */
 164 
 165 static bool
 166 set_match_v3(const struct sk_buff *skb, struct xt_action_param *par)
 167 {
 168         const struct xt_set_info_match_v3 *info = par->matchinfo;
 169 
 170         ADT_OPT(opt, xt_family(par), info->match_set.dim,
 171                 info->match_set.flags, info->flags, UINT_MAX,
 172                 info->packets.value, info->bytes.value,
 173                 info->packets.op, info->bytes.op);
 174 
 175         if (info->packets.op != IPSET_COUNTER_NONE ||
 176             info->bytes.op != IPSET_COUNTER_NONE)
 177                 opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
 178 
 179         return match_set(info->match_set.index, skb, par, &opt,
 180                          info->match_set.flags & IPSET_INV_MATCH);
 181 }
 182 
 183 #define set_match_v3_checkentry set_match_v1_checkentry
 184 #define set_match_v3_destroy    set_match_v1_destroy
 185 
 186 /* Revision 4 match */
 187 
 188 static bool
 189 set_match_v4(const struct sk_buff *skb, struct xt_action_param *par)
 190 {
 191         const struct xt_set_info_match_v4 *info = par->matchinfo;
 192 
 193         ADT_OPT(opt, xt_family(par), info->match_set.dim,
 194                 info->match_set.flags, info->flags, UINT_MAX,
 195                 info->packets.value, info->bytes.value,
 196                 info->packets.op, info->bytes.op);
 197 
 198         if (info->packets.op != IPSET_COUNTER_NONE ||
 199             info->bytes.op != IPSET_COUNTER_NONE)
 200                 opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
 201 
 202         return match_set(info->match_set.index, skb, par, &opt,
 203                          info->match_set.flags & IPSET_INV_MATCH);
 204 }
 205 
 206 #define set_match_v4_checkentry set_match_v1_checkentry
 207 #define set_match_v4_destroy    set_match_v1_destroy
 208 
 209 /* Revision 0 interface: backward compatible with netfilter/iptables */
 210 
 211 static unsigned int
 212 set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
 213 {
 214         const struct xt_set_info_target_v0 *info = par->targinfo;
 215 
 216         ADT_OPT(add_opt, xt_family(par), info->add_set.u.compat.dim,
 217                 info->add_set.u.compat.flags, 0, UINT_MAX,
 218                 0, 0, 0, 0);
 219         ADT_OPT(del_opt, xt_family(par), info->del_set.u.compat.dim,
 220                 info->del_set.u.compat.flags, 0, UINT_MAX,
 221                 0, 0, 0, 0);
 222 
 223         if (info->add_set.index != IPSET_INVALID_ID)
 224                 ip_set_add(info->add_set.index, skb, par, &add_opt);
 225         if (info->del_set.index != IPSET_INVALID_ID)
 226                 ip_set_del(info->del_set.index, skb, par, &del_opt);
 227 
 228         return XT_CONTINUE;
 229 }
 230 
 231 static int
 232 set_target_v0_checkentry(const struct xt_tgchk_param *par)
 233 {
 234         struct xt_set_info_target_v0 *info = par->targinfo;
 235         ip_set_id_t index;
 236 
 237         if (info->add_set.index != IPSET_INVALID_ID) {
 238                 index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
 239                 if (index == IPSET_INVALID_ID) {
 240                         pr_info_ratelimited("Cannot find add_set index %u as target\n",
 241                                             info->add_set.index);
 242                         return -ENOENT;
 243                 }
 244         }
 245 
 246         if (info->del_set.index != IPSET_INVALID_ID) {
 247                 index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
 248                 if (index == IPSET_INVALID_ID) {
 249                         pr_info_ratelimited("Cannot find del_set index %u as target\n",
 250                                             info->del_set.index);
 251                         if (info->add_set.index != IPSET_INVALID_ID)
 252                                 ip_set_nfnl_put(par->net, info->add_set.index);
 253                         return -ENOENT;
 254                 }
 255         }
 256         if (info->add_set.u.flags[IPSET_DIM_MAX - 1] != 0 ||
 257             info->del_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
 258                 pr_info_ratelimited("SET target dimension over the limit!\n");
 259                 if (info->add_set.index != IPSET_INVALID_ID)
 260                         ip_set_nfnl_put(par->net, info->add_set.index);
 261                 if (info->del_set.index != IPSET_INVALID_ID)
 262                         ip_set_nfnl_put(par->net, info->del_set.index);
 263                 return -ERANGE;
 264         }
 265 
 266         /* Fill out compatibility data */
 267         compat_flags(&info->add_set);
 268         compat_flags(&info->del_set);
 269 
 270         return 0;
 271 }
 272 
 273 static void
 274 set_target_v0_destroy(const struct xt_tgdtor_param *par)
 275 {
 276         const struct xt_set_info_target_v0 *info = par->targinfo;
 277 
 278         if (info->add_set.index != IPSET_INVALID_ID)
 279                 ip_set_nfnl_put(par->net, info->add_set.index);
 280         if (info->del_set.index != IPSET_INVALID_ID)
 281                 ip_set_nfnl_put(par->net, info->del_set.index);
 282 }
 283 
 284 /* Revision 1 target */
 285 
 286 static unsigned int
 287 set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
 288 {
 289         const struct xt_set_info_target_v1 *info = par->targinfo;
 290 
 291         ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
 292                 info->add_set.flags, 0, UINT_MAX,
 293                 0, 0, 0, 0);
 294         ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
 295                 info->del_set.flags, 0, UINT_MAX,
 296                 0, 0, 0, 0);
 297 
 298         if (info->add_set.index != IPSET_INVALID_ID)
 299                 ip_set_add(info->add_set.index, skb, par, &add_opt);
 300         if (info->del_set.index != IPSET_INVALID_ID)
 301                 ip_set_del(info->del_set.index, skb, par, &del_opt);
 302 
 303         return XT_CONTINUE;
 304 }
 305 
 306 static int
 307 set_target_v1_checkentry(const struct xt_tgchk_param *par)
 308 {
 309         const struct xt_set_info_target_v1 *info = par->targinfo;
 310         ip_set_id_t index;
 311 
 312         if (info->add_set.index != IPSET_INVALID_ID) {
 313                 index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
 314                 if (index == IPSET_INVALID_ID) {
 315                         pr_info_ratelimited("Cannot find add_set index %u as target\n",
 316                                             info->add_set.index);
 317                         return -ENOENT;
 318                 }
 319         }
 320 
 321         if (info->del_set.index != IPSET_INVALID_ID) {
 322                 index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
 323                 if (index == IPSET_INVALID_ID) {
 324                         pr_info_ratelimited("Cannot find del_set index %u as target\n",
 325                                             info->del_set.index);
 326                         if (info->add_set.index != IPSET_INVALID_ID)
 327                                 ip_set_nfnl_put(par->net, info->add_set.index);
 328                         return -ENOENT;
 329                 }
 330         }
 331         if (info->add_set.dim > IPSET_DIM_MAX ||
 332             info->del_set.dim > IPSET_DIM_MAX) {
 333                 pr_info_ratelimited("SET target dimension over the limit!\n");
 334                 if (info->add_set.index != IPSET_INVALID_ID)
 335                         ip_set_nfnl_put(par->net, info->add_set.index);
 336                 if (info->del_set.index != IPSET_INVALID_ID)
 337                         ip_set_nfnl_put(par->net, info->del_set.index);
 338                 return -ERANGE;
 339         }
 340 
 341         return 0;
 342 }
 343 
 344 static void
 345 set_target_v1_destroy(const struct xt_tgdtor_param *par)
 346 {
 347         const struct xt_set_info_target_v1 *info = par->targinfo;
 348 
 349         if (info->add_set.index != IPSET_INVALID_ID)
 350                 ip_set_nfnl_put(par->net, info->add_set.index);
 351         if (info->del_set.index != IPSET_INVALID_ID)
 352                 ip_set_nfnl_put(par->net, info->del_set.index);
 353 }
 354 
 355 /* Revision 2 target */
 356 
 357 static unsigned int
 358 set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
 359 {
 360         const struct xt_set_info_target_v2 *info = par->targinfo;
 361 
 362         ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
 363                 info->add_set.flags, info->flags, info->timeout,
 364                 0, 0, 0, 0);
 365         ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
 366                 info->del_set.flags, 0, UINT_MAX,
 367                 0, 0, 0, 0);
 368 
 369         /* Normalize to fit into jiffies */
 370         if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
 371             add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
 372                 add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
 373         if (info->add_set.index != IPSET_INVALID_ID)
 374                 ip_set_add(info->add_set.index, skb, par, &add_opt);
 375         if (info->del_set.index != IPSET_INVALID_ID)
 376                 ip_set_del(info->del_set.index, skb, par, &del_opt);
 377 
 378         return XT_CONTINUE;
 379 }
 380 
 381 #define set_target_v2_checkentry        set_target_v1_checkentry
 382 #define set_target_v2_destroy           set_target_v1_destroy
 383 
 384 /* Revision 3 target */
 385 
 386 #define MOPT(opt, member)       ((opt).ext.skbinfo.member)
 387 
 388 static unsigned int
 389 set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
 390 {
 391         const struct xt_set_info_target_v3 *info = par->targinfo;
 392         int ret;
 393 
 394         ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
 395                 info->add_set.flags, info->flags, info->timeout,
 396                 0, 0, 0, 0);
 397         ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
 398                 info->del_set.flags, 0, UINT_MAX,
 399                 0, 0, 0, 0);
 400         ADT_OPT(map_opt, xt_family(par), info->map_set.dim,
 401                 info->map_set.flags, 0, UINT_MAX,
 402                 0, 0, 0, 0);
 403 
 404         /* Normalize to fit into jiffies */
 405         if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
 406             add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
 407                 add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
 408         if (info->add_set.index != IPSET_INVALID_ID)
 409                 ip_set_add(info->add_set.index, skb, par, &add_opt);
 410         if (info->del_set.index != IPSET_INVALID_ID)
 411                 ip_set_del(info->del_set.index, skb, par, &del_opt);
 412         if (info->map_set.index != IPSET_INVALID_ID) {
 413                 map_opt.cmdflags |= info->flags & (IPSET_FLAG_MAP_SKBMARK |
 414                                                    IPSET_FLAG_MAP_SKBPRIO |
 415                                                    IPSET_FLAG_MAP_SKBQUEUE);
 416                 ret = match_set(info->map_set.index, skb, par, &map_opt,
 417                                 info->map_set.flags & IPSET_INV_MATCH);
 418                 if (!ret)
 419                         return XT_CONTINUE;
 420                 if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
 421                         skb->mark = (skb->mark & ~MOPT(map_opt,skbmarkmask))
 422                                     ^ MOPT(map_opt, skbmark);
 423                 if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO)
 424                         skb->priority = MOPT(map_opt, skbprio);
 425                 if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) &&
 426                     skb->dev &&
 427                     skb->dev->real_num_tx_queues > MOPT(map_opt, skbqueue))
 428                         skb_set_queue_mapping(skb, MOPT(map_opt, skbqueue));
 429         }
 430         return XT_CONTINUE;
 431 }
 432 
 433 static int
 434 set_target_v3_checkentry(const struct xt_tgchk_param *par)
 435 {
 436         const struct xt_set_info_target_v3 *info = par->targinfo;
 437         ip_set_id_t index;
 438         int ret = 0;
 439 
 440         if (info->add_set.index != IPSET_INVALID_ID) {
 441                 index = ip_set_nfnl_get_byindex(par->net,
 442                                                 info->add_set.index);
 443                 if (index == IPSET_INVALID_ID) {
 444                         pr_info_ratelimited("Cannot find add_set index %u as target\n",
 445                                             info->add_set.index);
 446                         return -ENOENT;
 447                 }
 448         }
 449 
 450         if (info->del_set.index != IPSET_INVALID_ID) {
 451                 index = ip_set_nfnl_get_byindex(par->net,
 452                                                 info->del_set.index);
 453                 if (index == IPSET_INVALID_ID) {
 454                         pr_info_ratelimited("Cannot find del_set index %u as target\n",
 455                                             info->del_set.index);
 456                         ret = -ENOENT;
 457                         goto cleanup_add;
 458                 }
 459         }
 460 
 461         if (info->map_set.index != IPSET_INVALID_ID) {
 462                 if (strncmp(par->table, "mangle", 7)) {
 463                         pr_info_ratelimited("--map-set only usable from mangle table\n");
 464                         ret = -EINVAL;
 465                         goto cleanup_del;
 466                 }
 467                 if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
 468                      (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) &&
 469                      (par->hook_mask & ~(1 << NF_INET_FORWARD |
 470                                          1 << NF_INET_LOCAL_OUT |
 471                                          1 << NF_INET_POST_ROUTING))) {
 472                         pr_info_ratelimited("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");
 473                         ret = -EINVAL;
 474                         goto cleanup_del;
 475                 }
 476                 index = ip_set_nfnl_get_byindex(par->net,
 477                                                 info->map_set.index);
 478                 if (index == IPSET_INVALID_ID) {
 479                         pr_info_ratelimited("Cannot find map_set index %u as target\n",
 480                                             info->map_set.index);
 481                         ret = -ENOENT;
 482                         goto cleanup_del;
 483                 }
 484         }
 485 
 486         if (info->add_set.dim > IPSET_DIM_MAX ||
 487             info->del_set.dim > IPSET_DIM_MAX ||
 488             info->map_set.dim > IPSET_DIM_MAX) {
 489                 pr_info_ratelimited("SET target dimension over the limit!\n");
 490                 ret = -ERANGE;
 491                 goto cleanup_mark;
 492         }
 493 
 494         return 0;
 495 cleanup_mark:
 496         if (info->map_set.index != IPSET_INVALID_ID)
 497                 ip_set_nfnl_put(par->net, info->map_set.index);
 498 cleanup_del:
 499         if (info->del_set.index != IPSET_INVALID_ID)
 500                 ip_set_nfnl_put(par->net, info->del_set.index);
 501 cleanup_add:
 502         if (info->add_set.index != IPSET_INVALID_ID)
 503                 ip_set_nfnl_put(par->net, info->add_set.index);
 504         return ret;
 505 }
 506 
 507 static void
 508 set_target_v3_destroy(const struct xt_tgdtor_param *par)
 509 {
 510         const struct xt_set_info_target_v3 *info = par->targinfo;
 511 
 512         if (info->add_set.index != IPSET_INVALID_ID)
 513                 ip_set_nfnl_put(par->net, info->add_set.index);
 514         if (info->del_set.index != IPSET_INVALID_ID)
 515                 ip_set_nfnl_put(par->net, info->del_set.index);
 516         if (info->map_set.index != IPSET_INVALID_ID)
 517                 ip_set_nfnl_put(par->net, info->map_set.index);
 518 }
 519 
 520 static struct xt_match set_matches[] __read_mostly = {
 521         {
 522                 .name           = "set",
 523                 .family         = NFPROTO_IPV4,
 524                 .revision       = 0,
 525                 .match          = set_match_v0,
 526                 .matchsize      = sizeof(struct xt_set_info_match_v0),
 527                 .checkentry     = set_match_v0_checkentry,
 528                 .destroy        = set_match_v0_destroy,
 529                 .me             = THIS_MODULE
 530         },
 531         {
 532                 .name           = "set",
 533                 .family         = NFPROTO_IPV4,
 534                 .revision       = 1,
 535                 .match          = set_match_v1,
 536                 .matchsize      = sizeof(struct xt_set_info_match_v1),
 537                 .checkentry     = set_match_v1_checkentry,
 538                 .destroy        = set_match_v1_destroy,
 539                 .me             = THIS_MODULE
 540         },
 541         {
 542                 .name           = "set",
 543                 .family         = NFPROTO_IPV6,
 544                 .revision       = 1,
 545                 .match          = set_match_v1,
 546                 .matchsize      = sizeof(struct xt_set_info_match_v1),
 547                 .checkentry     = set_match_v1_checkentry,
 548                 .destroy        = set_match_v1_destroy,
 549                 .me             = THIS_MODULE
 550         },
 551         /* --return-nomatch flag support */
 552         {
 553                 .name           = "set",
 554                 .family         = NFPROTO_IPV4,
 555                 .revision       = 2,
 556                 .match          = set_match_v1,
 557                 .matchsize      = sizeof(struct xt_set_info_match_v1),
 558                 .checkentry     = set_match_v1_checkentry,
 559                 .destroy        = set_match_v1_destroy,
 560                 .me             = THIS_MODULE
 561         },
 562         {
 563                 .name           = "set",
 564                 .family         = NFPROTO_IPV6,
 565                 .revision       = 2,
 566                 .match          = set_match_v1,
 567                 .matchsize      = sizeof(struct xt_set_info_match_v1),
 568                 .checkentry     = set_match_v1_checkentry,
 569                 .destroy        = set_match_v1_destroy,
 570                 .me             = THIS_MODULE
 571         },
 572         /* counters support: update, match */
 573         {
 574                 .name           = "set",
 575                 .family         = NFPROTO_IPV4,
 576                 .revision       = 3,
 577                 .match          = set_match_v3,
 578                 .matchsize      = sizeof(struct xt_set_info_match_v3),
 579                 .checkentry     = set_match_v3_checkentry,
 580                 .destroy        = set_match_v3_destroy,
 581                 .me             = THIS_MODULE
 582         },
 583         {
 584                 .name           = "set",
 585                 .family         = NFPROTO_IPV6,
 586                 .revision       = 3,
 587                 .match          = set_match_v3,
 588                 .matchsize      = sizeof(struct xt_set_info_match_v3),
 589                 .checkentry     = set_match_v3_checkentry,
 590                 .destroy        = set_match_v3_destroy,
 591                 .me             = THIS_MODULE
 592         },
 593         /* new revision for counters support: update, match */
 594         {
 595                 .name           = "set",
 596                 .family         = NFPROTO_IPV4,
 597                 .revision       = 4,
 598                 .match          = set_match_v4,
 599                 .matchsize      = sizeof(struct xt_set_info_match_v4),
 600                 .checkentry     = set_match_v4_checkentry,
 601                 .destroy        = set_match_v4_destroy,
 602                 .me             = THIS_MODULE
 603         },
 604         {
 605                 .name           = "set",
 606                 .family         = NFPROTO_IPV6,
 607                 .revision       = 4,
 608                 .match          = set_match_v4,
 609                 .matchsize      = sizeof(struct xt_set_info_match_v4),
 610                 .checkentry     = set_match_v4_checkentry,
 611                 .destroy        = set_match_v4_destroy,
 612                 .me             = THIS_MODULE
 613         },
 614 };
 615 
 616 static struct xt_target set_targets[] __read_mostly = {
 617         {
 618                 .name           = "SET",
 619                 .revision       = 0,
 620                 .family         = NFPROTO_IPV4,
 621                 .target         = set_target_v0,
 622                 .targetsize     = sizeof(struct xt_set_info_target_v0),
 623                 .checkentry     = set_target_v0_checkentry,
 624                 .destroy        = set_target_v0_destroy,
 625                 .me             = THIS_MODULE
 626         },
 627         {
 628                 .name           = "SET",
 629                 .revision       = 1,
 630                 .family         = NFPROTO_IPV4,
 631                 .target         = set_target_v1,
 632                 .targetsize     = sizeof(struct xt_set_info_target_v1),
 633                 .checkentry     = set_target_v1_checkentry,
 634                 .destroy        = set_target_v1_destroy,
 635                 .me             = THIS_MODULE
 636         },
 637         {
 638                 .name           = "SET",
 639                 .revision       = 1,
 640                 .family         = NFPROTO_IPV6,
 641                 .target         = set_target_v1,
 642                 .targetsize     = sizeof(struct xt_set_info_target_v1),
 643                 .checkentry     = set_target_v1_checkentry,
 644                 .destroy        = set_target_v1_destroy,
 645                 .me             = THIS_MODULE
 646         },
 647         /* --timeout and --exist flags support */
 648         {
 649                 .name           = "SET",
 650                 .revision       = 2,
 651                 .family         = NFPROTO_IPV4,
 652                 .target         = set_target_v2,
 653                 .targetsize     = sizeof(struct xt_set_info_target_v2),
 654                 .checkentry     = set_target_v2_checkentry,
 655                 .destroy        = set_target_v2_destroy,
 656                 .me             = THIS_MODULE
 657         },
 658         {
 659                 .name           = "SET",
 660                 .revision       = 2,
 661                 .family         = NFPROTO_IPV6,
 662                 .target         = set_target_v2,
 663                 .targetsize     = sizeof(struct xt_set_info_target_v2),
 664                 .checkentry     = set_target_v2_checkentry,
 665                 .destroy        = set_target_v2_destroy,
 666                 .me             = THIS_MODULE
 667         },
 668         /* --map-set support */
 669         {
 670                 .name           = "SET",
 671                 .revision       = 3,
 672                 .family         = NFPROTO_IPV4,
 673                 .target         = set_target_v3,
 674                 .targetsize     = sizeof(struct xt_set_info_target_v3),
 675                 .checkentry     = set_target_v3_checkentry,
 676                 .destroy        = set_target_v3_destroy,
 677                 .me             = THIS_MODULE
 678         },
 679         {
 680                 .name           = "SET",
 681                 .revision       = 3,
 682                 .family         = NFPROTO_IPV6,
 683                 .target         = set_target_v3,
 684                 .targetsize     = sizeof(struct xt_set_info_target_v3),
 685                 .checkentry     = set_target_v3_checkentry,
 686                 .destroy        = set_target_v3_destroy,
 687                 .me             = THIS_MODULE
 688         },
 689 };
 690 
 691 static int __init xt_set_init(void)
 692 {
 693         int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches));
 694 
 695         if (!ret) {
 696                 ret = xt_register_targets(set_targets,
 697                                           ARRAY_SIZE(set_targets));
 698                 if (ret)
 699                         xt_unregister_matches(set_matches,
 700                                               ARRAY_SIZE(set_matches));
 701         }
 702         return ret;
 703 }
 704 
 705 static void __exit xt_set_fini(void)
 706 {
 707         xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches));
 708         xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets));
 709 }
 710 
 711 module_init(xt_set_init);
 712 module_exit(xt_set_fini);

/* [<][>][^][v][top][bottom][index][help] */