]> git.pld-linux.org Git - packages/kernel.git/blob - pom-ng-connlimit-20060829.patch
- revert
[packages/kernel.git] / pom-ng-connlimit-20060829.patch
1  include/linux/netfilter_ipv4/ipt_connlimit.h |   12 +
2  net/ipv4/netfilter/Kconfig                   |   10 +
3  net/ipv4/netfilter/Makefile                  |    1 
4  net/ipv4/netfilter/ipt_connlimit.c           |  255 +++++++++++++++++++++++++++
5  4 files changed, 278 insertions(+)
6
7 diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux/include/linux/netfilter_ipv4/ipt_connlimit.h
8 --- linux.org/include/linux/netfilter_ipv4/ipt_connlimit.h      1970-01-01 00:00:00.000000000 +0000
9 +++ linux/include/linux/netfilter_ipv4/ipt_connlimit.h  2006-08-29 12:32:46.000000000 +0000
10 @@ -0,0 +1,12 @@
11 +#ifndef _IPT_CONNLIMIT_H
12 +#define _IPT_CONNLIMIT_H
13 +
14 +struct ipt_connlimit_data;
15 +
16 +struct ipt_connlimit_info {
17 +       int limit;
18 +       int inverse;
19 +       u_int32_t mask;
20 +       struct ipt_connlimit_data *data;
21 +};
22 +#endif /* _IPT_CONNLIMIT_H */
23 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ipt_connlimit.c linux/net/ipv4/netfilter/ipt_connlimit.c
24 --- linux.org/net/ipv4/netfilter/ipt_connlimit.c        1970-01-01 00:00:00.000000000 +0000
25 +++ linux/net/ipv4/netfilter/ipt_connlimit.c    2006-08-29 12:32:46.000000000 +0000
26 @@ -0,0 +1,255 @@
27 +/*
28 + * netfilter module to limit the number of parallel tcp
29 + * connections per IP address.
30 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
31 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
32 + *             only ignore TIME_WAIT or gone connections
33 + *
34 + * based on ...
35 + *
36 + * Kernel module to match connection tracking information.
37 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
38 + */
39 +#include <linux/module.h>
40 +#include <linux/skbuff.h>
41 +#include <linux/version.h>
42 +#include <linux/list.h>
43 +#include <linux/netfilter_ipv4/ip_conntrack.h>
44 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
45 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
46 +#include <linux/netfilter_ipv4/ip_tables.h>
47 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
48 +
49 +#define DEBUG 0
50 +
51 +MODULE_LICENSE("GPL");
52 +
53 +/* we'll save the tuples of all connections we care about */
54 +struct ipt_connlimit_conn
55 +{
56 +        struct list_head list;
57 +       struct ip_conntrack_tuple tuple;
58 +};
59 +
60 +struct ipt_connlimit_data {
61 +       spinlock_t lock;
62 +       struct list_head iphash[256];
63 +};
64 +
65 +static inline unsigned ipt_iphash(const unsigned addr)
66 +{
67 +       return ((addr ^ (addr >> 8) ^ (addr >> 16) ^ (addr >> 24)) & 0xff);
68 +}
69 +
70 +static int count_them(struct ipt_connlimit_data *data,
71 +                     u_int32_t addr, u_int32_t mask,
72 +                     struct ip_conntrack *ct)
73 +{
74 +#if DEBUG
75 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
76 +                                    "fin_wait", "time_wait", "close", "close_wait",
77 +                                    "last_ack", "listen" };
78 +#endif
79 +       int addit = 1, matches = 0;
80 +       struct ip_conntrack_tuple tuple;
81 +       struct ip_conntrack_tuple_hash *found;
82 +       struct ipt_connlimit_conn *conn;
83 +       struct list_head *hash,*lh;
84 +
85 +       spin_lock_bh(&data->lock);
86 +       tuple = ct->tuplehash[0].tuple;
87 +       hash = &data->iphash[ipt_iphash(addr & mask)];
88 +
89 +       /* check the saved connections */
90 +       for (lh = hash->next; lh != hash; lh = lh->next) {
91 +               struct ip_conntrack *found_ct = NULL;
92 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
93 +               found = ip_conntrack_find_get(&conn->tuple,ct);
94 +                if (found != NULL 
95 +                    && (found_ct = tuplehash_to_ctrack(found)) != NULL
96 +                    && 0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) 
97 +                    && found_ct->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
98 +                       /* Just to be sure we have it only once in the list.
99 +                          We should'nt see tuples twice unless someone hooks this
100 +                          into a table without "-p tcp --syn" */
101 +                       addit = 0;
102 +               }
103 +#if DEBUG
104 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
105 +                      ipt_iphash(addr & mask),
106 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
107 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
108 +                      (NULL != found) ? tcp[found_ct->proto.tcp.state] : "gone");
109 +#endif
110 +               if (NULL == found) {
111 +                       /* this one is gone */
112 +                       lh = lh->prev;
113 +                       list_del(lh->next);
114 +                       kfree(conn);
115 +                       continue;
116 +               }
117 +               if (found_ct->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
118 +                       /* we don't care about connections which are
119 +                          closed already -> ditch it */
120 +                       lh = lh->prev;
121 +                       list_del(lh->next);
122 +                       kfree(conn);
123 +                       nf_conntrack_put(&found_ct->ct_general);
124 +                       continue;
125 +               }
126 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
127 +                       /* same source IP address -> be counted! */
128 +                       matches++;
129 +               }
130 +               nf_conntrack_put(&found_ct->ct_general);
131 +       }
132 +       if (addit) {
133 +               /* save the new connection in our list */
134 +#if DEBUG
135 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
136 +                      ipt_iphash(addr & mask),
137 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
138 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
139 +#endif
140 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
141 +               if (NULL == conn) {
142 +                       spin_unlock_bh(&data->lock);
143 +                       return -1;
144 +               }
145 +               memset(conn,0,sizeof(*conn));
146 +               INIT_LIST_HEAD(&conn->list);
147 +               conn->tuple = tuple;
148 +               list_add(&conn->list,hash);
149 +               matches++;
150 +       }
151 +       spin_unlock_bh(&data->lock);
152 +       return matches;
153 +}
154 +
155 +static int
156 +match(const struct sk_buff *skb,
157 +      const struct net_device *in,
158 +      const struct net_device *out,
159 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
160 +      const struct xt_match *match,
161 +#endif
162 +      const void *matchinfo,
163 +      int offset,
164 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
165 +      unsigned int protoff,
166 +#endif
167 +      int *hotdrop)
168 +{
169 +       const struct ipt_connlimit_info *info = matchinfo;
170 +       int connections, rv;
171 +       struct ip_conntrack *ct;
172 +       enum ip_conntrack_info ctinfo;
173 +
174 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
175 +       if (NULL == ct) {
176 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
177 +               *hotdrop = 1;
178 +               return 0;
179 +       }
180 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
181 +       if (-1 == connections) {
182 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
183 +               *hotdrop = 1; /* let's free some memory :-) */
184 +               return 0;
185 +       }
186 +        rv = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
187 +#if DEBUG
188 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
189 +              "connections=%d limit=%d match=%s\n",
190 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
191 +              connections, info->limit, rv?"yes":"no");
192 +#endif
193 +
194 +       return rv;
195 +}
196 +
197 +static int check(const char *tablename,
198 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
199 +                const void *ip_void,
200 +#else
201 +                const struct ipt_ip *ip,
202 +#endif
203 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
204 +                const struct xt_match *match,
205 +#endif
206 +                void *matchinfo,
207 +                unsigned int matchsize,
208 +                unsigned int hook_mask)
209 +{
210 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
211 +       const struct ipt_ip *ip = ip_void;
212 +#endif
213 +
214 +       struct ipt_connlimit_info *info = matchinfo;
215 +       int i;
216 +
217 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
218 +       /* verify size */
219 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
220 +               return 0;
221 +#endif
222 +
223 +       /* refuse anything but tcp */
224 +       if (ip->proto != IPPROTO_TCP)
225 +               return 0;
226 +
227 +       /* init private data */
228 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
229 +       spin_lock_init(&(info->data->lock));
230 +       for (i = 0; i < 256; i++)
231 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
232 +       
233 +       return 1;
234 +}
235 +
236 +static void destroy(
237 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
238 +                   const struct xt_match *match,
239 +#endif
240 +                   void *matchinfo, unsigned int matchsize)
241 +{
242 +       struct ipt_connlimit_info *info = matchinfo;
243 +       struct ipt_connlimit_conn *conn;
244 +       struct list_head *hash;
245 +       int i;
246 +
247 +       /* cleanup */
248 +       for (i = 0; i < 256; i++) {
249 +               hash = &(info->data->iphash[i]);
250 +               while (hash != hash->next) {
251 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
252 +                       list_del(hash->next);
253 +                       kfree(conn);
254 +               }
255 +       }
256 +       kfree(info->data);
257 +}
258 +
259 +static struct ipt_match connlimit_match = { 
260 +       .name           = "connlimit",
261 +       .match          = &match,
262 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
263 +       .matchsize      = sizeof(struct ipt_connlimit_info),
264 +#endif
265 +       .checkentry     = &check,
266 +       .destroy        = &destroy,
267 +       .me             = THIS_MODULE
268 +};
269 +
270 +static int __init init(void)
271 +{
272 +       return ipt_register_match(&connlimit_match);
273 +}
274 +
275 +static void __exit fini(void)
276 +{
277 +       ipt_unregister_match(&connlimit_match);
278 +}
279 +
280 +module_init(init);
281 +module_exit(fini);
282 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Kconfig linux/net/ipv4/netfilter/Kconfig
283 --- linux.org/net/ipv4/netfilter/Kconfig        2006-06-18 01:49:35.000000000 +0000
284 +++ linux/net/ipv4/netfilter/Kconfig    2006-08-29 12:32:46.000000000 +0000
285 @@ -613,5 +613,15 @@
286           Allows altering the ARP packet payload: source and destination
287           hardware and network addresses.
288  
289 +config IP_NF_MATCH_CONNLIMIT
290 +       tristate  'Connections/IP limit match support'
291 +       depends on IP_NF_IPTABLES
292 +       help
293 +         This match allows you to restrict the number of parallel TCP
294 +         connections to a server per client IP address (or address block).
295 +       
296 +         If you want to compile it as a module, say M here and read
297 +         Documentation/modules.txt.  If unsure, say `N'.
298 +
299  endmenu
300  
301 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Makefile linux/net/ipv4/netfilter/Makefile
302 --- linux.org/net/ipv4/netfilter/Makefile       2006-06-18 01:49:35.000000000 +0000
303 +++ linux/net/ipv4/netfilter/Makefile   2006-08-29 12:32:46.000000000 +0000
304 @@ -0,0 +0,1 @@
305 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
This page took 0.052357 seconds and 3 git commands to generate.