SOURCES (LINUX_2_6): linux-2.6-nf-connlimit.patch (NEW) - [base] c...
pluto
pluto at pld-linux.org
Thu Sep 15 09:45:22 CEST 2005
Author: pluto Date: Thu Sep 15 07:45:22 2005 GMT
Module: SOURCES Tag: LINUX_2_6
---- Log message:
- [base] connlimit match.
---- Files affected:
SOURCES:
linux-2.6-nf-connlimit.patch (NONE -> 1.1.2.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/linux-2.6-nf-connlimit.patch
diff -u /dev/null SOURCES/linux-2.6-nf-connlimit.patch:1.1.2.1
--- /dev/null Thu Sep 15 09:45:22 2005
+++ SOURCES/linux-2.6-nf-connlimit.patch Thu Sep 15 09:45:17 2005
@@ -0,0 +1,278 @@
+ include/linux/netfilter_ipv4/ipt_connlimit.h | 12 +
+ net/ipv4/netfilter/Kconfig | 10 +
+ net/ipv4/netfilter/Makefile | 1
+ net/ipv4/netfilter/ipt_connlimit.c | 228 +++++++++++++++++++++++++++
+ 4 files changed, 251 insertions(+)
+
+diff -uNr linux-2.6.13.1/include.orig/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.13.1/include/linux/netfilter_ipv4/ipt_connlimit.h
+--- linux-2.6.13.1/include.orig/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.13.1/include/linux/netfilter_ipv4/ipt_connlimit.h 2005-09-15 09:44:11.684458000 +0200
+@@ -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 -uNr linux-2.6.13.1/net.orig/ipv4/netfilter/ipt_connlimit.c linux-2.6.13.1/net/ipv4/netfilter/ipt_connlimit.c
+--- linux-2.6.13.1/net.orig/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.13.1/net/ipv4/netfilter/ipt_connlimit.c 2005-09-15 09:44:11.688458250 +0200
+@@ -0,0 +1,228 @@
++/*
++ * 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/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,
++ const void *matchinfo,
++ int offset,
++ int *hotdrop)
++{
++ const struct ipt_connlimit_info *info = matchinfo;
++ int connections, match;
++ 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;
++ }
++ match = (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, match ? "yes" : "no");
++#endif
++
++ return match;
++}
++
++static int check(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ struct ipt_connlimit_info *info = matchinfo;
++ int i;
++
++ /* verify size */
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
++ return 0;
++
++ /* 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(void *matchinfo, unsigned int matchinfosize)
++{
++ 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,
++ .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 -uNr linux-2.6.13.1/net.orig/ipv4/netfilter/Kconfig linux-2.6.13.1/net/ipv4/netfilter/Kconfig
+--- linux-2.6.13.1/net.orig/ipv4/netfilter/Kconfig 2005-09-10 04:42:58.000000000 +0200
++++ linux-2.6.13.1/net/ipv4/netfilter/Kconfig 2005-09-15 09:44:11.692458500 +0200
+@@ -692,5 +692,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 -uNr linux-2.6.13.1/net.orig/ipv4/netfilter/Makefile linux-2.6.13.1/net/ipv4/netfilter/Makefile
+--- linux-2.6.13.1/net.orig/ipv4/netfilter/Makefile 2005-09-10 04:42:58.000000000 +0200
++++ linux-2.6.13.1/net/ipv4/netfilter/Makefile 2005-09-15 09:44:11.696458750 +0200
+@@ -0,0 +0,1 @@
++obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
================================================================
More information about the pld-cvs-commit
mailing list