~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/netfilter/xt_set.c

Version: ~ [ linux-5.4-rc7 ] ~ [ linux-5.3.11 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.84 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.154 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.201 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.201 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.77 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp