SOURCES (LINUX_2_6): pom-ng-connlimit-20060829.patch (NEW) - new s...

cieciwa cieciwa at pld-linux.org
Tue Aug 29 12:35:38 CEST 2006


Author: cieciwa                      Date: Tue Aug 29 10:35:38 2006 GMT
Module: SOURCES                       Tag: LINUX_2_6
---- Log message:
- new snap of connlimit module.

---- Files affected:
SOURCES:
   pom-ng-connlimit-20060829.patch (NONE -> 1.1.2.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/pom-ng-connlimit-20060829.patch
diff -u /dev/null SOURCES/pom-ng-connlimit-20060829.patch:1.1.2.1
--- /dev/null	Tue Aug 29 12:35:38 2006
+++ SOURCES/pom-ng-connlimit-20060829.patch	Tue Aug 29 12:35:33 2006
@@ -0,0 +1,305 @@
+ include/linux/netfilter_ipv4/ipt_connlimit.h |   12 +
+ net/ipv4/netfilter/Kconfig                   |   10 +
+ net/ipv4/netfilter/Makefile                  |    1 
+ net/ipv4/netfilter/ipt_connlimit.c           |  255 +++++++++++++++++++++++++++
+ 4 files changed, 278 insertions(+)
+
+diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux/include/linux/netfilter_ipv4/ipt_connlimit.h
+--- linux.org/include/linux/netfilter_ipv4/ipt_connlimit.h	1970-01-01 00:00:00.000000000 +0000
++++ linux/include/linux/netfilter_ipv4/ipt_connlimit.h	2006-08-29 12:32:46.000000000 +0000
+@@ -0,0 +1,12 @@
++#ifndef _IPT_CONNLIMIT_H
++#define _IPT_CONNLIMIT_H
++
++struct ipt_connlimit_data;
++
++struct ipt_connlimit_info {
++	int limit;
++	int inverse;
++	u_int32_t mask;
++	struct ipt_connlimit_data *data;
++};
++#endif /* _IPT_CONNLIMIT_H */
+diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ipt_connlimit.c linux/net/ipv4/netfilter/ipt_connlimit.c
+--- linux.org/net/ipv4/netfilter/ipt_connlimit.c	1970-01-01 00:00:00.000000000 +0000
++++ linux/net/ipv4/netfilter/ipt_connlimit.c	2006-08-29 12:32:46.000000000 +0000
+@@ -0,0 +1,255 @@
++/*
++ * netfilter module to limit the number of parallel tcp
++ * connections per IP address.
++ *   (c) 2000 Gerd Knorr <kraxel at bytesex.org>
++ *   Nov 2002: Martin Bene <martin.bene at icomedias.com>:
++ *		only ignore TIME_WAIT or gone connections
++ *
++ * based on ...
++ *
++ * Kernel module to match connection tracking information.
++ * GPL (C) 1999  Rusty Russell (rusty at rustcorp.com.au).
++ */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/version.h>
++#include <linux/list.h>
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++#include <linux/netfilter_ipv4/ip_conntrack_core.h>
++#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_connlimit.h>
++
++#define DEBUG 0
++
++MODULE_LICENSE("GPL");
++
++/* we'll save the tuples of all connections we care about */
++struct ipt_connlimit_conn
++{
++        struct list_head list;
++	struct ip_conntrack_tuple tuple;
++};
++
++struct ipt_connlimit_data {
++	spinlock_t lock;
++	struct list_head iphash[256];
++};
++
++static inline unsigned ipt_iphash(const unsigned addr)
++{
++	return ((addr ^ (addr >> 8) ^ (addr >> 16) ^ (addr >> 24)) & 0xff);
++}
++
++static int count_them(struct ipt_connlimit_data *data,
++		      u_int32_t addr, u_int32_t mask,
++		      struct ip_conntrack *ct)
++{
++#if DEBUG
++	const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
++				     "fin_wait", "time_wait", "close", "close_wait",
++				     "last_ack", "listen" };
++#endif
++	int addit = 1, matches = 0;
++	struct ip_conntrack_tuple tuple;
++	struct ip_conntrack_tuple_hash *found;
++	struct ipt_connlimit_conn *conn;
++	struct list_head *hash,*lh;
++
++	spin_lock_bh(&data->lock);
++	tuple = ct->tuplehash[0].tuple;
++	hash = &data->iphash[ipt_iphash(addr & mask)];
++
++	/* check the saved connections */
++	for (lh = hash->next; lh != hash; lh = lh->next) {
++		struct ip_conntrack *found_ct = NULL;
++		conn = list_entry(lh,struct ipt_connlimit_conn,list);
++		found = ip_conntrack_find_get(&conn->tuple,ct);
++		 if (found != NULL 
++		     && (found_ct = tuplehash_to_ctrack(found)) != NULL
++		     && 0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) 
++		     && found_ct->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
++			/* Just to be sure we have it only once in the list.
++			   We should'nt see tuples twice unless someone hooks this
++			   into a table without "-p tcp --syn" */
++			addit = 0;
++		}
++#if DEBUG
++		printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
++		       ipt_iphash(addr & mask),
++		       NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
++		       NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
++		       (NULL != found) ? tcp[found_ct->proto.tcp.state] : "gone");
++#endif
++		if (NULL == found) {
++			/* this one is gone */
++			lh = lh->prev;
++			list_del(lh->next);
++			kfree(conn);
++			continue;
++		}
++		if (found_ct->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
++			/* we don't care about connections which are
++			   closed already -> ditch it */
++			lh = lh->prev;
++			list_del(lh->next);
++			kfree(conn);
++			nf_conntrack_put(&found_ct->ct_general);
++			continue;
++		}
++		if ((addr & mask) == (conn->tuple.src.ip & mask)) {
++			/* same source IP address -> be counted! */
++			matches++;
++		}
++		nf_conntrack_put(&found_ct->ct_general);
++	}
++	if (addit) {
++		/* save the new connection in our list */
++#if DEBUG
++		printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
++		       ipt_iphash(addr & mask),
++		       NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
++		       NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
++#endif
++		conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
++		if (NULL == conn) {
++			spin_unlock_bh(&data->lock);
++			return -1;
++		}
++		memset(conn,0,sizeof(*conn));
++		INIT_LIST_HEAD(&conn->list);
++		conn->tuple = tuple;
++		list_add(&conn->list,hash);
++		matches++;
++	}
++	spin_unlock_bh(&data->lock);
++	return matches;
++}
++
++static int
++match(const struct sk_buff *skb,
++      const struct net_device *in,
++      const struct net_device *out,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
++      const struct xt_match *match,
++#endif
++      const void *matchinfo,
++      int offset,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++      unsigned int protoff,
++#endif
++      int *hotdrop)
++{
++	const struct ipt_connlimit_info *info = matchinfo;
++	int connections, rv;
++	struct ip_conntrack *ct;
++	enum ip_conntrack_info ctinfo;
++
++	ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
++	if (NULL == ct) {
++		printk("ipt_connlimit: Oops: invalid ct state ?\n");
++		*hotdrop = 1;
++		return 0;
++	}
++	connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
++	if (-1 == connections) {
++		printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
++		*hotdrop = 1; /* let's free some memory :-) */
++		return 0;
++	}
++        rv = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
++#if DEBUG
++	printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
++	       "connections=%d limit=%d match=%s\n",
++	       NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
++	       connections, info->limit, rv?"yes":"no");
++#endif
++
++	return rv;
++}
++
++static int check(const char *tablename,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++		 const void *ip_void,
++#else
++		 const struct ipt_ip *ip,
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
++		 const struct xt_match *match,
++#endif
++		 void *matchinfo,
++		 unsigned int matchsize,
++		 unsigned int hook_mask)
++{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++	const struct ipt_ip *ip = ip_void;
++#endif
++
++	struct ipt_connlimit_info *info = matchinfo;
++	int i;
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
++	/* verify size */
++	if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
++		return 0;
++#endif
++
++	/* refuse anything but tcp */
++	if (ip->proto != IPPROTO_TCP)
++		return 0;
++
++	/* init private data */
++	info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
++	spin_lock_init(&(info->data->lock));
++	for (i = 0; i < 256; i++)
++		INIT_LIST_HEAD(&(info->data->iphash[i]));
++	
++	return 1;
++}
++
++static void destroy(
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
++		    const struct xt_match *match,
++#endif
++		    void *matchinfo, unsigned int matchsize)
++{
++	struct ipt_connlimit_info *info = matchinfo;
++	struct ipt_connlimit_conn *conn;
++	struct list_head *hash;
++	int i;
++
++	/* cleanup */
++	for (i = 0; i < 256; i++) {
++		hash = &(info->data->iphash[i]);
++		while (hash != hash->next) {
++			conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
++			list_del(hash->next);
++			kfree(conn);
++		}
++	}
++	kfree(info->data);
++}
++
++static struct ipt_match connlimit_match = { 
++	.name		= "connlimit",
++	.match		= &match,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
++	.matchsize	= sizeof(struct ipt_connlimit_info),
++#endif
++	.checkentry	= &check,
++	.destroy	= &destroy,
++	.me		= THIS_MODULE
++};
++
++static int __init init(void)
++{
++	return ipt_register_match(&connlimit_match);
++}
++
++static void __exit fini(void)
++{
++	ipt_unregister_match(&connlimit_match);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Kconfig linux/net/ipv4/netfilter/Kconfig
+--- linux.org/net/ipv4/netfilter/Kconfig	2006-06-18 01:49:35.000000000 +0000
++++ linux/net/ipv4/netfilter/Kconfig	2006-08-29 12:32:46.000000000 +0000
+@@ -613,5 +613,15 @@
+ 	  Allows altering the ARP packet payload: source and destination
+ 	  hardware and network addresses.
+ 
++config IP_NF_MATCH_CONNLIMIT
++	tristate  'Connections/IP limit match support'
++	depends on IP_NF_IPTABLES
++	help
++	  This match allows you to restrict the number of parallel TCP
++	  connections to a server per client IP address (or address block).
++	
++	  If you want to compile it as a module, say M here and read
++	  Documentation/modules.txt.  If unsure, say `N'.
++
+ endmenu
+ 
+diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Makefile linux/net/ipv4/netfilter/Makefile
+--- linux.org/net/ipv4/netfilter/Makefile	2006-06-18 01:49:35.000000000 +0000
++++ linux/net/ipv4/netfilter/Makefile	2006-08-29 12:32:46.000000000 +0000
+@@ -0,0 +0,1 @@
++obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
================================================================


More information about the pld-cvs-commit mailing list