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