Patches and isapplied script for reducing bug reports.
diff --git a/patch-test3-pre6-reject-enhancements b/patch-test3-pre6-reject-enhancements
new file mode 100644
index 0000000..a2c679e
--- /dev/null
+++ b/patch-test3-pre6-reject-enhancements
@@ -0,0 +1,305 @@
+diff -urN -X /tmp/fileVB9oIz --minimal tmp/include/linux/netfilter_ipv4/ipt_REJECT.h working-2.4.0-test3-9/include/linux/netfilter_ipv4/ipt_REJECT.h
+--- tmp/include/linux/netfilter_ipv4/ipt_REJECT.h	Tue Mar 28 04:35:56 2000
++++ working-2.4.0-test3-9/include/linux/netfilter_ipv4/ipt_REJECT.h	Tue Jul 11 17:36:54 2000
+@@ -6,7 +6,10 @@
+ 	IPT_ICMP_HOST_UNREACHABLE,
+ 	IPT_ICMP_PROT_UNREACHABLE,
+ 	IPT_ICMP_PORT_UNREACHABLE,
+-	IPT_ICMP_ECHOREPLY
++	IPT_ICMP_ECHOREPLY,
++	IPT_ICMP_NET_PROHIBITED,
++	IPT_ICMP_HOST_PROHIBITED,
++	IPT_TCP_RESET
+ };
+ 
+ struct ipt_reject_info {
+diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/core/netfilter.c working-2.4.0-test3-9/net/core/netfilter.c
+--- tmp/net/core/netfilter.c	Fri Apr 14 10:19:57 2000
++++ working-2.4.0-test3-9/net/core/netfilter.c	Wed Jul 12 12:18:42 2000
+@@ -261,11 +261,11 @@
+ 		if (skb->nf_debug != ((1 << NF_IP_PRE_ROUTING)
+ 				      | (1 << NF_IP_FORWARD)
+ 				      | (1 << NF_IP_POST_ROUTING))) {
+-			/* Fragments will have no owners, but still
+-                           may be local */
+-			if (!(skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET))
+-			    || skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
+-						 | (1 << NF_IP_POST_ROUTING))){
++			/* Fragments, entunnelled packets, TCP RSTs
++                           generated by ipt_REJECT will have no
++                           owners, but still may be local */
++			if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
++					      | (1 << NF_IP_POST_ROUTING))){
+ 				printk("ip_finish_output:"
+ 				       " bad unowned skb = %p: ",skb);
+ 				debug_print_hooks_ip(skb->nf_debug);
+diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ip_conntrack_core.c working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_core.c
+--- tmp/net/ipv4/netfilter/ip_conntrack_core.c	Tue Jul 11 12:08:17 2000
++++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_core.c	Tue Jul 11 17:12:08 2000
+@@ -551,6 +551,7 @@
+ resolve_normal_ct(struct sk_buff *skb,
+ 		  struct ip_conntrack_protocol *proto,
+ 		  int *set_reply,
++		  unsigned int hooknum,
+ 		  enum ip_conntrack_info *ctinfo)
+ {
+ 	struct ip_conntrack_tuple tuple;
+@@ -573,6 +574,21 @@
+ 	if (DIRECTION(h) == IP_CT_DIR_REPLY) {
+ 		/* Reply on unconfirmed connection => unclassifiable */
+ 		if (!(h->ctrack->status & IPS_CONFIRMED)) {
++			/* Exception: local TCP RSTs (generated by
++                           REJECT target). */
++			if (hooknum == NF_IP_LOCAL_OUT
++			    && h->tuple.dst.protonum == IPPROTO_TCP) {
++				const struct tcphdr *tcph
++					= (const struct tcphdr *)
++					((u_int32_t *)skb->nh.iph
++					 + skb->nh.iph->ihl);
++				if (tcph->rst) {
++					*ctinfo	= IP_CT_ESTABLISHED
++						+ IP_CT_IS_REPLY;
++					*set_reply = 0;
++					goto set_skb;
++				}
++			}
+ 			DEBUGP("Reply on unconfirmed connection\n");
+ 			ip_conntrack_put(h->ctrack);
+ 			return NULL;
+@@ -598,6 +614,7 @@
+ 		}
+ 		*set_reply = 0;
+ 	}
++ set_skb:
+ 	skb->nfct = &h->ctrack->infos[*ctinfo];
+ 	return h->ctrack;
+ }
+@@ -669,7 +686,7 @@
+ 	    && icmp_error_track(*pskb, &ctinfo, hooknum))
+ 		return NF_ACCEPT;
+ 
+-	if (!(ct = resolve_normal_ct(*pskb, proto, &set_reply, &ctinfo)))
++	if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo)))
+ 		/* Not valid part of a connection */
+ 		return NF_ACCEPT;
+ 
+diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ip_conntrack_standalone.c working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_standalone.c
+--- tmp/net/ipv4/netfilter/ip_conntrack_standalone.c	Fri Apr 28 08:43:15 2000
++++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_standalone.c	Tue Jul 11 17:12:08 2000
+@@ -169,11 +169,15 @@
+ 			       const struct net_device *out,
+ 			       int (*okfn)(struct sk_buff *))
+ {
+-	/* We've seen it coming out the other side: confirm */
++	/* We've seen it coming out the other side: confirm (only if
++           new packet: REJECT can generate TCP RESET response, or ICMP
++           errors) */
+ 	if ((*pskb)->nfct) {
+ 		struct ip_conntrack *ct
+ 			= (struct ip_conntrack *)(*pskb)->nfct->master;
+-		if (!(ct->status & IPS_CONFIRMED))
++		/* ctinfo is the index of the nfct inside the conntrack */
++		if ((*pskb)->nfct - ct->infos == IP_CT_NEW
++		    && !(ct->status & IPS_CONFIRMED))
+ 			ip_conntrack_confirm(ct);
+ 	}
+ 	return NF_ACCEPT;
+@@ -191,7 +195,8 @@
+ 	if ((*pskb)->nfct) {
+ 		struct ip_conntrack *ct
+ 			= (struct ip_conntrack *)(*pskb)->nfct->master;
+-		if (!(ct->status & IPS_CONFIRMED))
++		if ((*pskb)->nfct - ct->infos == IP_CT_NEW
++		    && !(ct->status & IPS_CONFIRMED))
+ 			ip_conntrack_confirm(ct);
+ 	}
+ 
+diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ip_fw_compat.c working-2.4.0-test3-9/net/ipv4/netfilter/ip_fw_compat.c
+--- tmp/net/ipv4/netfilter/ip_fw_compat.c	Tue Jul 11 12:08:17 2000
++++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_fw_compat.c	Tue Jul 11 17:12:08 2000
+@@ -71,7 +71,8 @@
+ 		struct ip_conntrack *ct
+ 			= (struct ip_conntrack *)skb->nfct->master;
+ 
+-		if (!(ct->status & IPS_CONFIRMED))
++		if (skb->nfct - ct->infos == IP_CT_NEW
++		    && !(ct->status & IPS_CONFIRMED))
+ 			ip_conntrack_confirm(ct);
+ 	}
+ }
+diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ipt_REJECT.c working-2.4.0-test3-9/net/ipv4/netfilter/ipt_REJECT.c
+--- tmp/net/ipv4/netfilter/ipt_REJECT.c	Tue Jun 27 14:52:47 2000
++++ working-2.4.0-test3-9/net/ipv4/netfilter/ipt_REJECT.c	Wed Jul 12 17:46:26 2000
+@@ -7,6 +7,7 @@
+ #include <linux/ip.h>
+ #include <net/icmp.h>
+ #include <net/ip.h>
++#include <net/tcp.h>
+ struct in_device;
+ #include <net/route.h>
+ #include <linux/netfilter_ipv4/ip_tables.h>
+@@ -18,6 +19,113 @@
+ #define DEBUGP(format, args...)
+ #endif
+ 
++/* Send RST reply */
++static void send_reset(struct sk_buff *oldskb)
++{
++	struct sk_buff *nskb;
++	struct tcphdr *tcph;
++	struct rtable *rt;
++	unsigned int tcplen;
++	int needs_ack;
++
++	/* Clone skb (skb is about to be dropped, so we don't care) */
++	nskb = skb_clone(oldskb, 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
++
++	/* IP header checks: fragment, too short. */
++	if (nskb->nh.iph->frag_off & htons(IP_OFFSET)
++	    || nskb->len < (nskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
++		goto free_nskb;
++
++	tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
++	tcplen = nskb->len - nskb->nh.iph->ihl*4;
++
++	/* Check checksum. */
++	if (tcp_v4_check(tcph, tcplen, nskb->nh.iph->saddr,
++			 nskb->nh.iph->daddr,
++			 csum_partial((char *)tcph, tcplen, 0)) != 0)
++		goto free_nskb;
++
++	/* No RST for RST. */
++	if (tcph->rst)
++		goto free_nskb;
++
++	nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
++	tcph->source = xchg(&tcph->dest, tcph->source);
++
++	/* Truncate to length (no data) */
++	tcph->doff = sizeof(struct tcphdr)/4;
++	skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
++
++	if (tcph->ack) {
++		needs_ack = 0;
++		tcph->seq = tcph->ack_seq;
++		tcph->ack_seq = 0;
++	} else {
++		needs_ack = 1;
++		tcph->seq = 0;
++		tcph->ack_seq = htonl(ntohl(tcph->seq) + tcph->syn + tcph->fin
++				      + tcplen - (tcph->doff<<2));
++	}
++
++	/* Reset flags */
++	((u_int8_t *)tcph)[13] = 0;
++	tcph->rst = 1;
++	if (needs_ack)
++		tcph->ack = 1;
++
++	tcph->window = 0;
++	tcph->urg_ptr = 0;
++
++	/* Adjust TCP checksum */
++	tcph->check = 0;
++	tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
++				   nskb->nh.iph->saddr,
++				   nskb->nh.iph->daddr,
++				   csum_partial((char *)tcph,
++						sizeof(struct tcphdr), 0));
++
++	/* Adjust IP TTL, DF */
++	nskb->nh.iph->ttl = MAXTTL;
++	/* 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);
++
++	/* Routing */
++	if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
++			    RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
++			    0) != 0)
++		goto free_nskb;
++
++	dst_release(nskb->dst);
++	nskb->dst = &rt->u.dst;
++
++	/* "Never happens" */
++	if (nskb->len > nskb->dst->pmtu)
++		goto free_nskb;
++
++	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
++		ip_finish_output);
++	return;
++
++ free_nskb:
++	kfree_skb(nskb);
++}
++
+ static unsigned int reject(struct sk_buff **pskb,
+ 			   unsigned int hooknum,
+ 			   const struct net_device *in,
+@@ -43,6 +151,12 @@
+     	case IPT_ICMP_PORT_UNREACHABLE:
+     		icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+     		break;
++    	case IPT_ICMP_NET_PROHIBITED:
++    		icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
++    		break;
++	case IPT_ICMP_HOST_PROHIBITED:
++    		icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
++    		break;
+     	case IPT_ICMP_ECHOREPLY: {
+ 		struct icmphdr *icmph  = (struct icmphdr *)
+ 			((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
+@@ -64,6 +178,9 @@
+ 		}
+ 	}
+ 	break;
++	case IPT_TCP_RESET:
++		send_reset(*pskb);
++		break;
+ 	}
+ 
+ 	return NF_DROP;
+@@ -96,7 +213,7 @@
+ 
+ 	/* Only allow these for packet filtering. */
+ 	if (strcmp(tablename, "filter") != 0) {
+-		DEBUGP("REJECT: bad table `%s'.\n", table);
++		DEBUGP("REJECT: bad table `%s'.\n", tablename);
+ 		return 0;
+ 	}
+ 	if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
+@@ -116,6 +233,18 @@
+ 		/* Must contain ICMP match. */
+ 		if (IPT_MATCH_ITERATE(e, find_ping_match) == 0) {
+ 			DEBUGP("REJECT: ECHOREPLY illegal for non-ping\n");
++			return 0;
++		}
++	} else if (rejinfo->with == IPT_TCP_RESET) {
++		/* Must specify that it's a TCP packet */
++		if (e->ip.proto != IPPROTO_TCP
++		    || (e->ip.invflags & IPT_INV_PROTO)) {
++			DEBUGP("REJECT: TCP_RESET illegal for non-tcp\n");
++			return 0;
++		}
++		/* Only for local input.  Rest is too dangerous. */
++		if ((hook_mask & ~(1 << NF_IP_LOCAL_IN)) != 0) {
++			DEBUGP("REJECT: TCP_RESET only from INPUT\n");
+ 			return 0;
+ 		}
+ 	}