This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / net / ipv4 / netfilter / ipt_set.c
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-2004 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 to match an IP set. */
12
13 #include <linux/module.h>
14 #include <linux/ip.h>
15 #include <linux/skbuff.h>
16
17 #include <linux/netfilter_ipv4/ip_tables.h>
18 #include <linux/netfilter_ipv4/ip_set.h>
19 #include <linux/netfilter_ipv4/ipt_set.h>
20
21 static inline int
22 match_set(const struct ipt_set_info *info,
23           const struct sk_buff *skb,
24           int inv)
25 {       
26         if (ip_set_testip_kernel(info->index, skb, info->flags))
27                 inv = !inv;
28         return inv;
29 }
30
31 static int
32 match(const struct sk_buff *skb,
33       const struct net_device *in,
34       const struct net_device *out,
35       const void *matchinfo,
36       int offset,
37       int *hotdrop)
38 {
39         const struct ipt_set_info_match *info = matchinfo;
40                 
41         return match_set(&info->match_set,
42                          skb,
43                          info->match_set.flags[0] & IPSET_MATCH_INV);
44 }
45
46 static int
47 checkentry(const char *tablename,
48            const struct ipt_ip *ip,
49            void *matchinfo,
50            unsigned int matchsize,
51            unsigned int hook_mask)
52 {
53         struct ipt_set_info_match *info = 
54                 (struct ipt_set_info_match *) matchinfo;
55         ip_set_id_t index;
56
57         if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
58                 ip_set_printk("invalid matchsize %d", matchsize);
59                 return 0;
60         }
61
62         index = ip_set_get_byindex(info->match_set.index);
63                 
64         if (index == IP_SET_INVALID_ID) {
65                 ip_set_printk("Cannot find set indentified by id %u to match",
66                               info->match_set.index);
67                 return 0;       /* error */
68         }
69         if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) {
70                 ip_set_printk("That's nasty!");
71                 return 0;       /* error */
72         }
73
74         return 1;
75 }
76
77 static void destroy(void *matchinfo, unsigned int matchsize)
78 {
79         struct ipt_set_info_match *info = matchinfo;
80
81         if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
82                 ip_set_printk("invalid matchsize %d", matchsize);
83                 return;
84         }
85
86         ip_set_put(info->match_set.index);
87 }
88
89 static struct ipt_match set_match = {
90         .name           = "set",
91         .match          = &match,
92         .checkentry     = &checkentry,
93         .destroy        = &destroy,
94         .me             = THIS_MODULE
95 };
96
97 MODULE_LICENSE("GPL");
98 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
99 MODULE_DESCRIPTION("iptables IP set match module");
100
101 static int __init init(void)
102 {
103         return ipt_register_match(&set_match);
104 }
105
106 static void __exit fini(void)
107 {
108         ipt_unregister_match(&set_match);
109 }
110
111 module_init(init);
112 module_exit(fini);