--- /dev/null
+diff -urN linux-2.4-brcm.orig/Documentation/Configure.help linux-2.4-brcm/Documentation/Configure.help
+--- linux-2.4-brcm.orig/Documentation/Configure.help 2006-12-08 20:40:01.000000000 +0000
++++ linux-2.4-brcm/Documentation/Configure.help 2006-12-08 21:01:59.000000000 +0000
+@@ -3025,6 +3025,21 @@
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
++TARPIT target support
++CONFIG_IP_NF_TARGET_TARPIT
++ Adds a TARPIT target to iptables, which captures and holds
++ incoming TCP connections using no local per-connection resources.
++ Connections are accepted, but immediately switched to the persist
++ state (0 byte window), in which the remote side stops sending data
++ and asks to continue every 60-240 seconds. Attempts to close the
++ connection are ignored, forcing the remote side to time out the
++ connection in 12-24 minutes.
++
++ This offers similar functionality to LaBrea
++ <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
++ hardware or IPs. Any TCP port that you would normally DROP or REJECT
++ can instead become a tarpit.
++
+ REJECT target support
+ CONFIG_IP_NF_TARGET_REJECT
+ The REJECT target allows a filtering rule to specify that an ICMP
+diff -urN linux-2.4-brcm.orig/net/ipv4/netfilter/Config.in linux-2.4-brcm/net/ipv4/netfilter/Config.in
+--- linux-2.4-brcm.orig/net/ipv4/netfilter/Config.in 2006-12-08 20:39:48.000000000 +0000
++++ linux-2.4-brcm/net/ipv4/netfilter/Config.in 2006-12-08 21:01:59.000000000 +0000
+@@ -68,6 +68,7 @@
+ dep_tristate ' REJECT target support' CONFIG_IP_NF_TARGET_REJECT $CONFIG_IP_NF_FILTER
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' MIRROR target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_MIRROR $CONFIG_IP_NF_FILTER
++ dep_tristate ' TARPIT target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_TARPIT $CONFIG_IP_NF_FILTER
+ fi
+ fi
+
+diff -urN linux-2.4-brcm.orig/net/ipv4/netfilter/ipt_TARPIT.c linux-2.4-brcm/net/ipv4/netfilter/ipt_TARPIT.c
+--- linux-2.4-brcm.orig/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4-brcm/net/ipv4/netfilter/ipt_TARPIT.c 2006-12-08 21:01:58.000000000 +0000
+@@ -0,0 +1,284 @@
++/*
++ * Kernel module to capture and hold incoming TCP connections using
++ * no local per-connection resources.
++ *
++ * Based on ipt_REJECT.c and offering functionality similar to
++ * LaBrea <http://www.hackbusters.net/LaBrea/>.
++ *
++ * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Goal:
++ * - Allow incoming TCP connections to be established.
++ * - Passing data should result in the connection being switched to the
++ * persist state (0 byte window), in which the remote side stops sending
++ * data and asks to continue every 60 seconds.
++ * - Attempts to shut down the connection should be ignored completely, so
++ * the remote side ends up having to time it out.
++ *
++ * This means:
++ * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
++ * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
++ * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <net/icmp.h>
++struct in_device;
++#include <net/route.h>
++#include <linux/random.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++
++#if 0
++#define DEBUGP printk
++#else
++#define DEBUGP(format, args...)
++#endif
++
++
++/* Stolen from ip_finish_output2 */
++static int ip_direct_send(struct sk_buff *skb)
++{
++ struct dst_entry *dst = skb->dst;
++ struct hh_cache *hh = dst->hh;
++
++ if (hh) {
++ read_lock_bh(&hh->hh_lock);
++ memcpy(skb->data - 16, hh->hh_data, 16);
++ read_unlock_bh(&hh->hh_lock);
++ skb_push(skb, hh->hh_len);
++ return hh->hh_output(skb);
++ } else if (dst->neighbour)
++ return dst->neighbour->output(skb);
++
++ if (net_ratelimit())
++ printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
++ kfree_skb(skb);
++ return -EINVAL;
++}
++
++
++/* Send reply */
++static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
++{
++ struct sk_buff *nskb;
++ struct rtable *nrt;
++ struct tcphdr *otcph, *ntcph;
++ unsigned int otcplen;
++ u_int16_t tmp;
++
++ /* A truncated TCP header isn't going to be useful */
++ if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
++ return;
++
++ otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
++ + oskb->nh.iph->ihl);
++ otcplen = oskb->len - oskb->nh.iph->ihl*4;
++
++ /* No replies for RST or FIN */
++ if (otcph->rst || otcph->fin)
++ return;
++
++ /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
++ if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
++ return;
++
++ /* Check checksum. */
++ if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
++ oskb->nh.iph->daddr,
++ csum_partial((char *)otcph, otcplen, 0)) != 0)
++ return;
++
++ /* Copy skb (even if skb is about to be dropped, we can't just
++ clone it because there may be other things, such as tcpdump,
++ interested in it) */
++ nskb = skb_copy(oskb, GFP_ATOMIC);
++ if (!nskb)
++ return;
++
++ /* This packet will not be the same as the other: clear nf fields */
++ nf_conntrack_put(nskb->nfct);
++ nskb->nfct = NULL;
++ nskb->nfcache = 0;
++#ifdef CONFIG_NETFILTER_DEBUG
++ nskb->nf_debug = 0;
++#endif
++
++ ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
++
++ /* Truncate to length (no data) */
++ ntcph->doff = sizeof(struct tcphdr)/4;
++ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
++ nskb->nh.iph->tot_len = htons(nskb->len);
++
++ /* Swap source and dest */
++ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
++ tmp = ntcph->source;
++ ntcph->source = ntcph->dest;
++ ntcph->dest = tmp;
++
++ /* Use supplied sequence number or make a new one */
++ ntcph->seq = otcph->ack ? otcph->ack_seq
++ : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
++ nskb->nh.iph->daddr,
++ ntcph->source,
++ ntcph->dest));
++
++ /* Our SYN-ACKs must have a >0 window */
++ ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
++
++ ntcph->urg_ptr = 0;
++
++ /* Reset flags */
++ ((u_int8_t *)ntcph)[13] = 0;
++
++ if (otcph->syn && otcph->ack) {
++ ntcph->rst = 1;
++ ntcph->ack_seq = 0;
++ } else {
++ ntcph->syn = otcph->syn;
++ ntcph->ack = 1;
++ ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
++ }
++
++ /* Adjust TCP checksum */
++ ntcph->check = 0;
++ ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
++ nskb->nh.iph->saddr,
++ nskb->nh.iph->daddr,
++ csum_partial((char *)ntcph,
++ sizeof(struct tcphdr), 0));
++
++ /* Adjust IP TTL */
++ nskb->nh.iph->ttl = sysctl_ip_default_ttl;
++
++ /* Set DF, id = 0 */
++ nskb->nh.iph->frag_off = htons(IP_DF);
++ nskb->nh.iph->id = 0;
++
++ /* Adjust IP checksum */
++ nskb->nh.iph->check = 0;
++ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
++ nskb->nh.iph->ihl);
++
++ if (ip_route_output(&nrt, nskb->nh.iph->daddr,
++ local ? nskb->nh.iph->saddr : 0,
++ RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
++ 0) != 0)
++ goto free_nskb;
++
++ dst_release(nskb->dst);
++ nskb->dst = &nrt->u.dst;
++
++ /* "Never happens" */
++ if (nskb->len > nskb->dst->pmtu)
++ goto free_nskb;
++
++ ip_direct_send (nskb);
++
++ return;
++
++ free_nskb:
++ kfree_skb(nskb);
++}
++
++
++static unsigned int tarpit(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ struct sk_buff *skb = *pskb;
++ struct rtable *rt = (struct rtable*)skb->dst;
++
++ /* Do we have an input route cache entry? */
++ if (!rt)
++ return NF_DROP;
++
++ /* No replies to physical multicast/broadcast */
++ if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
++ return NF_DROP;
++
++ /* Now check at the protocol level */
++ if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
++ return NF_DROP;
++
++ /* Our naive response construction doesn't deal with IP
++ options, and probably shouldn't try. */
++ if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
++ return NF_DROP;
++
++ /* We aren't interested in fragments */
++ if (skb->nh.iph->frag_off & htons(IP_OFFSET))
++ return NF_DROP;
++
++ tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
++
++ return NF_DROP;
++}
++
++
++static int check(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ /* Only allow these for input/forward packet filtering. */
++ if (strcmp(tablename, "filter") != 0) {
++ DEBUGP("TARPIT: bad table %s'.\n", tablename);
++ return 0;
++ }
++ if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
++ | (1 << NF_IP_FORWARD))) != 0) {
++ DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
++ return 0;
++ }
++
++ /* Must specify that it's a TCP packet */
++ if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
++ DEBUGP("TARPIT: not valid for non-tcp\n");
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ipt_target ipt_tarpit_reg
++= { { NULL, NULL }, "TARPIT", tarpit, check, NULL, THIS_MODULE };
++
++static int __init init(void)
++{
++ if (ipt_register_target(&ipt_tarpit_reg))
++ return -EINVAL;
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&ipt_tarpit_reg);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
+diff -urN linux-2.4-brcm.orig/net/ipv4/netfilter/Makefile linux-2.4-brcm/net/ipv4/netfilter/Makefile
+--- linux-2.4-brcm.orig/net/ipv4/netfilter/Makefile 2006-12-08 20:39:48.000000000 +0000
++++ linux-2.4-brcm/net/ipv4/netfilter/Makefile 2006-12-08 21:01:59.000000000 +0000
+@@ -118,6 +118,7 @@
+ obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
+ obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
+ obj-$(CONFIG_IP_NF_TARGET_MIRROR) += ipt_MIRROR.o
++obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
+ obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
+ obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
+ obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
+Package: iptables-mod-tarpit
+Priority: optional
+Section: net
+Depends: kmod-ipt-tarpit
+Description: Iptables (IPv4) extension for tarpit