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

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

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

~ [ 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