]> git.pld-linux.org Git - packages/kernel.git/blame - pom-ng-connlimit-20060829.patch
- use CUBIC by default:
[packages/kernel.git] / pom-ng-connlimit-20060829.patch
CommitLineData
e282ae16 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
7diff -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 */
23diff -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);
282diff -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
301diff -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.121466 seconds and 4 git commands to generate.