Merge to Fedora kernel-2.6.18-1.2260_FC5 patched with stable patch-2.6.18.5-vs2.0...
[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 #include <linux/version.h>
17
18 #include <linux/netfilter_ipv4/ip_tables.h>
19 #include <linux/netfilter_ipv4/ip_set.h>
20 #include <linux/netfilter_ipv4/ipt_set.h>
21
22 static inline int
23 match_set(const struct ipt_set_info *info,
24           const struct sk_buff *skb,
25           int inv)
26 {       
27         if (ip_set_testip_kernel(info->index, skb, info->flags))
28                 inv = !inv;
29         return inv;
30 }
31
32 static int
33 match(const struct sk_buff *skb,
34       const struct net_device *in,
35       const struct net_device *out,
36 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
37       const struct xt_match *match,
38 #endif
39       const void *matchinfo,
40 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
41       int offset, unsigned int protoff, int *hotdrop)
42 #else
43       int offset, int *hotdrop)
44 #endif
45 {
46         const struct ipt_set_info_match *info = matchinfo;
47                 
48         return match_set(&info->match_set,
49                          skb,
50                          info->match_set.flags[0] & IPSET_MATCH_INV);
51 }
52
53 static int
54 checkentry(const char *tablename,
55 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
56            const void *inf,
57 #else
58            const struct ipt_ip *ip,
59 #endif
60 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
61            const struct xt_match *match,
62 #endif
63            void *matchinfo,
64 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
65            unsigned int matchsize,
66 #endif
67            unsigned int hook_mask)
68 {
69         struct ipt_set_info_match *info = 
70                 (struct ipt_set_info_match *) matchinfo;
71         ip_set_id_t index;
72
73 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
74         if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
75                 ip_set_printk("invalid matchsize %d", matchsize);
76                 return 0;
77         }
78 #endif
79
80         index = ip_set_get_byindex(info->match_set.index);
81                 
82         if (index == IP_SET_INVALID_ID) {
83                 ip_set_printk("Cannot find set indentified by id %u to match",
84                               info->match_set.index);
85                 return 0;       /* error */
86         }
87         if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) {
88                 ip_set_printk("That's nasty!");
89                 return 0;       /* error */
90         }
91
92         return 1;
93 }
94
95 static void destroy(
96 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
97                     const struct xt_match *match,
98 #endif
99 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
100                     void *matchinfo, unsigned int matchsize)
101 #else
102                     void *matchinfo)
103 #endif
104 {
105         struct ipt_set_info_match *info = matchinfo;
106
107 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
108         if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
109                 ip_set_printk("invalid matchsize %d", matchsize);
110                 return;
111         }
112 #endif
113         ip_set_put(info->match_set.index);
114 }
115
116 static struct ipt_match set_match = {
117         .name           = "set",
118         .match          = &match,
119 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
120         .matchsize      = sizeof(struct ipt_set_info_match),
121 #endif
122         .checkentry     = &checkentry,
123         .destroy        = &destroy,
124         .me             = THIS_MODULE
125 };
126
127 MODULE_LICENSE("GPL");
128 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
129 MODULE_DESCRIPTION("iptables IP set match module");
130
131 static int __init ipt_ipset_init(void)
132 {
133         return ipt_register_match(&set_match);
134 }
135
136 static void __exit ipt_ipset_fini(void)
137 {
138         ipt_unregister_match(&set_match);
139 }
140
141 module_init(ipt_ipset_init);
142 module_exit(ipt_ipset_fini);