diff -u --recursive --new-file v1.3.65/linux/Makefile linux/Makefile
--- v1.3.65/linux/Makefile	Sat Feb 17 16:02:44 1996
+++ linux/Makefile	Sat Feb 17 17:28:07 1996
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 65
+SUBLEVEL = 66
 
 ARCH = i386
 
diff -u --recursive --new-file v1.3.65/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.3.65/linux/drivers/char/console.c	Sat Feb 17 16:02:47 1996
+++ linux/drivers/char/console.c	Sat Feb 17 17:15:10 1996
@@ -1386,7 +1386,7 @@
 	if (currcons == sel_cons)
 		clear_selection();
 
-	disable_bh(KEYBOARD_BH);
+	disable_bh(CONSOLE_BH);
 	while (!tty->stopped &&	count) {
 		c = from_user ? get_user(buf) : *buf;
 		buf++; n++; count--;
@@ -1820,7 +1820,7 @@
 	}
 	if (vcmode != KD_GRAPHICS)
 		set_cursor(currcons);
-	enable_bh(KEYBOARD_BH);
+	enable_bh(CONSOLE_BH);
 	return n;
 }
 
diff -u --recursive --new-file v1.3.65/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v1.3.65/linux/drivers/char/keyboard.c	Sat Feb 17 16:02:48 1996
+++ linux/drivers/char/keyboard.c	Sat Feb 17 16:59:52 1996
@@ -376,6 +376,7 @@
 		goto end_kbd_intr;
 	}
 	do_poke_blanked_console = 1;
+	mark_bh(CONSOLE_BH);
 	add_keyboard_randomness(scancode);
 
 	tty = ttytab[fg_console];
diff -u --recursive --new-file v1.3.65/linux/include/linux/ip_fw.h linux/include/linux/ip_fw.h
--- v1.3.65/linux/include/linux/ip_fw.h	Fri Feb  9 17:53:08 1996
+++ linux/include/linux/ip_fw.h	Sat Feb 17 17:42:52 1996
@@ -20,6 +20,7 @@
  *					chains, new "insert" and "append"
  *					commands to replace "add" commands,
  *					add ICMP header to struct ip_fwpkt.
+ *	Jos Vos			:	Add support for matching device names.
  *
  *	All the real work was done by .....
  */
@@ -55,6 +56,7 @@
 	struct in_addr fw_src, fw_dst;		/* Source and destination IP addr */
 	struct in_addr fw_smsk, fw_dmsk;	/* Mask for src and dest IP addr */
 	struct in_addr fw_via;			/* IP address of interface "via" */
+	struct device *fw_viadev;		/* device of interface "via" */
 	unsigned short fw_flg;			/* Flags word */
 	unsigned short fw_nsp, fw_ndp;          /* N'of src ports and # of dst ports */
 						/* in ports array (dst ports follow */
@@ -63,7 +65,8 @@
 #define IP_FW_MAX_PORTS	10      		/* A reasonable maximum */
 	unsigned short fw_pts[IP_FW_MAX_PORTS]; /* Array of port numbers to match */
 	unsigned long  fw_pcnt,fw_bcnt;		/* Packet and byte counters */
-	unsigned char fw_tosand, fw_tosxor;	/* Revised packet priority */
+	unsigned char  fw_tosand, fw_tosxor;	/* Revised packet priority */
+	char           fw_vianame[IFNAMSIZ];	/* name of interface "via" */
 };
 
 /*
@@ -112,6 +115,7 @@
 #define IP_FW_IN		1
 #define IP_FW_OUT		2
 #define IP_FW_ACCT		3
+#define IP_FW_CHAINS		4	/* total number of ip_fw chains */
 
 #define IP_FW_INSERT		(IP_FW_BASE_CTL)
 #define IP_FW_APPEND		(IP_FW_BASE_CTL+1)
@@ -160,6 +164,7 @@
 		struct icmphdr fwp_icmph;	/* ICMP header */
 	} fwp_protoh;
 	struct in_addr fwp_via;			/* interface address */
+	char           fwp_vianame[IFNAMSIZ];	/* interface name */
 };
 
 /*
diff -u --recursive --new-file v1.3.65/linux/include/net/tcp.h linux/include/net/tcp.h
--- v1.3.65/linux/include/net/tcp.h	Wed Feb 14 14:37:19 1996
+++ linux/include/net/tcp.h	Sat Feb 17 17:34:24 1996
@@ -295,24 +295,33 @@
 
 static __inline__ void tcp_set_state(struct sock *sk, int state)
 {
-	if(sk->state==TCP_ESTABLISHED)
-		tcp_statistics.TcpCurrEstab--;
+	int oldstate = sk->state;
+
+	sk->state = state;
+
 #ifdef STATE_TRACE
 	if(sk->debug)
-		printk("TCP sk=%p, State %s -> %s\n",sk, statename[sk->state],statename[state]);
+		printk("TCP sk=%p, State %s -> %s\n",sk, statename[oldstate],statename[state]);
 #endif	
-	/* This is a hack but it doesn't occur often and it's going to
-	   be a real        to fix nicely */
-	   
-	if(state==TCP_ESTABLISHED && sk->state==TCP_SYN_RECV)
-	{
-		wake_up_interruptible(&master_select_wakeup);
-	}
-	sk->state=state;
-	if(state==TCP_ESTABLISHED)
-		tcp_statistics.TcpCurrEstab++;
-	if(sk->state==TCP_CLOSE)
+
+	switch (state) {
+	case TCP_ESTABLISHED:
+		if (oldstate != TCP_ESTABLISHED) {
+			tcp_statistics.TcpCurrEstab++;
+			/* This is a hack but it doesn't occur often and it's going to
+			   be a real        to fix nicely */
+			if (oldstate == TCP_SYN_RECV)
+				wake_up_interruptible(&master_select_wakeup);
+		}
+		break;
+
+	case TCP_CLOSE:
 		tcp_cache_zap();
+		/* fall through */
+	default:
+		if (oldstate==TCP_ESTABLISHED)
+			tcp_statistics.TcpCurrEstab--;
+	}
 }
 
 #endif	/* _TCP_H */
diff -u --recursive --new-file v1.3.65/linux/net/core/sock.c linux/net/core/sock.c
--- v1.3.65/linux/net/core/sock.c	Sat Feb 17 16:02:57 1996
+++ linux/net/core/sock.c	Sat Feb 17 16:02:22 1996
@@ -570,10 +570,10 @@
 		sk->users = 0;
 		barrier();
 	}
-	if (sk->dead && sk->state == TCP_CLOSE) 
-	{
+
+	if (sk->dead && sk->state == TCP_CLOSE) {
 		/* Should be about 2 rtt's */
-		reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME));
+   		reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME));
 	}
 #endif  
 }
diff -u --recursive --new-file v1.3.65/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v1.3.65/linux/net/ipv4/ip_fw.c	Sat Feb 17 16:02:58 1996
+++ linux/net/ipv4/ip_fw.c	Sat Feb 17 16:42:40 1996
@@ -31,6 +31,8 @@
  *	only delete the first matching entry, use 0xFFFF (0xFF) as ports (ICMP
  *	types) when counting packets being 2nd and further fragments.
  *		Jos Vos <jos@xos.nl> 8/2/1996.
+ *	Add support for matching on device names.
+ *		Jos Vos <jos@xos.nl> 15/2/1996.
  *
  * Masquerading functionality
  *
@@ -363,13 +365,23 @@
 		if (match)
 		{
 			/*
-			 *	Look for a VIA match 
+			 *	Look for a VIA address match 
 			 */
 			if(f->fw_via.s_addr && rif)
 			{
 				if(rif->pa_addr!=f->fw_via.s_addr)
 					continue;	/* Mismatch */
 			}
+
+			/*
+			 *	Look for a VIA device match 
+			 */
+			if(f->fw_viadev)
+			{
+				if(rif!=f->fw_viadev)
+					continue;	/* Mismatch */
+			}
+
 			/*
 			 *	Drop through - this is a match
 			 */
@@ -472,43 +484,39 @@
 			break;
 	} /* Loop */
 	
-	answer = FW_BLOCK;
-	
-	/*
-	 * We rely on policy defined in the rejecting entry or, if no match
-	 * was found, we rely on the general policy variable for this type
-	 * of firewall.
-	 */
+	if (opt != 1) {
 
-	if(f!=NULL) 
-	{
-		policy=f->fw_flg;
-		tosand=f->fw_tosand;
-		tosxor=f->fw_tosxor;
-	}
-	else
-	{
-		tosand=0xFF;
-		tosxor=0x00;
-	}
-	
-	if(opt != 1) 
-	{
-		if(policy&IP_FW_F_ACCEPT)
+		/*
+		 * We rely on policy defined in the rejecting entry or, if no match
+		 * was found, we rely on the general policy variable for this type
+		 * of firewall.
+		 */
+
+		if (f!=NULL) {
+			policy=f->fw_flg;
+			tosand=f->fw_tosand;
+			tosxor=f->fw_tosxor;
+		} else {
+			tosand=0xFF;
+			tosxor=0x00;
+		}
+
+		if (policy&IP_FW_F_ACCEPT) {
+			/* Adjust priority and recompute checksum */
+			__u8 old_tos = ip->tos;
+			ip->tos = (old_tos & tosand) ^ tosxor;
+			if (ip->tos != old_tos)
+		 		ip_send_check(ip);
 			answer=(policy&IP_FW_F_MASQ)?FW_MASQUERADE:FW_ACCEPT;
+		} else if(policy&IP_FW_F_ICMPRPL)
+			answer = FW_REJECT;
 		else
-			if(policy&IP_FW_F_ICMPRPL)
-				answer = FW_REJECT;
-	}
-
-	if (policy&IP_FW_F_ACCEPT) { /* Adjust priority and recompute checksum */
-		__u8 old_tos = ip->tos;
-		ip->tos = (old_tos & tosand) ^ tosxor;
-		if (ip->tos != old_tos)
-		 	ip_send_check(ip);
-	}
+			answer = FW_BLOCK;
 
-	return answer;
+		return answer;
+	} else
+		/* we're doing accounting, always ok */
+		return 0;
 }
 
 #ifdef CONFIG_IP_MASQUERADE
@@ -897,6 +905,7 @@
  		}
  		else ms->timer.expires = jiffies+MASQUERADE_EXPIRE_TCP;
  
+		skb->csum = csum_partial(th + 1, size - sizeof(*th), 0);
  		tcp_send_check(th,iph->saddr,iph->daddr,size,skb);
  	}
  	add_timer(&ms->timer);
@@ -1002,6 +1011,8 @@
 #endif
 					}
 				}
+				skb->csum = csum_partial(portptr + sizeof(struct tcphdr),
+					size - sizeof(struct tcphdr), 0);
  				tcp_send_check((struct tcphdr *)portptr,iph->saddr,iph->daddr,size,skb);
  			}
  			ip_send_check(iph);
@@ -1072,6 +1083,12 @@
 
 	cli();
 
+	if ((ftmp->fw_vianame)[0]) {
+		if (!(ftmp->fw_viadev = dev_get(ftmp->fw_vianame)))
+			ftmp->fw_viadev = (struct device *) -1;
+	} else
+		ftmp->fw_viadev = NULL;
+
 	ftmp->fw_next = *chainptr;
        	*chainptr=ftmp;
 	restore_flags(flags);
@@ -1106,6 +1123,12 @@
 
 	cli();
 
+	if ((ftmp->fw_vianame)[0]) {
+		if (!(ftmp->fw_viadev = dev_get(ftmp->fw_vianame)))
+			ftmp->fw_viadev = (struct device *) -1;
+	} else
+		ftmp->fw_viadev = NULL;
+
 	chtmp_prev=NULL;
 	for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next) 
 		chtmp_prev=chtmp;
@@ -1145,7 +1168,7 @@
 	while( !was_found && ftmp != NULL )
 	{
 		matches=1;
-	     if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr 
+		if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr 
 		     ||  ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
 		     ||  ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
 		     ||  ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
@@ -1163,6 +1186,8 @@
         		if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
 				matches=0;
 		}
+		if (strncmp(ftmp->fw_vianame, frwl->fw_vianame, IFNAMSIZ))
+		        matches=0;
 		if(matches)
 		{
 			was_found=1;
@@ -1332,11 +1357,11 @@
 
 	if ( cmd == IP_FW_CHECK )
 	{
-		struct device viadev;
+		struct device *viadev;
 		struct ip_fwpkt *ipfwp;
 		struct iphdr *ip;
 
-		if ( len < sizeof(struct ip_fwpkt) )
+		if ( len != sizeof(struct ip_fwpkt) )
 		{
 #ifdef DEBUG_CONFIG_IP_FIREWALL
 			printk("ip_fw_ctl: length=%d, expected %d\n",
@@ -1348,8 +1373,18 @@
 	 	ipfwp = (struct ip_fwpkt *)m;
 	 	ip = &(ipfwp->fwp_iph);
 
-		if ( ip->ihl != sizeof(struct iphdr) / sizeof(int))
-		{
+		if ( !(viadev = dev_get(ipfwp->fwp_vianame)) ) {
+#ifdef DEBUG_CONFIG_IP_FIREWALL
+			printk("ip_fw_ctl: invalid device \"%s\"\n", ipfwp->fwp_vianame);
+#endif
+			return(EINVAL);
+		} else if ( viadev->pa_addr != ipfwp->fwp_via.s_addr ) {
+#ifdef DEBUG_CONFIG_IP_FIREWALL
+			printk("ip_fw_ctl: device \"%s\" has another IP address\n",
+				ipfwp->fwp_vianame);
+#endif
+			return(EINVAL);
+		} else if ( ip->ihl != sizeof(struct iphdr) / sizeof(int)) {
 #ifdef DEBUG_CONFIG_IP_FIREWALL
 			printk("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl,
 					sizeof(struct iphdr)/sizeof(int));
@@ -1357,9 +1392,7 @@
 			return(EINVAL);
 		}
 
-		viadev.pa_addr = ipfwp->fwp_via.s_addr;
-
-		if ((ret = ip_fw_chk(ip, &viadev, *chains[fwtype],
+		if ((ret = ip_fw_chk(ip, viadev, *chains[fwtype],
 				*policies[fwtype], 2)) == FW_ACCEPT)
 			return(0);
 	    	else if (ret == FW_MASQUERADE)	
@@ -1459,9 +1492,10 @@
 	
 	while(i!=NULL)
 	{
-		len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %08lX %X ",
+		len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %.16s %08lX %X ",
 			ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
 			ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
+			(i->fw_vianame)[0] ? i->fw_vianame : "-",
 			ntohl(i->fw_via.s_addr),i->fw_flg);
 		len+=sprintf(buffer+len,"%u %u %-9lu %-9lu",
 			i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
@@ -1611,6 +1645,46 @@
 
 #endif
 
+#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
+
+int ipfw_device_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct device *dev=ptr;
+	char *devname = dev->name;
+	unsigned long flags;
+	struct ip_fw *fw;
+	int chn;
+
+	save_flags(flags);
+	cli();
+	
+	if (event == NETDEV_UP) {
+		for (chn = 0; chn < IP_FW_CHAINS; chn++)
+			for (fw = *chains[chn]; fw; fw = fw->fw_next)
+				if ((fw->fw_vianame)[0] && !strncmp(devname,
+						fw->fw_vianame, IFNAMSIZ))
+					fw->fw_viadev = dev;
+	} else if (event == NETDEV_DOWN) {
+		for (chn = 0; chn < IP_FW_CHAINS; chn++)
+			for (fw = *chains[chn]; fw; fw = fw->fw_next)
+				/* we could compare just the pointers ... */
+				if ((fw->fw_vianame)[0] && !strncmp(devname,
+						fw->fw_vianame, IFNAMSIZ))
+					fw->fw_viadev = (struct device *) -1;
+	}
+
+	restore_flags(flags);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ipfw_dev_notifier={
+	ipfw_device_event,
+	NULL,
+	0
+};
+
+#endif
+
 void ip_fw_init(void)
 {
 #ifdef CONFIG_IP_ACCT
@@ -1652,5 +1726,9 @@
 		0, &proc_net_inode_operations,
 		ip_msqhst_procinfo
 	});
+#endif
+#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
+	/* Register for device up/down reports */
+	register_netdevice_notifier(&ipfw_dev_notifier);
 #endif
 }
diff -u --recursive --new-file v1.3.65/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v1.3.65/linux/net/ipv4/tcp_input.c	Sat Feb 17 16:02:58 1996
+++ linux/net/ipv4/tcp_input.c	Sat Feb 17 16:02:22 1996
@@ -1930,6 +1930,15 @@
 		kfree_skb(skb, FREE_READ);
 
 	/*
+	 * Finally, if we've moved to TCP_CLOSE, check if we should
+	 * get rid of the socket
+	 */
+	if (sk->dead && sk->state == TCP_CLOSE) {
+		/* Should be about 2 rtt's */
+   		reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME));
+	}
+
+	/*
 	 *	And done
 	 */	
 	
