ALPHA-pl14h
diff --git a/Makefile b/Makefile
index 467a14a..9d1f047 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 0.99
 PATCHLEVEL = 14
-ALPHA = g
+ALPHA = h
 
 all:	Version zImage
 
@@ -135,14 +135,13 @@
 	@echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h
 	@echo \#define LINUX_COMPILE_DOMAIN \"`domainname`\" >> tools/version.h
 
-tools/build: $(CONFIGURE) tools/build.c
-	$(HOSTCC) $(CFLAGS) \
-	-o tools/build tools/build.c
+tools/build: tools/build.c $(CONFIGURE)
+	$(HOSTCC) $(CFLAGS) -o $@ $<
 
 boot/head.o: $(CONFIGURE) boot/head.s
 
-boot/head.s: $(CONFIGURE) boot/head.S include/linux/tasks.h
-	$(CPP) -traditional boot/head.S -o boot/head.s
+boot/head.s: boot/head.S $(CONFIGURE) include/linux/tasks.h
+	$(CPP) -traditional $< -o $@
 
 tools/version.o: tools/version.c tools/version.h
 
@@ -159,19 +158,23 @@
 	nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \
 		sort > System.map
 
-boot/setup: boot/setup.s
-	$(AS86) -o boot/setup.o boot/setup.s
-	$(LD86) -s -o boot/setup boot/setup.o
+boot/setup: boot/setup.o
+	$(LD86) -s -o $@ $<
 
-boot/setup.s: $(CONFIGURE) boot/setup.S include/linux/config.h Makefile
-	$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) boot/setup.S -o boot/setup.s
+boot/setup.o: boot/setup.s
+	$(AS86) -o $@ $<
 
-boot/bootsect.s: $(CONFIGURE) boot/bootsect.S include/linux/config.h Makefile
-	$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) boot/bootsect.S -o boot/bootsect.s
+boot/setup.s: boot/setup.S $(CONFIGURE) include/linux/config.h Makefile
+	$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
 
-boot/bootsect:	boot/bootsect.s
-	$(AS86) -o boot/bootsect.o boot/bootsect.s
-	$(LD86) -s -o boot/bootsect boot/bootsect.o
+boot/bootsect: boot/bootsect.o
+	$(LD86) -s -o $@ $<
+
+boot/bootsect.o: boot/bootsect.s
+	$(AS86) -o $@ $<
+
+boot/bootsect.s: boot/bootsect.S $(CONFIGURE) include/linux/config.h Makefile
+	$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
 
 zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem
 	$(MAKE) -C zBoot
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 37eb05d..ff9b04a 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -419,10 +419,7 @@
 		bh->b_uptodate = 0;
 		ll_rw_block(READ, 1, &bh);
 	}
-	cli();
-	while (bh->b_lock)
-		sleep_on(&bh->b_wait);
-	sti();
+	wait_on_buffer(bh);
 	if (changed_floppies & mask) {
 		changed_floppies &= ~mask;
 		recalibrate = 1;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index fb46cd4..8a74b8f 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -196,8 +196,7 @@
 	mpnt->vm_end = addr + len;
 	mpnt->vm_page_prot = prot;
 	mpnt->vm_share = NULL;
-	mpnt->vm_inode = inode;
-	inode->i_count++;
+	mpnt->vm_inode = NULL;
 	mpnt->vm_offset = off;
 	mpnt->vm_ops = NULL;
 	insert_vm_struct(current, mpnt);
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index 172d8db..cb7a649 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -1573,7 +1573,7 @@
 	 */
 	if (info->flags & ASYNC_CLOSING) {
 		interruptible_sleep_on(&info->close_wait);
-		return -ERESTARTNOINTR;
+		return -EAGAIN;
 	}
 
 	/*
@@ -1631,10 +1631,7 @@
 		current->state = TASK_INTERRUPTIBLE;
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ASYNC_INITIALIZED)) {
-			if (info->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTNOINTR;
+			retval = -EAGAIN;
 			break;
 		}
 		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
@@ -1696,10 +1693,10 @@
 	tty->stop = rs_stop;
 	tty->start = rs_start;
 	tty->hangup = rs_hangup;
-	if (info->flags & ASYNC_SPLIT_TERMIOS) {
-		if (info->flags & ASYNC_NORMAL_ACTIVE)
+	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
+		if (MAJOR(filp->f_rdev) == 4) 
 			*tty->termios = info->normal_termios;
-		if (info->flags & ASYNC_CALLOUT_ACTIVE)
+		else 
 			*tty->termios = info->callout_termios;
 	}
 	/*
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 422ab50..6b58c28 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -28,11 +28,6 @@
 	@echo "Please make a new /usr/include/sys/soundcard.h containing
 	@echo "just a line #include <linux/soundcard.h>"
 
-os.h:
-	@$(MAKE) setup-$(TARGET_OS)
-	@$(MAKE) config
-	@$(MAKE) dep
-
 sound.a: $(OBJS) 
 	-rm -f sound.a
 	$(AR) rcs sound.a $(OBJS)
@@ -40,7 +35,7 @@
 
 clean:
 	rm -f core core.* *.o *.a tmp_make *~ x z *%
-	rm -f configure Makefile sound_stub.c
+	rm -f configure sound_stub.c
 	for i in *.c;do rm -f `basename $$i .c`.s;done
 
 indent:
@@ -48,15 +43,10 @@
 
 local.h:
 	$(MAKE) clean
-	$(MAKE) setup-$(TARGET_OS)
 	$(MAKE) config
 	$(MAKE) dep
 
-soundcard.c: $(TARGET_OS)/soundcard.c
-	ln -sf $(TARGET_OS)/soundcard.c soundcard.c
-
 config: configure /usr/include/sys/soundcard.h
-	@$(MAKE) setup-$(TARGET_OS)
 	@echo Compiling Sound Driver v $(VERSION) for Linux
 	@./configure > local.h
 	@echo \#define SOUND_VERSION_STRING \"$(VERSION)\" >> local.h
@@ -66,7 +56,7 @@
 	@echo \#define SOUND_CONFIG_DOMAIN \"`domainname`\" >> local.h
 
 clrconf:
-	rm -f local.h .depend os.h soundcard.c
+	rm -f local.h .depend
 
 configure: configure.c /usr/include/sys/soundcard.h
 	$(HOSTCC) -o configure configure.c
diff --git a/fs/devices.c b/fs/devices.c
index 02b5cfa..fb6e2c7 100644
--- a/fs/devices.c
+++ b/fs/devices.c
@@ -11,7 +11,6 @@
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/ext_fs.h>
-#include <linux/tty.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
diff --git a/fs/ext/fsync.c b/fs/ext/fsync.c
index a0c5d01..bb20383 100644
--- a/fs/ext/fsync.c
+++ b/fs/ext/fsync.c
@@ -16,7 +16,6 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
-#include <linux/tty.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/locks.h>
diff --git a/fs/ext/truncate.c b/fs/ext/truncate.c
index d7a6506..d14dc6c 100644
--- a/fs/ext/truncate.c
+++ b/fs/ext/truncate.c
@@ -12,7 +12,6 @@
 
 #include <linux/sched.h>
 #include <linux/ext_fs.h>
-#include <linux/tty.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
diff --git a/fs/minix/fsync.c b/fs/minix/fsync.c
index 3f2f831..737a5bf 100644
--- a/fs/minix/fsync.c
+++ b/fs/minix/fsync.c
@@ -13,7 +13,6 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
-#include <linux/tty.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/locks.h>
diff --git a/fs/minix/truncate.c b/fs/minix/truncate.c
index 0c0b0c6..bef81a3 100644
--- a/fs/minix/truncate.c
+++ b/fs/minix/truncate.c
@@ -7,7 +7,6 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
-#include <linux/tty.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index e577d29..812ee3d 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -9,7 +9,6 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/tty.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
diff --git a/fs/xiafs/fsync.c b/fs/xiafs/fsync.c
index 039272f..67681b2 100644
--- a/fs/xiafs/fsync.c
+++ b/fs/xiafs/fsync.c
@@ -13,7 +13,6 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
-#include <linux/tty.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/locks.h>
diff --git a/fs/xiafs/truncate.c b/fs/xiafs/truncate.c
index 6d7cb7f..336dcb0 100644
--- a/fs/xiafs/truncate.c
+++ b/fs/xiafs/truncate.c
@@ -12,7 +12,6 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/xia_fs.h>
-#include <linux/tty.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 
diff --git a/include/linux/sys.h b/include/linux/sys.h
index b0f4ff0..49803fb 100644
--- a/include/linux/sys.h
+++ b/include/linux/sys.h
@@ -1,3 +1,5 @@
+#ifndef _LINUX_SYS_H
+#define _LINUX_SYS_H
 /*
  * system call entry points
  */
@@ -170,3 +172,4 @@
 }
 #endif
 
+#endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index fc7f9bf..38fb5d1 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -97,7 +97,6 @@
 /*
  * Definitions for async_struct (and serial_struct) flags field
  */
-#define ASYNC_HUP_NOTIFY 0x0001 /* Notify blocked open on hangups */
 #define ASYNC_FOURPORT  0x0002	/* Set OU1, OUT2 per AST Fourport settings */
 #define ASYNC_SAK	0x0004	/* Secure Attention Key (Orange book) */
 #define ASYNC_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 42d330b..d40dc7d 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -101,6 +101,9 @@
 		do_no_page(0,addr,tsk,0);
 		goto repeat;
 	}
+/* this is a hack for non-kernel-mapped video buffers and similar */
+	if (page >= high_memory)
+		return 0;
 	page &= PAGE_MASK;
 	page += addr & ~PAGE_MASK;
 	return *(unsigned long *) page;
@@ -139,6 +142,9 @@
 		do_wp_page(PAGE_RW | PAGE_PRESENT,addr,tsk,0);
 		goto repeat;
 	}
+/* this is a hack for non-kernel-mapped video buffers and similar */
+	if (page >= high_memory)
+		return;
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 	*(unsigned long *) pte |= (PAGE_DIRTY|PAGE_COW);
 	page &= PAGE_MASK;
diff --git a/net/inet/loopback.c b/net/inet/loopback.c
index 7629425..66203eb 100644
--- a/net/inet/loopback.c
+++ b/net/inet/loopback.c
@@ -16,22 +16,22 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  */
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/io.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
-#include <linux/tty.h>
 #include <linux/types.h>
-#include <linux/ptrace.h>
 #include <linux/string.h>
 #include <linux/socket.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
 #include <linux/in.h>
 #include <linux/if_ether.h>	/* For the statistics structure. */
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+
 #include "inet.h"
 #include "dev.h"
 #include "eth.h"
diff --git a/net/inet/raw.c b/net/inet/raw.c
index 3fe317c..7533532 100644
--- a/net/inet/raw.c
+++ b/net/inet/raw.c
@@ -19,7 +19,6 @@
  *		Alan Cox	:	Checks sk->broadcast.
  *		Alan Cox	:	Uses skb_free_datagram/skb_copy_datagram
  *		Alan Cox	:	Raw passes ip options too
- *		Gerhard Koerting:	Pass the right part of the data!
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -113,9 +112,6 @@
   skb->sk = sk;
   skb->len = len;
   skb->dev = dev;
-  /* Undo IP's work and go get the IP header back [HACK] */
-  skb->h.raw = ((char *)(skb+1))+dev->hard_header_len;
-  skb->len += skb->h.iph->ihl*sizeof(long);
   skb->saddr = daddr;
   skb->daddr = saddr;
 
diff --git a/net/inet/route.c b/net/inet/route.c
index ad0572b..a06c349 100644
--- a/net/inet/route.c
+++ b/net/inet/route.c
@@ -62,222 +62,143 @@
 }
 
 
-/* Remove a routing table entry. */
-static void
-rt_del(unsigned long dst)
+/*
+ * Remove a routing table entry.
+ */
+static void rt_del(unsigned long dst)
 {
-  struct rtable *r, *x, *p;
-  unsigned long flags;
-  
-  DPRINTF((DBG_RT, "RT: flushing for dst %s\n", in_ntoa(dst)));
-  if ((r = rt_base) == NULL) 
-  	return;
+	struct rtable *r, **rp;
+	unsigned long flags;
 
-  save_flags(flags);
-  cli();
-  p = NULL;
-  while(r != NULL) 
-  {
-	if (r->rt_dst == dst) 
-	{
-		if (p == NULL)
-			rt_base = r->rt_next;
-		else 
-			p->rt_next = r->rt_next;
-		x = r->rt_next;
+	DPRINTF((DBG_RT, "RT: flushing for dst %s\n", in_ntoa(dst)));
+	rp = &rt_base;
+	save_flags(flags);
+	cli();
+	while((r = *rp) != NULL) {
+		if (r->rt_dst != dst) {
+			rp = &r->rt_next;
+			continue;
+		}
+		*rp = r->rt_next;
 		kfree_s(r, sizeof(struct rtable));
-		r = x;
 	} 
-	else 
-	{
-		p = r;
-		r = r->rt_next;
-	}
-  }
-  restore_flags(flags);
+	restore_flags(flags);
 }
 
 
-/* Remove all routing table entries for a device. */
-void
-rt_flush(struct device *dev)
+/*
+ * Remove all routing table entries for a device.
+ */
+void rt_flush(struct device *dev)
 {
-  struct rtable *r, *x, *p;
-  unsigned long flags;
-  
-  DPRINTF((DBG_RT, "RT: flushing for dev 0x%08lx (%s)\n", (long)dev, dev->name));
-  if ((r = rt_base) == NULL) return;
-  
-  cli();
-  save_flags(flags);
-  
-  p = NULL;
-  while(r != NULL) 
-  {
-	if (r->rt_dev == dev)
-	{
-		if (p == NULL) 
-			rt_base = r->rt_next;
-		else 
-		  	p->rt_next = r->rt_next;
-		x = r->rt_next;
+	struct rtable *r;
+	struct rtable **rp;
+	unsigned long flags;
+
+	DPRINTF((DBG_RT, "RT: flushing for dev 0x%08lx (%s)\n", (long)dev, dev->name));
+	rp = &rt_base;
+	cli();
+	save_flags(flags);
+	while ((r = *rp) != NULL) {
+		if (r->rt_dev != dev) {
+			rp = &r->rt_next;
+			continue;
+		}
+		*rp = r->rt_next;
 		kfree_s(r, sizeof(struct rtable));
-		r = x;
 	} 
-	else 
-	{
-		p = r;
-		r = r->rt_next;
-	}
-  }
-  restore_flags(flags);
+	restore_flags(flags);
 }
 
+/*
+ * Used by 'rt_add()' when we can't get the netmask from the device..
+ */
+static unsigned long guess_mask(unsigned long dst)
+{
+	unsigned long mask = 0xffffffff;
 
+	while (mask & dst)
+		mask <<= 8;
+	return ~mask;
+}
+
+/*
+ * rewrote rt_add(), as the old one was weird. Linus
+ */
 void
 rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
 {
-  struct rtable *r, *r1;
-  struct rtable *rt;
-  int mask=0;
-  unsigned long cpuflags;
+	struct rtable *r, *rt;
+	struct rtable **rp;
+	unsigned long mask;
+	unsigned long cpuflags;
 
-  /* Allocate an entry. */
-  rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC);
-  if (rt == NULL) {
-	DPRINTF((DBG_RT, "RT: no memory for new route!\n"));
-	return;
-  }
-
-  /* Fill in the fields. */
-  memset(rt, 0, sizeof(struct rtable));
-  rt->rt_flags = (flags | RTF_UP);
-  
-  /*
-   *	Gateway to our own interface is really direct
-   */
-  if (gw==dev->pa_addr || gw==dst)
-  {
-  	gw=0;
-  	rt->rt_flags&=~RTF_GATEWAY;
-  }
-  
-  if (gw != 0) 
-  	rt->rt_flags |= RTF_GATEWAY;
-  rt->rt_dev = dev;
-  rt->rt_gateway = gw;
-
-  /*
-   * If this is coming from an ICMP redirect message, truncate
-   * the TARGET if we are creating an entry for a NETWORK. Use
-   * an Internet class C network mask.  Yuck :-(
-   */
-  if (flags & RTF_DYNAMIC) 
-  {
-	if (flags & RTF_HOST)
+	/* Allocate an entry. */
+	rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC);
+	if (rt == NULL) {
+		DPRINTF((DBG_RT, "RT: no memory for new route!\n"));
+		return;
+	}
+	/* Fill in the fields. */
+	memset(rt, 0, sizeof(struct rtable));
+	rt->rt_flags = (flags | RTF_UP);
+  	/*
+	 * Gateway to our own interface is really direct
+	 */
+	if (gw == dev->pa_addr || gw == dst) {
+		gw=0;
+		rt->rt_flags&=~RTF_GATEWAY;
+	}
+	if (gw != 0) 
+		rt->rt_flags |= RTF_GATEWAY;
+	rt->rt_dev = dev;
+	rt->rt_gateway = gw;
+	if (flags & RTF_HOST) {
+		mask = 0xffffffff;
 		rt->rt_dst = dst;
-	else
-	{
-		/* Cut down to the route at interface mask level */
-		rt->rt_dst = (dst & dev->pa_mask);
-		mask=dev->pa_mask;
-		/* We don't want new routes to our own net*/
-		if(rt->rt_dst == (dev->pa_addr & dev->pa_mask))
-		{
-			kfree_s(rt, sizeof(struct rtable));
-			/*printk("Dynamic route to my own net rejected\n");*/
-			return;
-		}
+	} else {
+		if (!((dst ^ dev->pa_addr) & dev->pa_mask)) {
+			mask = dev->pa_mask;
+			dst &= mask;
+			if (flags & RTF_DYNAMIC) {
+				kfree_s(rt, sizeof(struct rtable));
+				/*printk("Dynamic route to my own net rejected\n");*/
+				return;
+			}
+		} else
+			mask = guess_mask(dst);
+		rt->rt_dst = dst;
 	}
-  } 
-  else 
-  	rt->rt_dst = dst;
-
-  rt_print(rt);
-
-  if (rt_base == NULL) 
-  {
-	rt->rt_next = NULL;
-	rt_base = rt;
-	return;
-  }
-
-  /*
-   * What we have to do is loop though this until we have
-   * found the first address which has the same generality
-   * as the one in rt.  Then we can put rt in after it.
-   */
-   
-  if(mask==0)	/* Dont figure out masks for DYNAMIC routes. The mask is (our should be!)
-  		   the device mask (obtained above) */
-  {
-	  for (mask = 0xff000000L; mask != 0xffffffffL; mask = (mask >> 8) | mask) 
-	  {
-		if (mask & dst) 
-		{
-			mask = mask << 8;
-			break;
-		}
-	  }
-	  DPRINTF((DBG_RT, "RT: mask = %X\n", mask));
-  }
-    
-  save_flags(cpuflags);
-  cli();
-  
-  r1 = rt_base;
-
-  /* See if we are getting a duplicate. */
-  for (r = rt_base; r != NULL; r = r->rt_next) 
-  {
-	if (r->rt_dst == dst) 
-	{
-		if (r == rt_base) 
-		{
-			rt->rt_next = r->rt_next;
-			rt_base = rt;
-		} 
-		else 
-		{
-			rt->rt_next = r->rt_next;
-			r1->rt_next = rt;
-		}
+	rt->rt_mask = mask;
+	rt_print(rt);
+	/*
+	 * What we have to do is loop though this until we have
+	 * found the first address which has a higher generality than
+	 * the one in rt.  Then we can put rt in right before it.
+	 */
+	save_flags(cpuflags);
+	cli();
+	/* remove old route if we are getting a duplicate. */
+	rp = &rt_base;
+	while ((r = *rp) != NULL) {
+	  	if (r->rt_dst != dst) {
+  			rp = &r->rt_next;
+  			continue;
+	  	}
+  		*rp = r->rt_next;
 		kfree_s(r, sizeof(struct rtable));
-		restore_flags(cpuflags);
-		return;
 	}
-	r1 = r;
-  }
-
-  r1 = rt_base;
-  for (r = rt_base; r != NULL; r = r->rt_next) 
-  {
-  	/* When we find a route more general than ourselves, and we are not a gateway or it is a gateway then use it 
-  	   This puts gateways after direct links in the table and sorts (most) of the bit aligned subnetting out */
-	if (! (r->rt_dst & mask) && (gw==0 || r->rt_flags&RTF_GATEWAY)) 
-	{
-		DPRINTF((DBG_RT, "RT: adding before r=%X\n", r));
-		rt_print(r);
-		if (r == rt_base) 
-		{
-			rt->rt_next = rt_base;
-			rt_base = rt;
-			restore_flags(cpuflags);
-			return;
-		}
-		rt->rt_next = r;
-		r1->rt_next = rt;
-		restore_flags(cpuflags);
-		return;
+	/* add the new route */
+	rp = &rt_base;
+	while ((r = *rp) != NULL) {
+		if ((r->rt_mask & mask) != mask)
+			break;
+		rp = &r->rt_next;
 	}
-	r1 = r;
-  }
-  DPRINTF((DBG_RT, "RT: adding after r1=%X\n", r1));
-  rt_print(r1);
-
-  /* Goes at the end. */
-  rt->rt_next = NULL;
-  r1->rt_next = rt;
+	rt->rt_next = r;
+	*rp = rt;
+	restore_flags(cpuflags);
+	return;
 }
 
 
@@ -360,16 +281,18 @@
 }
 
 
-struct rtable *
-rt_route(unsigned long daddr, struct options *opt)
+/*
+ * rewrote this too.. Maybe somebody can understand it now. Linus
+ */
+struct rtable * rt_route(unsigned long daddr, struct options *opt)
 {
-  struct rtable *rt;
-  int type;
+	struct rtable *rt;
+	int type;
 
   /*
    * This is a hack, I think. -FvK
    */
-  if ((type=chk_addr(daddr)) == IS_MYADDR) daddr = my_addr();
+	if ((type=chk_addr(daddr)) == IS_MYADDR) daddr = my_addr();
 
   /*
    * Loop over the IP routing table to find a route suitable
@@ -377,33 +300,23 @@
    * at the IP options to see if we have been given a hint as
    * to what kind of path we should use... -FvK
    */
-  for (rt = rt_base; rt != NULL; rt = rt->rt_next)
-	if ((rt->rt_flags & RTF_HOST) && rt->rt_dst == daddr) {
-		DPRINTF((DBG_RT, "%s (%s)\n",
-			rt->rt_dev->name, in_ntoa(rt->rt_gateway)));
-		rt->rt_use++;
-		return(rt);
+  /*
+   * This depends on 'rt_mask' and the ordering set up in 'rt_add()' - Linus
+   */
+	for (rt = rt_base; rt != NULL; rt = rt->rt_next) {
+		if (!((rt->rt_dst ^ daddr) & rt->rt_mask)) {
+			rt->rt_use++;
+			return rt;
+		}
+		/* broadcast addresses can be special cases.. */
+		if ((rt->rt_dev->flags & IFF_BROADCAST) &&
+		     rt->rt_dev->pa_brdaddr == daddr) {
+			rt->rt_use++;
+			return(rt);
+		}
 	}
-  for (rt = rt_base; rt != NULL; rt = rt->rt_next) {
-	DPRINTF((DBG_RT, "RT: %s via ", in_ntoa(daddr)));
-	if (!(rt->rt_flags & RTF_HOST) && ip_addr_match(rt->rt_dst, daddr)) {
-		DPRINTF((DBG_RT, "%s (%s)\n",
-			rt->rt_dev->name, in_ntoa(rt->rt_gateway)));
-		rt->rt_use++;
-		return(rt);
-	}
-	if ((rt->rt_dev->flags & IFF_BROADCAST) &&
-	     rt->rt_dev->pa_brdaddr == daddr) {
-		DPRINTF((DBG_RT, "%s (BCAST %s)\n",
-			rt->rt_dev->name, in_ntoa(rt->rt_dev->pa_brdaddr)));
-		rt->rt_use++;
-		return(rt);
-	}
-  }
-
-  DPRINTF((DBG_RT, "NONE\n"));
-  return(NULL);
-};
+	return NULL;
+}
 
 
 int
diff --git a/net/inet/route.h b/net/inet/route.h
index 38536d9..3d9caf6 100644
--- a/net/inet/route.h
+++ b/net/inet/route.h
@@ -26,6 +26,7 @@
 struct rtable {
   struct rtable		*rt_next;
   unsigned long		rt_dst;
+  unsigned long		rt_mask;
   unsigned long		rt_gateway;
   u_char		rt_flags;
   u_char		rt_metric;