## Automatically generated incremental diff
## From:   linux-2.4.22-pre8
## To:     linux-2.4.22-pre9
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.4.22-pre8/Documentation/Configure.help linux-2.4.22-pre9/Documentation/Configure.help
--- linux-2.4.22-pre8/Documentation/Configure.help	2003-07-29 13:06:15.000000000 -0700
+++ linux-2.4.22-pre9/Documentation/Configure.help	2003-07-29 13:06:20.000000000 -0700
@@ -2589,6 +2589,17 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+recent match support
+CONFIG_IP_NF_MATCH_RECENT
+  This match is used for creating one or many lists of recently
+  used addresses and then matching against that/those list(s).
+
+  Short options are available by using 'iptables -m recent -h'
+  Official Website: <http://snowman.net/projects/ipt_recent/>
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
 limit match support
 CONFIG_IP_NF_MATCH_LIMIT
   limit matching allows you to control the rate at which a rule can be
@@ -12967,22 +12978,40 @@
   <file:Documentation/modules.txt>. The module will be called
   redboot.o
 
-Compaq bootldr partition table parsing
-CONFIG_MTD_BOOTLDR_PARTS
-  The Compaq bootldr deals with multiple 'images' in flash devices
-  by putting a table in one of the first erase blocks of the device,
-  similar to a partition table, which gives the offsets, lengths and
-  names of all the images stored in the flash.
-
-  If you need code which can detect and parse this table, and register
-  MTD 'partitions' corresponding to each image in the table, enable
-  this option.
+CONFIG_MTD_CMDLINE_PARTS
+  Allow generic configuration of the MTD paritition tables via the kernel
+  command line. Multiple flash resources are supported for hardware where
+  different kinds of flash memory are available. 
 
   You will still need the parsing functions to be called by the driver
   for your particular device. It won't happen automatically. The 
   SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for 
   example.
 
+  The format for the command line is as follows:
+
+  mtdparts=<mtddef>[;<mtddef]
+  <mtddef>  := <mtd-id>:<partdef>[,<partdef>]
+  <partdef> := <size>[@offset][<name>][ro]
+  <mtd-id>  := unique id used in mapping driver/device
+  <size>    := standard linux memsize OR "-" to denote all 
+  remaining space
+  <name>    := (NAME)
+
+  Due to the way Linux handles the command line, no spaces are 
+  allowed in the partition definition, including mtd id's and partition 
+  names.
+
+  Examples:
+
+  1 flash resource (mtd-id "sa1100"), with 1 single writable partition:
+  mtdparts=sa1100:-
+
+  Same flash, but 2 named partitions, the first one being read-only:
+  mtdparts=sa1100:256k(ARMboot)ro,-(root)
+
+  If unsure, say 'N'.
+
 ARM Firmware Suite flash layout / partition parsing
 CONFIG_MTD_AFS_PARTS
   The ARM Firmware Suite allows the user to divide flash devices into
@@ -13150,6 +13179,10 @@
   If you wish to support CFI devices on a physical bus which is
   32 bits wide, say 'Y'.
 
+CONFIG_MTD_CFI_B8
+  If you wish to support CFI devices on a physical bus which is
+  64 bits wide, say 'Y'.
+
 Support 1-chip flash interleave
 CONFIG_MTD_CFI_I1
   If your flash chips are not interleaved - i.e. you only have one
@@ -13165,6 +13198,10 @@
   If your flash chips are interleaved in fours - i.e. you have four
   flash chips addressed by each bus cycle, then say 'Y'.
 
+CONFIG_MTD_CFI_I8
+  If your flash chips are interleaved in eights - i.e. you have eight
+  flash chips addressed by each bus cycle, then say 'Y'.
+
 # Choice: mtd_data_swap
 Flash cmd/query data swapping
 CONFIG_MTD_CFI_NOSWAP
@@ -13229,6 +13266,11 @@
   <file:Documentation/modules.txt>. The module will be called
   amd_flash.o
 
+CONFIG_MTD_CFI_STAA
+  The Common Flash Interface defines a number of different command
+  sets which a CFI-compliant chip may claim to implement. This code
+  provides support for one of those command sets.
+
 Support for RAM chips in bus mapping
 CONFIG_MTD_RAM
   This option enables basic support for RAM chips accessed through 
diff -urN linux-2.4.22-pre8/Documentation/nmi_watchdog.txt linux-2.4.22-pre9/Documentation/nmi_watchdog.txt
--- linux-2.4.22-pre8/Documentation/nmi_watchdog.txt	2001-09-17 23:03:09.000000000 -0700
+++ linux-2.4.22-pre9/Documentation/nmi_watchdog.txt	2003-07-29 13:06:20.000000000 -0700
@@ -8,9 +8,20 @@
 which get executed even if the system is otherwise locked up hard).
 This can be used to debug hard kernel lockups.  By executing periodic
 NMI interrupts, the kernel can monitor whether any CPU has locked up,
-and print out debugging messages if so.  You must enable the NMI
-watchdog at boot time with the 'nmi_watchdog=n' boot parameter.  Eg.
-the relevant lilo.conf entry:
+and print out debugging messages if so.  
+
+In order to use the NMI watchdoc, you need to have APIC support in your
+kernel. For SMP kernels, APIC support gets compiled in automatically. For
+UP, enable either CONFIG_X86_UP_APIC (Processor type and features -> Local
+APIC support on uniprocessors) or CONFIG_X86_UP_IOAPIC (Processor type and
+features -> IO-APIC support on uniprocessors) in your kernel config.
+CONFIG_X86_UP_APIC is for uniprocessor machines without an IO-APIC.
+CONFIG_X86_UP_IOAPIC is for uniprocessor with an IO-APIC. [Note: certain
+kernel debugging options, such as Kernel Stack Meter or Kernel Tracer,
+may implicitly disable the NMI watchdog.]
+
+To actually enable the NMI watchdog, use the 'nmi_watchdog=N' boot
+parameter.  Eg. the relevant lilo.conf entry:
 
         append="nmi_watchdog=1"
 
diff -urN linux-2.4.22-pre8/Makefile linux-2.4.22-pre9/Makefile
--- linux-2.4.22-pre8/Makefile	2003-07-29 13:06:15.000000000 -0700
+++ linux-2.4.22-pre9/Makefile	2003-07-29 13:06:20.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 22
-EXTRAVERSION = -pre8
+EXTRAVERSION = -pre9
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.22-pre8/arch/ppc/8xx_io/fec.c linux-2.4.22-pre9/arch/ppc/8xx_io/fec.c
--- linux-2.4.22-pre8/arch/ppc/8xx_io/fec.c	2003-07-29 13:06:16.000000000 -0700
+++ linux-2.4.22-pre9/arch/ppc/8xx_io/fec.c	2003-07-29 13:06:21.000000000 -0700
@@ -1019,7 +1019,7 @@
 		{ mk_mii_end, }
 	},
 	(const phy_cmd_t []) {  /* startup - enable interrupts */
-		{ mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
+		{ mk_mii_write(MII_QS6612_IMR, 0x0050), NULL },
 		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
 		{ mk_mii_end, }
 	},
diff -urN linux-2.4.22-pre8/arch/ppc/boot/simple/embed_config.c linux-2.4.22-pre9/arch/ppc/boot/simple/embed_config.c
--- linux-2.4.22-pre8/arch/ppc/boot/simple/embed_config.c	2003-06-13 07:51:31.000000000 -0700
+++ linux-2.4.22-pre9/arch/ppc/boot/simple/embed_config.c	2003-07-29 13:06:21.000000000 -0700
@@ -369,8 +369,8 @@
 
 	bd->bi_memstart = 0;
 	bd->bi_memsize = (8 * 1024 * 1024);
-	bd->bi_intfreq = 40000000;
-	bd->bi_busfreq = 40000000;
+	bd->bi_intfreq = 48000000;
+	bd->bi_busfreq = 48000000;
 }
 #endif /* FADS */
 
diff -urN linux-2.4.22-pre8/drivers/char/random.c linux-2.4.22-pre9/drivers/char/random.c
--- linux-2.4.22-pre8/drivers/char/random.c	2003-07-29 13:06:17.000000000 -0700
+++ linux-2.4.22-pre9/drivers/char/random.c	2003-07-29 13:06:22.000000000 -0700
@@ -251,6 +251,8 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
@@ -2069,7 +2071,7 @@
 static struct keydata *__check_and_rekey(time_t time)
 {
 	struct keydata *keyptr;
-	spin_lock(&ip_lock);
+	spin_lock_bh(&ip_lock);
 	keyptr = &ip_keydata[ip_cnt&1];
 	if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) {
 		keyptr = &ip_keydata[1^(ip_cnt&1)];
@@ -2079,7 +2081,7 @@
 		mb();
 		ip_cnt++;
 	}
-	spin_unlock(&ip_lock);
+	spin_unlock_bh(&ip_lock);
 	return keyptr;
 }
 
diff -urN linux-2.4.22-pre8/drivers/ieee1394/csr.c linux-2.4.22-pre9/drivers/ieee1394/csr.c
--- linux-2.4.22-pre8/drivers/ieee1394/csr.c	2003-07-29 13:06:17.000000000 -0700
+++ linux-2.4.22-pre9/drivers/ieee1394/csr.c	2003-07-29 13:06:22.000000000 -0700
@@ -19,6 +19,7 @@
 
 #include <linux/string.h>
 #include <linux/module.h> /* needed for MODULE_PARM */
+#include <linux/param.h>
 
 #include "ieee1394_types.h"
 #include "hosts.h"
@@ -87,6 +88,35 @@
                                                          0x3f1));
 }
 
+/* 
+ * HI == seconds (bits 0:2)
+ * LO == fraction units of 1/8000 of a second, as per 1394 (bits 19:31)
+ *
+ * Convert to units and then to HZ, for comparison to jiffies.
+ *
+ * By default this will end up being 800 units, or 100ms (125usec per
+ * unit).
+ *
+ * NOTE: The spec says 1/8000, but also says we can compute based on 1/8192
+ * like CSR specifies. Should make our math less complex.
+ */
+static inline void calculate_expire(struct csr_control *csr)
+{
+	unsigned long units;
+	
+	/* Take the seconds, and convert to units */
+	units = (unsigned long)(csr->split_timeout_hi & 0x07) << 13;
+
+	/* Add in the fractional units */
+	units += (unsigned long)(csr->split_timeout_lo >> 19);
+
+	/* Convert to jiffies */
+	csr->expire = (unsigned long)(units * HZ) >> 13UL;
+
+	/* Just to keep from rounding low */
+	csr->expire++;
+}
+
 
 static void add_host(struct hpsb_host *host)
 {
@@ -98,6 +128,7 @@
         host->csr.node_ids              = 0;
         host->csr.split_timeout_hi      = 0;
         host->csr.split_timeout_lo      = 800 << 19;
+	calculate_expire(&host->csr);
         host->csr.cycle_time            = 0;
         host->csr.bus_time              = 0;
         host->csr.bus_manager_id        = 0x3f;
@@ -334,10 +365,12 @@
         case CSR_SPLIT_TIMEOUT_HI:
                 host->csr.split_timeout_hi = 
                         be32_to_cpu(*(data++)) & 0x00000007;
+		calculate_expire(&host->csr);
                 out;
         case CSR_SPLIT_TIMEOUT_LO:
                 host->csr.split_timeout_lo = 
                         be32_to_cpu(*(data++)) & 0xfff80000;
+		calculate_expire(&host->csr);
                 out;
 
                 /* address gap */
diff -urN linux-2.4.22-pre8/drivers/ieee1394/csr.h linux-2.4.22-pre9/drivers/ieee1394/csr.h
--- linux-2.4.22-pre8/drivers/ieee1394/csr.h	2003-07-29 13:06:17.000000000 -0700
+++ linux-2.4.22-pre9/drivers/ieee1394/csr.h	2003-07-29 13:06:22.000000000 -0700
@@ -41,6 +41,7 @@
         quadlet_t state;
         quadlet_t node_ids;
         quadlet_t split_timeout_hi, split_timeout_lo;
+	unsigned long expire;	// Calculated from split_timeout
         quadlet_t cycle_time;
         quadlet_t bus_time;
         quadlet_t bus_manager_id;
diff -urN linux-2.4.22-pre8/drivers/ieee1394/dma.c linux-2.4.22-pre9/drivers/ieee1394/dma.c
--- linux-2.4.22-pre8/drivers/ieee1394/dma.c	2003-07-29 13:06:17.000000000 -0700
+++ linux-2.4.22-pre9/drivers/ieee1394/dma.c	2003-07-29 13:06:22.000000000 -0700
@@ -151,16 +151,15 @@
 	for (i = 0; i < dma->n_dma_pages; i++) {
 		if (off < sg_dma_len(&dma->sglist[i])) {
 			*rem = off;
-			return i;
+			break;
 		}
 
 		off -= sg_dma_len(&dma->sglist[i]);
 	}
 
-	printk("dma_region_find: offset %lu beyond end of DMA mapping\n", offset);
-	BUG();
+	BUG_ON(i >= dma->n_dma_pages);
 
-	return -ENOENT;
+	return i;
 }
 
 dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset)
diff -urN linux-2.4.22-pre8/drivers/ieee1394/hosts.c linux-2.4.22-pre9/drivers/ieee1394/hosts.c
--- linux-2.4.22-pre8/drivers/ieee1394/hosts.c	2003-06-13 07:51:34.000000000 -0700
+++ linux-2.4.22-pre9/drivers/ieee1394/hosts.c	2003-07-29 13:06:22.000000000 -0700
@@ -138,7 +138,10 @@
 
 	atomic_set(&h->generation, 0);
 
-	INIT_TQUEUE(&h->timeout_tq, (void (*)(void*))abort_timedouts, h);
+	init_timer(&h->timeout);
+	h->timeout.data = (unsigned long) h;
+	h->timeout.function = abort_timedouts;
+	h->timeout_interval = HZ / 20; // 50ms by default
 
         h->topology_map = h->csr.topology_map + 3;
         h->speed_map = (u8 *)(h->csr.speed_map + 2);
diff -urN linux-2.4.22-pre8/drivers/ieee1394/hosts.h linux-2.4.22-pre9/drivers/ieee1394/hosts.h
--- linux-2.4.22-pre8/drivers/ieee1394/hosts.h	2003-07-29 13:06:17.000000000 -0700
+++ linux-2.4.22-pre9/drivers/ieee1394/hosts.h	2003-07-29 13:06:22.000000000 -0700
@@ -3,7 +3,7 @@
 
 #include <linux/wait.h>
 #include <linux/list.h>
-#include <linux/tqueue.h>
+#include <linux/timer.h>
 #include <asm/semaphore.h>
 
 #include "ieee1394_types.h"
@@ -32,7 +32,8 @@
 
         struct list_head pending_packets;
         spinlock_t pending_pkt_lock;
-        struct tq_struct timeout_tq;
+	struct timer_list timeout;
+	unsigned long timeout_interval;
 
         unsigned char iso_listen_count[64];
 
diff -urN linux-2.4.22-pre8/drivers/ieee1394/ieee1394_core.c linux-2.4.22-pre9/drivers/ieee1394/ieee1394_core.c
--- linux-2.4.22-pre8/drivers/ieee1394/ieee1394_core.c	2003-07-29 13:06:17.000000000 -0700
+++ linux-2.4.22-pre9/drivers/ieee1394/ieee1394_core.c	2003-07-29 13:06:22.000000000 -0700
@@ -439,7 +439,7 @@
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
         up(&packet->state_change);
-        schedule_task(&host->timeout_tq);
+	mod_timer(&host->timeout, jiffies + host->timeout_interval);
 }
 
 /**
@@ -958,28 +958,23 @@
         }
 }
 
-void abort_timedouts(struct hpsb_host *host)
+void abort_timedouts(unsigned long __opaque)
 {
+	struct hpsb_host *host = (struct hpsb_host *)__opaque;
         unsigned long flags;
         struct hpsb_packet *packet;
         unsigned long expire;
-        struct list_head *lh, *next, *tlh;
+        struct list_head *lh, *tlh;
         LIST_HEAD(expiredlist);
 
         spin_lock_irqsave(&host->csr.lock, flags);
-        expire = (host->csr.split_timeout_hi * 8000 
-                  + (host->csr.split_timeout_lo >> 19))
-                * HZ / 8000;
-        /* Avoid shortening of timeout due to rounding errors: */
-        expire++;
+	expire = host->csr.expire;
         spin_unlock_irqrestore(&host->csr.lock, flags);
 
-
         spin_lock_irqsave(&host->pending_pkt_lock, flags);
 
-	for (lh = host->pending_packets.next; lh != &host->pending_packets; lh = next) {
+	list_for_each_safe(lh, tlh, &host->pending_packets) {
                 packet = list_entry(lh, struct hpsb_packet, list);
-		next = lh->next;
                 if (time_before(packet->sendtime + expire, jiffies)) {
                         list_del(&packet->list);
                         list_add(&packet->list, &expiredlist);
@@ -987,7 +982,7 @@
         }
 
         if (!list_empty(&host->pending_packets))
-		schedule_task(&host->timeout_tq);
+		mod_timer(&host->timeout, jiffies + host->timeout_interval);
 
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
diff -urN linux-2.4.22-pre8/drivers/ieee1394/ieee1394_core.h linux-2.4.22-pre9/drivers/ieee1394/ieee1394_core.h
--- linux-2.4.22-pre8/drivers/ieee1394/ieee1394_core.h	2003-07-29 13:06:17.000000000 -0700
+++ linux-2.4.22-pre9/drivers/ieee1394/ieee1394_core.h	2003-07-29 13:06:22.000000000 -0700
@@ -88,7 +88,7 @@
 	return list_entry(l, struct hpsb_packet, driver_list);
 }
 
-void abort_timedouts(struct hpsb_host *host);
+void abort_timedouts(unsigned long __opaque);
 void abort_requests(struct hpsb_host *host);
 
 struct hpsb_packet *alloc_hpsb_packet(size_t data_size);
diff -urN linux-2.4.22-pre8/drivers/input/keybdev.c linux-2.4.22-pre9/drivers/input/keybdev.c
--- linux-2.4.22-pre8/drivers/input/keybdev.c	2003-06-13 07:51:34.000000000 -0700
+++ linux-2.4.22-pre9/drivers/input/keybdev.c	2003-07-29 13:06:22.000000000 -0700
@@ -172,7 +172,8 @@
 	if (type != EV_KEY) return;
 
 	if (emulate_raw(code, down))
-		printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", code);
+		if(code < BTN_MISC)
+			printk(KERN_WARNING "keybdev.c: can't emulate rawmode for keycode %d\n", code);
 
 	tasklet_schedule(&keyboard_tasklet);
 }
diff -urN linux-2.4.22-pre8/drivers/md/md.c linux-2.4.22-pre9/drivers/md/md.c
--- linux-2.4.22-pre8/drivers/md/md.c	2003-07-29 13:06:17.000000000 -0700
+++ linux-2.4.22-pre9/drivers/md/md.c	2003-07-29 13:06:22.000000000 -0700
@@ -1805,10 +1805,12 @@
 	int err = 0, resync_interrupted = 0;
 	kdev_t dev = mddev_to_kdev(mddev);
 
+#if 0 /* ->active is not currently reliable */
 	if (atomic_read(&mddev->active)>1) {
 		printk(STILL_IN_USE, mdidx(mddev));
 		OUT(-EBUSY);
 	}
+#endif
 
 	if (mddev->pers) {
 		/*
@@ -2742,12 +2744,17 @@
 			goto done_unlock;
 
 		case STOP_ARRAY:
-			if (!(err = do_md_stop (mddev, 0)))
+			if (inode->i_bdev->bd_openers > 1)
+				err = -EBUSY;
+			else if (!(err = do_md_stop (mddev, 0)))
 				mddev = NULL;
 			goto done_unlock;
 
 		case STOP_ARRAY_RO:
-			err = do_md_stop (mddev, 1);
+			if (inode->i_bdev->bd_openers > 1)
+				err = -EBUSY;
+			else 
+				err = do_md_stop (mddev, 1);
 			goto done_unlock;
 
 	/*
diff -urN linux-2.4.22-pre8/fs/binfmt_elf.c linux-2.4.22-pre9/fs/binfmt_elf.c
--- linux-2.4.22-pre8/fs/binfmt_elf.c	2003-07-29 13:06:18.000000000 -0700
+++ linux-2.4.22-pre9/fs/binfmt_elf.c	2003-07-29 13:06:23.000000000 -0700
@@ -797,10 +797,8 @@
 	if (current->ptrace & PT_PTRACED)
 		send_sig(SIGTRAP, current, 0);
 	retval = 0;
+	steal_locks(files, current->files);
 out:
-	if (!retval)
-		steal_locks(files, current->files);
-
 	return retval;
 
 	/* error cleanup */
diff -urN linux-2.4.22-pre8/fs/nfsd/export.c linux-2.4.22-pre9/fs/nfsd/export.c
--- linux-2.4.22-pre8/fs/nfsd/export.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-pre9/fs/nfsd/export.c	2003-07-29 13:06:23.000000000 -0700
@@ -19,6 +19,7 @@
 #include <linux/stat.h>
 #include <linux/in.h>
 #include <linux/seq_file.h>
+#include <linux/smp_lock.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
@@ -571,6 +572,7 @@
 	svc_client *clp;
 	struct list_head *p;
 	
+	lock_kernel();
 	exp_readlock();
 	if (!n--)
 		return (void *)1;
@@ -622,6 +624,7 @@
 static void e_stop(struct seq_file *m, void *p)
 {
 	exp_unlock();
+	unlock_kernel();
 }
 
 struct flags {
diff -urN linux-2.4.22-pre8/fs/nfsd/vfs.c linux-2.4.22-pre9/fs/nfsd/vfs.c
--- linux-2.4.22-pre8/fs/nfsd/vfs.c	2003-06-13 07:51:37.000000000 -0700
+++ linux-2.4.22-pre9/fs/nfsd/vfs.c	2003-07-29 13:06:23.000000000 -0700
@@ -1151,7 +1151,9 @@
 				iap->ia_mode = (iap->ia_mode&S_IALLUGO)
 					| S_IFLNK;
 				err = notify_change(dnew, iap);
-				if (!err && EX_ISSYNC(fhp->fh_export))
+				if (err)
+					err = nfserrno(err);
+				else if (EX_ISSYNC(fhp->fh_export))
 					write_inode_now(dentry->d_inode, 1);
 		       }
 		}
diff -urN linux-2.4.22-pre8/include/linux/igmp.h linux-2.4.22-pre9/include/linux/igmp.h
--- linux-2.4.22-pre8/include/linux/igmp.h	2003-07-29 13:06:19.000000000 -0700
+++ linux-2.4.22-pre9/include/linux/igmp.h	2003-07-29 13:06:23.000000000 -0700
@@ -16,6 +16,8 @@
 #ifndef _LINUX_IGMP_H
 #define _LINUX_IGMP_H
 
+#include <asm/byteorder.h>
+
 /*
  *	IGMP protocol structures
  */
diff -urN linux-2.4.22-pre8/include/linux/netfilter_ipv4/ip_conntrack_core.h linux-2.4.22-pre9/include/linux/netfilter_ipv4/ip_conntrack_core.h
--- linux-2.4.22-pre8/include/linux/netfilter_ipv4/ip_conntrack_core.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-pre9/include/linux/netfilter_ipv4/ip_conntrack_core.h	2003-07-29 13:06:23.000000000 -0700
@@ -1,5 +1,6 @@
 #ifndef _IP_CONNTRACK_CORE_H
 #define _IP_CONNTRACK_CORE_H
+#include <linux/netfilter.h>
 #include <linux/netfilter_ipv4/lockhelp.h>
 
 /* This header is used to share core functionality between the
diff -urN linux-2.4.22-pre8/include/linux/netfilter_ipv4/ipt_REJECT.h linux-2.4.22-pre9/include/linux/netfilter_ipv4/ipt_REJECT.h
--- linux-2.4.22-pre8/include/linux/netfilter_ipv4/ipt_REJECT.h	2000-07-14 12:20:23.000000000 -0700
+++ linux-2.4.22-pre9/include/linux/netfilter_ipv4/ipt_REJECT.h	2003-07-29 13:06:23.000000000 -0700
@@ -9,7 +9,8 @@
 	IPT_ICMP_ECHOREPLY,
 	IPT_ICMP_NET_PROHIBITED,
 	IPT_ICMP_HOST_PROHIBITED,
-	IPT_TCP_RESET
+	IPT_TCP_RESET,
+	IPT_ICMP_ADMIN_PROHIBITED
 };
 
 struct ipt_reject_info {
diff -urN linux-2.4.22-pre8/net/core/filter.c linux-2.4.22-pre9/net/core/filter.c
--- linux-2.4.22-pre8/net/core/filter.c	2001-05-16 10:32:59.000000000 -0700
+++ linux-2.4.22-pre9/net/core/filter.c	2003-07-29 13:06:23.000000000 -0700
@@ -294,10 +294,9 @@
 				goto load_b;
 
 			case BPF_LDX|BPF_B|BPF_MSH:
-				k = fentry->k;
-				if(k >= 0 && (unsigned int)k >= len)
+				if(fentry->k >= len)
 					return (0);
-				X = (data[k] & 0xf) << 2;
+				X = (data[fentry->k] & 0xf) << 2;
 				continue;
 
 			case BPF_LD|BPF_IMM:
diff -urN linux-2.4.22-pre8/net/core/netfilter.c linux-2.4.22-pre9/net/core/netfilter.c
--- linux-2.4.22-pre8/net/core/netfilter.c	2002-08-02 17:39:46.000000000 -0700
+++ linux-2.4.22-pre9/net/core/netfilter.c	2003-07-29 13:06:23.000000000 -0700
@@ -563,64 +563,62 @@
 {
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct rtable *rt;
-	struct rt_key key = { dst:iph->daddr,
-			      src:iph->saddr,
-			      oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
-			      tos:RT_TOS(iph->tos)|RTO_CONN,
+	struct rt_key key = {};
+	struct dst_entry *odst;
+	unsigned int hh_len;
+
+	/* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
+	 * packets with foreign saddr to be appear on the NF_IP_LOCAL_OUT hook.
+	 */
+	if (inet_addr_type(iph->saddr) == RTN_LOCAL) {
+		key.dst = iph->daddr;
+		key.src = iph->saddr;
+		key.oif = (*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0;
+		key.tos = RT_TOS(iph->tos);
 #ifdef CONFIG_IP_ROUTE_FWMARK
-			      fwmark:(*pskb)->nfmark
+		key.fwmark = (*pskb)->nfmark;
 #endif
-			    };
-	struct net_device *dev_src = NULL;
-	int err;
-
-	/* accomodate ip_route_output_slow(), which expects the key src to be
-	   0 or a local address; however some non-standard hacks like
-	   ipt_REJECT.c:send_reset() can cause packets with foreign
-           saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */
-	if(key.src && !(dev_src = ip_dev_find(key.src)))
-		key.src = 0;
-
-	if ((err=ip_route_output_key(&rt, &key)) != 0) {
-		printk("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %d\n",
-			NIPQUAD(iph->daddr), NIPQUAD(iph->saddr),
-			(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
-			RT_TOS(iph->tos)|RTO_CONN,
-#ifdef CONFIG_IP_ROUTE_FWMARK
-			(*pskb)->nfmark,
-#else
-			0UL,
-#endif
-			err);
-		goto out;
-	}
-
-	/* Drop old route. */
-	dst_release((*pskb)->dst);
+		if (ip_route_output_key(&rt, &key) != 0)
+			return -1;
 
-	(*pskb)->dst = &rt->u.dst;
+		/* Drop old route. */
+		dst_release((*pskb)->dst);
+		(*pskb)->dst = &rt->u.dst;
+	} else {
+		/* non-local src, find valid iif to satisfy
+		 * rp-filter when calling ip_route_input. */
+		key.dst = iph->saddr;
+		if (ip_route_output_key(&rt, &key) != 0)
+			return -1;
+
+		odst = (*pskb)->dst;
+		if (ip_route_input(*pskb, iph->daddr, iph->saddr,
+		                   RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
+			dst_release(&rt->u.dst);
+			return -1;
+		}
+		dst_release(&rt->u.dst);
+		dst_release(odst);
+	}
+	
+	if ((*pskb)->dst->error)
+		return -1;
 
 	/* Change in oif may mean change in hh_len. */
-	if (skb_headroom(*pskb) < (*pskb)->dst->dev->hard_header_len) {
+	hh_len = (*pskb)->dst->dev->hard_header_len;
+	if (skb_headroom(*pskb) < hh_len) {
 		struct sk_buff *nskb;
 
-		nskb = skb_realloc_headroom(*pskb,
-					    (*pskb)->dst->dev->hard_header_len);
-		if (!nskb) {
-			err = -ENOMEM;
-			goto out;
-		}
+		nskb = skb_realloc_headroom(*pskb, hh_len);
+		if (!nskb)
+			return -1;
 		if ((*pskb)->sk)
 			skb_set_owner_w(nskb, (*pskb)->sk);
 		kfree_skb(*pskb);
 		*pskb = nskb;
 	}
 
-out:
-	if (dev_src)
-		dev_put(dev_src);
-
-	return err;
+	return 0;
 }
 #endif /*CONFIG_INET*/
 
diff -urN linux-2.4.22-pre8/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.22-pre9/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.4.22-pre8/net/ipv4/netfilter/ip_conntrack_core.c	2003-07-29 13:06:19.000000000 -0700
+++ linux-2.4.22-pre9/net/ipv4/netfilter/ip_conntrack_core.c	2003-07-29 13:06:23.000000000 -0700
@@ -257,7 +257,7 @@
 }
 
 /* delete all unconfirmed expectations for this conntrack */
-static void remove_expectations(struct ip_conntrack *ct)
+static void remove_expectations(struct ip_conntrack *ct, int drop_refcount)
 {
 	struct list_head *exp_entry, *next;
 	struct ip_conntrack_expect *exp;
@@ -272,8 +272,11 @@
 		 * the un-established ones only */
 		if (exp->sibling) {
 			DEBUGP("remove_expectations: skipping established %p of %p\n", exp->sibling, ct);
-			/* Indicate that this expectations parent is dead */
-			exp->expectant = NULL;
+			if (drop_refcount) {
+				/* Indicate that this expectations parent is dead */
+				ip_conntrack_put(exp->expectant);
+				exp->expectant = NULL;
+			}
 			continue;
 		}
 
@@ -298,7 +301,7 @@
 		    &ct->tuplehash[IP_CT_DIR_REPLY]);
 
 	/* Destroy all un-established, pending expectations */
-	remove_expectations(ct);
+	remove_expectations(ct, 1);
 }
 
 static void
@@ -1140,7 +1143,7 @@
 {
 	if (i->ctrack->helper == me) {
 		/* Get rid of any expected. */
-		remove_expectations(i->ctrack);
+		remove_expectations(i->ctrack, 0);
 		/* And *then* set helper to NULL */
 		i->ctrack->helper = NULL;
 	}
diff -urN linux-2.4.22-pre8/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.4.22-pre9/net/ipv4/netfilter/ip_conntrack_irc.c
--- linux-2.4.22-pre8/net/ipv4/netfilter/ip_conntrack_irc.c	2003-07-29 13:06:19.000000000 -0700
+++ linux-2.4.22-pre9/net/ipv4/netfilter/ip_conntrack_irc.c	2003-07-29 13:06:23.000000000 -0700
@@ -59,7 +59,7 @@
 	{"TSEND ", 6},
 	{"SCHAT ", 6}
 };
-#define MAXMATCHLEN	6
+#define MINMATCHLEN	5
 
 DECLARE_LOCK(ip_irc_lock);
 struct module *ip_conntrack_irc = THIS_MODULE;
@@ -92,9 +92,11 @@
 	*ip = simple_strtoul(data, &data, 10);
 
 	/* skip blanks between ip and port */
-	while (*data == ' ')
+	while (*data == ' ') {
+		if (data >= data_end) 
+			return -1;
 		data++;
-
+	}
 
 	*port = simple_strtoul(data, &data, 10);
 	*ad_end_p = data;
@@ -153,13 +155,17 @@
 	}
 
 	data_limit = (char *) data + datalen;
-	while (data < (data_limit - (22 + MAXMATCHLEN))) {
+
+	/* strlen("\1DCC SEND t AAAAAAAA P\1\n")=24
+	 *         5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
+	while (data < (data_limit - (19 + MINMATCHLEN))) {
 		if (memcmp(data, "\1DCC ", 5)) {
 			data++;
 			continue;
 		}
 
 		data += 5;
+		/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
 
 		DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
 			NIPQUAD(iph->saddr), ntohs(tcph->source),
@@ -174,6 +180,9 @@
 
 			DEBUGP("DCC %s detected\n", dccprotos[i].match);
 			data += dccprotos[i].matchlen;
+			/* we have at least
+			 * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
+			 * data left (== 14/13 bytes) */
 			if (parse_dcc((char *) data, data_limit, &dcc_ip,
 				       &dcc_port, &addr_beg_p, &addr_end_p)) {
 				/* unable to parse */
diff -urN linux-2.4.22-pre8/net/ipv4/netfilter/ipt_MIRROR.c linux-2.4.22-pre9/net/ipv4/netfilter/ipt_MIRROR.c
--- linux-2.4.22-pre8/net/ipv4/netfilter/ipt_MIRROR.c	2003-07-29 13:06:19.000000000 -0700
+++ linux-2.4.22-pre9/net/ipv4/netfilter/ipt_MIRROR.c	2003-07-29 13:06:23.000000000 -0700
@@ -32,7 +32,6 @@
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netdevice.h>
 #include <linux/route.h>
-struct in_device;
 #include <net/route.h>
 
 #if 0
@@ -41,31 +40,47 @@
 #define DEBUGP(format, args...)
 #endif
 
-static int route_mirror(struct sk_buff *skb)
+static inline struct rtable *route_mirror(struct sk_buff *skb, int local)
 {
         struct iphdr *iph = skb->nh.iph;
+	struct dst_entry *odst;
+	struct rt_key key = {};
 	struct rtable *rt;
 
-	/* Backwards */
-	if (ip_route_output(&rt, iph->saddr, iph->daddr,
-			    RT_TOS(iph->tos) | RTO_CONN,
-			    0)) {
-		return 0;
+	if (local) {
+		key.dst = iph->saddr;
+		key.src = iph->daddr;
+		key.tos = RT_TOS(iph->tos);
+
+		if (ip_route_output_key(&rt, &key) != 0)
+			return NULL;
+	} else {
+		/* non-local src, find valid iif to satisfy
+		 * rp-filter when calling ip_route_input. */
+		key.dst = iph->daddr;
+		if (ip_route_output_key(&rt, &key) != 0)
+			return NULL;
+
+		odst = skb->dst;
+		if (ip_route_input(skb, iph->saddr, iph->daddr,
+		                   RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
+			dst_release(&rt->u.dst);
+			return NULL;
+		}
+		dst_release(&rt->u.dst);
+		rt = (struct rtable *)skb->dst;
+		skb->dst = odst;
 	}
 
-	/* check if the interface we are leaving by is the same as the
-           one we arrived on */
-	if (skb->dev == rt->u.dst.dev) {
-		/* Drop old route. */
-		dst_release(skb->dst);
-		skb->dst = &rt->u.dst;
-		return 1;
+	if (rt->u.dst.error) {
+		dst_release(&rt->u.dst);
+		rt = NULL;
 	}
-	return 0;
+
+	return rt;
 }
 
-static void
-ip_rewrite(struct sk_buff *skb)
+static inline void ip_rewrite(struct sk_buff *skb)
 {
 	struct iphdr *iph = skb->nh.iph;
 	u32 odaddr = iph->saddr;
@@ -108,32 +123,48 @@
 				      const void *targinfo,
 				      void *userinfo)
 {
-	if (((*pskb)->dst != NULL) &&
-	    route_mirror(*pskb)) {
-
-		ip_rewrite(*pskb);
+	struct rtable *rt;
+	struct sk_buff *nskb;
+	unsigned int hh_len;
 
-		/* If we are not at FORWARD hook (INPUT/PREROUTING),
-		 * the TTL isn't decreased by the IP stack */
-		if (hooknum != NF_IP_FORWARD) {
-			struct iphdr *iph = (*pskb)->nh.iph;
-			if (iph->ttl <= 1) {
-				/* this will traverse normal stack, and 
-				 * thus call conntrack on the icmp packet */
-				icmp_send(*pskb, ICMP_TIME_EXCEEDED, 
-					  ICMP_EXC_TTL, 0);
-				return NF_DROP;
-			}
-			ip_decrease_ttl(iph);
+	/* If we are not at FORWARD hook (INPUT/PREROUTING),
+	 * the TTL isn't decreased by the IP stack */
+	if (hooknum != NF_IP_FORWARD) {
+		struct iphdr *iph = (*pskb)->nh.iph;
+		if (iph->ttl <= 1) {
+			/* this will traverse normal stack, and 
+			 * thus call conntrack on the icmp packet */
+			icmp_send(*pskb, ICMP_TIME_EXCEEDED, 
+				  ICMP_EXC_TTL, 0);
+			return NF_DROP;
 		}
+		ip_decrease_ttl(iph);
+	}
+
+	if ((rt = route_mirror(*pskb, hooknum == NF_IP_LOCAL_IN)) == NULL)
+		return NF_DROP;
 
-		/* Don't let conntrack code see this packet:
-                   it will think we are starting a new
-                   connection! --RR */
-		ip_direct_send(*pskb);
+	hh_len = (rt->u.dst.dev->hard_header_len + 15) & ~15;
 
-		return NF_STOLEN;
+	/* 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). We also need to expand headroom in case
+	 * hh_len of incoming interface < hh_len of outgoing interface */
+	nskb = skb_copy_expand(*pskb, hh_len, skb_tailroom(*pskb), GFP_ATOMIC);
+	if (nskb == NULL) {
+		dst_release(&rt->u.dst);
+		return NF_DROP;
 	}
+
+	dst_release(nskb->dst);
+	nskb->dst = &rt->u.dst;
+
+	ip_rewrite(nskb);
+	/* Don't let conntrack code see this packet:
+           it will think we are starting a new
+           connection! --RR */
+	ip_direct_send(nskb);
+
 	return NF_DROP;
 }
 
diff -urN linux-2.4.22-pre8/net/ipv4/netfilter/ipt_REJECT.c linux-2.4.22-pre9/net/ipv4/netfilter/ipt_REJECT.c
--- linux-2.4.22-pre8/net/ipv4/netfilter/ipt_REJECT.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.22-pre9/net/ipv4/netfilter/ipt_REJECT.c	2003-07-29 13:06:23.000000000 -0700
@@ -1,6 +1,7 @@
 /*
  * This is a module which is used for rejecting packets.
  * Added support for customized reject packets (Jozsef Kadlecsik).
+ * Added support for ICMP type-3-code-13 (Maciej Soltysiak). [RFC 1812]
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -33,6 +34,46 @@
 		attach(new_skb, nfct);
 }
 
+static inline struct rtable *route_reverse(struct sk_buff *skb, int local)
+{
+	struct iphdr *iph = skb->nh.iph;
+	struct dst_entry *odst;
+	struct rt_key key = {};
+	struct rtable *rt;
+
+	if (local) {
+		key.dst = iph->saddr;
+		key.src = iph->daddr;
+		key.tos = RT_TOS(iph->tos);
+
+		if (ip_route_output_key(&rt, &key) != 0)
+			return NULL;
+	} else {
+		/* non-local src, find valid iif to satisfy
+		 * rp-filter when calling ip_route_input. */
+		key.dst = iph->daddr;
+		if (ip_route_output_key(&rt, &key) != 0)
+			return NULL;
+
+		odst = skb->dst;
+		if (ip_route_input(skb, iph->saddr, iph->daddr,
+		                   RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
+			dst_release(&rt->u.dst);
+			return NULL;
+		}
+		dst_release(&rt->u.dst);
+		rt = (struct rtable *)skb->dst;
+		skb->dst = odst;
+	}
+
+	if (rt->u.dst.error) {
+		dst_release(&rt->u.dst);
+		rt = NULL;
+	}
+
+	return rt;
+}
+
 /* Send RST reply */
 static void send_reset(struct sk_buff *oldskb, int local)
 {
@@ -63,10 +104,7 @@
 			 csum_partial((char *)otcph, otcplen, 0)) != 0)
 		return;
 
-	/* Routing: if not headed for us, route won't like source */
-	if (ip_route_output(&rt, oldskb->nh.iph->saddr,
-			    local ? oldskb->nh.iph->daddr : 0,
-			    RT_TOS(oldskb->nh.iph->tos), 0) != 0)
+	if ((rt = route_reverse(oldskb, local)) == NULL)
 		return;
 
 	hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
@@ -330,6 +368,9 @@
 	case IPT_ICMP_HOST_PROHIBITED:
     		send_unreach(*pskb, ICMP_HOST_ANO);
     		break;
+    	case IPT_ICMP_ADMIN_PROHIBITED:
+		send_unreach(*pskb, ICMP_PKT_FILTERED);
+		break;
 	case IPT_TCP_RESET:
 		send_reset(*pskb, hooknum == NF_IP_LOCAL_IN);
 	case IPT_ICMP_ECHOREPLY:
diff -urN linux-2.4.22-pre8/net/ipv4/netfilter/ipt_helper.c linux-2.4.22-pre9/net/ipv4/netfilter/ipt_helper.c
--- linux-2.4.22-pre8/net/ipv4/netfilter/ipt_helper.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-pre9/net/ipv4/netfilter/ipt_helper.c	2003-07-29 13:06:23.000000000 -0700
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_helper.h>
@@ -36,6 +37,7 @@
 	struct ip_conntrack_expect *exp;
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
+	int ret = 0;
 	
 	ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
 	if (!ct) {
@@ -49,23 +51,27 @@
 	}
 
 	exp = ct->master;
+	READ_LOCK(&ip_conntrack_lock);
 	if (!exp->expectant) {
 		DEBUGP("ipt_helper: expectation %p without expectant !?!\n", 
 			exp);
-		return 0;
+		goto out_unlock;
 	}
 
 	if (!exp->expectant->helper) {
 		DEBUGP("ipt_helper: master ct %p has no helper\n", 
 			exp->expectant);
-		return 0;
+		goto out_unlock;
 	}
 
 	DEBUGP("master's name = %s , info->name = %s\n", 
 		exp->expectant->helper->name, info->name);
 
-	return !strncmp(exp->expectant->helper->name, info->name, 
-			strlen(exp->expectant->helper->name)) ^ info->invert;
+	ret = !strncmp(exp->expectant->helper->name, info->name, 
+	               strlen(exp->expectant->helper->name)) ^ info->invert;
+out_unlock:
+	READ_UNLOCK(&ip_conntrack_lock);
+	return ret;
 }
 
 static int check(const char *tablename,
