1 diff -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
5 +#ifndef _IPT_CONNLIMIT_H
6 +#define _IPT_CONNLIMIT_H
8 +struct ipt_connlimit_data;
10 +struct ipt_connlimit_info {
14 + struct ipt_connlimit_data *data;
16 +#endif /* _IPT_CONNLIMIT_H */
17 diff -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
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
30 + * Kernel module to match connection tracking information.
31 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
33 +#include <linux/module.h>
34 +#include <linux/skbuff.h>
35 +#include <linux/version.h>
36 +#include <linux/list.h>
38 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
39 +#define CONFIG_NF_CONNTRACK_SUPPORT
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>
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>
52 +#include <linux/netfilter_ipv4/ip_tables.h>
53 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
57 +MODULE_LICENSE("GPL");
59 +/* we'll save the tuples of all connections we care about */
60 +struct ipt_connlimit_conn
62 + struct list_head list;
63 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
64 + struct ip_conntrack_tuple tuple;
66 + struct nf_conntrack_tuple tuple;
70 +struct ipt_connlimit_data {
72 + struct list_head iphash[256];
75 +static inline unsigned ipt_iphash(const unsigned addr)
77 + return ((addr ^ (addr >> 8) ^ (addr >> 16) ^ (addr >> 24)) & 0xff);
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)
90 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
91 + "fin_wait", "time_wait", "close", "close_wait",
92 + "last_ack", "listen" };
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;
99 + struct nf_conntrack_tuple tuple;
100 + struct nf_conntrack_tuple_hash *found;
102 + struct ipt_connlimit_conn *conn;
103 + struct list_head *hash,*lh;
105 + spin_lock_bh(&data->lock);
106 + tuple = ct->tuplehash[0].tuple;
107 + hash = &data->iphash[ipt_iphash(addr & mask)];
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);
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);
122 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
123 + && (found_ct = tuplehash_to_ctrack(found)) != NULL
125 + && (found_ct = nf_ct_tuplehash_to_ctrack(found)) != NULL
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" */
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),
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),
144 + (NULL != found) ? tcp[found_ct->proto.tcp.state] : "gone");
146 + if (NULL == found) {
147 + /* this one is gone */
149 + list_del(lh->next);
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 */
157 + list_del(lh->next);
159 + nf_conntrack_put(&found_ct->ct_general);
162 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
163 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
165 + if ((addr & mask) == (conn->tuple.src.u3.ip & mask)) {
167 + /* same source IP address -> be counted! */
170 + nf_conntrack_put(&found_ct->ct_general);
173 + /* save the new connection in our list */
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));
181 + NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
182 + NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
186 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
187 + if (NULL == conn) {
188 + spin_unlock_bh(&data->lock);
191 + memset(conn,0,sizeof(*conn));
192 + INIT_LIST_HEAD(&conn->list);
193 + conn->tuple = tuple;
194 + list_add(&conn->list,hash);
197 + spin_unlock_bh(&data->lock);
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,
208 + const void *matchinfo,
210 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
211 + unsigned int protoff,
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;
221 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
223 + struct nf_conn *ct;
224 + enum ip_conntrack_info ctinfo;
226 + ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
229 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
234 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
235 + connections = count_them(info->data, ip_hdr(skb)->saddr, info->mask, ct);
237 + connections = count_them(info->data, skb->nh.iph->saddr, info->mask, ct);
239 + if (-1 == connections) {
240 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
241 + *hotdrop = 1; /* let's free some memory :-) */
244 + rv = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
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");
255 +static int checkentry(const char *tablename,
256 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
257 + const void *ip_void,
259 + const struct ipt_ip *ip,
261 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
262 + const struct xt_match *match,
265 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
266 + unsigned int matchsize,
268 + unsigned int hook_mask)
270 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
271 + const struct ipt_ip *ip = ip_void;
274 + struct ipt_connlimit_info *info = matchinfo;
277 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
279 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
283 + /* refuse anything but tcp */
284 + if (ip->proto != IPPROTO_TCP)
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]));
296 +static void destroy(
297 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
298 + const struct xt_match *match,
300 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
301 + void *matchinfo, unsigned int matchsize)
306 + struct ipt_connlimit_info *info = matchinfo;
307 + struct ipt_connlimit_conn *conn;
308 + struct list_head *hash;
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);
323 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
324 +static struct xt_match connlimit_match = {
326 +static struct ipt_match connlimit_match = {
328 + .name = "connlimit",
329 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
333 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
334 + .matchsize = sizeof(struct ipt_connlimit_info),
336 + .checkentry = &checkentry,
337 + .destroy = &destroy,
341 +static int __init init(void)
343 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
344 + return xt_register_match(&connlimit_match);
346 + return ipt_register_match(&connlimit_match);
350 +static void __exit fini(void)
352 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
353 + xt_unregister_match(&connlimit_match);
355 + ipt_unregister_match(&connlimit_match);
361 diff -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
365 Allows altering the ARP packet payload: source and destination
366 hardware and network addresses.
368 +config IP_NF_MATCH_CONNLIMIT
369 + tristate 'Connections/IP limit match support'
370 + depends on IP_NF_IPTABLES
372 + This match allows you to restrict the number of parallel TCP
373 + connections to a server per client IP address (or address block).
375 + If you want to compile it as a module, say M here and read
376 + Documentation/modules.txt. If unsure, say `N'.
380 diff -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
384 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
386 obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
387 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
389 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
390 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o