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