diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/Makefile linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/Makefile
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/Makefile	2001-04-26 00:00:28.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/Makefile	2004-12-05 18:20:15.000000000 +0100
@@ -30,6 +30,9 @@
 
 # connection tracking
 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
+# IRC support
+obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
+obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
 
 # connection tracking helpers
 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_conntrack_core.c	2001-04-27 23:15:01.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_conntrack_core.c	2004-12-05 18:20:15.000000000 +0100
@@ -356,7 +356,7 @@
 	inner = (struct iphdr *)(hdr + 1);
 	datalen = skb->len - iph->ihl*4 - sizeof(*hdr);
 
-	if (skb->len < iph->ihl * 4 + sizeof(struct icmphdr)) {
+	if (skb->len < iph->ihl * 4 + sizeof(*hdr) + sizeof(*iph)) {
 		DEBUGP("icmp_error_track: too short\n");
 		return NULL;
 	}
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_conntrack_standalone.c	2001-04-27 23:15:01.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-12-05 18:20:15.000000000 +0100
@@ -226,6 +226,7 @@
 
 static int init_or_cleanup(int init)
 {
+	struct proc_dir_entry *proc;
 	int ret = 0;
 
 	if (!init) goto cleanup;
@@ -234,11 +235,14 @@
 	if (ret < 0)
 		goto cleanup_nothing;
 
-	proc_net_create("ip_conntrack",0,list_conntracks);
+	proc = proc_net_create("ip_conntrack",0,list_conntracks);
+	if (!proc) goto cleanup_init;
+	proc->owner = THIS_MODULE;
+
 	ret = nf_register_hook(&ip_conntrack_in_ops);
 	if (ret < 0) {
 		printk("ip_conntrack: can't register in hook.\n");
-		goto cleanup_init;
+		goto cleanup_proc;
 	}
 	ret = nf_register_hook(&ip_conntrack_local_out_ops);
 	if (ret < 0) {
@@ -266,8 +270,9 @@
 	nf_unregister_hook(&ip_conntrack_local_out_ops);
  cleanup_inops:
 	nf_unregister_hook(&ip_conntrack_in_ops);
- cleanup_init:
+ cleanup_proc:
 	proc_net_remove("ip_conntrack");
+ cleanup_init:
 	ip_conntrack_cleanup();
  cleanup_nothing:
 	return ret;
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_fw_compat.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_fw_compat.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_fw_compat.c	2001-04-27 23:15:01.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_fw_compat.c	2004-12-05 18:20:15.000000000 +0100
@@ -47,6 +47,10 @@
 extern int __init masq_init(void);
 extern void masq_cleanup(void);
 
+/* From ip_vs_core.c */
+extern unsigned int
+check_for_ip_vs_out(struct sk_buff **skb_p, int (*okfn)(struct sk_buff *));
+
 /* They call these; we do what they want. */
 int register_firewall(int pf, struct firewall_ops *fw)
 {
@@ -162,8 +166,14 @@
 		return NF_ACCEPT;
 
 	case FW_MASQUERADE:
-		if (hooknum == NF_IP_FORWARD)
+		if (hooknum == NF_IP_FORWARD) {
+#ifdef CONFIG_IP_VS
+                        /* check if it is for ip_vs */
+                        if (check_for_ip_vs_out(pskb, okfn) == NF_STOLEN)
+                                return NF_STOLEN;
+#endif
 			return do_masquerade(pskb, out);
+                }
 		else return NF_ACCEPT;
 
 	case FW_REDIRECT:
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_fw_compat_masq.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_fw_compat_masq.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_fw_compat_masq.c	2000-09-19 00:09:55.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_fw_compat_masq.c	2004-12-05 18:20:15.000000000 +0100
@@ -14,6 +14,7 @@
 #include <linux/inetdevice.h>
 #include <linux/proc_fs.h>
 #include <linux/version.h>
+#include <linux/module.h>
 #include <net/route.h>
 
 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
@@ -302,13 +303,22 @@
 int __init masq_init(void)
 {
 	int ret;
+	struct proc_dir_entry *proc;
 
 	ret = ip_conntrack_init();
 	if (ret == 0) {
 		ret = ip_nat_init();
-		if (ret == 0)
-			proc_net_create("ip_masquerade", 0, masq_procinfo);
-		else
+		if (ret == 0) {
+			proc = proc_net_create("ip_masquerade",
+					       0, masq_procinfo);
+			if (proc)
+				proc->owner = THIS_MODULE;
+			else {
+				ip_nat_cleanup();
+				ip_conntrack_cleanup();
+				ret = -ENOMEM;
+			}
+		} else
 			ip_conntrack_cleanup();
 	}
 
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_nat_proto_tcp.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_nat_proto_tcp.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_nat_proto_tcp.c	2000-03-17 19:56:20.000000000 +0100
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_nat_proto_tcp.c	2004-12-05 18:20:15.000000000 +0100
@@ -92,10 +92,17 @@
 		oldip = iph->daddr;
 		portptr = &hdr->dest;
 	}
-	hdr->check = ip_nat_cheat_check(~oldip, manip->ip,
+
+	/* this could be a inner header returned in icmp packet; in such
+	   cases we cannot update the checksum field since it is outside of
+	   the 8 bytes of transport layer headers we are guaranteed */
+	if(((void *)&hdr->check + sizeof(hdr->check) - (void *)iph) <= len) {
+		hdr->check = ip_nat_cheat_check(~oldip, manip->ip,
 					ip_nat_cheat_check(*portptr ^ 0xFFFF,
 							   manip->u.tcp.port,
 							   hdr->check));
+	}
+
 	*portptr = manip->u.tcp.port;
 }
 
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_queue.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_queue.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_queue.c	2000-12-11 21:37:04.000000000 +0100
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_queue.c	2004-12-05 18:20:15.000000000 +0100
@@ -24,19 +24,28 @@
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
 #include <net/sock.h>
+#include <net/route.h>
 
 #include <linux/netfilter_ipv4/ip_queue.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
 
 #define IPQ_QMAX_DEFAULT 1024
 #define IPQ_PROC_FS_NAME "ip_queue"
 #define NET_IPQ_QMAX 2088
 #define NET_IPQ_QMAX_NAME "ip_queue_maxlen"
 
+typedef struct ipq_rt_info {
+	__u8 tos;
+	__u32 daddr;
+	__u32 saddr;
+} ipq_rt_info_t;
+
 typedef struct ipq_queue_element {
 	struct list_head list;		/* Links element into queue */
 	int verdict;			/* Current verdict */
 	struct nf_info *info;		/* Extra info from netfilter */
 	struct sk_buff *skb;		/* Packet inside */
+	ipq_rt_info_t rt_info;		/* May need post-mangle routing */
 } ipq_queue_element_t;
 
 typedef int (*ipq_send_cb_t)(ipq_queue_element_t *e);
@@ -64,7 +73,6 @@
  * Packet queue
  *
  ****************************************************************************/
-
 /* Dequeue a packet if matched by cmp, or the next available if cmp is NULL */
 static ipq_queue_element_t *
 ipq_dequeue(ipq_queue_t *q,
@@ -150,9 +158,19 @@
 		printk(KERN_ERR "ip_queue: OOM in enqueue\n");
 		return -ENOMEM;
 	}
+
 	e->verdict = NF_DROP;
 	e->info = info;
 	e->skb = skb;
+
+	if (e->info->hook == NF_IP_LOCAL_OUT) {
+		struct iphdr *iph = skb->nh.iph;
+
+		e->rt_info.tos = iph->tos;
+		e->rt_info.daddr = iph->daddr;
+		e->rt_info.saddr = iph->saddr;
+	}
+
 	spin_lock_bh(&q->lock);
 	if (q->len >= *q->maxlen) {
 		spin_unlock_bh(&q->lock);
@@ -198,6 +216,32 @@
 	kfree(q);
 }
 
+/* With a chainsaw... */
+static int route_me_harder(struct sk_buff *skb)
+{
+	struct iphdr *iph = skb->nh.iph;
+	struct rtable *rt;
+
+	struct rt_key key = {
+				dst:iph->daddr, src:iph->saddr,
+				oif:skb->sk ? skb->sk->bound_dev_if : 0,
+				tos:RT_TOS(iph->tos)|RTO_CONN,
+#ifdef CONFIG_IP_ROUTE_FWMARK
+				fwmark:skb->nfmark
+#endif
+			};
+
+	if (ip_route_output_key(&rt, &key) != 0) {
+		printk("route_me_harder: No more route.\n");
+		return -EINVAL;
+	}
+
+	/* Drop old route. */
+	dst_release(skb->dst);
+	skb->dst = &rt->u.dst;
+	return 0;
+}
+
 static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, ipq_queue_element_t *e)
 {
 	int diff;
@@ -223,6 +267,8 @@
 				      "in mangle, dropping packet\n");
 				return -ENOMEM;
 			}
+			if (e->skb->sk)
+				skb_set_owner_w(newskb, e->skb->sk);
 			kfree_skb(e->skb);
 			e->skb = newskb;
 		}
@@ -230,6 +276,19 @@
 	}
 	memcpy(e->skb->data, v->payload, v->data_len);
 	e->skb->nfcache |= NFC_ALTERED;
+
+	/*
+	 * Extra routing may needed on local out, as the QUEUE target never
+	 * returns control to the table.
+	 */
+	if (e->info->hook == NF_IP_LOCAL_OUT) {
+		struct iphdr *iph = e->skb->nh.iph;
+
+		if (!(iph->tos == e->rt_info.tos
+		      && iph->daddr == e->rt_info.daddr
+		      && iph->saddr == e->rt_info.saddr))
+			return route_me_harder(e->skb);
+	}
 	return 0;
 }
 
@@ -400,6 +459,13 @@
 	if (e->info->outdev) strcpy(pm->outdev_name, e->info->outdev->name);
 	else pm->outdev_name[0] = '\0';
 	pm->hw_protocol = e->skb->protocol;
+	if (e->info->indev && e->skb->dev) {
+		pm->hw_type = e->skb->dev->type;
+		if (e->skb->dev->hard_header_parse)
+			pm->hw_addrlen =
+				e->skb->dev->hard_header_parse(e->skb,
+				                               pm->hw_addr);
+	}
 	if (data_len)
 		memcpy(pm->payload, e->skb->data, data_len);
 	nlh->nlmsg_len = skb->tail - old_tail;
@@ -426,15 +492,20 @@
 
 #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0);
 
-extern __inline__ void netlink_receive_user_skb(struct sk_buff *skb)
+static __inline__ void netlink_receive_user_skb(struct sk_buff *skb)
 {
 	int status, type;
 	struct nlmsghdr *nlh;
 
+	if (skb->len < sizeof(struct nlmsghdr))
+		return;
+
 	nlh = (struct nlmsghdr *)skb->data;
-	if (nlh->nlmsg_len < sizeof(*nlh)
-	    || skb->len < nlh->nlmsg_len
-	    || nlh->nlmsg_pid <= 0
+	if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
+	    || skb->len < nlh->nlmsg_len)
+	    	return;
+
+	if(nlh->nlmsg_pid <= 0
 	    || !(nlh->nlmsg_flags & NLM_F_REQUEST)
 	    || nlh->nlmsg_flags & NLM_F_MULTI)
 		RCV_SKB_FAIL(-EINVAL);
@@ -576,6 +647,7 @@
 static int __init init(void)
 {
 	int status = 0;
+	struct proc_dir_entry *proc;
 	
 	nfnl = netlink_kernel_create(NETLINK_FIREWALL, netlink_receive_user_sk);
 	if (nfnl == NULL) {
@@ -591,8 +663,14 @@
 		sock_release(nfnl->socket);
 		return status;
 	}
+	proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info);
+	if (proc) proc->owner = THIS_MODULE;
+	else {
+		ipq_destroy_queue(nlq);
+		sock_release(nfnl->socket);
+		return -ENOMEM;
+	}
 	register_netdevice_notifier(&ipq_dev_notifier);
-	proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info);
 	ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
 	return status;
 }
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_tables.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_tables.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ip_tables.c	2001-05-15 10:29:35.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ip_tables.c	2004-12-05 18:20:15.000000000 +0100
@@ -1730,10 +1730,16 @@
 	}
 
 #ifdef CONFIG_PROC_FS
-	if (!proc_net_create("ip_tables_names", 0, ipt_get_tables)) {
+	{
+	struct proc_dir_entry *proc;
+
+	proc = proc_net_create("ip_tables_names", 0, ipt_get_tables);
+	if (!proc) {
 		nf_unregister_sockopt(&ipt_sockopts);
 		return -ENOMEM;
 	}
+	proc->owner = THIS_MODULE;
+	}
 #endif
 
 	printk("ip_tables: (c)2000 Netfilter core team\n");
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ipchains_core.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ipchains_core.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ipchains_core.c	2001-04-12 21:11:39.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ipchains_core.c	2004-12-05 18:20:15.000000000 +0100
@@ -74,6 +74,7 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/module.h>
 
 #include <linux/socket.h>
 #include <linux/sockios.h>
@@ -1100,9 +1101,9 @@
 {
 	unsigned int i;
 	struct ip_chain *label
-		= kmalloc(SIZEOF_STRUCT_IP_CHAIN, GFP_KERNEL);
+		= kmalloc(SIZEOF_STRUCT_IP_CHAIN, GFP_ATOMIC);
 	if (label == NULL)
-		panic("Can't kmalloc for firewall chains.\n");
+		return NULL;
 	strcpy(label->label,name);
 	label->next = NULL;
 	label->chain = NULL;
@@ -1140,7 +1141,7 @@
 					      * user defined chain *
 					      * and therefore can be
 					      * deleted */
-	return 0;
+	return tmp->next ? 0 : ENOMEM;
 }
 
 /* This function simply changes the policy on one of the built in
@@ -1706,11 +1707,10 @@
 
 int ipfw_init_or_cleanup(int init)
 {
+	struct proc_dir_entry *proc;
 	int ret = 0;
 	unsigned long flags;
 
-	FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags);
-
 	if (!init) goto cleanup;
 
 #ifdef DEBUG_IP_FIREWALL_LOCKING
@@ -1727,17 +1727,24 @@
 	if (ret < 0)
 		goto cleanup_netlink;
 
-	proc_net_create(IP_FW_PROC_CHAINS, S_IFREG | S_IRUSR | S_IWUSR, ip_chain_procinfo);
-	proc_net_create(IP_FW_PROC_CHAIN_NAMES, S_IFREG | S_IRUSR | S_IWUSR, ip_chain_name_procinfo);
+	proc = proc_net_create(IP_FW_PROC_CHAINS, S_IFREG | S_IRUSR | S_IWUSR,
+			       ip_chain_procinfo);
+	if (proc) proc->owner = THIS_MODULE;
+	proc = proc_net_create(IP_FW_PROC_CHAIN_NAMES,
+			       S_IFREG | S_IRUSR | S_IWUSR,
+			       ip_chain_name_procinfo);
+	if (proc) proc->owner = THIS_MODULE;
 
 	IP_FW_INPUT_CHAIN = ip_init_chain(IP_FW_LABEL_INPUT, 1, FW_ACCEPT);
 	IP_FW_FORWARD_CHAIN = ip_init_chain(IP_FW_LABEL_FORWARD, 1, FW_ACCEPT);
 	IP_FW_OUTPUT_CHAIN = ip_init_chain(IP_FW_LABEL_OUTPUT, 1, FW_ACCEPT);
 
-	FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
 	return ret;
 
  cleanup:
+	unregister_firewall(PF_INET, &ipfw_ops);
+
+	FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags);
 	while (ip_fw_chains) {
 		struct ip_chain *next = ip_fw_chains->next;
 
@@ -1745,18 +1752,16 @@
 		kfree(ip_fw_chains);
 		ip_fw_chains = next;
 	}
+	FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
 
 	proc_net_remove(IP_FW_PROC_CHAINS);
 	proc_net_remove(IP_FW_PROC_CHAIN_NAMES);
 
-	unregister_firewall(PF_INET, &ipfw_ops);
-
  cleanup_netlink:
 #if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
 	sock_release(ipfwsk->socket);
 
  cleanup_nothing:
 #endif
-	FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
 	return ret;
 }
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ipfwadm_core.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ipfwadm_core.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ipfwadm_core.c	2001-06-12 04:15:27.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ipfwadm_core.c	2004-12-05 18:20:15.000000000 +0100
@@ -3,6 +3,7 @@
 */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #define CONFIG_IP_FIREWALL
 #define CONFIG_IP_FIREWALL_VERBOSE
 #define CONFIG_IP_MASQUERADE
@@ -1358,6 +1359,7 @@
 
 int ipfw_init_or_cleanup(int init)
 {
+	struct proc_dir_entry *proc;
 	int ret = 0;
 
 	if (!init)
@@ -1368,11 +1370,15 @@
 		goto cleanup_nothing;
 
 #ifdef CONFIG_IP_ACCT
-	proc_net_create("ip_acct", S_IFREG | S_IRUGO | S_IWUSR, ip_acct_procinfo);
+	proc = proc_net_create("ip_acct", S_IFREG | S_IRUGO | S_IWUSR, ip_acct_procinfo);
+	if (proc) proc->owner = THIS_MODULE;
 #endif
-	proc_net_create("ip_input", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_in_procinfo);
-	proc_net_create("ip_output", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_out_procinfo);
-	proc_net_create("ip_forward", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_fwd_procinfo);
+	proc = proc_net_create("ip_input", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_in_procinfo);
+	if (proc) proc->owner = THIS_MODULE;
+	proc = proc_net_create("ip_output", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_out_procinfo);
+	if (proc) proc->owner = THIS_MODULE;
+	proc = proc_net_create("ip_forward", S_IFREG | S_IRUGO | S_IWUSR, ip_fw_fwd_procinfo);
+	if (proc) proc->owner = THIS_MODULE;
 
 	/* Register for device up/down reports */
 	register_netdevice_notifier(&ipfw_dev_notifier);
@@ -1383,6 +1389,7 @@
 	return ret;
 
  cleanup:
+	unregister_firewall(PF_INET, &ipfw_ops);
 #ifdef CONFIG_IP_FIREWALL_NETLINK
 	sock_release(ipfwsk->socket);
 #endif
@@ -1400,8 +1407,6 @@
 	free_fw_chain(chains[IP_FW_OUT]);
 	free_fw_chain(chains[IP_FW_ACCT]);
 
-	unregister_firewall(PF_INET, &ipfw_ops);
-
  cleanup_nothing:
 	return ret;
 }
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ipt_unclean.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ipt_unclean.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/ipt_unclean.c	2001-06-21 01:05:21.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/ipt_unclean.c	2004-12-05 18:20:15.000000000 +0100
@@ -268,6 +268,7 @@
 	  int embedded)
 {
 	u_int8_t *opt = (u_int8_t *)tcph;
+	u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
 	u_int8_t tcpflags;
 	int end_of_options = 0;
 	size_t i;
@@ -330,6 +331,7 @@
 	tcpflags = ((u_int8_t *)tcph)[13];
 	if (tcpflags != TH_SYN
 	    && tcpflags != (TH_SYN|TH_ACK)
+	    && tcpflags != TH_RST
 	    && tcpflags != (TH_RST|TH_ACK)
 	    && tcpflags != (TH_RST|TH_ACK|TH_PUSH)
 	    && tcpflags != (TH_FIN|TH_ACK)
@@ -373,7 +375,7 @@
 				return 0;
 			}
 			/* CHECK: oversize options. */
-			else if (opt[i+1] + i >= tcph->doff * 4) {
+			else if (&opt[i] + opt[i+1] > endhdr) {
 				limpk("TCP option %u at %Zu too long\n",
 				      (unsigned int) opt[i], i);
 				return 0;
@@ -392,6 +394,7 @@
 check_ip(struct iphdr *iph, size_t length, int embedded)
 {
 	u_int8_t *opt = (u_int8_t *)iph;
+	u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
 	int end_of_options = 0;
 	void *protoh;
 	size_t datalen;
@@ -444,7 +447,7 @@
 				return 0;
 			}
 			/* CHECK: oversize options. */
-			else if (opt[i+1] + i > iph->ihl * 4) {
+			else if (&opt[i] + opt[i+1] > endhdr) {
 				limpk("IP option %u at %u too long\n",
 				      opt[i], i);
 				return 0;
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/iptable_mangle.c linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/iptable_mangle.c
--- linux-2.4.6.uc0pre0.orig/net/ipv4/netfilter/iptable_mangle.c	2001-01-29 17:07:30.000000000 +0100
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv4/netfilter/iptable_mangle.c	2004-12-05 18:20:15.000000000 +0100
@@ -148,7 +148,7 @@
 
 	ret = ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL);
 	/* Reroute for ANY change. */
-	if (ret != NF_DROP && ret != NF_STOLEN
+	if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
 	    && ((*pskb)->nh.iph->saddr != saddr
 		|| (*pskb)->nh.iph->daddr != daddr
 		|| (*pskb)->nfmark != nfmark
diff -ur linux-2.4.6.uc0pre0.orig/net/ipv6/netfilter/ip6t_MARK.c linux-2.4.6.uc0pre0.actiontec/net/ipv6/netfilter/ip6t_MARK.c
--- linux-2.4.6.uc0pre0.orig/net/ipv6/netfilter/ip6t_MARK.c	2001-01-22 22:30:21.000000000 +0100
+++ linux-2.4.6.uc0pre0.actiontec/net/ipv6/netfilter/ip6t_MARK.c	2004-12-05 18:20:15.000000000 +0100
@@ -1,66 +1,49 @@
-/* This is a module which is used for setting the NFMARK field of an skb. */
+/* Kernel module to match NFMARK values. */
 #include <linux/module.h>
 #include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <net/checksum.h>
 
+#include <linux/netfilter_ipv6/ip6t_mark.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_MARK.h>
 
-static unsigned int
-target(struct sk_buff **pskb,
-       unsigned int hooknum,
-       const struct net_device *in,
-       const struct net_device *out,
-       const void *targinfo,
-       void *userinfo)
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      const void *hdr,
+      u_int16_t datalen,
+      int *hotdrop)
 {
-	const struct ip6t_mark_target_info *markinfo = targinfo;
+	const struct ip6t_mark_info *info = matchinfo;
 
-	if((*pskb)->nfmark != markinfo->mark) {
-		(*pskb)->nfmark = markinfo->mark;
-		(*pskb)->nfcache |= NFC_ALTERED;
-	}
-	return IP6T_CONTINUE;
+	return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
 }
 
 static int
 checkentry(const char *tablename,
-	   const struct ip6t_entry *e,
-           void *targinfo,
-           unsigned int targinfosize,
+           const struct ip6t_ip6 *ip,
+           void *matchinfo,
+           unsigned int matchsize,
            unsigned int hook_mask)
 {
-	if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))) {
-		printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
-		       targinfosize,
-		       IP6T_ALIGN(sizeof(struct ip6t_mark_target_info)));
-		return 0;
-	}
-
-	if (strcmp(tablename, "mangle") != 0) {
-		printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
+	if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mark_info)))
 		return 0;
-	}
 
 	return 1;
 }
 
-static struct ip6t_target ip6t_mark_reg
-= { { NULL, NULL }, "MARK", target, checkentry, NULL, THIS_MODULE };
+static struct ip6t_match mark_match
+= { { NULL, NULL }, "mark", &match, &checkentry, NULL, THIS_MODULE };
 
 static int __init init(void)
 {
-	printk(KERN_DEBUG "registreing ipv6 mark target\n");
-	if (ip6t_register_target(&ip6t_mark_reg))
-		return -EINVAL;
-
-	return 0;
+	return ip6t_register_match(&mark_match);
 }
 
 static void __exit fini(void)
 {
-	ip6t_unregister_target(&ip6t_mark_reg);
+	ip6t_unregister_match(&mark_match);
 }
 
 module_init(init);
diff -ur linux-2.4.6.uc0pre0.orig/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.6.uc0pre0.actiontec/include/linux/netfilter_ipv4/ip_conntrack.h
--- linux-2.4.6.uc0pre0.orig/include/linux/netfilter_ipv4/ip_conntrack.h	2001-04-27 23:15:01.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/include/linux/netfilter_ipv4/ip_conntrack.h	2004-12-05 18:20:15.000000000 +0100
@@ -83,6 +83,13 @@
 
 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
 
+#if defined(CONFIG_IP_NF_IRC) || defined(CONFIG_IP_NF_IRC_MODULE)
+#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+#include <linux/netfilter_ipv4/ip_nat_irc.h>
+#endif
+#endif
+
 struct ip_conntrack
 {
 	/* Usage count in here is 1 for hash table/destruct timer, 1 per skb,
@@ -121,6 +128,10 @@
 
 	union {
 		struct ip_ct_ftp ct_ftp_info;
+#if defined(CONFIG_IP_NF_IRC) || defined(CONFIG_IP_NF_IRC_MODULE)
+                struct ip_ct_irc ct_irc_info;
+#endif
+ 		
 	} help;
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
@@ -128,6 +139,10 @@
 		struct ip_nat_info info;
 		union {
 			/* insert nat helper private data here */
+#if defined(CONFIG_IP_NF_IRC) || defined(CONFIG_IP_NF_IRC_MODULE)
+                       struct ip_nat_irc_info irc_info;
+#endif
+ 			
 		} help;
 #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
 	defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
diff -ur linux-2.4.6.uc0pre0.orig/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.4.6.uc0pre0.actiontec/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
--- linux-2.4.6.uc0pre0.orig/include/linux/netfilter_ipv4/ip_conntrack_tuple.h	2000-08-10 21:35:15.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/include/linux/netfilter_ipv4/ip_conntrack_tuple.h	2004-12-05 18:20:15.000000000 +0100
@@ -82,14 +82,14 @@
 	IP_CT_DIR_MAX
 };
 
-extern inline int ip_ct_tuple_src_equal(const struct ip_conntrack_tuple *t1,
+static inline int ip_ct_tuple_src_equal(const struct ip_conntrack_tuple *t1,
 				        const struct ip_conntrack_tuple *t2)
 {
 	return t1->src.ip == t2->src.ip
 		&& t1->src.u.all == t2->src.u.all;
 }
 
-extern inline int ip_ct_tuple_dst_equal(const struct ip_conntrack_tuple *t1,
+static inline int ip_ct_tuple_dst_equal(const struct ip_conntrack_tuple *t1,
 				        const struct ip_conntrack_tuple *t2)
 {
 	return t1->dst.ip == t2->dst.ip
@@ -97,13 +97,13 @@
 		&& t1->dst.protonum == t2->dst.protonum;
 }
 
-extern inline int ip_ct_tuple_equal(const struct ip_conntrack_tuple *t1,
+static inline int ip_ct_tuple_equal(const struct ip_conntrack_tuple *t1,
 				    const struct ip_conntrack_tuple *t2)
 {
 	return ip_ct_tuple_src_equal(t1, t2) && ip_ct_tuple_dst_equal(t1, t2);
 }
 
-extern inline int ip_ct_tuple_mask_cmp(const struct ip_conntrack_tuple *t,
+static inline int ip_ct_tuple_mask_cmp(const struct ip_conntrack_tuple *t,
 				       const struct ip_conntrack_tuple *tuple,
 				       const struct ip_conntrack_tuple *mask)
 {
diff -ur linux-2.4.6.uc0pre0.orig/include/linux/netfilter_ipv4/ip_tables.h linux-2.4.6.uc0pre0.actiontec/include/linux/netfilter_ipv4/ip_tables.h
--- linux-2.4.6.uc0pre0.orig/include/linux/netfilter_ipv4/ip_tables.h	2001-06-12 04:15:27.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/include/linux/netfilter_ipv4/ip_tables.h	2004-12-05 18:20:15.000000000 +0100
@@ -289,7 +289,7 @@
 #define IPT_ERROR_TARGET "ERROR"
 
 /* Helper functions */
-extern __inline__ struct ipt_entry_target *
+static __inline__ struct ipt_entry_target *
 ipt_get_target(struct ipt_entry *e)
 {
 	return (void *)e + e->target_offset;
diff -ur linux-2.4.6.uc0pre0.orig/include/linux/netfilter_ipv4/listhelp.h linux-2.4.6.uc0pre0.actiontec/include/linux/netfilter_ipv4/listhelp.h
--- linux-2.4.6.uc0pre0.orig/include/linux/netfilter_ipv4/listhelp.h	2000-12-11 22:31:23.000000000 +0100
+++ linux-2.4.6.uc0pre0.actiontec/include/linux/netfilter_ipv4/listhelp.h	2004-12-05 18:20:15.000000000 +0100
@@ -39,11 +39,11 @@
 	(type)__i;				\
 })
 
-extern inline int
+static inline int
 __list_cmp_same(const void *p1, const void *p2) { return p1 == p2; }
 
 /* Is this entry in the list? */
-extern inline int
+static inline int
 list_inlist(struct list_head *head, const void *entry)
 {
 	return LIST_FIND(head, __list_cmp_same, void *, entry) != NULL;
@@ -64,7 +64,7 @@
 #endif
 
 /* Append. */
-extern inline void
+static inline void
 list_append(struct list_head *head, void *new)
 {
 	ASSERT_WRITE_LOCK(head);
@@ -72,7 +72,7 @@
 }
 
 /* Prepend. */
-extern inline void
+static inline void
 list_prepend(struct list_head *head, void *new)
 {
 	ASSERT_WRITE_LOCK(head);
@@ -92,13 +92,13 @@
 
 /* If the field after the list_head is a nul-terminated string, you
    can use these functions. */
-extern inline int __list_cmp_name(const void *i, const char *name)
+static inline int __list_cmp_name(const void *i, const char *name)
 {
 	return strcmp(name, i+sizeof(struct list_head)) == 0;
 }
 
 /* Returns false if same name already in list, otherwise does insert. */
-extern inline int
+static inline int
 list_named_insert(struct list_head *head, void *new)
 {
 	if (LIST_FIND(head, __list_cmp_name, void *,
diff -ur linux-2.4.6.uc0pre0.orig/include/linux/netfilter_ipv6/ip6t_MARK.h linux-2.4.6.uc0pre0.actiontec/include/linux/netfilter_ipv6/ip6t_MARK.h
--- linux-2.4.6.uc0pre0.orig/include/linux/netfilter_ipv6/ip6t_MARK.h	2000-06-20 23:32:27.000000000 +0200
+++ linux-2.4.6.uc0pre0.actiontec/include/linux/netfilter_ipv6/ip6t_MARK.h	2004-12-05 18:20:15.000000000 +0100
@@ -1,8 +1,9 @@
-#ifndef _IP6T_MARK_H_target
-#define _IP6T_MARK_H_target
+#ifndef _IP6T_MARK_H
+#define _IP6T_MARK_H
 
-struct ip6t_mark_target_info {
-	unsigned long mark;
+struct ip6t_mark_info {
+    unsigned long mark, mask;
+    u_int8_t invert;
 };
 
-#endif /*_IPT_MARK_H_target*/
+#endif /*_IPT_MARK_H*/

