diff -u --recursive --new-file v1.3.19/linux/Makefile linux/Makefile
--- v1.3.19/linux/Makefile	Tue Aug 15 20:38:59 1995
+++ linux/Makefile	Wed Aug 16 14:24:02 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 19
+SUBLEVEL = 20
 
 ARCH = i386
 
@@ -113,7 +113,7 @@
 	$(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
 
 Version: dummy
-	rm -f include/linux/version.h
+	@rm -f include/linux/compile.h
 
 boot: vmlinux
 	@$(MAKE) -C arch/$(ARCH)/boot
@@ -140,6 +140,7 @@
 	set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done
 
 $(TOPDIR)/include/linux/version.h: include/linux/version.h
+$(TOPDIR)/include/linux/compile.h: include/linux/compile.h
 
 newversion:
 	@if [ ! -f .version ]; then \
@@ -148,8 +149,7 @@
 		expr `cat .version` + 1 > .version; \
 	fi
 
-include/linux/version.h: $(CONFIGURATION) Makefile newversion
-	@echo \#define UTS_RELEASE \"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)\" > .ver
+include/linux/compile.h: $(CONFIGURATION) include/linux/version.h newversion
 	@if [ -f .name ]; then \
 	   echo \#define UTS_VERSION \"\#`cat .version`-`cat .name` `date`\"; \
 	 else \
@@ -166,10 +166,14 @@
 	   echo \#define LINUX_COMPILE_DOMAIN ; \
 	 fi >> .ver
 	@echo \#define LINUX_COMPILER \"`$(HOSTCC) -v 2>&1 | tail -1`\" >> .ver
+	@mv -f .ver $@
+
+include/linux/version.h: ./Makefile
+	@echo \#define UTS_RELEASE \"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)\" > .ver
 	@echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)` >> .ver
-	if [ ! -f $@ ]; then mv .ver $@; fi
+	@mv -f .ver $@
 
-init/version.o: init/version.c include/linux/version.h
+init/version.o: init/version.c include/linux/compile.h
 	$(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c
 
 init/main.o: init/main.c
@@ -225,7 +229,7 @@
 	)
 
 clean:	archclean
-	rm -f kernel/ksyms.lst
+	rm -f kernel/ksyms.lst include/linux/compile.h
 	rm -f core `find . -name '*.[oas]' -print`
 	rm -f core `find . -type f -name 'core' -print`
 	rm -f vmlinux System.map
@@ -253,11 +257,9 @@
 	sync
 
 #depend dep: .hdepend
-depend dep: archdep .hdepend
-	touch include/linux/version.h
+depend dep: archdep .hdepend include/linux/version.h
 	awk -f scripts/depend.awk init/*.c > .tmpdepend
 	set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep; done
-	rm -f include/linux/version.h
 	mv .tmpdepend .depend
 ifdef CONFIG_MODVERSIONS
 	@echo updating $(TOPDIR)/include/linux/modversions.h
diff -u --recursive --new-file v1.3.19/linux/drivers/block/sbpcd.c linux/drivers/block/sbpcd.c
--- v1.3.19/linux/drivers/block/sbpcd.c	Wed Aug  2 13:20:59 1995
+++ linux/drivers/block/sbpcd.c	Wed Aug 16 07:29:53 1995
@@ -695,7 +695,6 @@
 {
 	char buf[256];
 	va_list args;
-	extern int vsprintf(char *, const char *, va_list);
 	
 	if (!(sbpcd_debug&(1<<level))) return;
 	
diff -u --recursive --new-file v1.3.19/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v1.3.19/linux/drivers/net/Makefile	Tue Aug 15 20:39:02 1995
+++ linux/drivers/net/Makefile	Wed Aug 16 07:24:29 1995
@@ -127,13 +127,13 @@
 else
 M_OBJS += de600.o
 endif
-	
+
 ifdef CONFIG_DE620
 L_OBJS += de620.o
 else
 M_OBJS += de620.o
 endif
-	
+
 ifdef CONFIG_AT1500
 L_OBJS += lance.o
 endif
diff -u --recursive --new-file v1.3.19/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v1.3.19/linux/drivers/net/slip.c	Sun Aug 13 14:45:32 1995
+++ linux/drivers/net/slip.c	Wed Aug 16 15:10:11 1995
@@ -385,7 +385,7 @@
 	skb->dev = sl->dev;
 	memcpy(skb_put(skb,count), sl->rbuff, count);
 	skb->mac.raw=skb->data;
-	if(sl->mode&(SL_MODE_AX25|SL_MODE_AX25VC))
+	if(sl->mode & SL_MODE_AX25)
 		skb->protocol=htons(ETH_P_AX25);
 	else
 		skb->protocol=htons(ETH_P_IP);
@@ -537,7 +537,7 @@
 #ifdef CONFIG_INET
 	struct slip *sl = (struct slip*)(dev->priv);
 
-	if (((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) && type != htons(ETH_P_AX25))  {
+	if (sl->mode & SL_MODE_AX25 && type != htons(ETH_P_AX25))  {
 		return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
 	}
 #endif
@@ -555,7 +555,7 @@
 #ifdef CONFIG_INET
 	struct slip *sl = (struct slip*)(dev->priv);
 
-	if ((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) {
+	if (sl->mode & SL_MODE_AX25) {
 		return ax25_rebuild_header(buff, dev, raddr, skb);
 	}
 #endif
@@ -752,7 +752,7 @@
 	sl->mode      = SL_MODE_DEFAULT;
 	sl->dev->type = ARPHRD_SLIP + sl->mode;
 #ifdef CONFIG_AX25	
-	if (sl->dev->type == 260 || sl->dev->type == 272) {	/* KISS */
+	if (sl->dev->type == 260) {		/* KISS */
 		sl->dev->type = ARPHRD_AX25;
 	}
 #endif	
@@ -1008,14 +1008,6 @@
 	memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
 	return 0;
 }
-
-int sl_get_ax25_mode(struct device *dev)
-{
-	struct slip *sl = (struct slip*)(dev->priv);
-
-	return sl->mode & SL_MODE_AX25VC;
-}
-
 #endif /* CONFIG_AX25 */
 
 
@@ -1072,13 +1064,13 @@
 		}
 #endif
 #ifndef CONFIG_AX25
-		if ((tmp & SL_MODE_AX25) || (tmp & SL_MODE_AX25VC)) {
+		if (tmp & SL_MODE_AX25) {
 			return -EINVAL;
 		}
 #else
-		if ((tmp & SL_MODE_AX25) || (tmp & SL_MODE_AX25VC)) {
+		if (tmp & SL_MODE_AX25) {
 			sl->dev->addr_len=AX25_ADDR_LEN;	  /* sizeof an AX.25 addr */
-			sl->dev->hard_header_len=73; /* We don't do digipeaters */
+			sl->dev->hard_header_len=AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
 		} else	{
 			sl->dev->addr_len=0;	/* No mac addr in slip mode */
 			sl->dev->hard_header_len=0;
@@ -1087,7 +1079,7 @@
 		sl->mode = tmp;
 		sl->dev->type = ARPHRD_SLIP+sl->mode;
 #ifdef CONFIG_AX25		
-		if (sl->dev->type == 260 || sl->dev->type == 272)  {
+		if (sl->dev->type == 260)  {
 			sl->dev->type = ARPHRD_AX25;
 		}
 #endif		
@@ -1221,7 +1213,7 @@
 	dev->addr_len		= 0;
 	dev->type		= ARPHRD_SLIP + SL_MODE_DEFAULT;
 #ifdef CONFIG_AX25
-	if (sl->dev->type == 260 || sl->dev->type == 272)  {
+	if (sl->dev->type == 260) {
 		sl->dev->type = ARPHRD_AX25;
 	}
 	memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);	/* Only activated in AX.25 mode */
diff -u --recursive --new-file v1.3.19/linux/drivers/net/slip.h linux/drivers/net/slip.h
--- v1.3.19/linux/drivers/net/slip.h	Tue Aug  8 12:31:37 1995
+++ linux/drivers/net/slip.h	Wed Aug 16 15:10:11 1995
@@ -95,7 +95,6 @@
 #define SL_MODE_CSLIP6	(SL_MODE_SLIP6|SL_MODE_CSLIP)
 #define SL_MODE_AX25	4
 #define SL_MODE_ADAPTIVE 8
-#define	SL_MODE_AX25VC	16
 };
 
 
diff -u --recursive --new-file v1.3.19/linux/drivers/net/tunnel.c linux/drivers/net/tunnel.c
--- v1.3.19/linux/drivers/net/tunnel.c	Thu Jul 13 16:20:21 1995
+++ linux/drivers/net/tunnel.c	Wed Aug 16 11:37:30 1995
@@ -36,6 +36,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/ip.h>
 
diff -u --recursive --new-file v1.3.19/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v1.3.19/linux/drivers/scsi/Makefile	Tue Aug 15 20:39:04 1995
+++ linux/drivers/scsi/Makefile	Wed Aug 16 09:27:41 1995
@@ -34,7 +34,7 @@
 endif
 
 ifdef CONFIG_SCSI
-L_OBJS := hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o scsi_proc.o
+L_OBJS += hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o scsi_proc.o
 else
 ifdef CONFIG_MODVERSIONS
 # Create this before we build anything else.
diff -u --recursive --new-file v1.3.19/linux/fs/buffer.c linux/fs/buffer.c
--- v1.3.19/linux/fs/buffer.c	Tue Aug  8 12:31:39 1995
+++ linux/fs/buffer.c	Wed Aug 16 15:22:59 1995
@@ -228,7 +228,7 @@
 
 asmlinkage int sys_sync(void)
 {
-	sync_dev(0);
+	fsync_dev(0);
 	return 0;
 }
 
@@ -440,6 +440,7 @@
 	for (;;) {
 		if (!(bh=find_buffer(dev,block,size)))
 			return NULL;
+		bh->b_reuse=0;
 		bh->b_count++;
 		wait_on_buffer(bh);
 		if (bh->b_dev == dev && bh->b_blocknr == block && bh->b_size == size)
@@ -1075,6 +1076,7 @@
 		arr[block++] = bh;
 		bh->b_count = 1;
 		bh->b_dirt = 0;
+		bh->b_reuse = 0;
 		bh->b_flushtime = 0;
 		bh->b_uptodate = 0;
 		bh->b_req = 0;
diff -u --recursive --new-file v1.3.19/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v1.3.19/linux/fs/proc/mem.c	Tue May 30 12:17:18 1995
+++ linux/fs/proc/mem.c	Wed Aug 16 14:06:44 1995
@@ -23,6 +23,33 @@
  */
 #define mem_write NULL
 
+static int check_range(struct task_struct * tsk, unsigned long addr, int count)
+{
+	struct vm_area_struct *vma;
+	int retval;
+
+	vma = find_vma(tsk, addr);
+	if (!vma)
+		return -EACCES;
+	if (vma->vm_start > addr)
+		return -EACCES;
+	if (!(vma->vm_flags & VM_READ))
+		return -EACCES;
+	while ((retval = vma->vm_end - addr) < count) {
+		struct vm_area_struct *next = vma->vm_next;
+		if (!next)
+			break;
+		if (vma->vm_end != next->vm_start)
+			break;
+		if (!(next->vm_flags & VM_READ))
+			break;
+		vma = next;
+	}
+	if (retval > count)
+		retval = count;
+	return retval;
+}
+
 static int mem_read(struct inode * inode, struct file * file,char * buf, int count)
 {
 	pgd_t *page_dir;
@@ -47,6 +74,9 @@
 	if (!tsk)
 		return -EACCES;
 	addr = file->f_pos;
+	count = check_range(tsk, addr, count);
+	if (count < 0)
+		return count;
 	tmp = buf;
 	while (count > 0) {
 		if (current->signal & ~current->blocked)
diff -u --recursive --new-file v1.3.19/linux/include/linux/ax25.h linux/include/linux/ax25.h
--- v1.3.19/linux/include/linux/ax25.h	Mon Jul 31 15:59:02 1995
+++ linux/include/linux/ax25.h	Wed Aug 16 15:10:11 1995
@@ -24,6 +24,14 @@
 	ax25_address fsa_digipeater[AX25_MAX_DIGIS];
 };
 
+struct ax25_routes_struct
+{
+	ax25_address port_addr;
+	ax25_address dest_addr;
+	unsigned char digi_count;
+	ax25_address digi_addr[AX25_MAX_DIGIS - 2];
+};
+
 #define AX25_WINDOW	1
 #define AX25_T1		2
 #define AX25_N2		3
@@ -31,12 +39,35 @@
 #define AX25_T2		5
 #define	AX25_BACKOFF	6
 #define	AX25_EXTSEQ	7
+#define	AX25_HDRINCL	8
 
 #define SIOCAX25GETUID		(SIOCPROTOPRIVATE)
 #define SIOCAX25ADDUID		(SIOCPROTOPRIVATE+1)
 #define SIOCAX25DELUID		(SIOCPROTOPRIVATE+2)
 #define SIOCAX25NOUID		(SIOCPROTOPRIVATE+3)
 #define	SIOCAX25DIGCTL		(SIOCPROTOPRIVATE+4)
+#define	SIOCAX25GETPARMS	(SIOCPROTOPRIVATE+5)
+#define	SIOCAX25SETPARMS	(SIOCPROTOPRIVATE+6)
 
 #define AX25_NOUID_DEFAULT	0
 #define AX25_NOUID_BLOCK	1
+
+#define	AX25_VALUES_IPDEFMODE	0	/* 'D'=DG 'V'=VC */
+#define	AX25_VALUES_AXDEFMODE	1	/* 8=Normal 128=Extended Seq Nos */
+#define	AX25_VALUES_NETROM	2	/* Allow NET/ROM  - 0=No 1=Yes */
+#define	AX25_VALUES_TEXT	3	/* Allow PID=Text - 0=No 1=Yes */
+#define	AX25_VALUES_BACKOFF	4	/* 'E'=Exponential 'L'=Linear */
+#define	AX25_VALUES_CONMODE	5	/* Allow connected modes - 0=No 1=Yes */
+#define	AX25_VALUES_WINDOW	6	/* Default window size for standard AX.25 */
+#define	AX25_VALUES_EWINDOW	7	/* Default window size for extended AX.25 */
+#define	AX25_VALUES_T1		8	/* Default T1 timeout value */
+#define	AX25_VALUES_T2		9	/* Default T2 timeout value */
+#define	AX25_VALUES_T3		10	/* Default T3 timeout value */
+#define	AX25_VALUES_N2		11	/* Default N2 value */
+#define	AX25_MAX_VALUES		20
+
+struct ax25_parms_struct
+{
+	ax25_address port_addr;
+	unsigned short values[AX25_MAX_VALUES];
+};
diff -u --recursive --new-file v1.3.19/linux/include/linux/netrom.h linux/include/linux/netrom.h
--- v1.3.19/linux/include/linux/netrom.h	Mon Jul 31 15:59:02 1995
+++ linux/include/linux/netrom.h	Wed Aug 16 15:10:11 1995
@@ -4,6 +4,7 @@
 #define NETROM_T1	1
 #define NETROM_T2	2
 #define NETROM_N2	3
+#define	NETROM_HDRINCL	4
 
 #define	SIOCNRGETPARMS		(SIOCPROTOPRIVATE+0)
 #define	SIOCNRSETPARMS		(SIOCPROTOPRIVATE+1)
diff -u --recursive --new-file v1.3.19/linux/include/net/ax25.h linux/include/net/ax25.h
--- v1.3.19/linux/include/net/ax25.h	Tue Aug 15 20:39:05 1995
+++ linux/include/net/ax25.h	Wed Aug 16 15:10:11 1995
@@ -101,14 +101,22 @@
 #define AX25_STATE_4	4
 
 #define PR_SLOWHZ	10			/*  Run timing at 1/10 second - gives us better resolution for 56kbit links */
-#define DEFAULT_T1	(10  * PR_SLOWHZ)	/*  Outstanding frames - 10 seconds */
-#define DEFAULT_T2	(3   * PR_SLOWHZ)	/*  Response delay     - 3 seconds */
-#define DEFAULT_T3	(300 * PR_SLOWHZ)	/*  Idle supervision   - 300 seconds */
-#define DEFAULT_N2	10			/*  Number of retries */
-#define	DEFAULT_WINDOW	2			/*  Default window size	*/
 #define MODULUS 	8			/*  Standard AX.25 modulus */
 #define	EMODULUS	128			/*  Extended AX.25 modulus */
 
+#define	AX25_DEF_IPDEFMODE	'D'
+#define	AX25_DEF_AXDEFMODE	8
+#define	AX25_DEF_NETROM		1
+#define	AX25_DEF_TEXT		1
+#define	AX25_DEF_BACKOFF	'E'
+#define	AX25_DEF_CONMODE	1
+#define	AX25_DEF_WINDOW		2
+#define	AX25_DEF_EWINDOW	32
+#define	AX25_DEF_T1		10
+#define	AX25_DEF_T2		3
+#define	AX25_DEF_T3		300
+#define	AX25_DEF_N2		10
+
 typedef struct ax25_uid_assoc {
 	struct ax25_uid_assoc *next;
 	uid_t uid;
@@ -126,7 +134,7 @@
 	struct ax25_cb		*next;
 	ax25_address		source_addr, dest_addr;
 	struct device		*device;
-	unsigned char		state, modulus;
+	unsigned char		state, modulus, hdrincl;
 	unsigned short		vs, vr, va;
 	unsigned char		condition, backoff;
 	unsigned char		n2, n2count;
@@ -152,7 +160,6 @@
 extern int  ax25_encapsulate(struct sk_buff *, struct device *, unsigned short,
 	void *, void *, unsigned int);
 extern int  ax25_rebuild_header(unsigned char *, struct device *, unsigned long, struct sk_buff *);
-extern int  ax25_get_info(char *, char **, off_t, int, int);
 extern ax25_uid_assoc *ax25_uid_list;
 extern int  ax25_uid_policy;
 extern ax25_address *ax25_findbyuid(uid_t);
@@ -171,17 +178,23 @@
 extern void ax25_establish_data_link(ax25_cb *);
 extern void ax25_transmit_enquiry(ax25_cb *);
 extern void ax25_enquiry_response(ax25_cb *);
+extern void ax25_timeout_response(ax25_cb *);
 extern void ax25_check_iframes_acked(ax25_cb *, unsigned short);
 extern void ax25_check_need_response(ax25_cb *, int, int);
 
 /* ax25_route.c */
-extern void ax25_rt_rx_frame(ax25_address *, struct device *);
+extern void ax25_rt_rx_frame(ax25_address *, struct device *, ax25_digi *);
 extern int  ax25_rt_get_info(char *, char **, off_t, int, int);
 extern int  ax25_cs_get_info(char *, char **, off_t, int, int);
 extern int  ax25_rt_autobind(ax25_cb *, ax25_address *);
 extern void ax25_rt_device_down(struct device *);
+extern int  ax25_rt_ioctl(unsigned int, void *);
 extern void ax25_ip_mode_set(ax25_address *, struct device *, char);
 extern char ax25_ip_mode_get(ax25_address *, struct device *);
+extern unsigned short ax25_dev_get_value(struct device *, int);
+extern void ax25_dev_device_up(struct device *);
+extern void ax25_dev_device_down(struct device *);
+extern int  ax25_dev_ioctl(unsigned int, void *);
 
 /* ax25_subr.c */
 extern void ax25_clear_queues(ax25_cb *);
@@ -201,8 +214,5 @@
 
 /* ax25_timer */
 extern void ax25_set_timer(ax25_cb *);
-
-/* slip.c */
-extern int  sl_get_ax25_mode(struct device *);
 
 #endif
diff -u --recursive --new-file v1.3.19/linux/include/net/netrom.h linux/include/net/netrom.h
--- v1.3.19/linux/include/net/netrom.h	Tue Aug 15 20:39:05 1995
+++ linux/include/net/netrom.h	Wed Aug 16 15:10:11 1995
@@ -46,11 +46,10 @@
 typedef struct {
 	ax25_address		user_addr, source_addr, dest_addr;
 	struct device		*device;
-	unsigned char		my_index,    my_id;
-	unsigned char		your_index,  your_id;
-	unsigned char		state, bpqext;
+	unsigned char		my_index,   my_id;
+	unsigned char		your_index, your_id;
+	unsigned char		state, condition, bpqext, hdrincl;
 	unsigned short		vs, vr, va, vl;
-	unsigned char		condition;
 	unsigned char		n2, n2count;
 	unsigned short		t1, t2, rtt;
 	unsigned short		t1timer, t2timer, t4timer;
diff -u --recursive --new-file v1.3.19/linux/init/version.c linux/init/version.c
--- v1.3.19/linux/init/version.c	Wed Aug  2 13:21:17 1995
+++ linux/init/version.c	Wed Aug 16 12:17:25 1995
@@ -9,6 +9,7 @@
 #include <linux/config.h>
 #include <linux/utsname.h>
 #include <linux/version.h>
+#include <linux/compile.h>
 
 struct new_utsname system_utsname = {
 	UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION,
diff -u --recursive --new-file v1.3.19/linux/kernel/Makefile linux/kernel/Makefile
--- v1.3.19/linux/kernel/Makefile	Tue Aug 15 20:39:05 1995
+++ linux/kernel/Makefile	Wed Aug 16 14:57:02 1995
@@ -14,10 +14,13 @@
 O_OBJS    = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.o \
 	module.o exit.o signal.o itimer.o info.o time.o softirq.o \
 	resource.o
+
 SYMTAB_OBJS = ksyms.o
 O_OBJS     += $(SYMTAB_OBJS)
 
+ifdef CONFIG_MODVERSIONS
 $(O_TARGET): $(SYMTAB_OBJS:.o=.ver)
+endif
 
 include $(TOPDIR)/Rules.make
 
diff -u --recursive --new-file v1.3.19/linux/net/Makefile linux/net/Makefile
--- v1.3.19/linux/net/Makefile	Tue Aug 15 20:39:05 1995
+++ linux/net/Makefile	Wed Aug 16 13:11:08 1995
@@ -11,6 +11,6 @@
 ALL_SUB_DIRS := 802 ax25 core ethernet ipv4 ipx unix appletalk netrom
 SUB_DIRS     := $(ALL_SUB_DIRS)
 L_TARGET     := network.a
-L_OBJS	     :=  socket.o protocols.o $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
+L_OBJS	     := socket.o protocols.o $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.19/linux/net/appletalk/aarp.c linux/net/appletalk/aarp.c
--- v1.3.19/linux/net/appletalk/aarp.c	Tue Aug 15 20:39:05 1995
+++ linux/net/appletalk/aarp.c	Wed Aug 16 11:16:37 1995
@@ -38,6 +38,7 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/if_ether.h>
+#include <linux/if_arp.h>
 #include <linux/inet.h>
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v1.3.19/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v1.3.19/linux/net/appletalk/ddp.c	Tue Aug 15 20:39:05 1995
+++ linux/net/appletalk/ddp.c	Wed Aug 16 11:24:36 1995
@@ -38,6 +38,8 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <linux/route.h>
 #include <linux/inet.h>
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
@@ -50,6 +52,7 @@
 #include <net/sock.h>
 #include <linux/atalk.h>
 #include <linux/proc_fs.h>
+#include <linux/stat.h>
 
 #ifdef CONFIG_ATALK
 
@@ -211,7 +214,7 @@
 
 
 /* Called from proc fs */
-int atalk_get_info(char *buffer, char **start, off_t offset, int length)
+int atalk_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	atalk_socket *s;
 	int len=0;
@@ -813,7 +816,7 @@
 
 /* Called from proc fs - just make it print the ifaces neatly */
 
-int atalk_if_get_info(char *buffer, char **start, off_t offset, int length)
+int atalk_if_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	struct atalk_iface *iface;
 	int len=0;
@@ -846,7 +849,7 @@
 
 /* Called from proc fs - just make it print the routes neatly */
 
-int atalk_rt_get_info(char *buffer, char **start, off_t offset, int length)
+int atalk_rt_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	struct atalk_route *rt;
 	int len=0;
@@ -1873,6 +1876,7 @@
 	proc_net_register(&(struct proc_dir_entry) {
 		PROC_NET_AT_ROUTE, 11,"atalk_route",
 		S_IFREG | S_IRUGO, 1, 0, 0,
+		0, &proc_net_inode_operations,
 		atalk_rt_get_info
 	});
 	proc_net_register(&(struct proc_dir_entry) {
diff -u --recursive --new-file v1.3.19/linux/net/ax25/Makefile linux/net/ax25/Makefile
--- v1.3.19/linux/net/ax25/Makefile	Tue Aug 15 20:39:06 1995
+++ linux/net/ax25/Makefile	Wed Aug 16 13:03:17 1995
@@ -12,7 +12,7 @@
 O_OBJS	 := af_ax25.o
 
 ifdef CONFIG_AX25
-OBJS	+= ax25_in.o ax25_out.o ax25_route.o ax25_subr.o ax25_timer.o
+O_OBJS	+= ax25_in.o ax25_out.o ax25_route.o ax25_subr.o ax25_timer.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.19/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v1.3.19/linux/net/ax25/af_ax25.c	Tue Aug 15 20:39:07 1995
+++ linux/net/ax25/af_ax25.c	Wed Aug 16 15:12:54 1995
@@ -63,12 +63,10 @@
  *						Added AX.25 frame segmentation.
  *
  *	To do:
- *		Support use as digipeater, including an on/off ioctl
  *		Restructure the ax25_rcv code to be cleaner/faster and
  *		copy only when needed.
  *		Consider better arbitary protocol support.
  *		Fix non-blocking connect failure.
- *		VC mode doesnt work on the PI card.
  *		Settable protocol id for SEQPACKET sockets
  */
  
@@ -87,6 +85,7 @@
 #include <net/ax25.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/segment.h>
@@ -97,6 +96,7 @@
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/proc_fs.h>
+#include <linux/stat.h>
 
 #include <net/ip.h>
 #include <net/arp.h>
@@ -213,8 +213,6 @@
 			}
 		}
 	}
-	
-	ax25_rt_device_down(dev);
 }
 
 /*
@@ -222,11 +220,21 @@
  */
 static int ax25_device_event(unsigned long event, void *ptr)
 {
-	if (event != NETDEV_DOWN)
-		return NOTIFY_DONE;
-		
-	ax25_kill_by_device(ptr);
-	
+	struct device *dev = (struct device *)ptr;
+
+	switch (event) {
+		case NETDEV_UP:
+			ax25_dev_device_up(dev);
+			break;
+		case NETDEV_DOWN:
+			ax25_kill_by_device(dev);
+			ax25_rt_device_down(dev);
+			ax25_dev_device_down(dev);
+			break;
+		default:
+			break;
+	}
+
 	return NOTIFY_DONE;
 }
 
@@ -514,16 +522,17 @@
 
 	init_timer(&ax25->timer);
 
-	ax25->rtt     = DEFAULT_T1;
-	ax25->t1      = DEFAULT_T1;
-	ax25->t2      = DEFAULT_T2;
-	ax25->n2      = DEFAULT_N2;
-	ax25->t3      = DEFAULT_T3;
+	ax25->rtt     = (AX25_DEF_T1 * PR_SLOWHZ) / 2;
+	ax25->t1      = AX25_DEF_T1 * PR_SLOWHZ;
+	ax25->t2      = AX25_DEF_T2 * PR_SLOWHZ;
+	ax25->t3      = AX25_DEF_T3 * PR_SLOWHZ;
+	ax25->n2      = AX25_DEF_N2;
 
-	ax25->modulus   = MODULUS;
+	ax25->modulus   = AX25_DEF_AXDEFMODE;
 	ax25->fragno    = 0;
 	ax25->fraglen   = 0;
-	ax25->backoff   = 1;
+	ax25->hdrincl   = 0;
+	ax25->backoff   = AX25_DEF_BACKOFF == 'E';
 	ax25->condition = 0x00;
 	ax25->t1timer   = 0;
 	ax25->t2timer   = 0;
@@ -534,7 +543,11 @@
 	ax25->vr      = 0;
 	ax25->vs      = 0;
 
-	ax25->window   = DEFAULT_WINDOW;
+	if (AX25_DEF_AXDEFMODE == EMODULUS) {
+		ax25->window = AX25_DEF_EWINDOW;
+	} else {
+		ax25->window = AX25_DEF_WINDOW;
+	}
 	ax25->device   = NULL;
 	ax25->digipeat = NULL;
 	ax25->sk       = NULL;
@@ -547,6 +560,31 @@
 	return ax25;
 }
 
+/*
+ *	Fill in a created AX.25 created control block with the default
+ *	values for a particular device.
+ */
+static void ax25_fillin_cb(ax25_cb *ax25, struct device *dev)
+{
+	ax25->device = dev;
+
+	ax25->rtt = ax25_dev_get_value(dev, AX25_VALUES_T1);
+	ax25->t1  = ax25_dev_get_value(dev, AX25_VALUES_T1);
+	ax25->t2  = ax25_dev_get_value(dev, AX25_VALUES_T2);
+	ax25->t3  = ax25_dev_get_value(dev, AX25_VALUES_T3);
+	ax25->n2  = ax25_dev_get_value(dev, AX25_VALUES_N2);
+
+	ax25->modulus = ax25_dev_get_value(dev, AX25_VALUES_AXDEFMODE);
+
+	if (ax25->modulus == MODULUS) {
+		ax25->window = ax25_dev_get_value(dev, AX25_VALUES_WINDOW);
+	} else {
+		ax25->window = ax25_dev_get_value(dev, AX25_VALUES_EWINDOW);
+	}
+
+	ax25->backoff = ax25_dev_get_value(dev, AX25_VALUES_BACKOFF) == 'E';
+}
+
 int ax25_send_frame(struct sk_buff *skb, ax25_address *src, ax25_address *dest,
 	ax25_digi *digi, struct device *dev)
 {
@@ -571,7 +609,7 @@
 	if ((ax25 = ax25_create_cb()) == NULL)
 		return 0;
 
-	ax25->device = dev;
+	ax25_fillin_cb(ax25, dev);
 
 	memcpy(&ax25->source_addr, src,  sizeof(ax25_address));
 	memcpy(&ax25->dest_addr,   dest, sizeof(ax25_address));
@@ -709,6 +747,10 @@
 			sk->ax25->modulus = opt ? EMODULUS : MODULUS;
 			return 0;
 
+		case AX25_HDRINCL:
+			sk->ax25->hdrincl = opt ? 1 : 0;
+			return 0;
+
 		default:
 			return -ENOPROTOOPT;
 	}
@@ -735,7 +777,7 @@
 			break;
 
 		case AX25_T1:
-			val = sk->ax25->t1 / PR_SLOWHZ;
+			val = (sk->ax25->t1 * 2) / PR_SLOWHZ;
 			break;
 
 		case AX25_T2:
@@ -756,7 +798,11 @@
 
 		case AX25_EXTSEQ:
 			val = (sk->ax25->modulus == EMODULUS);
-			return 0;
+			break;
+
+		case AX25_HDRINCL:
+			val = sk->ax25->hdrincl;
+			break;
 
 		default:
 			return -ENOPROTOOPT;
@@ -884,6 +930,8 @@
 		return NULL;
 	}
 
+	ax25_fillin_cb(ax25, dev);
+
 	sk->type   = osk->type;
 	sk->socket = osk->socket;
 
@@ -933,6 +981,7 @@
 
 	ax25->modulus = osk->ax25->modulus;
 	ax25->backoff = osk->ax25->backoff;
+	ax25->hdrincl = osk->ax25->hdrincl;
 	ax25->rtt     = osk->ax25->rtt;
 	ax25->t1      = osk->ax25->t1;
 	ax25->t2      = osk->ax25->t2;
@@ -940,7 +989,6 @@
 	ax25->n2      = osk->ax25->n2;
 
 	ax25->window  = osk->ax25->window;
-	ax25->device  = dev;
 
 	memcpy(&ax25->source_addr, &osk->ax25->source_addr, sizeof(ax25_address));
 	
@@ -1073,7 +1121,7 @@
 		return -EADDRNOTAVAIL;
 	}
 
-	sk->ax25->device = dev;
+	ax25_fillin_cb(sk->ax25, dev);
 	ax25_insert_socket(sk->ax25);
 
 	sk->zapped = 0;
@@ -1298,6 +1346,7 @@
 	/*
 	 *	Process the AX.25/LAPB frame.
 	 */
+	skb->h.raw = skb->data;
 
 	/*
 	 *	Parse the address header.
@@ -1310,7 +1359,7 @@
 	/*
 	 *	Send the frame to the AX.25 auto-router
 	 */
-	ax25_rt_rx_frame(&src, dev);
+	ax25_rt_rx_frame(&src, dev, &dp);
 	
 	/*
 	 *	Ours perhaps ?
@@ -1413,6 +1462,16 @@
 
 		return 0;
 	}
+
+	/*
+	 *	Is connected mode supported on this device ?
+	 *	If not, should we DM the incoming frame (except DMs) or
+	 *	silently ignore them. For now we stay quiet.
+	 */
+	if (!ax25_dev_get_value(dev, AX25_VALUES_CONMODE)) {
+		kfree_skb(skb, FREE_READ);
+		return 0;
+	}
 	
 	/* LAPB */
 	if ((ax25 = ax25_find_cb(&dest, &src, dev)) != NULL) {
@@ -1469,6 +1528,8 @@
 			kfree_skb(skb, FREE_READ);
 			return 0;
 		}
+
+		ax25_fillin_cb(ax25, dev);
 #else
 		if (mine)
 			ax25_return_dm(dev, &src, &dest, &dp);
@@ -1502,8 +1563,10 @@
 
 	if ((*skb->data & ~PF) == SABME) {
 		ax25->modulus = EMODULUS;
+		ax25->window  = ax25_dev_get_value(dev, AX25_VALUES_EWINDOW);
 	} else {
 		ax25->modulus = MODULUS;
+		ax25->window  = ax25_dev_get_value(dev, AX25_VALUES_WINDOW);
 	}
 
 	ax25->device = dev;
@@ -1733,10 +1796,9 @@
 	struct sock *sk = (struct sock *)sock->data;
 	struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)sip;
 	char *addrptr = (char *)sip;
-	int copied = 0;
+	int copied, length;
 	struct sk_buff *skb;
 	int er;
-	int bias = 0;
 
 	if (sk->err) {
 		er      = -sk->err;
@@ -1747,19 +1809,28 @@
 	if (addr_len != NULL)
 		*addr_len = sizeof(*sax);
 
-	/* This works for seqpacket too. The receiver has ordered the queue for us! We do one quick check first though */
-	if (sk->type == SOCK_SEQPACKET) {
-		if (sk->state != TCP_ESTABLISHED)
-			return -ENOTCONN;
-		bias = 1;
-	}
+	/*
+	 * 	This works for seqpacket too. The receiver has ordered the
+	 *	queue for us! We do one quick check first though
+	 */
+	if (sk->type == SOCK_SEQPACKET && sk->state != TCP_ESTABLISHED)
+		return -ENOTCONN;
 
 	/* Now we can treat all alike */
 	if ((skb = skb_recv_datagram(sk, flags, noblock, &er)) == NULL)
 		return er;
 
-	copied = (size < skb->len - bias) ? size : skb->len - bias;
-	skb_copy_datagram(skb, bias, ubuf, copied);
+	if (sk->ax25->hdrincl) {
+		length = skb->len + (skb->data - skb->h.raw);
+	} else {
+		if (sk->type == SOCK_SEQPACKET)
+			skb_pull(skb, 1);		/* Remove PID */
+		length     = skb->len;
+		skb->h.raw = skb->data;
+	}
+
+	copied = (size < length) ? size : length;
+	skb_copy_datagram(skb, 0, ubuf, copied);
 	
 	if (sax) {
 		struct sockaddr_ax25 addr;
@@ -1887,6 +1958,16 @@
 			ax25_digi_on = amount ? 1 : 0;
 			return 0;
 
+		case SIOCAX25GETPARMS:
+		case SIOCAX25SETPARMS:
+			return ax25_dev_ioctl(cmd, (void *)arg);
+
+		case SIOCADDRT:
+		case SIOCDELRT:
+			if (!suser())
+				return -EPERM;
+			return ax25_rt_ioctl(cmd, (void *)arg);
+
 		case SIOCGIFADDR:
 		case SIOCSIFADDR:
 		case SIOCGIFDSTADDR:
@@ -1907,7 +1988,7 @@
 	return(0);
 }
 
-int ax25_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+static int ax25_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	ax25_cb *ax25;
 	struct device *dev;
@@ -2050,7 +2131,7 @@
 		ax25_cs_get_info
 	});
 
-	printk("GW4PTS/G4KLX AX.25 for Linux. Version 0.30 ALPHA for Linux NET3.030 (Linux 1.3.0)\n");
+	printk("G4KLX/GW4PTS AX.25 for Linux. Version 0.30 ALPHA for Linux NET3.030 (Linux 1.3.20)\n");
 }
 
 /*
@@ -2158,8 +2239,7 @@
 
 	if (bp[16] == AX25_P_IP) {
 		mode = ax25_ip_mode_get((ax25_address *)(bp + 1), dev);
-
-		if (mode == 'V' || mode == 'v' || (mode == ' ' && sl_get_ax25_mode(dev))) {
+		if (mode == 'V' || mode == 'v' || (mode == ' ' && ax25_dev_get_value(dev, AX25_VALUES_IPDEFMODE) == 'V')) {
 			skb_device_unlock(skb);
 			skb_pull(skb, AX25_HEADER_LEN - 1);	/* Keep PID */
 			ax25_send_frame(skb, (ax25_address *)(bp + 8), (ax25_address *)(bp + 1), NULL, dev);
diff -u --recursive --new-file v1.3.19/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
--- v1.3.19/linux/net/ax25/ax25_in.c	Mon Jul 31 15:59:04 1995
+++ linux/net/ax25/ax25_in.c	Wed Aug 16 15:10:12 1995
@@ -64,6 +64,7 @@
 static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
 {
 	struct sk_buff *skbn, *skbo;
+	int hdrlen;
 	
 	if (ax25->fragno != 0) {
 		if (!(*skb->data & SEG_FIRST)) {
@@ -86,6 +87,14 @@
 					}
 
 					skb_reserve(skbn, AX25_MAX_HEADER_LEN);
+					skbn->h.raw = skbn->data;
+
+					skbo = skb_dequeue(&ax25->frag_queue);
+					hdrlen = skbo->data - skbo->h.raw;
+					skb_push(skbo, hdrlen);
+					memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
+					skb_pull(skbn, hdrlen);
+					kfree_skb(skbo, FREE_READ);
 
 					while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
 						memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
@@ -122,13 +131,13 @@
 {
 	int queued = 0;
 
-	skb->h.raw = skb->data;
-
 	switch (*skb->data) {
 #ifdef CONFIG_NETROM
 		case AX25_P_NETROM:
-			skb_pull(skb, 1);	/* Remove PID */
-			queued = nr_route_frame(skb, ax25);
+			if (ax25_dev_get_value(ax25->device, AX25_VALUES_NETROM)) {
+				skb_pull(skb, 1);	/* Remove PID */
+				queued = nr_route_frame(skb, ax25);
+			}
 			break;
 #endif
 #ifdef CONFIG_INET
@@ -141,7 +150,7 @@
 			break;
 #endif
 		case AX25_P_TEXT:
-			if (ax25->sk != NULL) {
+			if (ax25->sk != NULL && ax25_dev_get_value(ax25->device, AX25_VALUES_TEXT)) {
 				if (sock_queue_rcv_skb(ax25->sk, skb) == 0) {
 					queued = 1;
 				} else {
@@ -172,11 +181,13 @@
 	switch (frametype) {
 		case SABM:
 			ax25->modulus = MODULUS;
+			ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
 			ax25_send_control(ax25, UA, pf, C_RESPONSE);
 			break;
 
 		case SABME:
 			ax25->modulus = EMODULUS;
+			ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW);
 			ax25_send_control(ax25, UA, pf, C_RESPONSE);
 			break;
 
@@ -217,6 +228,7 @@
 					}
 				} else {
 					ax25->modulus = MODULUS;
+					ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
 				}
 			}
 			break;
@@ -298,6 +310,7 @@
 	switch (frametype) {
 		case SABM:
 			ax25->modulus   = MODULUS;
+			ax25->window    = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
 			ax25_send_control(ax25, UA, pf, C_RESPONSE);
 			ax25->condition = 0x00;
 			ax25->t1timer   = 0;
@@ -309,6 +322,7 @@
 
 		case SABME:
 			ax25->modulus   = EMODULUS;
+			ax25->window    = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW);
 			ax25_send_control(ax25, UA, pf, C_RESPONSE);
 			ax25->condition = 0x00;
 			ax25->t1timer   = 0;
@@ -455,6 +469,7 @@
 	switch (frametype) {
 		case SABM:
 			ax25->modulus   = MODULUS;
+			ax25->window    = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
 			ax25_send_control(ax25, UA, pf, C_RESPONSE);
 			ax25->condition = 0x00;
 			ax25->t1timer   = 0;
@@ -468,6 +483,7 @@
 
 		case SABME:
 			ax25->modulus   = EMODULUS;
+			ax25->window    = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW);
 			ax25_send_control(ax25, UA, pf, C_RESPONSE);
 			ax25->condition = 0x00;
 			ax25->t1timer   = 0;
diff -u --recursive --new-file v1.3.19/linux/net/ax25/ax25_out.c linux/net/ax25/ax25_out.c
--- v1.3.19/linux/net/ax25/ax25_out.c	Mon Jul 31 15:59:04 1995
+++ linux/net/ax25/ax25_out.c	Wed Aug 16 15:10:12 1995
@@ -286,6 +286,16 @@
 	ax25->condition &= ~ACK_PENDING_CONDITION;
 }
 
+void ax25_timeout_response(ax25_cb *ax25)
+{
+	if (ax25->condition & OWN_RX_BUSY_CONDITION)
+		ax25_send_control(ax25, RNR, POLLOFF, C_RESPONSE);
+	else
+		ax25_send_control(ax25, RR, POLLOFF, C_RESPONSE);
+
+	ax25->condition &= ~ACK_PENDING_CONDITION;
+}
+
 void ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
 {
 	if (ax25->vs == nr) {
diff -u --recursive --new-file v1.3.19/linux/net/ax25/ax25_route.c linux/net/ax25/ax25_route.c
--- v1.3.19/linux/net/ax25/ax25_route.c	Wed Aug  9 14:55:43 1995
+++ linux/net/ax25/ax25_route.c	Wed Aug 16 15:10:12 1995
@@ -24,6 +24,9 @@
  *					removes the heard structure.
  *	AX.25 029	Steven(GW7RRM)	Added /proc information for uid/callsign mapping.
  *			Jonathan(G4KLX)	Handling of IP mode in the routing list and /proc entry.
+ *	AX.25 030	Jonathan(G4KLX)	Added digi-peaters to routing table, and
+ *					ioctls to manipulate them. Added port
+ *					configuration.
  */
  
 #include <linux/config.h>
@@ -55,12 +58,19 @@
 	struct ax25_route *next;
 	ax25_address callsign;
 	struct device *dev;
+	ax25_digi *digipeat;
 	struct timeval stamp;
 	int n;
 	char ip_mode;
 } *ax25_route = NULL;
 
-void ax25_rt_rx_frame(ax25_address *src, struct device *dev)
+static struct ax25_dev {
+	struct ax25_dev *next;
+	struct device *dev;
+	unsigned short values[AX25_MAX_VALUES];
+} *ax25_device = NULL;
+
+void ax25_rt_rx_frame(ax25_address *src, struct device *dev, ax25_digi *digi)
 {
 	unsigned long flags;
 	extern struct timeval xtime;
@@ -72,11 +82,12 @@
 	oldest = NULL;
 
 	for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
-		if (count == 0 || ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec)
+		if (count == 0 || (ax25_rt->stamp.tv_sec != 0 && ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec))
 			oldest = ax25_rt;
 		
 		if (ax25cmp(&ax25_rt->callsign, src) == 0 && ax25_rt->dev == dev) {
-			ax25_rt->stamp = xtime;
+			if (ax25_rt->stamp.tv_sec != 0)
+				ax25_rt->stamp = xtime;
 			ax25_rt->n++;
 			return;			
 		}
@@ -87,6 +98,10 @@
 	if (count > AX25_ROUTE_MAX) {
 		oldest->callsign = *src;
 		oldest->dev      = dev;
+		if (oldest->digipeat != NULL) {
+			kfree_s(oldest->digipeat, sizeof(ax25_digi));
+			oldest->digipeat = NULL;
+		}
 		oldest->stamp    = xtime;
 		oldest->n        = 1;
 		oldest->ip_mode  = ' ';
@@ -98,10 +113,19 @@
 
 	ax25_rt->callsign = *src;
 	ax25_rt->dev      = dev;
+	ax25_rt->digipeat = NULL;
 	ax25_rt->stamp    = xtime;
 	ax25_rt->n        = 1;
 	ax25_rt->ip_mode  = ' ';
 
+	if (digi != NULL) {
+		if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+			kfree_s(ax25_rt, sizeof(struct ax25_route));
+			return;
+		}
+		memcpy(ax25_rt->digipeat, digi, sizeof(ax25_digi));
+	}
+
 	save_flags(flags);
 	cli();
 
@@ -122,11 +146,15 @@
 		if (s->dev == dev) {
 			if (ax25_route == s) {
 				ax25_route = s->next;
+				if (s->digipeat != NULL)
+					kfree_s((void *)s->digipeat, sizeof(ax25_digi));
 				kfree_s((void *)s, (sizeof *s));
 			} else {
 				for (t = ax25_route; t != NULL; t = t->next) {
 					if (t->next == s) {
 						t->next = s->next;
+						if (s->digipeat != NULL)
+							kfree_s((void *)s->digipeat, sizeof(ax25_digi));
 						kfree_s((void *)s, sizeof(*s));
 						break;
 					}
@@ -136,16 +164,116 @@
 	}
 }
 
+int ax25_rt_ioctl(unsigned int cmd, void *arg)
+{
+	unsigned long flags;
+	struct ax25_route *s, *t, *ax25_rt;
+	struct ax25_routes_struct route;
+	struct device *dev;
+	int i, err;
+
+	switch (cmd) {
+		case SIOCADDRT:
+			if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0)
+				return err;		
+			memcpy_fromfs(&route, arg, sizeof(route));
+			if ((dev = ax25rtr_get_dev(&route.port_addr)) == NULL)
+				return -EINVAL;
+			if (route.digi_count > 6)
+				return -EINVAL;
+			for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
+				if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == dev) {
+					if (ax25_rt->digipeat != NULL) {
+						kfree_s(ax25_rt->digipeat, sizeof(ax25_digi));
+						ax25_rt->digipeat = NULL;
+					}
+					if (route.digi_count != 0) {
+						if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
+							return -ENOMEM;
+						ax25_rt->digipeat->lastrepeat = 0;
+						ax25_rt->digipeat->ndigi      = route.digi_count;
+						for (i = 0; i < route.digi_count; i++) {
+							ax25_rt->digipeat->repeated[i] = 0;
+							ax25_rt->digipeat->calls[i]    = route.digi_addr[i];
+						}
+					}
+					ax25_rt->stamp.tv_sec = 0;
+					return 0;
+				}
+			}
+			if ((ax25_rt = (struct ax25_route *)kmalloc(sizeof(struct ax25_route), GFP_ATOMIC)) == NULL)
+				return -ENOMEM;
+			ax25_rt->callsign     = route.dest_addr;
+			ax25_rt->dev          = dev;
+			ax25_rt->digipeat     = NULL;
+			ax25_rt->stamp.tv_sec = 0;
+			ax25_rt->n            = 0;
+			ax25_rt->ip_mode      = ' ';
+			if (route.digi_count != 0) {
+				if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+					kfree_s(ax25_rt, sizeof(struct ax25_route));
+					return -ENOMEM;
+				}
+				ax25_rt->digipeat->lastrepeat = 0;
+				ax25_rt->digipeat->ndigi      = route.digi_count;
+				for (i = 0; i < route.digi_count; i++) {
+					ax25_rt->digipeat->repeated[i] = 0;
+					ax25_rt->digipeat->calls[i]    = route.digi_addr[i];
+				}
+			}
+			save_flags(flags);
+			cli();
+			ax25_rt->next = ax25_route;
+			ax25_route    = ax25_rt;
+			restore_flags(flags);
+			break;
+
+		case SIOCDELRT:
+			if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0)
+				return err;
+			memcpy_fromfs(&route, arg, sizeof(route));
+			if ((dev = ax25rtr_get_dev(&route.port_addr)) == NULL)
+				return -EINVAL;
+			ax25_rt = ax25_route;
+			while (ax25_rt != NULL) {
+				s       = ax25_rt;
+				ax25_rt = ax25_rt->next;
+				if (s->dev == dev && ax25cmp(&route.dest_addr, &s->callsign) == 0) {
+					if (ax25_route == s) {
+						ax25_route = s->next;
+						if (s->digipeat != NULL)
+							kfree_s((void *)s->digipeat, sizeof(ax25_digi));
+						kfree_s((void *)s, (sizeof *s));
+					} else {
+						for (t = ax25_route; t != NULL; t = t->next) {
+							if (t->next == s) {
+								t->next = s->next;
+								if (s->digipeat != NULL)
+									kfree_s((void *)s->digipeat, sizeof(ax25_digi));
+								kfree_s((void *)s, sizeof(*s));
+								break;
+							}
+						}				
+					}
+				}
+			}
+			break;
+	}
+
+	return 0;
+}
+
 int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	struct ax25_route *ax25_rt;
 	int len     = 0;
 	off_t pos   = 0;
 	off_t begin = 0;
+	int i;
   
 	cli();
 
-	len += sprintf(buffer, "callsign  dev  count time      mode\n");
+	len += sprintf(buffer, "callsign  dev  count time      mode digipeaters\n");
 
 	for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
 		len += sprintf(buffer + len, "%-9s %-4s %5d %9d",
@@ -157,16 +285,22 @@
 		switch (ax25_rt->ip_mode) {
 			case 'V':
 			case 'v':
-				len += sprintf(buffer + len, "   vc\n");
+				len += sprintf(buffer + len, "   vc");
 				break;
 			case 'D':
 			case 'd':
-				len += sprintf(buffer + len, "   dg\n");
+				len += sprintf(buffer + len, "   dg");
 				break;
 			default:
-				len += sprintf(buffer + len, "\n");
+				len += sprintf(buffer + len, "     ");
 				break;
 		}
+
+		if (ax25_rt->digipeat != NULL)
+			for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
+				len += sprintf(buffer + len, " %s", ax2asc(&ax25_rt->digipeat->calls[i]));
+		
+		len += sprintf(buffer + len, "\n");
 				
 		pos = begin + len;
 
@@ -245,6 +379,11 @@
 				call = (ax25_address *)ax25->device->dev_addr;
 			}
 			memcpy(&ax25->source_addr, call, sizeof(ax25_address));
+			if (ax25_rt->digipeat != NULL) {
+				if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
+					return -ENOMEM;
+				memcpy(ax25->digipeat, ax25_rt->digipeat, sizeof(ax25_digi));
+			}
 			if (ax25->sk != NULL)
 				ax25->sk->zapped = 0;
 
@@ -283,6 +422,169 @@
 			return ax25_rt->ip_mode;
 
 	return ' ';
+}
+
+static struct ax25_dev *ax25_dev_get_dev(struct device *dev)
+{
+	struct ax25_dev *s;
+
+	for (s = ax25_device; s != NULL; s = s->next)
+		if (s->dev == dev)
+			return s;
+	
+	return NULL;
+}
+
+/*
+ *	Wow, a bit of data hiding. Is this C++ or what ?
+ */
+unsigned short ax25_dev_get_value(struct device *dev, int valueno)
+{
+	struct ax25_dev *ax25_dev;
+
+	if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL) {
+		printk("ax25_dev_get_flag called with invalid device\n");
+		return 1;
+	}
+
+	return ax25_dev->values[valueno];
+}
+
+/*
+ *	This is called when an interface is brought up. These are
+ *	reasonable defaults.
+ */
+void ax25_dev_device_up(struct device *dev)
+{
+	unsigned long flags;
+	struct ax25_dev *ax25_dev;
+	
+	if ((ax25_dev = (struct ax25_dev *)kmalloc(sizeof(struct ax25_dev), GFP_ATOMIC)) == NULL)
+		return;		/* No space */
+
+	ax25_dev->dev        = dev;
+
+	ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE;
+	ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE;
+	ax25_dev->values[AX25_VALUES_NETROM]    = AX25_DEF_NETROM;
+	ax25_dev->values[AX25_VALUES_TEXT]      = AX25_DEF_TEXT;
+	ax25_dev->values[AX25_VALUES_BACKOFF]   = AX25_DEF_BACKOFF;
+	ax25_dev->values[AX25_VALUES_CONMODE]   = AX25_DEF_CONMODE;
+	ax25_dev->values[AX25_VALUES_WINDOW]    = AX25_DEF_WINDOW;
+	ax25_dev->values[AX25_VALUES_EWINDOW]   = AX25_DEF_EWINDOW;
+	ax25_dev->values[AX25_VALUES_T1]        = (AX25_DEF_T1 * PR_SLOWHZ) / 2;
+	ax25_dev->values[AX25_VALUES_T2]        = AX25_DEF_T2 * PR_SLOWHZ;
+	ax25_dev->values[AX25_VALUES_T3]        = AX25_DEF_T3 * PR_SLOWHZ;
+	ax25_dev->values[AX25_VALUES_N2]        = AX25_DEF_N2;
+
+	save_flags(flags);
+	cli();
+
+	ax25_dev->next = ax25_device;
+	ax25_device    = ax25_dev;
+
+	restore_flags(flags);
+}
+
+void ax25_dev_device_down(struct device *dev)
+{
+	struct ax25_dev *s, *t, *ax25_dev = ax25_device;
+	
+	while (ax25_dev != NULL) {
+		s        = ax25_dev;
+		ax25_dev = ax25_dev->next;
+
+		if (s->dev == dev) {
+			if (ax25_device == s) {
+				ax25_device = s->next;
+				kfree_s((void *)s, (sizeof *s));
+			} else {
+				for (t = ax25_device; t != NULL; t = t->next) {
+					if (t->next == s) {
+						t->next = s->next;
+						kfree_s((void *)s, sizeof(*s));
+						break;
+					}
+				}				
+			}
+		}
+	}
+}
+
+int ax25_dev_ioctl(unsigned int cmd, void *arg)
+{
+	struct ax25_parms_struct ax25_parms;
+	struct device *dev;
+	struct ax25_dev *ax25_dev;
+	int err;
+
+	switch (cmd) {
+		case SIOCAX25SETPARMS:
+			if (!suser())
+				return -EPERM;
+			if ((err = verify_area(VERIFY_READ, arg, sizeof(ax25_parms))) != 0)
+				return err;
+			memcpy_fromfs(&ax25_parms, arg, sizeof(ax25_parms));
+			if ((dev = ax25rtr_get_dev(&ax25_parms.port_addr)) == NULL)
+				return -EINVAL;
+			if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL)
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_IPDEFMODE] != 'D' &&
+			    ax25_parms.values[AX25_VALUES_IPDEFMODE] != 'V')
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_AXDEFMODE] != MODULUS &&
+			    ax25_parms.values[AX25_VALUES_AXDEFMODE] != EMODULUS)
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_NETROM] != 0 &&
+			    ax25_parms.values[AX25_VALUES_NETROM] != 1)
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_TEXT] != 0 &&
+			    ax25_parms.values[AX25_VALUES_TEXT] != 1)
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_BACKOFF] != 'E' &&
+			    ax25_parms.values[AX25_VALUES_BACKOFF] != 'L')
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_CONMODE] != 0 &&
+			    ax25_parms.values[AX25_VALUES_CONMODE] != 1)
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_WINDOW] < 1 ||
+			    ax25_parms.values[AX25_VALUES_WINDOW] > 7)
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_EWINDOW] < 1 ||
+			    ax25_parms.values[AX25_VALUES_EWINDOW] > 63)
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_T1] < 1)
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_T2] < 1)
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_T3] < 1)
+				return -EINVAL;
+			if (ax25_parms.values[AX25_VALUES_N2] < 1 ||
+			    ax25_parms.values[AX25_VALUES_N2] > 31)
+				return -EINVAL;
+			memcpy(ax25_dev->values, ax25_parms.values, AX25_MAX_VALUES * sizeof(short));
+			ax25_dev->values[AX25_VALUES_T1] *= (PR_SLOWHZ / 2);
+			ax25_dev->values[AX25_VALUES_T2] *= PR_SLOWHZ;
+			ax25_dev->values[AX25_VALUES_T3] *= PR_SLOWHZ;
+			break;
+
+		case SIOCAX25GETPARMS:
+			if ((err = verify_area(VERIFY_WRITE, arg, sizeof(struct ax25_parms_struct))) != 0)
+				return err;
+			memcpy_fromfs(&ax25_parms, arg, sizeof(ax25_parms));
+			if ((dev = ax25rtr_get_dev(&ax25_parms.port_addr)) == NULL)
+				return -EINVAL;
+			if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL)
+				return -EINVAL;
+			memcpy(ax25_parms.values, ax25_dev->values, AX25_MAX_VALUES * sizeof(short));
+			ax25_parms.values[AX25_VALUES_T1] /= (PR_SLOWHZ * 2);
+			ax25_parms.values[AX25_VALUES_T2] /= PR_SLOWHZ;
+			ax25_parms.values[AX25_VALUES_T3] /= PR_SLOWHZ;
+			memcpy_tofs(arg, &ax25_parms, sizeof(ax25_parms));
+			break;
+	}
+
+	return 0;
 }
 
 #endif
diff -u --recursive --new-file v1.3.19/linux/net/ax25/ax25_timer.c linux/net/ax25/ax25_timer.c
--- v1.3.19/linux/net/ax25/ax25_timer.c	Mon Jul 31 15:59:04 1995
+++ linux/net/ax25/ax25_timer.c	Wed Aug 16 15:10:12 1995
@@ -130,7 +130,7 @@
 		if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4) {
 			if (ax25->condition & ACK_PENDING_CONDITION) {
 				ax25->condition &= ~ACK_PENDING_CONDITION;
-				ax25_enquiry_response(ax25);
+				ax25_timeout_response(ax25);
 			}
 		}
 	}
@@ -167,7 +167,9 @@
 					}
 				} else {
 					ax25->modulus = MODULUS;
+					ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
 					ax25->n2count = 0;
+					ax25_send_control(ax25, SABM, POLLON, C_COMMAND);
 				}
 			} else {
 				ax25->n2count++;
diff -u --recursive --new-file v1.3.19/linux/net/core/Makefile linux/net/core/Makefile
--- v1.3.19/linux/net/core/Makefile	Tue Aug 15 20:39:07 1995
+++ linux/net/core/Makefile	Wed Aug 16 13:31:12 1995
@@ -9,8 +9,10 @@
 
 O_TARGET := core.o
 
+O_OBJS	:=
+
 ifdef CONFIG_NET
-O_OBJS	 := sock.o dev.o dev_mcast.o skbuff.o datagram.o iovec.o
+O_OBJS	+= sock.o dev.o dev_mcast.o iovec.o skbuff.o datagram.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.19/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v1.3.19/linux/net/ipv4/arp.c	Tue Aug 15 20:39:11 1995
+++ linux/net/ipv4/arp.c	Wed Aug 16 15:10:12 1995
@@ -1240,13 +1240,13 @@
 #ifdef CONFIG_AX25
 		case ARPHRD_AX25:
 			htype = ARPHRD_AX25;
-			hlen = 7;
+			hlen = AX25_ADDR_LEN;
 			break;
 #endif
 #ifdef CONFIG_NETROM
 		case ARPHRD_NETROM:
 			htype = ARPHRD_NETROM;
-			hlen = 7;
+			hlen = AX25_ADDR_LEN;
 			break;
 #endif
 		case ARPHRD_IEEE802:
diff -u --recursive --new-file v1.3.19/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c
--- v1.3.19/linux/net/ipv4/igmp.c	Mon Jul 31 15:59:04 1995
+++ linux/net/ipv4/igmp.c	Wed Aug 16 11:57:40 1995
@@ -30,6 +30,7 @@
 #include <linux/in.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/if_arp.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 #include <net/route.h>
diff -u --recursive --new-file v1.3.19/linux/net/ipv4/ip.c linux/net/ipv4/ip.c
--- v1.3.19/linux/net/ipv4/ip.c	Tue Aug 15 20:39:11 1995
+++ linux/net/ipv4/ip.c	Wed Aug 16 11:50:57 1995
@@ -127,6 +127,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/proc_fs.h>
+#include <linux/stat.h>
 
 #include <net/snmp.h>
 #include <net/ip.h>
@@ -1695,7 +1696,6 @@
  
 static void ip_loopback(struct device *old_dev, struct sk_buff *skb)
 {
-	extern struct device loopback_dev;
 	struct device *dev=&loopback_dev;
 	int len=skb->len-old_dev->hard_header_len;
 	struct sk_buff *newskb=dev_alloc_skb(len+dev->hard_header_len+15);
diff -u --recursive --new-file v1.3.19/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v1.3.19/linux/net/ipv4/ip_fw.c	Tue Aug 15 20:39:11 1995
+++ linux/net/ipv4/ip_fw.c	Wed Aug 16 12:04:18 1995
@@ -84,6 +84,7 @@
 #include <linux/ip_fw.h>
 #include <net/checksum.h>
 #include <linux/proc_fs.h>
+#include <linux/stat.h>
 
 /*
  *	Implement IP packet firewall
diff -u --recursive --new-file v1.3.19/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c
--- v1.3.19/linux/net/ipv4/ipip.c	Thu Jul 13 16:20:22 1995
+++ linux/net/ipv4/ipip.c	Wed Aug 16 15:10:11 1995
@@ -7,6 +7,8 @@
  *	Fixes:
  *		Alan Cox	:	Merged and made usable non modular (its so tiny its silly as
  *					a module taking up 2 pages).
+ *		Alan Cox	: 	Fixed bug with 1.3.18 and IPIP not working (now needs to set skb->h.iph)
+ *					to keep ip_forward happy.
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -56,6 +58,7 @@
 #ifdef TUNNEL_DEBUG
 	printk("ipip_rcv: got a packet!\n");
 #endif
+	skb->h.iph=skb->data;	/* Correct IP header pointer on to new header */
 	if(ip_forward(skb, dev, 0, daddr, 0))
 		kfree_skb(skb, FREE_READ);
 	MOD_DEC_USE_COUNT;
diff -u --recursive --new-file v1.3.19/linux/net/ipv4/rarp.c linux/net/ipv4/rarp.c
--- v1.3.19/linux/net/ipv4/rarp.c	Tue Aug 15 20:39:11 1995
+++ linux/net/ipv4/rarp.c	Wed Aug 16 12:05:56 1995
@@ -66,6 +66,7 @@
 #include <net/ax25.h>
 #endif
 #include <linux/proc_fs.h>
+#include <linux/stat.h>
 
 #if	defined(CONFIG_INET_RARP) || defined(MODULE)
 
diff -u --recursive --new-file v1.3.19/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v1.3.19/linux/net/ipx/af_ipx.c	Tue Aug 15 20:39:12 1995
+++ linux/net/ipx/af_ipx.c	Wed Aug 16 12:07:11 1995
@@ -60,6 +60,7 @@
 #include <linux/ipx.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/route.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/segment.h>
@@ -71,6 +72,7 @@
 #include <net/p8022.h>
 #include <net/psnap.h>
 #include <linux/proc_fs.h>
+#include <linux/stat.h>
 
 #ifdef CONFIG_IPX
 /* Configuration Variables */
diff -u --recursive --new-file v1.3.19/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v1.3.19/linux/net/netrom/af_netrom.c	Tue Aug 15 20:39:12 1995
+++ linux/net/netrom/af_netrom.c	Wed Aug 16 15:10:12 1995
@@ -50,7 +50,7 @@
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <net/netrom.h>
-
+#include <linux/proc_fs.h>
 #include <net/ip.h>
 #include <net/arp.h>
 
@@ -115,8 +115,6 @@
 			s->dead  = 1;
 		}
 	}
-
-	nr_rt_device_down(dev);
 }
 
 /*
@@ -124,10 +122,13 @@
  */
 static int nr_device_event(unsigned long event, void *ptr)
 {
+	struct device *dev = (struct device *)ptr;
+
 	if (event != NETDEV_DOWN)
 		return NOTIFY_DONE;
 		
-	nr_kill_by_device(ptr);
+	nr_kill_by_device(dev);
+	nr_rt_device_down(dev);
 	
 	return NOTIFY_DONE;
 }
@@ -329,6 +330,10 @@
 			sk->nr->n2 = opt;
 			return 0;
 			
+		case NETROM_HDRINCL:
+			sk->nr->hdrincl = opt ? 1 : 0;
+			return 0;
+			
 		default:
 			return -ENOPROTOOPT;
 	}
@@ -351,7 +356,7 @@
 	
 	switch (optname) {
 		case NETROM_T1:
-			val = sk->nr->t1 / PR_SLOWHZ;
+			val = (sk->nr->t1 * 2) / PR_SLOWHZ;
 			break;
 			
 		case NETROM_T2:
@@ -362,6 +367,10 @@
 			val = sk->nr->n2;
 			break;
 						
+		case NETROM_HDRINCL:
+			val = sk->nr->hdrincl;
+			break;
+
 		default:
 			return -ENOPROTOOPT;
 	}
@@ -497,6 +506,7 @@
 
 	nr->bpqext     = 1;
 	nr->fraglen    = 0;
+	nr->hdrincl    = 0;
 	nr->state      = NR_STATE_0;
 	nr->device     = NULL;
 
@@ -580,6 +590,7 @@
 
 	nr->device   = osk->nr->device;
 	nr->bpqext   = osk->nr->bpqext;
+	nr->hdrincl  = osk->nr->hdrincl;
 	nr->fraglen  = 0;
 
 	nr->t1timer  = 0;
@@ -931,10 +942,9 @@
 	 */
 	if (((frametype & 0x0F) != NR_CONNREQ && (sk = nr_find_socket(circuit_index, circuit_id, SOCK_SEQPACKET)) != NULL) ||
 	    ((frametype & 0x0F) == NR_CONNREQ && (sk = nr_find_peer(circuit_index, circuit_id, SOCK_SEQPACKET)) != NULL)) {
-		skb_pull(skb, NR_NETWORK_LEN);
-		skb->h.raw = skb->data + NR_TRANSPORT_LEN;
+		skb->h.raw = skb->data;
 
-		if ((frametype & 0x0F) == NR_CONNACK && skb->len == 7)
+		if ((frametype & 0x0F) == NR_CONNACK && skb->len == 22)
 			sk->nr->bpqext = 1;
 		else
 			sk->nr->bpqext = 0;
@@ -1129,7 +1139,7 @@
 {
 	struct sock *sk = (struct sock *)sock->data;
 	struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)sip;
-	int copied = 0;
+	int copied;
 	struct sk_buff *skb;
 	int er;
 
@@ -1142,7 +1152,10 @@
 	if (addr_len != NULL)
 		*addr_len = sizeof(*sax);
 
-	/* This works for seqpacket too. The receiver has ordered the queue for us! We do one quick check first though */
+	/*
+	 * This works for seqpacket too. The receiver has ordered the queue for
+	 * us! We do one quick check first though
+	 */
 	if (sk->type == SOCK_SEQPACKET && sk->state != TCP_ESTABLISHED)
 		return -ENOTCONN;
 
@@ -1150,8 +1163,12 @@
 	if ((skb = skb_recv_datagram(sk, flags, noblock, &er)) == NULL)
 		return er;
 
-	copied = (size < skb->len - NR_TRANSPORT_LEN) ? size : skb->len - NR_TRANSPORT_LEN;
+	if (!sk->nr->hdrincl) {
+		skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
+		skb->h.raw = skb->data;
+	}
 
+	copied = (size < skb->len) ? size : skb->len;
 	skb_copy_datagram(skb, 0, ubuf, copied);
 	
 	if (sax != NULL) {
@@ -1286,8 +1303,7 @@
 	return(0);
 }
 
-static int nr_get_info(char *buffer, char **start, off_t offset,
-		       int length, int dummy)
+static int nr_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	struct sock *s;
 	struct device *dev;
diff -u --recursive --new-file v1.3.19/linux/net/netrom/nr_dev.c linux/net/netrom/nr_dev.c
--- v1.3.19/linux/net/netrom/nr_dev.c	Mon Jul 31 15:59:05 1995
+++ linux/net/netrom/nr_dev.c	Wed Aug 16 15:10:12 1995
@@ -211,7 +211,7 @@
 	dev->stop		= nr_close;
 
 	dev->hard_header	= nr_header;
-	dev->hard_header_len	= AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + 2 + NR_NETWORK_LEN + NR_TRANSPORT_LEN;
+	dev->hard_header_len	= AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + 3 + NR_NETWORK_LEN + NR_TRANSPORT_LEN;
 	dev->addr_len		= AX25_ADDR_LEN;
 	dev->type		= ARPHRD_NETROM;
 	dev->rebuild_header	= nr_rebuild_header;
diff -u --recursive --new-file v1.3.19/linux/net/netrom/nr_in.c linux/net/netrom/nr_in.c
--- v1.3.19/linux/net/netrom/nr_in.c	Mon Jul 31 15:59:05 1995
+++ linux/net/netrom/nr_in.c	Wed Aug 16 15:10:12 1995
@@ -68,11 +68,16 @@
 		skbn->free = 1;
 		skbn->arp  = 1;
 		skbn->sk   = sk;
-		sk->rmem_alloc += skb->truesize;
-			
+		sk->rmem_alloc += skbn->truesize;
+		skbn->h.raw = skbn->data;
+
+		skbo = skb_dequeue(&sk->nr->frag_queue);
+		memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
+		kfree_skb(skbo, FREE_READ);
+
 		while ((skbo = skb_dequeue(&sk->nr->frag_queue)) != NULL) {
+			skb_pull(skbo, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
 			memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
-
 			kfree_skb(skbo, FREE_READ);
 		}
 
@@ -93,9 +98,9 @@
 
 		case NR_CONNACK:
 			nr_calculate_rtt(sk);
-			sk->window         = skb->data[5];
-			sk->nr->your_index = skb->data[2];
-			sk->nr->your_id    = skb->data[3];
+			sk->window         = skb->data[20];
+			sk->nr->your_index = skb->data[17];
+			sk->nr->your_id    = skb->data[18];
 			sk->nr->t1timer    = 0;
 			sk->nr->t2timer    = 0;
 			sk->nr->t4timer    = 0;
@@ -170,8 +175,8 @@
 	unsigned short nr, ns;
 	int queued = 0;
 
-	nr = skb->data[3];
-	ns = skb->data[2];
+	nr = skb->data[18];
+	ns = skb->data[17];
 
 	switch (frametype) {
 
@@ -276,7 +281,7 @@
 			do {
 				save_vr = sk->nr->vr;
 				while ((skbn = skb_dequeue(&sk->nr->reseq_queue)) != NULL) {
-					ns = skbn->data[2];
+					ns = skbn->data[17];
 					if (ns == sk->nr->vr) {
 						if (nr_queue_rx_frame(sk, skbn, frametype & NR_MORE_FLAG) == 0) {
 							sk->nr->vr = (sk->nr->vr + 1) % NR_MODULUS;
@@ -328,7 +333,7 @@
 
 	del_timer(&sk->timer);
 
-	frametype = skb->data[4];
+	frametype = skb->data[19];
 
 	switch (sk->nr->state)
 	{
diff -u --recursive --new-file v1.3.19/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v1.3.19/linux/net/unix/af_unix.c	Tue Aug 15 20:39:12 1995
+++ linux/net/unix/af_unix.c	Wed Aug 16 15:10:11 1995
@@ -15,6 +15,8 @@
  *
  * Fixes:
  *		Linus Torvalds	:	Assorted bug cures.
+ *		Niibe Yutaka	:	async I/O support
+ *		Carsten Paeth	:	PF_UNIX check, address fixes.
  */
 
 #include <linux/config.h>
@@ -237,14 +239,26 @@
 static void def_callback2(struct sock *sk, int len)
 {
 	if(!sk->dead)
+	{
 		wake_up_interruptible(sk->sleep);
+		sock_wake_async(sk->socket, 1);
+	}
+}
+
+static void def_callback3(struct sock *sk)
+{
+	if(!sk->dead)
+	{
+		wake_up_interruptible(sk->sleep);
+		sock_wake_async(sk->socket, 2);
+	}
 }
 
 static int unix_create(struct socket *sock, int protocol)
 {
 	unix_socket *sk;
 /*	printk("Unix create\n");*/
-	if(protocol)
+	if(protocol && protocol != PF_UNIX)
 		return -EPROTONOSUPPORT;
 	sk=(unix_socket *)kmalloc(sizeof(*sk),GFP_KERNEL);
 	if(sk==NULL)
@@ -289,7 +303,7 @@
 	sk->shutdown=0;
 	sk->state_change=def_callback1;
 	sk->data_ready=def_callback2;
-	sk->write_space=def_callback1;
+	sk->write_space=def_callback3;
 	sk->error_report=def_callback1;
 	sk->mtu=4096;
 	sk->socket=sock;
@@ -410,7 +424,6 @@
 	struct sk_buff *skb;
 	int err;
 
-	unix_mkname(sun, addr_len);
 	if(sk->type==SOCK_STREAM && sk->protinfo.af_unix.other)
 	{
 		if(sock->state==SS_CONNECTING && sk->state==TCP_ESTABLISHED)
@@ -428,9 +441,11 @@
 		return -EISCONN;
 	}
 	
-	if(sun->sun_family!=AF_UNIX)
+	if(addr_len < sizeof(sun->sun_family)+1 || sun->sun_family!=AF_UNIX)
 		return -EINVAL;
-
+		
+	unix_mkname(sun, addr_len);
+		
 	if(sk->type==SOCK_DGRAM && sk->protinfo.af_unix.other)
 	{
 		sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
@@ -440,6 +455,11 @@
 
 	if(sock->type==SOCK_DGRAM)
 	{
+		other=unix_find_other(sun->sun_path, &err);
+		if(other==NULL)
+			return err;
+		other->protinfo.af_unix.locks++;
+		sk->protinfo.af_unix.other=other;
 		sock->state=SS_CONNECTED;
 		sk->state=TCP_ESTABLISHED;
 		return 0;			/* Done */
@@ -601,6 +621,7 @@
 	tsk->protinfo.af_unix.locks++;	/* Back lock */
 	sti();
 	tsk->state_change(tsk);		/* Wake up any sleeping connect */
+	sock_wake_async(tsk->socket, 0);
 	return 0;
 }
 
@@ -619,10 +640,10 @@
 	if(sk->protinfo.af_unix.name==NULL)
 	{
 		*sun->sun_path=0;
-		*uaddr_len=3;
+		*uaddr_len=sizeof(sun->sun_family)+1;
 		return 0;		/* Not bound */
 	}
-	*uaddr_len=sizeof(short)+strlen(sk->protinfo.af_unix.name)+1;
+	*uaddr_len=sizeof(sun->sun_family)+strlen(sk->protinfo.af_unix.name)+1;
 	strcpy(sun->sun_path,sk->protinfo.af_unix.name);		/* 108 byte limited */
 	return 0;
 }
@@ -688,6 +709,13 @@
 	if(sun==NULL)
 	{
 		other=sk->protinfo.af_unix.other;
+		if(sock->type==SOCK_DGRAM && other->dead)
+		{
+			other->protinfo.af_unix.locks--;
+			sk->protinfo.af_unix.other=NULL;
+			sock->state=SS_UNCONNECTED;
+			return -ECONNRESET;
+		}
 	}
 	else
 	{
@@ -761,7 +789,9 @@
 				{
 					return -EAGAIN;
 				}
+				sk->socket->flags |= SO_WAITDATA;
 				interruptible_sleep_on(sk->sleep);
+				sk->socket->flags &= ~SO_WAITDATA;
 				if( current->signal & ~current->blocked)
 				{
 					sti();
