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

diff -urN linux-2.0.39-pre3/drivers/block/ide.c linux-2.0.39-pre4/drivers/block/ide.c
--- linux-2.0.39-pre3/drivers/block/ide.c	1999-06-13 10:21:00.000000000 -0700
+++ linux-2.0.39-pre4/drivers/block/ide.c	2003-08-15 15:04:55.000000000 -0700
@@ -606,6 +606,9 @@
  *
  * Returns:	1 if lba_capacity looks sensible
  *		0 otherwise
+ *
+ * Note: we must not change id->cyls here, otherwise a second call
+ * of this routine might no longer find lba_capacity ok.
  */
 static int lba_capacity_is_ok (struct hd_driveid *id)
 {
@@ -614,14 +617,15 @@
 	unsigned long _10_percent = chs_sects / 10;
 
 	/*
-	 * very large drives (8GB+) may lie about the number of cylinders
-	 * This is a split test for drives 8 Gig and Bigger only.
-	 */
-	if ((id->lba_capacity >= 16514064) && (id->cyls == 0x3fff) &&
-	    (id->heads == 16) && (id->sectors == 63)) {
-		id->cyls = lba_sects / (16 * 63); /* correct cyls */
+	 * The ATA spec tells large drives to return
+	 * C/H/S = 16383/16/63 independent of their size.
+	 * Some drives can be jumpered to use 15 heads instead of 16.
+	 */
+	if (id->cyls == 16383 && id->sectors == 63 &&
+	    (id->heads == 15 || id->heads == 16) &&
+	    id->lba_capacity >= 16383*63*id->heads)
 		return 1;	/* lba_capacity is our only option */
-	}
+
 	/* perform a rough sanity check on lba_sects:  within 10% is "okay" */
 	if ((lba_sects - chs_sects) < _10_percent)
 		return 1;	/* lba_capacity is good */
@@ -638,11 +642,13 @@
 /*
  * current_capacity() returns the capacity (in sectors) of a drive
  * according to its current geometry/LBA settings.
+ *
+ * It also sets select.b.lba.
  */
 static unsigned long current_capacity (ide_drive_t  *drive)
 {
 	struct hd_driveid *id = drive->id;
-	unsigned long capacity = drive->cyl * drive->head * drive->sect;
+	unsigned long capacity;
 
 	if (!drive->present)
 		return 0;
@@ -652,22 +658,14 @@
 #endif /* CONFIG_BLK_DEV_IDEFLOPPY */
 	if (drive->media != ide_disk)
 		return 0x7fffffff;	/* cdrom or tape */
+
 	drive->select.b.lba = 0;
 	/* Determine capacity, and use LBA if the drive properly supports it */
+	capacity = drive->cyl * drive->head * drive->sect;
 	if (id != NULL && (id->capability & 2) && lba_capacity_is_ok(id)) {
 		if (id->lba_capacity >= capacity) {
-			drive->cyl = id->lba_capacity / (drive->head * drive->sect);
 			capacity = id->lba_capacity;
 			drive->select.b.lba = 1;
-#if 0
-			/*
-			 * This is the correct place to perform this task;
-			 * however, we do this later for reporting.
-			 */
-			if (*(int *)&id->cur_capacity0 != id->lba_capacity) {
-				*(int *)&id->cur_capacity0 = id->lba_capacity;
-			}
-#endif
 		}
 	}
 	return (capacity - drive->sect0);
@@ -697,8 +695,9 @@
 			idefloppy_setup(drive);
 #endif /* CONFIG_BLK_DEV_IDEFLOPPY */
 		drive->part[0].nr_sects = current_capacity(drive);
-		if (!drive->present || (drive->media != ide_disk && drive->media != ide_floppy) ||
-		    !drive->part[0].nr_sects) {
+		if (!drive->present
+		    || (drive->media != ide_disk && drive->media != ide_floppy)
+		    || !drive->part[0].nr_sects) {
 			drive->part[0].start_sect = -1; /* skip partition check */
 		}
 	}
@@ -2127,7 +2126,8 @@
 	};
 
 	drive->part[0].nr_sects = current_capacity(drive);
-	if ((drive->media != ide_disk && drive->media != ide_floppy) || !drive->part[0].nr_sects)
+	if ((drive->media != ide_disk && drive->media != ide_floppy)
+	    || !drive->part[0].nr_sects)
 		drive->part[0].start_sect = -1;
 	resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit);
 
@@ -2565,8 +2565,8 @@
 		drive->sect    = drive->bios_sect = id->sectors;
 	}
 	/* Handle logical geometry translation by the drive */
-	if ((id->field_valid & 1) && id->cur_cyls &&
-		id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
+	if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads
+	    && (id->cur_heads <= 16) && id->cur_sectors) {
 		/*
 		 * Extract the physical drive geometry for our use.
 		 * Note that we purposely do *not* update the bios info.
@@ -2593,12 +2593,9 @@
 	/* Use physical geometry if what we have still makes no sense */
 	if ((!drive->head || drive->head > 16) &&
 	    id->heads && id->heads <= 16) {
-		if ((id->lba_capacity > 16514064) || (id->cyls == 0x3fff)) {
-			id->cyls = ((int)(id->lba_capacity/(id->heads * id->sectors)));
-		}
-		drive->cyl  = id->cur_cyls    = id->cyls;
-		drive->head = id->cur_heads   = id->heads;
-		drive->sect = id->cur_sectors = id->sectors;
+		drive->cyl  = id->cyls;
+		drive->head = id->heads;
+		drive->sect = id->sectors;
 	}
 
 	/* calculate drive capacity, and select LBA if possible */
@@ -2608,21 +2605,17 @@
 	 * if possible, give fdisk access to more of the drive,
 	 * by correcting bios_cyls:
 	 */
-	if ((capacity >= (id->cyls * id->heads * id->sectors)) &&
-	    (!drive->forced_geom) && drive->bios_sect && drive->bios_head) {
-		drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head;
-#ifdef DEBUG
-		printk("FDISK Fixing Geometry :: CHS=%d/%d/%d to CHS=%d/%d/%d\n",
-			drive->id->cur_cyls,
-			drive->id->cur_heads,
-			drive->id->cur_sectors,
-			drive->bios_cyl,
-			drive->bios_head,
-			drive->bios_sect);
-#endif
-		drive->id->cur_cyls    = drive->bios_cyl;
-		drive->id->cur_heads   = drive->bios_head;
-		drive->id->cur_sectors = drive->bios_sect;
+	if (capacity > drive->bios_cyl * drive->bios_head * drive->bios_sect
+	    && !drive->forced_geom && drive->bios_sect && drive->bios_head) {
+		int cyl = (capacity / drive->bios_sect) / drive->bios_head;
+		if (cyl <= 65535)
+			drive->bios_cyl = cyl;
+		else {
+			/* OK until 539 GB */
+			drive->bios_sect = 63;
+			drive->bios_head = 255;
+			drive->bios_cyl = capacity / (63*255);
+		}
 	}
 
 	if (!strncmp(id->model, "BMI ", 4) &&
@@ -2666,18 +2659,6 @@
 		}
 	}
 	printk("\n");
-	if (drive->select.b.lba) {
-		if (*(int *)&id->cur_capacity0 != id->lba_capacity) {
-#ifdef DEBUG
-			printk("     CurSects=%d, LBASects=%d, ",
-				*(int *)&id->cur_capacity0, id->lba_capacity);
-#endif
-			*(int *)&id->cur_capacity0 = id->lba_capacity;
-#ifdef DEBUG
-			printk( "Fixed CurSects=%d\n", *(int *)&id->cur_capacity0);
-#endif
-		}
-	}
 }
 
 /*
@@ -3380,12 +3361,6 @@
  * Returns 1 if the geometry translation was successful.
  */
 
-/*
- * We update the values if the current CHS as determined by the kernel.
- * This now allows for the hdparm tool to read the actual settings of the
- * being used by the kernel.  This removes the need for doing guess
- * translations based on the raw values of the drive.
- */
 int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
 {
 	ide_drive_t *drive;
@@ -3397,48 +3372,14 @@
 	if (!drive)
 		return 0;
 
-	if (drive->forced_geom) {
-		/*
-		 * Update the current 3D drive values.
-		 */
-		drive->id->cur_cyls	= drive->bios_cyl;
-		drive->id->cur_heads	= drive->bios_head;
-		drive->id->cur_sectors	= drive->bios_sect;
+	if (drive->forced_geom)
 		return 0;
-	}
 
-	if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) {
-		/*
-		 * Update the current 3D drive values.
-		 */
-		drive->id->cur_cyls	= drive->bios_cyl;
-		drive->id->cur_heads	= drive->bios_head;
-		drive->id->cur_sectors	= drive->bios_sect;
+	if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63)
 		return 0;		/* we already have a translation */
-	}
 
 	printk("%s ", msg);
 
-	if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) {
-		/*
-		 * Update the current 3D drive values.
-		 */
-		drive->id->cur_cyls	= drive->bios_cyl;
-		drive->id->cur_heads	= drive->bios_head;
-		drive->id->cur_sectors	= drive->bios_sect;
-		return 0;		/* small disk: no translation needed */
-	}
-
-	if (drive->id) {
-		drive->cyl  = drive->id->cyls;
-		drive->head = drive->id->heads;
-		drive->sect = drive->id->sectors;
-	}
-	drive->bios_cyl  = drive->cyl;
-	drive->bios_head = drive->head;
-	drive->bios_sect = drive->sect;
-	drive->special.b.set_geometry = 1;
-
 	tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
 	drive->bios_sect = 63;
 	if (xparm > 1) {
@@ -3466,12 +3407,6 @@
 	}
 	drive->part[0].nr_sects = current_capacity(drive);
 	printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect);
-	/*
-	 * Update the current 3D drive values.
-	 */
-	drive->id->cur_cyls	= drive->bios_cyl;
-	drive->id->cur_heads	= drive->bios_head;
-	drive->id->cur_sectors	= drive->bios_sect;
 	return 1;
 }
 
diff -urN linux-2.0.39-pre3/drivers/net/ppp.c linux-2.0.39-pre4/drivers/net/ppp.c
--- linux-2.0.39-pre3/drivers/net/ppp.c	1999-06-13 10:21:01.000000000 -0700
+++ linux-2.0.39-pre4/drivers/net/ppp.c	2003-08-15 15:04:55.000000000 -0700
@@ -780,11 +780,16 @@
 static int
 ppp_tty_open (struct tty_struct *tty)
 {
-	struct ppp *ppp = tty2ppp (tty);
+	struct ppp *ppp;
 	int indx;
+
+	if (!suser())
+		return -EPERM;
+
 /*
  * There should not be an existing table for this slot.
  */
+	ppp = tty2ppp (tty);
 	if (ppp) {
 		if (ppp->flags & SC_DEBUG)
 			printk (KERN_ERR
diff -urN linux-2.0.39-pre3/drivers/net/slip.c linux-2.0.39-pre4/drivers/net/slip.c
--- linux-2.0.39-pre3/drivers/net/slip.c	1998-07-13 13:47:31.000000000 -0700
+++ linux-2.0.39-pre4/drivers/net/slip.c	2003-08-15 15:04:55.000000000 -0700
@@ -698,10 +698,14 @@
 static int
 slip_open(struct tty_struct *tty)
 {
-	struct slip *sl = (struct slip *) tty->disc_data;
+	struct slip *sl;
 	int err;
 
+	if (!suser())
+		return -EPERM;
+
 	/* First make sure we're not already connected. */
+	sl = (struct slip *) tty->disc_data;
 	if (sl && sl->magic == SLIP_MAGIC) {
 		return -EEXIST;
 	}
diff -urN linux-2.0.39-pre3/drivers/net/wavelan.c linux-2.0.39-pre4/drivers/net/wavelan.c
--- linux-2.0.39-pre3/drivers/net/wavelan.c	1999-06-13 10:21:02.000000000 -0700
+++ linux-2.0.39-pre4/drivers/net/wavelan.c	2003-08-15 15:04:55.000000000 -0700
@@ -324,6 +324,7 @@
 
   return crc_bytes;
 } /* psa_crc */
+#endif	/* SET_PSA_CRC */
 
 /*------------------------------------------------------------------*/
 /*
@@ -334,6 +335,7 @@
 		    u_long	ioaddr,
 		    u_short	hacr)
 {
+#ifdef SET_PSA_CRC
   psa_t		psa;
   u_short	crc;
 
@@ -363,8 +365,8 @@
   if(crc != 0)
     printk(KERN_WARNING "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n", dev->name);
 #endif /* DEBUG_IOCTL_INFO */
-} /* update_psa_checksum */
 #endif	/* SET_PSA_CRC */
+} /* update_psa_checksum */
 
 /*------------------------------------------------------------------*/
 /*
@@ -748,23 +750,23 @@
       unsigned short	ias_addr;
 
       /* Check mc_config command */
-      if((status & AC_SFLD_OK) != 0)
-	printk(KERN_INFO "wv_config_complete(): set_multicast_address failed; status = 0x%x\n",
-	       dev->name, str, status);
+      if((status & AC_SFLD_OK) != AC_SFLD_OK)
+	printk(KERN_INFO "%s: wv_config_complete(): set_multicast_address failed; status = 0x%x\n",
+	       dev->name, status);
 
       /* check ia-config command */
       ias_addr = mcs_addr - sizeof(ac_ias_t);
       obram_read(ioaddr, acoff(ias_addr, ac_status), (unsigned char *)&status, sizeof(status));
-      if((status & AC_SFLD_OK) != 0)
-	printk(KERN_INFO "wv_config_complete(): set_MAC_address; status = 0x%x\n",
-	       dev->name, str, status);
+      if((status & AC_SFLD_OK) != AC_SFLD_OK)
+	printk(KERN_INFO "%s: wv_config_complete(): set_MAC_address failed; status = 0x%x\n",
+	       dev->name, status);
 
       /* Check config command */
       cfg_addr = ias_addr - sizeof(ac_cfg_t);
       obram_read(ioaddr, acoff(cfg_addr, ac_status), (unsigned char *)&status, sizeof(status));
-      if((status & AC_SFLD_OK) != 0)
-	printk(KERN_INFO "wv_config_complete(): configure; status = 0x%x\n",
-	       dev->name, str, status);
+      if((status & AC_SFLD_OK) != AC_SFLD_OK)
+	printk(KERN_INFO "%s: wv_config_complete(): configure failed; status = 0x%x\n",
+	       dev->name, status);
 #endif	/* DEBUG_CONFIG_ERROR */
 
       ret = 1;		/* Ready to be scrapped */
@@ -800,15 +802,15 @@
       /* Read the first transmit buffer */
       obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status));
 
+      /* If not completed -> exit */
+      if((tx_status & AC_SFLD_C) == 0)
+	break;
+
       /* Hack for reconfiguration... */
       if(tx_status == 0xFFFF)
 	if(!wv_config_complete(dev, ioaddr, lp))
 	  break;	/* Not completed */
 
-      /* If not completed -> exit */
-      if((tx_status & AC_SFLD_C) == 0)
-	break;
-
       /* We now remove this buffer */
       nreaped++;
       --lp->tx_n_in_use;
@@ -841,7 +843,7 @@
 	  lp->stats.tx_packets++;
 	  ncollisions = tx_status & AC_SFLD_MAXCOL;
 	  lp->stats.collisions += ncollisions;
-#ifdef DEBUG_INTERRUPT_INFO
+#ifdef DEBUG_TX_INFO
 	  if(ncollisions > 0)
 	    printk(KERN_DEBUG "%s: wv_complete(): tx completed after %d collisions.\n",
 		   dev->name, ncollisions);
@@ -850,53 +852,49 @@
       else
 	{
 	  lp->stats.tx_errors++;
-#ifndef IGNORE_NORMAL_XMIT_ERRS
 	  if(tx_status & AC_SFLD_S10)
 	    {
 	      lp->stats.tx_carrier_errors++;
-#ifdef DEBUG_INTERRUPT_ERROR
-	      printk(KERN_INFO "%s: wv_complete(): tx error: no CS.\n",
+#ifdef DEBUG_TX_FAIL
+	      printk(KERN_DEBUG "%s: wv_complete(): tx error: no CS.\n",
 		     dev->name);
 #endif
 	    }
-#endif	/* IGNORE_NORMAL_XMIT_ERRS */
 	  if(tx_status & AC_SFLD_S9)
 	    {
 	      lp->stats.tx_carrier_errors++;
-#ifdef DEBUG_INTERRUPT_ERROR
-	      printk(KERN_INFO "%s: wv_complete(): tx error: lost CTS.\n",
+#ifdef DEBUG_TX_FAIL
+	      printk(KERN_DEBUG "%s: wv_complete(): tx error: lost CTS.\n",
 		     dev->name);
 #endif
 	    }
 	  if(tx_status & AC_SFLD_S8)
 	    {
 	      lp->stats.tx_fifo_errors++;
-#ifdef DEBUG_INTERRUPT_ERROR
-	      printk(KERN_INFO "%s: wv_complete(): tx error: slow DMA.\n",
+#ifdef DEBUG_TX_FAIL
+	      printk(KERN_DEBUG "%s: wv_complete(): tx error: slow DMA.\n",
 		     dev->name);
 #endif
 	    }
-#ifndef IGNORE_NORMAL_XMIT_ERRS
 	  if(tx_status & AC_SFLD_S6)
 	    {
 	      lp->stats.tx_heartbeat_errors++;
-#ifdef DEBUG_INTERRUPT_ERROR
-	      printk(KERN_INFO "%s: wv_complete(): tx error: heart beat.\n",
+#ifdef DEBUG_TX_FAIL
+	      printk(KERN_DEBUG "%s: wv_complete(): tx error: heart beat.\n",
 		     dev->name);
 #endif
 	    }
 	  if(tx_status & AC_SFLD_S5)
 	    {
 	      lp->stats.tx_aborted_errors++;
-#ifdef DEBUG_INTERRUPT_ERROR
-	      printk(KERN_INFO "%s: wv_complete(): tx error: too many collisions.\n",
+#ifdef DEBUG_TX_FAIL
+	      printk(KERN_DEBUG "%s: wv_complete(): tx error: too many collisions.\n",
 		     dev->name);
 #endif
 	    }
-#endif	/* IGNORE_NORMAL_XMIT_ERRS */
 	}
 
-#ifdef DEBUG_INTERRUPT_INFO
+#ifdef DEBUG_TX_INFO
       printk(KERN_DEBUG "%s: wv_complete(): tx completed, tx_status 0x%04x\n",
 	     dev->name, tx_status);
 #endif
@@ -1323,21 +1321,21 @@
 	       char *		msg1,		/* Name of the device */
 	       char *		msg2)		/* Name of the function */
 {
-#ifndef DEBUG_PACKET_DUMP
+  int		i;
+  int		maxi;
+
   printk(KERN_DEBUG "%s: %s(): dest %02X:%02X:%02X:%02X:%02X:%02X, length %d\n",
 	 msg1, msg2, p[0], p[1], p[2], p[3], p[4], p[5], length);
   printk(KERN_DEBUG "%s: %s(): src %02X:%02X:%02X:%02X:%02X:%02X, type 0x%02X%02X\n",
 	 msg1, msg2, p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13]);
 
-#else	/* DEBUG_PACKET_DUMP */
-  int		i;
-  int		maxi;
+#ifdef DEBUG_PACKET_DUMP
 
-  printk(KERN_DEBUG "%s: %s(): len=%d, data=\"", msg1, msg2, length);
+  printk(KERN_DEBUG "data=\"");
 
   if((maxi = length) > DEBUG_PACKET_DUMP)
     maxi = DEBUG_PACKET_DUMP;
-  for(i = 0; i < maxi; i++)
+  for(i = 14; i < maxi; i++)
     if(p[i] >= ' ' && p[i] <= '~')
       printk(" %c", p[i]);
     else
@@ -1565,7 +1563,9 @@
 /*------------------------------------------------------------------*/
 /*
  * This function doesn't exist...
+ * (Note : it was a nice way to test the reconfigure stuff...)
  */
+#ifdef SET_MAC_ADDRESS
 static int
 wavelan_set_mac_address(device *	dev,
 			void *		addr)
@@ -1580,6 +1580,7 @@
 
   return 0;
 }
+#endif	/* SET_MAC_ADDRESS */
 
 #ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
 
@@ -1940,10 +1941,8 @@
 	  /* Disable nwid in the mmc (no filtering) */
 	  mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
 	}
-#ifdef SET_PSA_CRC
       /* update the Wavelan checksum */
       update_psa_checksum(dev, ioaddr, lp->hacr);
-#endif
       break;
 
     case SIOCGIWNWID:
@@ -2001,10 +2000,8 @@
       psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F;
       psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
 	       (unsigned char *) &psa.psa_thr_pre_set, 1);
-#ifdef SET_PSA_CRC
       /* update the Wavelan checksum */
       update_psa_checksum(dev, ioaddr, lp->hacr);
-#endif
       mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set);
       break;
 
@@ -2052,10 +2049,8 @@
 
 	   mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
 	 }
-#ifdef SET_PSA_CRC
        /* update the Wavelan checksum */
        update_psa_checksum(dev, ioaddr, lp->hacr);
-#endif
        break;
 
      case SIOCGIWENCODE:
@@ -2269,10 +2264,8 @@
       psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
       psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
 	       (unsigned char *)&psa.psa_quality_thr, 1);
-#ifdef SET_PSA_CRC
       /* update the Wavelan checksum */
       update_psa_checksum(dev, ioaddr, lp->hacr);
-#endif
       mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr);
       break;
 
@@ -2435,7 +2428,7 @@
 
 #ifdef DEBUG_RX_TRACE
   printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n",
-	 dev->name, fd_p, sksize);
+	 dev->name, buf_off, sksize);
 #endif
 
   /* Allocate buffer for the data */
@@ -2520,6 +2513,8 @@
 {
   u_long	ioaddr = dev->base_addr;
   net_local *	lp = (net_local *)dev->priv;
+  fd_t		fd;
+  rbd_t		rbd;
   int		nreaped = 0;
 
 #ifdef DEBUG_RX_TRACE
@@ -2529,48 +2524,62 @@
   /* Loop on each received packet */
   for(;;)
     {
-      fd_t		fd;
-      rbd_t		rbd;
-      ushort		pkt_len;
-
       obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd, sizeof(fd));
 
-      /* If the current frame is not complete, we have reach the end... */
+      /* Note about the status :
+       * It start up to be 0 (the value we set). Then, when the RU
+       * grab the buffer to prepare for reception, it sets the
+       * FD_STATUS_B flag. When the RU has finished receiving the
+       * frame, it clears FD_STATUS_B, set FD_STATUS_C to indicate
+       * completion and set the other flags to indicate the eventual
+       * errors. FD_STATUS_OK indicates that the reception was OK.
+       */
+
+      /* If the current frame is not complete, we have reached the end. */
       if((fd.fd_status & FD_STATUS_C) != FD_STATUS_C)
-	break;		/* This is how we exit the loop */
+	break;		/* This is how we exit the loop. */
 
       nreaped++;
 
-      /* Check if frame correctly received */
-      if((fd.fd_status & (FD_STATUS_B | FD_STATUS_OK)) !=
-	 (FD_STATUS_B | FD_STATUS_OK))
+      /* Check whether frame was correctly received. */
+      if((fd.fd_status & FD_STATUS_OK) == FD_STATUS_OK)
 	{
-	  /*
-	   * Not sure about this one -- it does not seem
-	   * to be an error so we will keep quiet about it.
-	   */
-#ifndef IGNORE_NORMAL_XMIT_ERRS
-#ifdef DEBUG_RX_ERROR
-	  if((fd.fd_status & FD_STATUS_B) != FD_STATUS_B)
-	    printk(KERN_INFO "%s: wv_receive(): frame not consumed by RU.\n",
-		   dev->name);
-#endif
-#endif	/* IGNORE_NORMAL_XMIT_ERRS */
+	  /* Does the frame contain a pointer to the data?  Let's check. */
+	  if(fd.fd_rbd_offset != I82586NULL)
+	    {
+	      /* Read the receive buffer descriptor */
+	      obram_read(ioaddr, fd.fd_rbd_offset,
+			 (unsigned char *) &rbd, sizeof(rbd));
 
 #ifdef DEBUG_RX_ERROR
-	  if((fd.fd_status & FD_STATUS_OK) != FD_STATUS_OK)
-	    printk(KERN_INFO "%s: wv_receive(): frame not received successfully.\n",
+	      if((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF)
+		printk(KERN_INFO "%s: wv_receive(): missing EOF flag.\n",
+		       dev->name);
+
+	      if((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F)
+		printk(KERN_INFO "%s: wv_receive(): missing F flag.\n",
+		       dev->name);
+#endif	/* DEBUG_RX_ERROR */
+
+	      /* Read the packet and transmit to Linux */
+	      wv_packet_read(dev, rbd.rbd_bufl,
+			     rbd.rbd_status & RBD_STATUS_ACNT);
+	    }
+#ifdef DEBUG_RX_ERROR
+	  else	/* if frame has no data */
+	    printk(KERN_INFO "%s: wv_receive(): frame has no data.\n",
 		   dev->name);
 #endif
 	}
-
-      /* Were there problems in processing the frame?  Let's check. */
-      if((fd.fd_status & (FD_STATUS_S6 | FD_STATUS_S7 | FD_STATUS_S8 |
-			  FD_STATUS_S9 | FD_STATUS_S10 | FD_STATUS_S11))
-	 != 0)
+      else	/* If reception was no successful */
 	{
 	  lp->stats.rx_errors++;
 
+#ifdef DEBUG_RX_INFO
+	  printk(KERN_DEBUG "%s: wv_receive(): frame not received successfully (%X).\n",
+		 dev->name, fd.fd_status);
+#endif
+
 #ifdef DEBUG_RX_ERROR
 	  if((fd.fd_status & FD_STATUS_S6) != 0)
 	    printk(KERN_INFO "%s: wv_receive(): no EOF flag.\n", dev->name);
@@ -2579,8 +2588,8 @@
 	  if((fd.fd_status & FD_STATUS_S7) != 0)
 	    {
 	      lp->stats.rx_length_errors++;
-#ifdef DEBUG_RX_ERROR
-	      printk(KERN_INFO "%s: wv_receive(): frame too short.\n",
+#ifdef DEBUG_RX_FAIL
+	      printk(KERN_DEBUG "%s: wv_receive(): frame too short.\n",
 		     dev->name);
 #endif
 	    }
@@ -2588,8 +2597,8 @@
 	  if((fd.fd_status & FD_STATUS_S8) != 0)
 	    {
 	      lp->stats.rx_over_errors++;
-#ifdef DEBUG_RX_ERROR
-	      printk(KERN_INFO "%s: wv_receive(): rx DMA overrun.\n",
+#ifdef DEBUG_RX_FAIL
+	      printk(KERN_DEBUG "%s: wv_receive(): rx DMA overrun.\n",
 		     dev->name);
 #endif
 	    }
@@ -2597,8 +2606,8 @@
 	  if((fd.fd_status & FD_STATUS_S9) != 0)
 	    {
 	      lp->stats.rx_fifo_errors++;
-#ifdef DEBUG_RX_ERROR
-	      printk(KERN_INFO "%s: wv_receive(): ran out of resources.\n",
+#ifdef DEBUG_RX_FAIL
+	      printk(KERN_DEBUG "%s: wv_receive(): ran out of resources.\n",
 		     dev->name);
 #endif
 	    }
@@ -2606,8 +2615,8 @@
 	  if((fd.fd_status & FD_STATUS_S10) != 0)
 	    {
 	      lp->stats.rx_frame_errors++;
-#ifdef DEBUG_RX_ERROR
-	      printk(KERN_INFO "%s: wv_receive(): alignment error.\n",
+#ifdef DEBUG_RX_FAIL
+	      printk(KERN_DEBUG "%s: wv_receive(): alignment error.\n",
 		     dev->name);
 #endif
 	    }
@@ -2615,38 +2624,12 @@
 	  if((fd.fd_status & FD_STATUS_S11) != 0)
 	    {
 	      lp->stats.rx_crc_errors++;
-#ifdef DEBUG_RX_ERROR
-	      printk(KERN_INFO "%s: wv_receive(): CRC error.\n", dev->name);
+#ifdef DEBUG_RX_FAIL
+	      printk(KERN_DEBUG "%s: wv_receive(): CRC error.\n", dev->name);
 #endif
 	    }
 	}
 
-      /* Does the frame contain a pointer to the data?  Let's check. */
-      if(fd.fd_rbd_offset == I82586NULL)
-#ifdef DEBUG_RX_ERROR
-	printk(KERN_INFO "%s: wv_receive(): frame has no data.\n", dev->name);
-#endif
-      else
-	{
-	  obram_read(ioaddr, fd.fd_rbd_offset,
-		     (unsigned char *) &rbd, sizeof(rbd));
-
-#ifdef DEBUG_RX_ERROR
-	  if((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF)
-	    printk(KERN_INFO "%s: wv_receive(): missing EOF flag.\n",
-		   dev->name);
-
-	  if((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F)
-	    printk(KERN_INFO "%s: wv_receive(): missing F flag.\n",
-		   dev->name);
-#endif
-
-	  pkt_len = rbd.rbd_status & RBD_STATUS_ACNT;
-
-	  /* Read the packet and transmit to Linux */
-	  wv_packet_read(dev, rbd.rbd_bufl, pkt_len);
-	}	/* if frame has data */
-
       fd.fd_status = 0;
       obram_write(ioaddr, fdoff(lp->rx_head, fd_status),
 		  (unsigned char *) &fd.fd_status, sizeof(fd.fd_status));
@@ -2781,7 +2764,7 @@
   /*
    * Data
    */
-  obram_write(ioaddr, buf_addr, buf, clen);
+  obram_write(ioaddr, buf_addr, buf, length);
 
   /*
    * Overwrite the predecessor NOP link
@@ -2967,11 +2950,9 @@
 		(unsigned char *)&psa.psa_quality_thr, 1);
       psa_write(ioaddr, lp->hacr, (char *)&psa.psa_conf_status - (char *)&psa,
 		(unsigned char *)&psa.psa_conf_status, 1);
-#ifdef SET_PSA_CRC
       /* update the Wavelan checksum */
       update_psa_checksum(dev, ioaddr, lp->hacr);
 #endif
-#endif
     }
 
   /* Zero the mmc structure */
@@ -3142,7 +3123,7 @@
 
   if(i <= 0)
     {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
       printk(KERN_INFO "%s: wavelan_ru_start(): board not accepting command.\n",
 	     dev->name);
 #endif
@@ -3246,7 +3227,7 @@
 
   if(i <= 0)
     {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
       printk(KERN_INFO "%s: wavelan_cu_start(): board not accepting command.\n",
 	     dev->name);
 #endif
@@ -3332,7 +3313,7 @@
 
   if(i <= 0)
     {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
       printk(KERN_INFO "%s: wv_82586_start(): iscp_busy timeout.\n",
 	     dev->name);
 #endif
@@ -3352,7 +3333,7 @@
 
   if (i <= 0)
     {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
       printk(KERN_INFO "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n",
 	     dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status);
 #endif
@@ -3373,7 +3354,7 @@
   obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
   if(cb.ac_status & AC_SFLD_FAIL)
     {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
       printk(KERN_INFO "%s: wv_82586_start(): i82586 Self Test failed.\n",
 	     dev->name);
 #endif
@@ -3654,13 +3635,16 @@
   wv_ints_on(dev);
 
   /* Start card functions */
-  if((wv_ru_start(dev) < 0) ||
-     (wv_cu_start(dev) < 0))
+  if(wv_cu_start(dev) < 0)
     return -1;
 
-  /* Finish configuration */
+  /* Setup the controller and parameters */
   wv_82586_config(dev);
 
+  /* Finish configuration with the receive unit */
+  if(wv_ru_start(dev) < 0)
+    return -1;
+
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name);
 #endif
@@ -3968,7 +3952,7 @@
   /* Check irq */
   if(dev->irq == 0)
     {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
       printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n", dev->name);
 #endif
       return -ENXIO;
@@ -3980,7 +3964,7 @@
      (request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", NULL) != 0))
     {
       irq2dev_map[dev->irq] = (device *) NULL;
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
       printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n", dev->name);
 #endif
       return -EAGAIN;
@@ -3996,7 +3980,7 @@
     {
       free_irq(dev->irq, NULL);
       irq2dev_map[dev->irq] = (device *) NULL;
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
       printk(KERN_INFO "%s: wavelan_open(): impossible to start the card\n",
 	     dev->name);
 #endif
@@ -4094,10 +4078,8 @@
 #endif
 	  psa_write(ioaddr, HACR_DEFAULT,
 		    psaoff(0, psa_int_req_no), &irq_mask, 1);
-#ifdef SET_PSA_CRC
 	  /* update the Wavelan checksum */
 	  update_psa_checksum(dev, ioaddr, HACR_DEFAULT);
-#endif
 	  wv_hacr_reset(ioaddr);
 	}
     }
@@ -4151,7 +4133,9 @@
   dev->hard_start_xmit = wavelan_packet_xmit;
   dev->get_stats = wavelan_get_stats;
   dev->set_multicast_list = &wavelan_set_multicast_list;
+#ifdef SET_MAC_ADDRESS
   dev->set_mac_address = &wavelan_set_mac_address;
+#endif	/* SET_MAC_ADDRESS */
 
 #ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
   dev->do_ioctl = wavelan_ioctl;
@@ -4207,7 +4191,7 @@
   /* Don't probe at all. */
   if(base_addr < 0)
     {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
       printk(KERN_WARNING "%s: wavelan_probe(): invalid base address\n",
 	     dev->name);
 #endif
@@ -4290,7 +4274,7 @@
   /* If probing is asked */
   if(io[0] == 0)
     {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
       printk(KERN_WARNING "WaveLAN init_module(): doing device probing (bad !)\n");
       printk(KERN_WARNING "Specify base addresses while loading module to correct the problem\n");
 #endif
@@ -4334,7 +4318,7 @@
 	}	/* if there is something at the address */
     }		/* Loop on all addresses. */
 
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
   if(wavelan_list == (net_local *) NULL)
     printk(KERN_WARNING "WaveLAN init_module(): no device found\n");
 #endif
diff -urN linux-2.0.39-pre3/drivers/net/wavelan.p.h linux-2.0.39-pre4/drivers/net/wavelan.p.h
--- linux-2.0.39-pre3/drivers/net/wavelan.p.h	1999-06-13 10:21:02.000000000 -0700
+++ linux-2.0.39-pre4/drivers/net/wavelan.p.h	2003-08-15 15:04:55.000000000 -0700
@@ -34,11 +34,22 @@
  *	I try to maintain a web page with the Wireless LAN Howto at :
  *		http://www-uk.hpl.hp.com/people/jt/Linux/Wavelan.html
  *
+ * Debugging and options
+ * ---------------------
+ *	You will find below a set of '#define" allowing a very fine control
+ *	on the driver behaviour and the debug messages printed.
+ *	The main options are :
+ *	o SET_PSA_CRC, to have your card correctly recognised by
+ *	  an access point and the Point-to-Point diagnostic tool.
+ *	o USE_PSA_CONFIG, to read configuration from the PSA (EEprom)
+ *	  (otherwise we always start afresh with some defaults)
+ *
  * wavelan.o is darn too big
  * -------------------------
  *	That's true ! There is a very simple way to reduce the driver
  *	object by 33% (yes !). Comment out the following line :
  *		#include <linux/wireless.h>
+ *	Other compile options can also reduce the size of it...
  *
  * Debugging and options
  * ---------------------
@@ -272,7 +283,17 @@
  *	- Correct i82586 configuration parameters
  *	- Encryption initialisation bug (Robert McCormack)
  *	- New mac addresses detected in the probe
- *	- Increase watchdog for busy envirnoments
+ *	- Increase watchdog for busy environments
+ *
+ * Changes made for release in 2.0.38 & 2.2.7 :
+ * ------------------------------------------
+ *	- Correct the reception logic to better report errors and avoid
+ *	  sending bogus packet up the stack
+ *	- Delay RU config to avoid corrupting first received packet
+ *	- Change config completion code (to actually check something)
+ *	- Avoid reading out of bound in skbuf to transmit
+ *	- Rectify a lot of (useless) debugging code
+ *	- Change the way to `#ifdef SET_PSA_CRC'
  *
  * Wishes & dreams :
  * ---------------
@@ -311,6 +332,24 @@
 #include	"i82586.h"
 #include	"wavelan.h"
 
+/************************** DRIVER OPTIONS **************************/
+/*
+ * `#define' or `#undef' the following constant to change the behaviour
+ * of the driver...
+ */
+#undef SET_PSA_CRC		/* Calculate and set the CRC on PSA (slower) */
+#define USE_PSA_CONFIG		/* Use info from the PSA. */
+#undef STRUCT_CHECK		/* Verify padding of structures. */
+#undef EEPROM_IS_PROTECTED	/* doesn't seem to be necessary */
+#define MULTICAST_AVOID		/* Avoid extra multicast (I'm sceptical). */
+#undef SET_MAC_ADDRESS		/* Experimental */
+
+#ifdef WIRELESS_EXT	/* If wireless extensions exist in the kernel */
+/* Warning:  this stuff will slow down the driver. */
+#define WIRELESS_SPY		/* Enable spying addresses. */
+#undef HISTOGRAM		/* Enable histogram of signal level. */
+#endif
+
 /****************************** DEBUG ******************************/
 
 #undef DEBUG_MODULE_TRACE	/* Module insertion/removal */
@@ -320,14 +359,16 @@
 #define DEBUG_INTERRUPT_ERROR	/* problems */
 #undef DEBUG_CONFIG_TRACE	/* Trace the config functions */
 #undef DEBUG_CONFIG_INFO	/* What's going on... */
-#define DEBUG_CONFIG_ERRORS	/* Errors on configuration */
+#define DEBUG_CONFIG_ERROR	/* Errors on configuration */
 #undef DEBUG_TX_TRACE		/* Transmission calls */
 #undef DEBUG_TX_INFO		/* Header of the transmited packet */
-#define DEBUG_TX_ERROR		/* unexpected conditions */
+#undef DEBUG_TX_FAIL		/* Normal failure conditions */
+#define DEBUG_TX_ERROR		/* Unexpected conditions */
 #undef DEBUG_RX_TRACE		/* Transmission calls */
-#undef DEBUG_RX_INFO		/* Header of the transmited packet */
-#define DEBUG_RX_ERROR		/* unexpected conditions */
-#undef DEBUG_PACKET_DUMP	16	/* Dump packet on the screen */
+#undef DEBUG_RX_INFO		/* Header of the received packet */
+#undef DEBUG_RX_FAIL		/* Normal failure conditions */
+#define DEBUG_RX_ERROR		/* Unexpected conditions */
+#undef DEBUG_PACKET_DUMP	32	/* Dump packet on the screen */
 #undef DEBUG_IOCTL_TRACE	/* Misc call by Linux */
 #undef DEBUG_IOCTL_INFO		/* Various debug info */
 #define DEBUG_IOCTL_ERROR	/* What's going wrong */
@@ -339,26 +380,10 @@
 #undef DEBUG_I82586_SHOW	/* Show i82586 status */
 #undef DEBUG_DEVICE_SHOW	/* Show device parameters */
 
-/* Options : */
-#define USE_PSA_CONFIG		/* Use info from the PSA */
-#define SET_PSA_CRC		/* Calculate and set the CRC on PSA */
-#define IGNORE_NORMAL_XMIT_ERRS	/* Don't bother with normal conditions */
-#undef STRUCT_CHECK		/* Verify padding of structures */
-#undef OLDIES			/* Old code (to redo) */
-#undef RECORD_SNR		/* To redo */
-#undef EEPROM_IS_PROTECTED	/* Doesn't seem to be necessary */
-#define MULTICAST_AVOID		/* Avoid extra multicast (I'm sceptical) */
-
-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
-/* Warning : these stuff will slow down the driver... */
-#define WIRELESS_SPY		/* Enable spying addresses */
-#undef HISTOGRAM		/* Enable histogram of sig level... */
-#endif
-
 /************************ CONSTANTS & MACROS ************************/
 
 #ifdef DEBUG_VERSION_SHOW
-static const char	*version	= "wavelan.c : v18 (wireless extensions) 18/2/99\n";
+static const char	*version	= "wavelan.c : v19 (wireless extensions) 20/4/99\n";
 #endif
 
 /* Watchdog temporisation */
diff -urN linux-2.0.39-pre3/fs/binfmt_elf.c linux-2.0.39-pre4/fs/binfmt_elf.c
--- linux-2.0.39-pre3/fs/binfmt_elf.c	1998-06-03 15:17:49.000000000 -0700
+++ linux-2.0.39-pre4/fs/binfmt_elf.c	2003-08-15 15:04:55.000000000 -0700
@@ -197,28 +197,20 @@
 	     interp_elf_ex->e_type != ET_DYN) ||
 	    !elf_check_arch(interp_elf_ex->e_machine) ||
 	    (!interpreter_inode->i_op ||
-	     !interpreter_inode->i_op->default_file_ops->mmap)) {
+	     !interpreter_inode->i_op->default_file_ops->mmap) ||
+	    interp_elf_ex->e_phentsize != sizeof(struct elf_phdr) ||
+	    interp_elf_ex->e_phnum < 1 ||
+	    interp_elf_ex->e_phnum > PAGE_SIZE / sizeof(struct elf_phdr)) {
 		return ~0UL;
 	}
 	/* Now read in all of the header information */
 
-	if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE)
-		 return ~0UL;
-
 	elf_phdata = (struct elf_phdr *)
 	    kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum,
 		    GFP_KERNEL);
 	if (!elf_phdata)
 		return ~0UL;
 
-	/*
-	 * If the size of this structure has changed, then punt, since
-	 * we will be doing the wrong thing.
-	 */
-	if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
-		kfree(elf_phdata);
-		return ~0UL;
-	}
 	retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff,
 			   (char *) elf_phdata,
 		    sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, 1);
@@ -306,6 +298,11 @@
 	kfree(elf_phdata);
 
 	*interp_load_addr = load_addr;
+	/*
+	 * AUDIT: is everything deallocated properly if this happens
+	 * to be ~0UL? We'd better switch to out-of-band error reporting.
+	 * Also for a.out.
+	 */
 	return ((unsigned long) interp_elf_ex->e_entry) + load_addr;
 }
 
@@ -397,7 +394,10 @@
 	     elf_ex.e_type != ET_DYN) ||
 	    (!elf_check_arch(elf_ex.e_machine)) ||
 	    (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
-	     !bprm->inode->i_op->default_file_ops->mmap)) {
+	     !bprm->inode->i_op->default_file_ops->mmap) ||
+	    elf_ex.e_phentsize != sizeof(struct elf_phdr) ||
+	    elf_ex.e_phnum < 1 ||
+	    elf_ex.e_phnum > 0xfff0 / sizeof(struct elf_phdr)) {
 		return -ENOEXEC;
 	}
 	/* Now read in all of the header information */
@@ -434,12 +434,14 @@
 
 	for (i = 0; i < elf_ex.e_phnum; i++) {
 		if (elf_ppnt->p_type == PT_INTERP) {
-			if (elf_interpreter != NULL) {
+			if (elf_interpreter != NULL ||
+			    elf_ppnt->p_filesz < 2 ||
+			    elf_ppnt->p_filesz > PAGE_SIZE) {
 				iput(interpreter_inode);
 				kfree(elf_phdata);
 				kfree(elf_interpreter);
 				sys_close(elf_exec_fileno);
-				return -EINVAL;
+				return -ENOEXEC;
 			}
 			/* This is the program interpreter used for
 			 * shared libraries - for now assume that this
@@ -456,6 +458,7 @@
 			retval = read_exec(bprm->inode, elf_ppnt->p_offset,
 					   elf_interpreter,
 					   elf_ppnt->p_filesz, 1);
+			elf_interpreter[elf_ppnt->p_filesz - 1] = 0;
 			/* If the program interpreter is one of these two,
 			   then assume an iBCS2 image. Otherwise assume
 			   a native linux image. */
@@ -629,14 +632,17 @@
 						    &interp_load_addr);
 
 		iput(interpreter_inode);
-		kfree(elf_interpreter);
 
 		if (elf_entry == ~0UL) {
-			printk("Unable to load interpreter\n");
+			printk("Unable to load interpreter %.128s\n",
+				elf_interpreter);
+			kfree(elf_interpreter);
 			kfree(elf_phdata);
 			send_sig(SIGSEGV, current, 0);
 			return 0;
 		}
+
+		kfree(elf_interpreter);
 	}
 	kfree(elf_phdata);
 
diff -urN linux-2.0.39-pre3/fs/dquot.c linux-2.0.39-pre4/fs/dquot.c
--- linux-2.0.39-pre3/fs/dquot.c	1998-07-13 13:47:34.000000000 -0700
+++ linux-2.0.39-pre4/fs/dquot.c	2003-08-15 15:04:55.000000000 -0700
@@ -143,14 +143,17 @@
 		return;
 	dqstats.pages_allocated++;
 	cnt = PAGE_SIZE / sizeof(struct dquot);
+	memset(dquot, 0, PAGE_SIZE);
 	nr_dquots += cnt;
 	nr_free_dquots += cnt;
 	if (!first_dquot) {
 		dquot->dq_next = dquot->dq_prev = first_dquot = dquot++;
 		cnt--;
 	}
-	for (; cnt; cnt--)
+	for (; cnt; cnt--) {
+		init_waitqueue(&dquot->dq_wait);
 		insert_dquot_free(dquot++);
+	}
 }
 
 /*
@@ -219,11 +222,18 @@
 	short type = dquot->dq_type;
 	struct file *filp = dquot->dq_mnt->mnt_quotas[type];
 	unsigned short fs;
+	struct dqblk wrt_dquot;
 
 	if (!(dquot->dq_flags & DQ_MOD) || (filp == (struct file *)NULL))
 		return;
 	lock_dquot(dquot);
+	if (!dquot->dq_mnt) {	/* Invalidated dquot? */
+		unlock_dquot(dquot);
+		return;
+	}
 	down(&dquot->dq_mnt->mnt_sem);
+	dquot->dq_flags &= ~DQ_MOD;	/* Clear the flag unconditionally - we don't want to loop on error */
+	memcpy(&wrt_dquot, &dquot->dq_dqb, sizeof(struct dqblk));	/* Copy structure so we can unlock it */
 	if (filp->f_op->lseek) {
 		if (filp->f_op->lseek(filp->f_inode, filp,
 		    dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) {
@@ -238,14 +248,13 @@
 		if(p>=0)
 			filp->f_pos = p;
 	}
+	unlock_dquot(dquot);	/* We have to unlock structure as write might need to update it */
 	fs = get_fs();
 	set_fs(KERNEL_DS);
-	if (filp->f_op->write(filp->f_inode, filp,
-	   (char *)&dquot->dq_dqb, sizeof(struct dqblk)) == sizeof(struct dqblk))
-		dquot->dq_flags &= ~DQ_MOD;
+	if (filp->f_op->write(filp->f_inode, filp, (char *)&wrt_dquot, sizeof(struct dqblk)) != sizeof(struct dqblk))
+		printk(KERN_ERR "VFS: write_dquot() failed.\n");
 	up(&dquot->dq_mnt->mnt_sem);
 	set_fs(fs);
-	unlock_dquot(dquot);
 	dqstats.writes++;
 }
 
@@ -286,14 +295,18 @@
 	int i;
 
 	dqstats.syncs++;
+restart:
 	for (i = 0; i < nr_dquots * 2; i++, dquot = dquot->dq_next) {
 		if (dev == NODEV || dquot->dq_count == 0 || dquot->dq_dev != dev)
 			continue;
 		if (type != -1 && dquot->dq_type != type)
 			continue;
+		if (!(dquot->dq_flags & DQ_MOD))	/* It might get modified I know but to restart after each locked dquot... */
+			continue;
 		wait_on_dquot(dquot);
 		if (dquot->dq_flags & DQ_MOD)
 			write_dquot(dquot);
+		goto restart;
 	}
 	return(0);
 }
@@ -306,6 +319,7 @@
 	struct dquot *dquot, *next;
 	int cnt;
 
+restart:
 	next = first_dquot;
 	for (cnt = nr_dquots ; cnt > 0 ; cnt--) {
 		dquot = next;
@@ -316,10 +330,14 @@
 			printk("VFS: dquot busy on removed device %s\n", kdevname(dev));
 			continue;
 		}
-		if (dquot->dq_flags & DQ_MOD)
+		if (dquot->dq_flags & DQ_MOD) {
 			write_dquot(dquot);
+			dqstats.drops++;
+			clear_dquot(dquot);
+			goto restart;	/* As we might block inside of write or clear_dquot */
+		}
 		dqstats.drops++;
-		clear_dquot(dquot);
+		clear_dquot(dquot);	/* Here we can't block - DQ_LOCKED was tested before */
 	}
 }
 
@@ -463,30 +481,34 @@
 	 * checking and doesn't need to be written. It just an empty
 	 * dquot that is put back into the freelist.
 	 */
-	if (dquot->dq_mnt != (struct vfsmount *)NULL) {
-		dqstats.drops++;
-		wait_on_dquot(dquot);
+repeat:
+	if (dquot->dq_mnt) {	/* We can block inside of wait and so we have to check again */
+		if (dquot->dq_flags & DQ_LOCKED) {
+			__wait_on_dquot(dquot);
+			goto repeat;
+		}
+			
 		if (!dquot->dq_count) {
 			printk("VFS: dqput: trying to free free dquot\n");
 			printk("VFS: device %s, dquot of %s %d\n", kdevname(dquot->dq_dev),
 			       quotatypes[dquot->dq_type], dquot->dq_id);
 			return;
 		}
-repeat:
 		if (dquot->dq_count > 1) {
 			dquot->dq_count--;
 			return;
 		}
-		wake_up(&dquot_wait);
 		if (dquot->dq_flags & DQ_MOD) {
 			write_dquot(dquot);	/* we can sleep - so do again */
 			wait_on_dquot(dquot);
 			goto repeat;
 		}
+		dqstats.drops++;
 	}
 	if (dquot->dq_count) {
 		dquot->dq_count--;
 		nr_free_dquots++;
+		wake_up(&dquot_wait);	/* Here the dquot is really free */
 	}
 	return;
 }
@@ -583,6 +605,14 @@
 	put_last_free(dquot);
 	insert_dquot_hash(dquot);
 	read_dquot(dquot);
+	if (!dquot->dq_mnt) {	/* Invalidated in the mean time? */
+	/*
+	 * As quota was turned off we can just return NODQUOT. I know it's
+	 * not perfect as somebody might turn quota on again but...
+	 */
+		dqput(dquot);
+		return NODQUOT;
+	}
 	return(dquot);
 }
 
@@ -959,9 +989,11 @@
 		vfsmnt->mnt_sb->dq_op = (struct dquot_operations *)NULL;
 		reset_dquot_ptrs(dev, cnt);
 		invalidate_dquots(dev, cnt);
+		down(&vfsmnt->mnt_sem);	/* Wait for any pending IO - dquot is not locked on write so we can easily go here during write */
 		close_fp(vfsmnt->mnt_quotas[cnt]);
 		vfsmnt->mnt_quotas[cnt] = (struct file *)NULL;
 		vfsmnt->mnt_iexp[cnt] = vfsmnt->mnt_bexp[cnt] = (time_t)NULL;
+		up(&vfsmnt->mnt_sem);
 	}
 	return(0);
 }
diff -urN linux-2.0.39-pre3/fs/exec.c linux-2.0.39-pre4/fs/exec.c
--- linux-2.0.39-pre3/fs/exec.c	1998-07-13 13:47:34.000000000 -0700
+++ linux-2.0.39-pre4/fs/exec.c	2003-08-15 15:04:55.000000000 -0700
@@ -178,26 +178,51 @@
 
 /*
  * count() counts the number of arguments/envelopes
- *
- * We also do some limited EFAULT checking: this isn't complete, but
- * it does cover most cases. I'll have to do this correctly some day..
  */
-static int count(char ** argv)
+static int count(void *base, int size, int max)
 {
 	int error, i = 0;
-	char ** tmp, *p;
+	void *tmp = base;
+	unsigned long length = 0, chunk = size, limit;
+	int grow = 1;
+
+	if (!tmp) return 0;
+
+	limit = PAGE_SIZE - ((unsigned long)tmp & (PAGE_SIZE - 1));
+	error = verify_area(VERIFY_READ, tmp, limit);
+	if (error) limit = 0;
+
+	do {
+		if (length >= limit)
+		do {
+			if (!grow) {
+				if (chunk <= sizeof(char *))
+					return -EFAULT;
+				chunk >>= 1;
+			}
+			error = verify_area(VERIFY_READ, tmp, chunk);
+			if (error) grow = 0; else {
+				limit += chunk;
+				if (grow) chunk <<= 1;
+			}
+		} while (error);
 
-	if ((tmp = argv) != NULL) {
-		error = verify_area(VERIFY_READ, tmp, sizeof(char *));
-		if (error)
-			return error;
-		while ((p = get_user(tmp++)) != NULL) {
-			i++;
-			error = verify_area(VERIFY_READ, p, 1);
-			if (error)
-				return error;
+		if (size == 1) {
+			do {
+				if (!get_user(((char *)tmp)++)) goto out;
+				if (++i > max) return -E2BIG;
+			} while (i < limit);
+			length = i;
+		} else {
+			do {
+				if (!get_user(((char **)tmp)++)) goto out;
+				if ((length += size) > max) return -E2BIG;
+				i++;
+			} while (length < limit);
 		}
-	}
+	} while (1);
+
+out:
 	return i;
 }
 
@@ -221,12 +246,12 @@
 unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
 		unsigned long p, int from_kmem)
 {
-	char *tmp, *tmp1, *pag = NULL;
+	char *tmp, *pag = NULL;
 	int len, offset = 0;
 	unsigned long old_fs, new_fs;
 
-	if (!p)
-		return 0;	/* bullet-proofing */
+	if ((long)p <= 0)
+		return p;	/* bullet-proofing */
 	new_fs = get_ds();
 	old_fs = get_fs();
 	if (from_kmem==2)
@@ -234,16 +259,16 @@
 	while (argc-- > 0) {
 		if (from_kmem == 1)
 			set_fs(new_fs);
-		if (!(tmp1 = tmp = get_user(argv+argc)))
+		if (!(tmp = get_user(argv+argc)))
 			panic("VFS: argc is wrong");
 		if (from_kmem == 1)
 			set_fs(old_fs);
-		while (get_user(tmp++));
-		len = tmp - tmp1;
-		if (p < len) {	/* this shouldn't happen - 128kB */
+		len = count(tmp, 1, p);
+		if (len < 0 || len >= p) {	/* EFAULT or E2BIG */
 			set_fs(old_fs);
-			return 0;
+			return len < 0 ? len : -E2BIG;
 		}
+		tmp += ++len;
 		while (len) {
 			--p; --tmp; --len;
 			if (--offset < 0) {
@@ -253,7 +278,7 @@
 				if (!(pag = (char *) page[p/PAGE_SIZE]) &&
 				    !(pag = (char *) page[p/PAGE_SIZE] =
 				      (unsigned long *) get_free_page(GFP_USER))) 
-					return 0;
+					return -EFAULT;
 				if (from_kmem==2)
 					set_fs(new_fs);
 
@@ -559,6 +584,27 @@
 			if (!suser())
 				return -EPERM;
 		}
+
+		/*
+		 * Increment the privileged execution counter, so that our
+		 * old children know not to send bad exit_signal's to us.
+		 */
+		if (!++current->priv) {
+			struct task_struct *p;
+
+			/*
+			 * The counter can't really overflow with real-world
+			 * programs (and it has to be the privileged program
+			 * itself that causes the overflow), but we handle
+			 * this case anyway, just for correctness.
+			 */
+			for_each_task(p) {
+				if (p->p_pptr == current) {
+					p->ppriv = 0;
+					current->priv = 1;
+				}
+			}
+		}
 	}
 
 	memset(bprm->buf,0,sizeof(bprm->buf));
@@ -601,6 +647,8 @@
 		bprm->dont_iput = 1;
 		remove_arg_zero(bprm);
 		bprm->p = copy_strings(1, dynloader, bprm->page, bprm->p, 2);
+		if ((long)bprm->p < 0)
+			return (long)bprm->p;
 		bprm->argc++;
 		bprm->loader = bprm->p;
 		retval = open_namei(dynloader[0], 0, 0, &bprm->inode, NULL);
@@ -673,9 +721,9 @@
 	bprm.loader = 0;
 	bprm.exec = 0;
 	bprm.dont_iput = 0;
-	if ((bprm.argc = count(argv)) < 0)
+	if ((bprm.argc = count(argv, sizeof(char *), bprm.p)) < 0)
 		return bprm.argc;
-	if ((bprm.envc = count(envp)) < 0)
+	if ((bprm.envc = count(envp, sizeof(char *), bprm.p)) < 0)
 		return bprm.envc;
 
 	retval = prepare_binprm(&bprm);
@@ -685,8 +733,8 @@
 		bprm.exec = bprm.p;
 		bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p,0);
 		bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p,0);
-		if (!bprm.p)
-			retval = -E2BIG;
+		if ((long)bprm.p < 0)
+			retval = (long)bprm.p;
 	}
 
 	if(retval>=0)
diff -urN linux-2.0.39-pre3/fs/proc/array.c linux-2.0.39-pre4/fs/proc/array.c
--- linux-2.0.39-pre3/fs/proc/array.c	1999-06-13 10:21:03.000000000 -0700
+++ linux-2.0.39-pre4/fs/proc/array.c	2003-08-15 15:04:55.000000000 -0700
@@ -610,6 +610,7 @@
 			vsize += vma->vm_end - vma->vm_start;
 			vma = vma->vm_next;
 		}
+		if ((current->fsuid == tsk->euid && tsk->dumpable) || suser())
 		if (tsk->kernel_stack_page) {
 			eip = KSTK_EIP(tsk);
 			esp = KSTK_ESP(tsk);
@@ -1026,7 +1027,7 @@
 		case PROC_PID_CMDLINE:
 			return 0;	
 	}
-	if(suser() || current->fsuid == (*p)->euid)
+	if ((current->fsuid == (*p)->euid && (*p)->dumpable) || suser())
 		return 0;
 	return 1;
 }
diff -urN linux-2.0.39-pre3/fs/proc/fd.c linux-2.0.39-pre4/fs/proc/fd.c
--- linux-2.0.39-pre3/fs/proc/fd.c	1997-11-12 20:36:41.000000000 -0800
+++ linux-2.0.39-pre4/fs/proc/fd.c	2003-08-15 15:04:55.000000000 -0700
@@ -86,6 +86,7 @@
 	}
 	iput(dir);
 	fd = 0;
+	if (len > 1 && *name == '0') fd = 0xfffff; else
 	while (len-- > 0) {
 		c = *name - '0';
 		name++;
diff -urN linux-2.0.39-pre3/fs/proc/mem.c linux-2.0.39-pre4/fs/proc/mem.c
--- linux-2.0.39-pre3/fs/proc/mem.c	2003-08-15 15:04:55.000000000 -0700
+++ linux-2.0.39-pre4/fs/proc/mem.c	1998-11-15 10:33:14.000000000 -0800
@@ -17,17 +17,16 @@
 
 /*
  * mem_write isn't really a good idea right now. It needs
- * to check a lot more: if the process we try to write to
+ * to check a lot more: if the process we try to write to 
  * dies in the middle right now, mem_write will overwrite
  * kernel memory.. This disables it altogether.
  */
 #define mem_write NULL
 
-static ssize_t check_range(struct mm_struct * mm, unsigned long addr,
-			   size_t count)
+static int check_range(struct mm_struct * mm, unsigned long addr, int count)
 {
 	struct vm_area_struct *vma;
-	ssize_t retval;
+	int retval;
 
 	vma = find_vma(mm, addr);
 	if (!vma)
@@ -77,8 +76,7 @@
 	return tsk;
 }
 
-static ssize_t mem_read(struct inode * inode, struct file * file,
-			char * buf, size_t count)
+static int mem_read(struct inode * inode, struct file * file,char * buf, int count)
 {
 	pgd_t *page_dir;
 	pmd_t *page_middle;
@@ -87,7 +85,7 @@
 	struct task_struct * tsk;
 	unsigned long addr;
 	char *tmp;
-	ssize_t scount, i;
+	int i;
 
 	if (count < 0)
 		return -EINVAL;
@@ -95,11 +93,11 @@
 	if (!tsk)
 		return -ESRCH;
 	addr = file->f_pos;
-	scount = check_range(tsk->mm, addr, count);
-	if (scount < 0)
-		return scount;
+	count = check_range(tsk->mm, addr, count);
+	if (count < 0)
+		return count;
 	tmp = buf;
-	while (scount > 0) {
+	while (count > 0) {
 		if (current->signal & ~current->blocked)
 			break;
 		page_dir = pgd_offset(tsk->mm,addr);
@@ -123,12 +121,12 @@
 			break;
 		page = (char *) pte_page(pte) + (addr & ~PAGE_MASK);
 		i = PAGE_SIZE-(addr & ~PAGE_MASK);
-		if (i > scount)
-			i = scount;
+		if (i > count)
+			i = count;
 		memcpy_tofs(tmp, page, i);
 		addr += i;
 		tmp += i;
-		scount -= i;
+		count -= i;
 	}
 	file->f_pos = addr;
 	return tmp-buf;
@@ -136,8 +134,7 @@
 
 #ifndef mem_write
 
-static ssize_t mem_write(struct inode * inode, struct file * file,
-			 char * buf, ssize_t count)
+static int mem_write(struct inode * inode, struct file * file,char * buf, int count)
 {
 	pgd_t *page_dir;
 	pmd_t *page_middle;
@@ -146,7 +143,7 @@
 	struct task_struct * tsk;
 	unsigned long addr;
 	char *tmp;
-	ssize_t i;
+	int i;
 
 	if (count < 0)
 		return -EINVAL;
@@ -198,8 +195,7 @@
 
 #endif
 
-static off_t mem_lseek(struct inode * inode, struct file * file,
-		       off_t offset, int orig)
+static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
 {
 	switch (orig) {
 		case 0:
diff -urN linux-2.0.39-pre3/fs/proc/root.c linux-2.0.39-pre4/fs/proc/root.c
--- linux-2.0.39-pre3/fs/proc/root.c	1996-04-30 03:09:45.000000000 -0700
+++ linux-2.0.39-pre4/fs/proc/root.c	2003-08-15 15:04:55.000000000 -0700
@@ -466,6 +466,7 @@
 		}
 		pid *= 10;
 		pid += c;
+		if (!pid) break;
 		if (pid & 0xffff0000) {
 			pid = 0;
 			break;
diff -urN linux-2.0.39-pre3/include/linux/sched.h linux-2.0.39-pre4/include/linux/sched.h
--- linux-2.0.39-pre3/include/linux/sched.h	1997-12-02 14:18:11.000000000 -0800
+++ linux-2.0.39-pre4/include/linux/sched.h	2003-08-15 15:04:55.000000000 -0700
@@ -244,6 +244,8 @@
 	struct mm_struct *mm;
 /* signal handlers */
 	struct signal_struct *sig;
+/* privileged execution counters, for exit_signal permission checking */
+	int priv, ppriv;
 #ifdef __SMP__
 	int processor;
 	int last_processor;
@@ -309,6 +311,7 @@
 /* files */	&init_files, \
 /* mm */	&init_mm, \
 /* signals */	&init_signals, \
+/* priv */	0, 0, \
 }
 
 extern struct   mm_struct init_mm;
diff -urN linux-2.0.39-pre3/include/net/ip_masq.h linux-2.0.39-pre4/include/net/ip_masq.h
--- linux-2.0.39-pre3/include/net/ip_masq.h	1999-06-13 10:21:04.000000000 -0700
+++ linux-2.0.39-pre4/include/net/ip_masq.h	2003-08-15 15:04:55.000000000 -0700
@@ -24,6 +24,8 @@
 #define PORT_MASQ_BEGIN	61000
 #define PORT_MASQ_END	(PORT_MASQ_BEGIN+4096)
 
+#define IP_MASQ_TAB_SIZE 256	/* MUST be a power of 2 */
+
 /*
  * Default timeouts for masquerade functions The control channels now
  * expire the same as TCP channels (other than being updated by
@@ -113,6 +115,18 @@
 
 extern int ip_masq_free_ports[3];
 
+#ifdef CONFIG_IP_MASQUERADE_IPSEC
+/*
+ *	Any application support module that changes the destination
+ *	IP or port *must* rehash if IPsec masq is enabled
+ */
+extern struct ip_masq *ip_masq_m_tab[IP_MASQ_TAB_SIZE];
+extern struct ip_masq *ip_masq_s_tab[IP_MASQ_TAB_SIZE];
+extern struct ip_masq *ip_masq_d_tab[IP_MASQ_TAB_SIZE];
+extern __inline__ int ip_masq_hash(struct ip_masq *ms);
+extern __inline__ int ip_masq_unhash(struct ip_masq *ms);
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
+
 /*
  *	ip_masq initializer (registers symbols and /proc/net entries)
  */
diff -urN linux-2.0.39-pre3/kernel/exit.c linux-2.0.39-pre4/kernel/exit.c
--- linux-2.0.39-pre3/kernel/exit.c	1998-06-03 15:17:50.000000000 -0700
+++ linux-2.0.39-pre4/kernel/exit.c	2003-08-15 15:04:55.000000000 -0700
@@ -118,7 +118,8 @@
 
 void notify_parent(struct task_struct * tsk, int signal)
 {
-	send_sig(signal, tsk->p_pptr, 1);
+	send_sig(signal, tsk->p_pptr, !signal || signal == SIGCHLD ||
+		tsk->p_pptr->priv == tsk->ppriv);
 	wake_up_interruptible(&tsk->p_pptr->wait_chldexit);
 }
 
diff -urN linux-2.0.39-pre3/kernel/fork.c linux-2.0.39-pre4/kernel/fork.c
--- linux-2.0.39-pre3/kernel/fork.c	1998-06-03 15:17:50.000000000 -0700
+++ linux-2.0.39-pre4/kernel/fork.c	2003-08-15 15:04:55.000000000 -0700
@@ -228,10 +228,23 @@
 int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
 {
 	int nr;
-	int error = -ENOMEM;
+	int error = -EINVAL;
 	unsigned long new_stack;
 	struct task_struct *p;
 
+/*
+ * Disallow unknown clone(2) flags, as well as CLONE_PID, unless we are
+ * the boot up thread.
+ *
+ * Avoid taking any branches in the common case.
+ */
+	if (clone_flags &
+	    (-(signed long)current->pid >> (sizeof(long) * 8 - 1)) &
+	    ~(unsigned long)(CSIGNAL |
+	    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND))
+		goto bad_fork;
+
+	error = -ENOMEM;
 	p = (struct task_struct *) kmalloc(sizeof(*p), GFP_KERNEL);
 	if (!p)
 		goto bad_fork;
@@ -264,6 +277,8 @@
 	p->p_cptr = NULL;
 	init_waitqueue(&p->wait_chldexit);
 	p->signal = 0;
+	p->priv = 0;
+	p->ppriv = current->priv;
 	p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
 	p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
 	init_timer(&p->real_timer);
diff -urN linux-2.0.39-pre3/net/ipv4/ip_masq.c linux-2.0.39-pre4/net/ipv4/ip_masq.c
--- linux-2.0.39-pre3/net/ipv4/ip_masq.c	1999-06-13 10:21:04.000000000 -0700
+++ linux-2.0.39-pre4/net/ipv4/ip_masq.c	2003-08-15 15:04:55.000000000 -0700
@@ -1,8 +1,8 @@
 /*
  *
- * 	Masquerading functionality
+ *	Masquerading functionality
  *
- * 	Copyright (c) 1994 Pauline Middelink
+ *	Copyright (c) 1994 Pauline Middelink
  *
  *	See ip_fw.c for original log
  *
@@ -20,8 +20,9 @@
  *	Delian Delchev		:	Added support for ICMP requests and replys
  *	Nigel Metheringham	:	ICMP in ICMP handling, tidy ups, bug fixes, made ICMP optional
  *	Juan Jose Ciarlante	:	re-assign maddr if no packet received from outside
- * 	John D. Hardin		:	Added PPTP and IPSEC protocols
- *	
+ *	John D. Hardin		:	Added PPTP and IPSEC protocols
+ *	Rudolf Lippan		:	dest hashing bugfix
+ *
  */
 
 #include <linux/config.h>
@@ -44,8 +45,6 @@
 #include <net/ip_masq.h>
 #include <linux/ip_fw.h>
 
-#define IP_MASQ_TAB_SIZE 256    /* must be power of 2 */
-
 #ifdef CONFIG_IP_MASQUERADE_PPTP
 /*
  * This is clumsier than it otherwise might be (i.e. the
@@ -301,6 +300,10 @@
         X(ip_masq_set_expire),
         X(ip_masq_free_ports),
 	X(ip_masq_expire),
+#ifdef CONFIG_IP_MASQUERADE_IPSEC
+	X(ip_masq_hash),
+	X(ip_masq_unhash),
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
 	X(ip_masq_out_get_2),
 #include <linux/symtab_end.h>
 };
@@ -445,7 +448,10 @@
  *	returns bool success.
  */
 
-static __inline__ int
+#ifndef CONFIG_IP_MASQUERADE_IPSEC
+static
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
+__inline__ int
 ip_masq_hash(struct ip_masq *ms)
 {
         unsigned hash;
@@ -495,7 +501,10 @@
  *	returns bool success.
  */
 
-static __inline__ int ip_masq_unhash(struct ip_masq *ms)
+#ifndef CONFIG_IP_MASQUERADE_IPSEC
+static
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
+__inline__ int ip_masq_unhash(struct ip_masq *ms)
 {
         unsigned hash;
         struct ip_masq ** ms_p;
@@ -3158,16 +3167,38 @@
                  */
 
                 if ( ms->flags & IP_MASQ_F_NO_DPORT && ms->protocol == IPPROTO_TCP ) {
+#ifdef CONFIG_IP_MASQUERADE_IPSEC
+			unsigned long flags;
+			save_flags(flags);
+			cli();
+			ip_masq_unhash(ms);
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
                         ms->flags &= ~IP_MASQ_F_NO_DPORT;
                         ms->dport = portptr[0];
+#ifdef CONFIG_IP_MASQUERADE_IPSEC
+			ip_masq_hash(ms);
+			restore_flags(flags);
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
+
 #ifdef DEBUG_CONFIG_IP_MASQUERADE
                         printk("ip_fw_demasquerade(): filled dport=%d\n",
                                ntohs(ms->dport));
 #endif
                 }
                 if (ms->flags & IP_MASQ_F_NO_DADDR && ms->protocol == IPPROTO_TCP)  {
+#ifdef CONFIG_IP_MASQUERADE_IPSEC
+			unsigned long flags;
+			save_flags(flags);
+			cli();
+			ip_masq_unhash(ms);
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
                         ms->flags &= ~IP_MASQ_F_NO_DADDR;
                         ms->daddr = iph->saddr;
+#ifdef CONFIG_IP_MASQUERADE_IPSEC
+			ip_masq_hash(ms);
+			restore_flags(flags);
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
+
 #ifdef DEBUG_CONFIG_IP_MASQUERADE
                         printk("ip_fw_demasquerade(): filled daddr=%X\n",
                                ntohs(ms->daddr));
diff -urN linux-2.0.39-pre3/net/ipv4/ip_masq_quake.c linux-2.0.39-pre4/net/ipv4/ip_masq_quake.c
--- linux-2.0.39-pre3/net/ipv4/ip_masq_quake.c	1998-11-15 10:33:21.000000000 -0800
+++ linux-2.0.39-pre4/net/ipv4/ip_masq_quake.c	2003-08-15 15:04:55.000000000 -0700
@@ -85,6 +85,9 @@
 int
 masq_quake_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, struct device *dev)
 {
+#ifdef CONFIG_IP_MASQUERADE_IPSEC
+	unsigned long flags;
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
 	struct sk_buff *skb;
 	struct iphdr *iph;
 	struct udphdr *uh;
@@ -155,7 +158,16 @@
 
 	  memcpy(&udp_port, data, 2);
 
+#ifdef CONFIG_IP_MASQUERADE_IPSEC
+	  save_flags(flags);
+	  cli();
+	  ip_masq_unhash(ms);
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
 	  ms->dport = htons(udp_port);
+#ifdef CONFIG_IP_MASQUERADE_IPSEC
+	  ip_masq_hash(ms);
+	  restore_flags(flags);
+#endif /* CONFIG_IP_MASQUERADE_IPSEC */
 
 #if DEBUG_CONFIG_IP_MASQ_QUAKE
 	  printk("Quake_in: in_rewrote UDP port %d \n", udp_port);
diff -urN linux-2.0.39-pre3/net/ipv4/tcp_input.c linux-2.0.39-pre4/net/ipv4/tcp_input.c
--- linux-2.0.39-pre3/net/ipv4/tcp_input.c	2003-08-15 15:04:55.000000000 -0700
+++ linux-2.0.39-pre4/net/ipv4/tcp_input.c	2003-08-15 15:04:55.000000000 -0700
@@ -1186,6 +1186,15 @@
 	 *	then we can probably ignore it.
 	 */
 	 
+	if (sk->state == TCP_SYN_RECV) {
+		/*
+		 * Should be the exact sequence number for the handshake
+		 * to succeed, or sequence prediction gets a bit easier.
+		 * Also, "partially-established" connections are bad for
+		 * the rest of our code.
+		 */
+		if (ack != sk->sent_seq) goto uninteresting_ack;
+	} else
 	if (after(ack, sk->sent_seq) || before(ack, sk->rcv_ack_seq)) 
 		goto uninteresting_ack;
 
