diff -ur --new-file old/atm/.kernel new/atm/.kernel
--- old/atm/.kernel	Fri Jul 19 17:42:11 1996
+++ new/atm/.kernel	Wed Aug 21 11:22:21 1996
@@ -1,2 +1,2 @@
 # this file is used to control automated generation of differences
-2.0
+2.0.14
diff -ur --new-file old/atm/CHANGES new/atm/CHANGES
--- old/atm/CHANGES	Wed Jul 31 19:25:05 1996
+++ new/atm/CHANGES	Thu Aug 29 17:14:02 1996
@@ -1,3 +1,51 @@
+Version 0.15 to 0.16 (29-AUG-1996)
+====================
+
+Bug fixes
+---------
+
+ - fixed an "unterminated character constant" warning by CPP in qgen/uni3x
+ - atm/sigd/q2931.c always tried to read the Cause IE of RELEASE COMPLETE
+   messages even if it wasn't included
+ - LANE: fixed buffer allocation and VCC timeouts (Marko Kiiskila)
+ - LANE: when connecting directly to LES, name of the ELAN was not set
+   properly (discoverd by Gerald Hanusch; fixed by Marko Kiiskila)
+ - LANE, ATMARP, signaling: control sockets didn't account for messages sent
+   back from demons (fixed by Marko Kiiskila)
+ - permanent ATMARP entries for SVCs were ignored if no ATMARP server was
+   configured (reported by Gerald Hanusch)
+ - atmarp option "temp" mis-spelled as "term" (fixed by Gerald Hanusch)
+ - forgot to undo experimental rcvbuf/sndbuf change to unsigned long
+ - make modules didn't generate ATM modules
+ - atmtcp_attach_hook wasn't defined when compiling ATMTCP as a module
+ - ATM patch set dev->ip_atm to ether_arp in net/ppp.c and net/eql.c, so they
+   failed to work as modules
+
+New features
+------------
+
+ - added LANE servers (LECS, LES, and BUS) by Marko Kiiskila
+ - Rules.make: new variable INSTROOT for easier cross-installation
+ - atmsigd: added option -P to set the maximum PCR used on the signaling VC
+ - atmarp: added option "pcr <value>" (proposed by Gerald Hanusch)
+ - added the usual  -l <logfile>  option to arequipad
+
+Other changes
+-------------
+
+ - upgrade to kernel version 2.0.14
+ - SVCs can now be bound with any SEL value
+ - messages of size > quota can be sent if the send buffer is empty
+ - ilmid no longer empties the address list when refreshing the NSAP address
+   (by Gerald Hanusch)
+ - LANE client should now survive network reset (e.g. restart) gracefully
+   (Marko Kiiskila)
+ - LANE: major cleanup of zeppelin code (Marko Kiiskila)
+ - improved loadable module support for eni and zatm (i.e. loading works now)
+ - the message dumper can now be linked to programs that also use the
+   compilation/parsing functions
+
+
 Version 0.14 to 0.15 (31-JUL-1996)
 ====================
 
diff -ur --new-file old/atm/COPYING new/atm/COPYING
--- old/atm/COPYING	Fri Jul 19 15:45:03 1996
+++ new/atm/COPYING	Wed Aug 21 11:30:50 1996
@@ -22,4 +22,5 @@
 Technology - Telecommunications Laboratory. In addition to that,
 portions of the LAN Emulation client code are Copyright (C) 1995 by
 Digital Equipment Corporation.
-See led/COPYRIGHT.TUT and led/COPYRIGHT.DEC for copying terms.
+See lane/COPYRIGHT.TUT, led/COPYRIGHT.TUT, and led/COPYRIGHT.DEC for
+copying terms.
diff -ur --new-file old/atm/Makefile new/atm/Makefile
--- old/atm/Makefile	Wed Jul 31 14:37:38 1996
+++ new/atm/Makefile	Wed Aug 28 11:48:46 1996
@@ -1,7 +1,7 @@
 # "qgen" and "saal" _must_ appear before "sigd"
 # "lib" must appear before anything else
 
-DIRS=lib maint ip test debug qgen saal sigd arpd ilmid led aqd
+DIRS=lib maint ip test debug qgen saal sigd arpd ilmid led lane aqd
 
 all:
 		for n in $(DIRS); do $(MAKE) -C $$n || exit; done
diff -ur --new-file old/atm/README new/atm/README
--- old/atm/README	Tue Jul 30 19:15:22 1996
+++ new/atm/README	Wed Aug 21 11:32:26 1996
@@ -1,4 +1,4 @@
-ATM on Linux, release 0.15 (pre-alpha) by Werner Almesberger, EPFL LRC
+ATM on Linux, release 0.16 (pre-alpha) by Werner Almesberger, EPFL LRC
 ====================================== werner.almesberger@lrc.di.epfl.ch
 
 This is experimental software. There are known major bugs and certainly
@@ -25,7 +25,7 @@
   "raw" unreliable ATM transport over AAL5
   IP over ATM (NULL or SNAP encapsulation)
   ATMARP as defined in RFC1577 (client and server)
-  LAN Emulation (client side only)
+  LAN Emulation (client and server side)
   Arequipa (Application REQUested IP over ATM)
 
 The API is based on the Linux ATM API proposed on the linux-atm mailing
diff -ur --new-file old/atm/Rules.make new/atm/Rules.make
--- old/atm/Rules.make	Tue Jul 30 21:36:22 1996
+++ new/atm/Rules.make	Mon Aug  5 14:16:39 1996
@@ -1,4 +1,4 @@
-# Default is UNI 3.0, foor good reasons, see below.
+# Default is UNI 3.0, for good reasons, see below.
 #
 STANDARDS=-DUNI30
 #
@@ -20,12 +20,13 @@
 LDFLAGS=
 LDLIBS=-L../lib -latm -larequipa
 YACC=bison -y -d #-v
-INSTPREFIX=/usr/local
+INSTROOT=
+INSTPREFIX=$(INSTROOT)/usr/local
 INSTBOOTBIN=$(INSTPREFIX)/sbin
 INSTUSRBIN=$(INSTPREFIX)/bin
 INSTSYSBIN=$(INSTPREFIX)/sbin
-INSTLIB=/usr/lib
-INSTHDR=/usr/include
+INSTLIB=$(INSTROOT)/usr/lib
+INSTHDR=$(INSTROOT)/usr/include
 INSTMAN=$(INSTPREFIX)/man/man8
 
 LINK.c = $(CC) $(LDFLAGS)
diff -ur --new-file old/atm/USAGE new/atm/USAGE
--- old/atm/USAGE	Wed Jul 31 18:58:08 1996
+++ new/atm/USAGE	Thu Aug 29 16:17:44 1996
@@ -1,4 +1,4 @@
-Usage instructions  -  ATM on Linux, release 0.15 (pre-alpha)
+Usage instructions  -  ATM on Linux, release 0.16 (pre-alpha)
 -------------------------------------------------------------
 
 For updates of ATM on Linux, please check the Web page at  
@@ -17,9 +17,9 @@
 In order to install this package, you need 
 
   - the package itself  
-    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.15.tar.gz  
-  - the Linux kernel, version 2.0, e.g. from  
-    ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.tar.gz  
+    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.16.tar.gz  
+  - the Linux kernel, version 2.0.14, e.g. from  
+    ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.14.tar.gz  
   - Perl, version 4 or 5 
 
 
@@ -31,11 +31,11 @@
 all the files listed above there. Then extract the ATM on Linux 
 distribution:
 
-tar xfz atm-0.15.tar.gz
+tar xfz atm-0.16.tar.gz
 
 and the kernel source:
 
-tar xfz linux-2.0.tar.gz
+tar xfz linux-2.0.14.tar.gz
 
 Finally, you can extract the ATM-related patches:
 
@@ -56,6 +56,7 @@
   atm/ip/  IP over ATM: clip, atmarp 
   atm/arpd/  ATMARP demon: atmarpd 
   atm/led/  LAN Emulation demon: led 
+  atm/lane/  LAN Emulation servers: bus, lecs, les 
   atm/aqd/  Arequipa demon: arequipad 
   atm/debug/  Debugging tools: ed, en, encopy, endump, and zndump 
   atm/lib/  Libraries for applications and demons 
@@ -748,7 +749,9 @@
 
   # atmarp -s <ip_address> <atm_address>  
 
-There is also a  temp  option for SVCs.
+There is also a (probably not very useful)  temp  option for SVCs. All  
+atmarp -s  commands also accept an option  pcr <value>  to change the 
+connection to CBR (default is UBR) and to set the peak cell rate.
 
   # atmarp -d <ip_address>  
 
@@ -768,7 +771,7 @@
 Besides Classical IP over ATM, LAN Emulation (LANE) can be used to carry IP 
 over ATM. LANE emulates the characteristics of legacy LAN technology, such 
 as support for broadcasts. LANE client support is described in the file 
-atm/led/USAGE.
+atm/led/USAGE, LANE server support is described in atm/lane/USAGE.
 
 
 Arequipa
@@ -779,10 +782,13 @@
 parameters, etc.) to carry traffic between INET sockets. On a system that 
 should use Arequipa connections, the Arequipa demon has to be started:
 
-  # arequipad [-b] [-d] [-n]  
+  # arequipad [-b] [-d] [-l <logfile>] [-n]  
 
    -b   background. Run in a forked child process after initializing. 
    -d   enables debugging output. By default, arequipad is very quiet. 
+   -l <logfile>   write diagnostic messages to the specified file instead 
+    of to standard error. The special name  syslog  is used to send 
+    diagnostics to the system logger. 
    -n   prints addresses in numeric format only, i.e. no address to name 
     translation is attempted. 
 
diff -ur --new-file old/atm/VERSION new/atm/VERSION
--- old/atm/VERSION	Tue Jul 30 18:02:35 1996
+++ new/atm/VERSION	Wed Aug 21 09:54:15 1996
@@ -1 +1 @@
-0.15
+0.16
diff -ur --new-file old/atm/aqd/arequipad.c new/atm/aqd/arequipad.c
--- old/atm/aqd/arequipad.c	Wed Jul 17 19:24:11 1996
+++ new/atm/aqd/arequipad.c	Thu Aug 29 16:01:52 1996
@@ -29,7 +29,7 @@
 
 static void usage(const char *name)
 {
-    fprintf(stderr,"usage: %s [ -b ] [ -d ] [ -n ] \n",name);
+    fprintf(stderr,"usage: %s [ -b ] [ -d ] [ -l logfile ] [ -n ] \n",name);
     exit(1);
 }
 
@@ -49,6 +49,9 @@
 	    case 'd':
 		set_verbosity(NULL,DIAG_DEBUG);
 		debug = 1;
+		break;
+	    case 'l':
+		set_logfile(optarg);
 		break;
 	    case 'n':
 		pretty = A2T_PRETTY;
diff -ur --new-file old/atm/arpd/arp.c new/atm/arpd/arp.c
--- old/atm/arpd/arp.c	Mon Jul 29 13:40:22 1996
+++ new/atm/arpd/arp.c	Tue Aug 27 10:37:47 1996
@@ -511,8 +511,9 @@
 	diag(COMPONENT,DIAG_ERROR,"itf %d not found",itf_num);
 	return;
     }
-    if (!itf->arp_srv) return; /* bad luck - no ARP server */
     entry = lookup_ip(itf,ip);
+    if ((!entry || entry->state != as_valid) && !itf->arp_srv)
+	return; /* bad luck - no ARP server when we need one */
     if (entry)
 	switch (entry->state) {
 	    case as_resolv:
diff -ur --new-file old/atm/atm.patch new/atm/atm.patch
--- old/atm/atm.patch	Wed Jul 31 19:45:24 1996
+++ new/atm/atm.patch	Thu Aug 29 17:14:24 1996
@@ -1,5 +1,5 @@
---- ref/Makefile	Fri Jun  7 10:55:00 1996
-+++ work/Makefile	Mon Jun 10 17:41:25 1996
+--- ref/Makefile	Sat Aug 17 20:19:04 1996
++++ work/Makefile	Wed Aug 21 10:55:30 1996
 @@ -126,6 +126,10 @@
  
  DRIVERS := $(DRIVERS) drivers/net/net.a
@@ -19,9 +19,9 @@
  	\
  	ls *.o > .allmods; \
  	echo $$MODULES | tr ' ' '\n' | sort | comm -23 .allmods - > .misc; \
---- ref/Documentation/Configure.help	Fri Jun  7 15:28:46 1996
-+++ work/Documentation/Configure.help	Wed Jul 31 19:23:00 1996
-@@ -1164,6 +1164,101 @@
+--- ref/Documentation/Configure.help	Wed Aug  7 08:45:41 1996
++++ work/Documentation/Configure.help	Wed Aug 21 10:55:34 1996
+@@ -1182,6 +1182,101 @@
    you can read some network related routing information from that
    file. Everything you write to that file will be discarded.
  
@@ -123,9 +123,9 @@
  SCSI support?
  CONFIG_SCSI
    If you want to use a SCSI harddisk, SCSI tapedrive, SCSI CDROM or
---- ref/kernel/ksyms.c	Wed May 29 15:42:27 1996
-+++ work/kernel/ksyms.c	Mon Jun 10 17:43:08 1996
-@@ -62,6 +62,9 @@
+--- ref/kernel/ksyms.c	Thu Jul 18 13:28:48 1996
++++ work/kernel/ksyms.c	Thu Aug 29 15:36:29 1996
+@@ -63,6 +63,9 @@
  #ifdef __SMP__
  #include <linux/smp.h>
  #endif
@@ -135,18 +135,18 @@
  
  extern char *get_options(char *str, int *ints);
  extern void set_device_ro(int dev,int flag);
-@@ -76,6 +79,10 @@
+@@ -77,6 +80,10 @@
  
  extern void hard_reset_now(void);
  
-+#ifdef CONFIG_ATM_TCP
++#ifdef CONFIG_ATM_TCP_MODULE
 +extern int (*atmtcp_attach_hook)(struct socket *sock);
 +#endif
 +
  struct symbol_table symbol_table = {
  #include <linux/symtab_begin.h>
  #ifdef MODVERSIONS
-@@ -348,7 +355,16 @@
+@@ -351,7 +358,16 @@
  #ifdef CONFIG_BLK_DEV_MD
  	X(disk_name),	/* for md.c */
  #endif
@@ -157,7 +157,7 @@
 +	X(atm_dev_deregister),
 +	X(atm_find_ci),
 +#endif
-+#ifdef CONFIG_ATM_TCP
++#ifdef CONFIG_ATM_TCP_MODULE
 +	X(atmtcp_attach_hook),
 +#endif
 +
@@ -165,7 +165,7 @@
  	X(get_write_access),
  	X(put_write_access),
 --- ref/arch/i386/config.in	Mon May 13 06:17:23 1996
-+++ work/arch/i386/config.in	Mon Jun 10 17:36:00 1996
++++ work/arch/i386/config.in	Wed Aug 21 10:55:35 1996
 @@ -72,6 +72,10 @@
    endmenu
  fi
@@ -178,7 +178,7 @@
  comment 'ISDN subsystem'
  
 --- ref/arch/sparc/config.in	Thu Apr 25 12:22:05 1996
-+++ work/arch/sparc/config.in	Thu Jul 11 13:50:26 1996
++++ work/arch/sparc/config.in	Wed Aug 21 10:55:35 1996
 @@ -100,6 +100,12 @@
  	endmenu
  fi
@@ -193,7 +193,7 @@
  
  mainmenu_option next_comment
 --- ref/drivers/Makefile	Mon Apr 22 09:59:39 1996
-+++ work/drivers/Makefile	Mon Jun 10 17:44:29 1996
++++ work/drivers/Makefile	Wed Aug 21 10:55:35 1996
 @@ -9,7 +9,7 @@
  
  SUB_DIRS     := block char net #streams
@@ -215,8 +215,8 @@
  endif
  
  ifeq ($(CONFIG_AP1000),y)
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/Config.in	Wed Jul 17 21:59:55 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/Config.in	Wed Aug 21 10:55:36 1996
 @@ -0,0 +1,21 @@
 +#
 +# ATM device configuration
@@ -239,8 +239,8 @@
 +    bool '  Enable extended debugging' CONFIG_ATM_TNETA1570_DEBUG n
 +  fi
 +fi
---- ref/net/Config.in	Wed Jun  5 13:42:27 1996
-+++ work/net/Config.in	Wed Jul 31 18:57:53 1996
+--- ref/net/Config.in	Mon Jul  8 09:21:46 1996
++++ work/net/Config.in	Wed Aug 21 10:55:36 1996
 @@ -27,4 +27,17 @@
  if [ "$CONFIG_NETLINK" = "y" ]; then
    bool 'Routing messages' CONFIG_RTNETLINK
@@ -259,9 +259,9 @@
 +  bool '  LANE support' CONFIG_ATM_LANE y
 +fi
  endmenu
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/Makefile	Thu Jul 18 20:51:29 1996
-@@ -0,0 +1,38 @@
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/Makefile	Thu Aug 29 13:50:20 1996
+@@ -0,0 +1,47 @@
 +# File: drivers/atm/Makefile
 +#
 +# Makefile for the Linux network (ATM) device drivers.
@@ -270,15 +270,24 @@
 +L_TARGET := atm.a
 +L_OBJS	 := atmdev_init.o
 +M_OBJS	 :=
++MOD_LIST_NAME := ATM_MODULES
 +
 +include ../../.config
 +
 +ifeq ($(CONFIG_ATM_ENI),y)
 +L_OBJS += eni.o suni.o
++else
++  ifeq ($(CONFIG_ATM_ENI),m)
++  M_OBJS += eni.o suni.o
++  endif
 +endif
 +
 +ifeq ($(CONFIG_ATM_ZATM),y)
 +L_OBJS += zatm.o uPD98402.o
++else
++  ifeq ($(CONFIG_ATM_ZATM),m)
++  M_OBJS += zatm.o uPD98402.o
++  endif
 +endif
 +
 +ifeq ($(CONFIG_ATM_TNETA1570),y)
@@ -300,8 +309,8 @@
 +EXTRA_CFLAGS=-g
 +
 +include $(TOPDIR)/Rules.make
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/atmdev_init.c	Thu Jul 18 20:50:30 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/atmdev_init.c	Wed Aug 21 10:55:36 1996
 @@ -0,0 +1,47 @@
 +/* drivers/atm/atmdev_init.c - ATM device driver initialization */
 + 
@@ -350,8 +359,8 @@
 +#endif
 +	return devs;
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/atmtcp.c	Thu Jul  4 17:05:57 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/atmtcp.c	Wed Aug 21 10:55:37 1996
 @@ -0,0 +1,316 @@
 +/* drivers/atm/atmtcp.c - ATM over TCP "device" driver */
 + 
@@ -669,8 +678,8 @@
 +}
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/eni.c	Tue Jul 30 16:32:24 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/eni.c	Thu Aug 29 13:41:36 1996
 @@ -0,0 +1,1954 @@
 +/* drivers/atm/eni.c - Efficient Networks ENI155P device driver */
 + 
@@ -2609,7 +2618,7 @@
 +int init_module(void)
 +{
 +	if (!eni_detect()) {
-+		printk(KERN_ERROR DEV_LABEL ": no adapter found\n");
++		printk(KERN_ERR DEV_LABEL ": no adapter found\n");
 +		return -ENXIO;
 +	}
 +	MOD_INC_USE_COUNT;
@@ -2626,8 +2635,8 @@
 +}
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/eni.h	Wed Jul 31 19:32:14 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/eni.h	Thu Aug 29 14:08:38 1996
 @@ -0,0 +1,113 @@
 +/* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */
 + 
@@ -2742,8 +2751,8 @@
 +#endif /* __KERNEL__ */
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/midway.h	Mon Jun 10 17:36:06 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/midway.h	Wed Aug 21 10:55:38 1996
 @@ -0,0 +1,265 @@
 +/* drivers/atm/midway.h - Efficient Networks Midway (SAR) description */
 + 
@@ -3010,14 +3019,16 @@
 +#define MID_DT_HWORD	0x2
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/suni.c	Mon Jun 10 17:36:06 1996
-@@ -0,0 +1,271 @@
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/suni.c	Thu Aug 29 15:21:02 1996
+@@ -0,0 +1,298 @@
 +/* drivers/atm/suni.c - PMC SUNI (PHY) driver */
 + 
 +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */
 +
 +
++#include <linux/config.h>
++#include <linux/module.h>
 +#include <linux/sched.h>
 +#include <linux/kernel.h>
 +#include <linux/mm.h>
@@ -3284,8 +3295,33 @@
 +	dev->phy = &suni_ops;
 +	return 0;
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/suni.h	Wed Jul 31 19:32:14 1996
++
++
++#ifdef MODULE
++
++static struct symbol_table suni_syms = {
++#include <linux/symtab_begin.h>
++	X(suni_init),
++#include <linux/symtab_end.h>
++};
++
++
++int init_module(void)
++{
++	if (register_symtab(&suni_syms)) return -EIO;
++	MOD_INC_USE_COUNT;
++	return 0;
++}
++
++
++void cleanup_module(void)
++{
++	/* Nay */
++}
++
++#endif
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/suni.h	Thu Aug 29 14:08:38 1996
 @@ -0,0 +1,219 @@
 +/* drivers/atm/suni.h - PMC SUNI (PHY) declarations */
 + 
@@ -3506,8 +3542,8 @@
 +#endif
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/tonga.h	Mon Jun 10 17:36:07 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/tonga.h	Wed Aug 21 10:55:39 1996
 @@ -0,0 +1,20 @@
 +/* drivers/atm/tonga.h - Efficient Networks Tonga (PCI bridge) declarations */
 + 
@@ -3529,8 +3565,8 @@
 +#define SEPROM_ESI_BASE	64	/* start of ESI in serial EEPROM */
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/uPD98401.h	Mon Jun 10 17:36:08 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/uPD98401.h	Wed Aug 21 10:55:39 1996
 @@ -0,0 +1,292 @@
 +/* drivers/atm/uPD98401.h - NEC uPD98401 (SAR) declarations */
 + 
@@ -3824,8 +3860,8 @@
 +#define uPD98401_RXLT_ENBL	0x8000	   /* Enable */
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/uPD98402.h	Mon Jun 10 17:36:08 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/uPD98402.h	Wed Aug 21 10:55:39 1996
 @@ -0,0 +1,106 @@
 +/* drivers/atm/uPD98402.h - NEC uPD98402 (PHY) declarations */
 + 
@@ -3933,14 +3969,16 @@
 +int uPD98402_init(struct atm_dev *dev);
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/uPD98402.c	Mon Jun 10 17:36:09 1996
-@@ -0,0 +1,201 @@
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/uPD98402.c	Thu Aug 29 15:19:33 1996
+@@ -0,0 +1,228 @@
 +/* drivers/atm/uPD98402.c - NEC uPD98402 (PHY) declarations */
 + 
 +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */
 + 
 +
++#include <linux/config.h>
++#include <linux/module.h>
 +#include <linux/sched.h> /* for jiffies */
 +#include <linux/mm.h>
 +#include <linux/errno.h>
@@ -4137,8 +4175,33 @@
 +	dev->phy = &uPD98402_ops;
 +	return 0;
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/zatm.c	Tue Jul 30 22:08:08 1996
++
++
++#ifdef MODULE
++
++static struct symbol_table uPD98402_syms = {
++#include <linux/symtab_begin.h>
++	X(uPD98402_init),
++#include <linux/symtab_end.h>
++};
++ 
++ 
++int init_module(void)
++{
++	if (register_symtab(&uPD98402_syms)) return -EIO;
++	MOD_INC_USE_COUNT;
++	return 0;
++}
++
++
++void cleanup_module(void)
++{
++	/* Nay */
++}
++ 
++#endif
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/zatm.c	Thu Aug 29 13:41:42 1996
 @@ -0,0 +1,1659 @@
 +/* drivers/atm/zatm.c - ZeitNet ZN122x device driver */
 + 
@@ -5782,7 +5845,7 @@
 +int init_module(void)
 +{
 +	if (!zatm_detect()) {
-+		printk(KERN_ERROR DEV_LABEL ": no adapter found\n");
++		printk(KERN_ERR DEV_LABEL ": no adapter found\n");
 +		return -ENXIO;
 +	}
 +	MOD_INC_USE_COUNT;
@@ -5799,8 +5862,8 @@
 +}
 + 
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/zatm.h	Wed Jul 31 19:32:42 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/zatm.h	Thu Aug 29 14:09:07 1996
 @@ -0,0 +1,128 @@
 +/* drivers/atm/zatm.h - ZeitNet ZN122x device driver declarations */
 +
@@ -5930,8 +5993,8 @@
 +
 +#endif __KERNEL__
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/zeprom.h	Wed Jul 10 20:16:37 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/zeprom.h	Wed Aug 21 10:55:41 1996
 @@ -0,0 +1,34 @@
 +/* drivers/atm/zeprom.h - ZeitNet ZN122x EEPROM (NM93C46) declarations */
 +
@@ -5967,8 +6030,8 @@
 +/* No other commands are needed. */
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/tneta1570.h	Mon Jun 10 17:36:11 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/tneta1570.h	Wed Aug 21 10:55:41 1996
 @@ -0,0 +1,310 @@
 +/* drivers/atm/tneta1570.h - TI TNETA1570 (SAR) declarations */
 + 
@@ -6280,8 +6343,8 @@
 +
 +#endif __KERNEL__
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/tneta1570.c	Fri Jul 26 17:35:25 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/tneta1570.c	Wed Aug 21 10:55:42 1996
 @@ -0,0 +1,1479 @@
 +/* drivers/atm/tneta1570.c - ti tneta1570 atm driver */
 + 
@@ -7762,8 +7825,8 @@
 +	}
 +	return index;
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/drivers/atm/fore200.c	Thu Jul 18 20:59:50 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/drivers/atm/fore200.c	Wed Aug 21 10:55:43 1996
 @@ -0,0 +1,26 @@
 +/* drivers/atm/fore200.c - This is just a test, not a real driver */
 + 
@@ -7791,8 +7854,8 @@
 +	}
 +	return 0;
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/atm.h	Wed Jul 31 17:57:46 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/atm.h	Wed Aug 21 11:13:55 1996
 @@ -0,0 +1,225 @@
 +/* atm.h - general ATM declarations */
 + 
@@ -8019,8 +8082,8 @@
 +#endif /* __KERNEL__ */
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/atmclip.h	Wed Jul 31 19:34:38 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/atmclip.h	Thu Aug 29 13:59:47 1996
 @@ -0,0 +1,37 @@
 +/* atmclip.h - Classical IP over ATM */
 + 
@@ -8059,8 +8122,8 @@
 +#endif /* __KERNEL__ */
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/atmdev.h	Wed Jul 31 19:30:44 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/atmdev.h	Thu Aug 29 13:41:21 1996
 @@ -0,0 +1,242 @@
 +/* atmdev.h - ATM device driver declarations */
 + 
@@ -8304,8 +8367,8 @@
 +#endif /* __KERNEL__ */
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/atmsap.h	Mon Jun 10 17:36:14 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/atmsap.h	Wed Aug 21 10:55:44 1996
 @@ -0,0 +1,129 @@
 +/* atmsap.h - ATM Service Access Point addressing definitions */
 +
@@ -8436,8 +8499,8 @@
 +};
 +
 +#endif
---- ref/include/linux/skbuff.h	Sun Jun  9 11:23:42 1996
-+++ work/include/linux/skbuff.h	Wed Jul 31 19:30:20 1996
+--- ref/include/linux/skbuff.h	Tue Aug 20 17:09:42 1996
++++ work/include/linux/skbuff.h	Thu Aug 29 13:41:21 1996
 @@ -112,6 +112,16 @@
  	unsigned char 	*end;			/* End pointer					*/
  	void 		(*destructor)(struct sk_buff *);	/* Destruct function		*/
@@ -8455,8 +8518,8 @@
  };
  
  #ifdef CONFIG_SKB_LARGE
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/sonet.h	Mon Jun 10 17:36:15 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/sonet.h	Wed Aug 21 10:55:45 1996
 @@ -0,0 +1,52 @@
 +/* sonet.h - SONET/SHD physical layer control */
 + 
@@ -8510,8 +8573,8 @@
 +#define SONET_FRSENSE_SIZE 6		/* C1[3],H1[3] (0xff for unknown) */
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/atmsvc.h	Wed Jul 31 18:20:21 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/atmsvc.h	Wed Aug 21 11:13:56 1996
 @@ -0,0 +1,75 @@
 +/* atmsvc.h - ATM signaling kernel-demon interface definitions */
 + 
@@ -8588,8 +8651,8 @@
 +  (tp).max_pcr : (tp).min_pcr)
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/atmioc.h	Mon Jun 10 17:36:16 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/atmioc.h	Wed Aug 21 10:55:45 1996
 @@ -0,0 +1,32 @@
 +/* atmioc.h - ranges for ATM-related ioctl numbers */
 + 
@@ -8624,12 +8687,14 @@
 +
 +#endif
 --- ref/net/Makefile	Thu May 16 15:35:55 1996
-+++ work/net/Makefile	Mon Jun 10 17:50:26 1996
-@@ -8,12 +8,17 @@
++++ work/net/Makefile	Thu Aug 29 12:11:54 1996
+@@ -7,13 +7,18 @@
+ #
  # Note 2! The CFLAGS definition is now in the main makefile...
  
- MOD_SUB_DIRS := ipv4
+-MOD_SUB_DIRS := ipv4
 -ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipx unix appletalk netrom #decnet
++MOD_SUB_DIRS := ipv4 atm
 +ALL_SUB_DIRS := 802 atm ax25 bridge core ethernet ipv4 ipx unix appletalk \
 +		netrom #decnet
  SUB_DIRS     := core ethernet unix
@@ -8644,8 +8709,8 @@
  endif
  
  ifeq ($(CONFIG_INET),y)
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/Makefile	Wed Jul 17 19:31:55 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/Makefile	Wed Aug 21 10:55:46 1996
 @@ -0,0 +1,54 @@
 +#
 +# Makefile for the ATM Protocol Families.
@@ -8701,8 +8766,8 @@
 +
 +
 +include $(TOPDIR)/Rules.make
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/clip.c	Wed Jul 31 17:15:40 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/clip.c	Wed Aug 21 10:55:46 1996
 @@ -0,0 +1,115 @@
 +/* net/atm/clip.c - Classical IP over ATM */
 + 
@@ -8819,9 +8884,9 @@
 +	DPRINTK("registered %s,0x%lx\n",dev->name,(unsigned long) vcc);
 +	return number;
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/common.c	Wed Jul 31 19:29:44 1996
-@@ -0,0 +1,899 @@
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/common.c	Wed Aug 21 11:07:21 1996
+@@ -0,0 +1,900 @@
 +/* net/atm/common.c - ATM sockets (common part for PVC and SVC) */
 +
 +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */
@@ -8874,7 +8939,8 @@
 +{
 +	struct sk_buff *skb;
 +
-+	if (size+vcc->tx_inuse+ATM_PDU_OVHD > vcc->tx_quota) return NULL;
++	if (vcc->tx_inuse && size+vcc->tx_inuse+ATM_PDU_OVHD > vcc->tx_quota)
++		return NULL;
 +	while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
 +	DPRINTK("AlTx %d += %d\n",vcc->tx_inuse,skb->truesize);
 +	atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
@@ -9721,8 +9787,8 @@
 +	if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL;
 +	return vcc->dev->ops->getsockopt(vcc,level,optname,optval,optlen);
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/common.h	Wed Jul 31 18:20:21 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/common.h	Wed Aug 21 10:55:47 1996
 @@ -0,0 +1,32 @@
 +/* net/atm/common.h - ATM sockets (common part for PVC and SVC) */
 + 
@@ -9756,8 +9822,8 @@
 +void svc_callback(struct atm_vcc *vcc);
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/dev.c	Mon Jun 10 17:36:19 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/dev.c	Wed Aug 21 10:55:47 1996
 @@ -0,0 +1,38 @@
 +/* net/atm/dev.c - ATM device registeration */
 +
@@ -9797,8 +9863,8 @@
 +{
 +	free_atm_dev(dev);
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/pvc.c	Mon Jul 29 10:40:33 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/pvc.c	Wed Aug 21 10:55:47 1996
 @@ -0,0 +1,162 @@
 +/* net/atm/pvc.c - ATM PVC sockets */
 +
@@ -9962,8 +10028,8 @@
 +	(void) atm_init_arequipa();
 +#endif
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/static.c	Fri Jul 19 15:21:05 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/static.c	Wed Aug 21 10:55:47 1996
 @@ -0,0 +1,114 @@
 +/* net/atm/static.c - Staticly allocated resources */
 +
@@ -10079,8 +10145,8 @@
 +	for (i = 0; i < MAX_ATM_VCC; i++)
 +		if (atm_vcc[i].family) fn(atm_vcc+i);
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/static.h	Wed Jul 31 19:34:38 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/static.h	Thu Aug 29 13:59:48 1996
 @@ -0,0 +1,29 @@
 +/* net/atm/static.h - Staticly allocated resources */
 +
@@ -10111,9 +10177,9 @@
 +void for_all_vccs(void (*fn)(struct atm_vcc *vcc));
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/svc.c	Mon Jul 29 10:44:01 1996
-@@ -0,0 +1,617 @@
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/svc.c	Wed Aug 21 10:55:48 1996
+@@ -0,0 +1,618 @@
 +/* net/atm/svc.c - ATM SVC sockets */
 +
 +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */
@@ -10408,6 +10474,7 @@
 +		old_vcc->backlog_quota++;
 +		if (!new_vcc->reply) break;
 +		dev_kfree_skb(skb,FREE_WRITE);
++		if (new_vcc->reply != -ERESTARTSYS) return new_vcc->reply;
 +	}
 +	if (!sigd) return -EUNATCH;
 +	msg = (struct atmsvc_msg *) skb->data;
@@ -10731,9 +10798,9 @@
 +		return;
 +	}
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/signaling.c	Wed Jul 31 19:29:23 1996
-@@ -0,0 +1,218 @@
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/signaling.c	Wed Aug 21 11:42:32 1996
+@@ -0,0 +1,219 @@
 +/* net/atm/signaling.c - ATM signaling */
 +
 +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */
@@ -10775,6 +10842,7 @@
 +	struct atmsvc_msg *msg;
 +
 +	msg = (struct atmsvc_msg *) skb->data;
++	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
 +	DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,msg->vcc);
 +	vcc = (struct atm_vcc *) msg->vcc;
 +	switch (msg->type) {
@@ -10952,8 +11020,8 @@
 +	wake_up(&sigd_sleep);
 +	return 0;
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/signaling.h	Wed Jul 31 19:34:38 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/signaling.h	Thu Aug 29 13:59:48 1996
 @@ -0,0 +1,25 @@
 +/* net/atm/signaling.h - ATM signaling */
 + 
@@ -10980,9 +11048,9 @@
 +int sigd_attach(struct atm_vcc *vcc);
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/atmarp.c	Wed Jul 31 15:25:49 1996
-@@ -0,0 +1,607 @@
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/atmarp.c	Wed Aug 21 11:42:49 1996
+@@ -0,0 +1,608 @@
 +/* atmarp.c - RFC1577 ATM ARP */
 +
 +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */
@@ -11057,6 +11125,7 @@
 +{
 +	struct atmarp_ctrl *ctrl;
 + 
++	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
 +        ctrl = (struct atmarp_ctrl *) skb->data;
 +	if (ctrl->magic != ATMARP_CTRL_MAGIC) {
 +		printk(KERN_ALERT "atmarpd_send: bad magic 0x%x\n",
@@ -11590,8 +11659,8 @@
 +	register_netdevice_notifier(&clip_dev_notifier);
 +	return 0;
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/atmarp.h	Wed Jul 31 19:34:38 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/atmarp.h	Thu Aug 29 13:59:48 1996
 @@ -0,0 +1,54 @@
 +/* net/atm/atmarp.h - RFC1577 ATM ARP */
 + 
@@ -11647,8 +11716,8 @@
 +int atmarp_encap(struct atm_vcc *vcc,int mode);
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/ipcommon.h	Tue Jul 30 18:42:55 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/ipcommon.h	Thu Aug 29 14:00:41 1996
 @@ -0,0 +1,66 @@
 +/* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */
 +
@@ -11716,8 +11785,8 @@
 +    unsigned short extra_flags);
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/ipcommon.c	Mon Jul 29 11:30:37 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/ipcommon.c	Wed Aug 21 10:55:49 1996
 @@ -0,0 +1,181 @@
 +/* net/atm/ipcommon.c - Common items for all ways of doing IP over ATM */
 +
@@ -11900,8 +11969,8 @@
 +	memset(&CLIP(dev)->stats,0,sizeof(struct enet_statistics));
 +
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/arequipa.c	Wed Jul 31 17:06:38 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/arequipa.c	Wed Aug 21 10:55:50 1996
 @@ -0,0 +1,367 @@
 +/* net/atm/arequipa.c - Application requested IP over ATM */
 + 
@@ -12270,8 +12339,8 @@
 +        return 0;
 +
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/tunable.h	Tue Jul 30 22:30:54 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/tunable.h	Wed Aug 21 10:55:50 1996
 @@ -0,0 +1,26 @@
 +/* net/atm/tunable.h - Tunable parameters of ATM support */
 +
@@ -12299,13 +12368,13 @@
 +				   quota per PDU */
 +
 +#endif
---- ref/net/ipv4/af_inet.c	Fri Jun  7 09:14:29 1996
-+++ work/net/ipv4/af_inet.c	Mon Jun 10 17:51:57 1996
+--- ref/net/ipv4/af_inet.c	Sun Aug  4 11:56:25 1996
++++ work/net/ipv4/af_inet.c	Thu Aug 29 15:37:26 1996
 @@ -105,6 +105,14 @@
  #include <linux/kerneld.h>
  #endif
  
-+#ifdef CONFIG_ATM_TCP
++#if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
 +#include <linux/atm.h>
 +int (*atmtcp_attach_hook)(struct socket *sock) = NULL;
 +#endif
@@ -12338,12 +12407,12 @@
  	sk->socket = sock;
  #ifdef CONFIG_TCP_NAGLE_OFF
  	sk->nonagle = 1;
-@@ -1334,7 +1350,18 @@
+@@ -1339,7 +1355,18 @@
  				return((*dlci_ioctl_hook)(cmd, (void *) arg));
  #endif
  			return -ENOPKG;
 -
-+#ifdef CONFIG_ATM_TCP
++#if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
 +		case SIOCSIFATMTCP:
 +			if (atmtcp_attach_hook)
 +				return atmtcp_attach_hook(sock);
@@ -12359,7 +12428,7 @@
  			if ((cmd >= SIOCDEVPRIVATE) &&
  			   (cmd <= (SIOCDEVPRIVATE + 15)))
 --- ref/net/protocols.c	Sat Mar 30 12:20:34 1996
-+++ work/net/protocols.c	Mon Jun 10 17:52:25 1996
++++ work/net/protocols.c	Wed Aug 21 10:55:51 1996
 @@ -42,6 +42,10 @@
  #include <linux/trdevice.h>
  extern void rif_init(struct net_proto *);
@@ -12382,8 +12451,8 @@
  #endif
    { NULL,	NULL		}			/* End marker			*/
  };
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/mmuio.c	Mon Jul 29 13:00:29 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/mmuio.c	Wed Aug 21 10:55:51 1996
 @@ -0,0 +1,455 @@
 +/* net/atm/mmuio.c - MMU-supported high-speed I/O */
 +
@@ -12840,8 +12909,8 @@
 +}
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/mmuio.h	Wed Jul 31 19:34:38 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/mmuio.h	Thu Aug 29 13:59:48 1996
 @@ -0,0 +1,25 @@
 +/* mmuio.h - MMU-supported high-speed I/O */
 +
@@ -12868,8 +12937,8 @@
 +#endif
 +
 +#endif
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/raw.c	Tue Jul 30 19:13:44 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/raw.c	Wed Aug 21 10:55:52 1996
 @@ -0,0 +1,139 @@
 +/* net/atm/raw.c - Raw AAL0 and AAL5 transports */
 +
@@ -13010,8 +13079,8 @@
 +	vcc->push_oam = NULL;
 +	return 0;
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/protocols.h	Mon Jun 10 17:36:28 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/protocols.h	Wed Aug 21 10:55:52 1996
 @@ -0,0 +1,17 @@
 +/* net/atm/protocols.h - ATM protocol handler entry points */
 +
@@ -13030,9 +13099,9 @@
 +int atm_init_atmarp(struct atm_vcc *vcc);/* ATM ARP */
 +
 +#endif
---- ref/include/linux/netdevice.h	Sun Jun  9 11:25:36 1996
-+++ work/include/linux/netdevice.h	Wed Jul 31 19:30:44 1996
-@@ -182,6 +182,8 @@
+--- ref/include/linux/netdevice.h	Tue Aug 20 17:11:35 1996
++++ work/include/linux/netdevice.h	Thu Aug 29 13:41:21 1996
+@@ -185,6 +185,8 @@
    int			  (*set_mac_address)(struct device *dev, void *addr);
  #define HAVE_PRIVATE_IOCTL
    int			  (*do_ioctl)(struct device *dev, struct ifreq *ifr, int cmd);
@@ -13041,7 +13110,7 @@
  #define HAVE_SET_CONFIG
    int			  (*set_config)(struct device *dev, struct ifmap *map);
  #define HAVE_HEADER_CACHE
-@@ -284,6 +286,8 @@
+@@ -285,6 +287,8 @@
  /* These functions live elsewhere (drivers/net/net_init.c, but related) */
  
  extern void		ether_setup(struct device *dev);
@@ -13050,8 +13119,8 @@
  extern void		tr_setup(struct device *dev);
  extern int		ether_config(struct device *dev, struct ifmap *map);
  /* Support for loadable net-drivers */
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/atmarp.h	Wed Jul 31 18:20:20 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/atmarp.h	Wed Aug 21 11:13:56 1996
 @@ -0,0 +1,98 @@
 +/* atmarp.h - ATM ARP protocol and kernel-demon interface definitions */
 + 
@@ -13152,7 +13221,7 @@
 +
 +#endif
 --- ref/net/ipv4/udp.c	Tue Jun  4 14:34:43 1996
-+++ work/net/ipv4/udp.c	Mon Jun 10 19:11:22 1996
++++ work/net/ipv4/udp.c	Wed Aug 21 10:55:53 1996
 @@ -109,6 +109,11 @@
  #include <net/route.h>
  #include <net/checksum.h>
@@ -13187,9 +13256,9 @@
  	skb->sk = sk;
  
  	if (sk->users) {
---- ref/net/ipv4/tcp.c	Sat Jun  8 11:09:09 1996
-+++ work/net/ipv4/tcp.c	Wed Jul 17 19:39:31 1996
-@@ -1926,6 +1926,11 @@
+--- ref/net/ipv4/tcp.c	Sun Aug  4 12:56:54 1996
++++ work/net/ipv4/tcp.c	Wed Aug 21 10:55:55 1996
+@@ -1991,6 +1991,11 @@
  	 *	Put in the IP header and routing stuff.
  	 */
  
@@ -13201,8 +13270,8 @@
  	tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
  		IPPROTO_TCP, sk->opt, MAX_SYN_SIZE,sk->ip_tos,sk->ip_ttl,&sk->ip_route_cache);
  	if (tmp < 0)
---- ref/include/linux/proc_fs.h	Sun Jun  9 11:23:42 1996
-+++ work/include/linux/proc_fs.h	Wed Jul 31 17:57:46 1996
+--- ref/include/linux/proc_fs.h	Tue Aug 20 17:09:42 1996
++++ work/include/linux/proc_fs.h	Thu Aug 29 13:41:21 1996
 @@ -34,6 +34,7 @@
  	PROC_KSYMS,
  	PROC_DMA,	
@@ -13211,7 +13280,7 @@
  #ifdef __SMP_PROF__
  	PROC_SMP_PROF,
  #endif
-@@ -148,6 +149,16 @@
+@@ -151,6 +152,16 @@
  #define PROC_DYNAMIC_FIRST 4096
  #define PROC_NDYNAMIC      4096
  
@@ -13228,7 +13297,7 @@
  #define PROC_SUPER_MAGIC 0x9fa0
  
  /*
-@@ -187,6 +198,7 @@
+@@ -190,6 +201,7 @@
  extern struct proc_dir_entry proc_root;
  extern struct proc_dir_entry proc_net;
  extern struct proc_dir_entry proc_scsi;
@@ -13236,7 +13305,7 @@
  extern struct proc_dir_entry proc_sys;
  extern struct proc_dir_entry proc_pid;
  extern struct proc_dir_entry proc_pid_fd;
-@@ -275,5 +287,6 @@
+@@ -278,5 +290,6 @@
  extern struct inode_operations proc_kmsg_inode_operations;
  extern struct inode_operations proc_link_inode_operations;
  extern struct inode_operations proc_fd_inode_operations;
@@ -13244,7 +13313,7 @@
  
  #endif
 --- ref/fs/proc/root.c	Tue Apr 30 12:09:45 1996
-+++ work/fs/proc/root.c	Mon Jun 10 17:36:31 1996
++++ work/fs/proc/root.c	Wed Aug 21 10:55:56 1996
 @@ -15,6 +15,10 @@
  #include <linux/config.h>
  #include <asm/bitops.h>
@@ -13286,7 +13355,7 @@
  #ifdef CONFIG_DEBUG_MALLOC
  	proc_register(&proc_root, &(struct proc_dir_entry) {
 --- ref/fs/proc/inode.c	Thu Apr 25 15:32:45 1996
-+++ work/fs/proc/inode.c	Mon Jun 10 17:36:32 1996
++++ work/fs/proc/inode.c	Wed Aug 21 10:55:56 1996
 @@ -4,6 +4,7 @@
   *  Copyright (C) 1991, 1992  Linus Torvalds
   */
@@ -13324,8 +13393,8 @@
  			case PROC_KCORE:
  				inode->i_mode = S_IFREG | S_IRUSR;
  				inode->i_op = &proc_kcore_inode_operations;
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/proc.c	Wed Jul 31 16:34:28 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/proc.c	Wed Aug 21 10:55:56 1996
 @@ -0,0 +1,484 @@
 +/* net/atm/proc.c - ATM /proc interface */
 +
@@ -13811,8 +13880,8 @@
 +	proc_register(FILE(PROC_ATM_AREQUIPA,"arequipa",8));
 +#endif
 +}
---- ref/drivers/char/console.c	Wed May 15 08:06:55 1996
-+++ work/drivers/char/console.c	Mon Jun 10 17:36:33 1996
+--- ref/drivers/char/console.c	Wed Jul 24 09:49:53 1996
++++ work/drivers/char/console.c	Wed Aug 21 10:55:58 1996
 @@ -1972,6 +1972,43 @@
  	}
  }
@@ -13870,7 +13939,7 @@
  	/*
  	 * can't register TGA yet, because PCI bus probe has *not* taken
 --- ref/init/main.c	Mon May 20 19:33:57 1996
-+++ work/init/main.c	Mon Jun 10 17:36:34 1996
++++ work/init/main.c	Wed Aug 21 10:55:58 1996
 @@ -172,6 +172,8 @@
  #endif
  
@@ -13888,9 +13957,9 @@
  	{ 0, 0 }
  };
  
---- ref/drivers/block/genhd.c	Sun May 19 12:29:22 1996
-+++ work/drivers/block/genhd.c	Thu Jul 18 21:05:07 1996
-@@ -52,6 +52,7 @@
+--- ref/drivers/block/genhd.c	Tue Aug 20 15:44:45 1996
++++ work/drivers/block/genhd.c	Wed Aug 21 10:55:59 1996
+@@ -53,6 +53,7 @@
  extern int blk_dev_init(void);
  extern int scsi_dev_init(void);
  extern int net_dev_init(void);
@@ -13898,7 +13967,7 @@
  
  /*
   * disk_name() is used by genhd.c and md.c.
-@@ -654,6 +655,9 @@
+@@ -743,6 +744,9 @@
  #endif
  #ifdef CONFIG_INET
  	net_dev_init();
@@ -13908,9 +13977,9 @@
  #endif
  	console_map_init();
  
---- ref/drivers/net/net_init.c	Mon Mar 25 07:58:21 1996
-+++ work/drivers/net/net_init.c	Mon Jun 10 17:36:34 1996
-@@ -170,6 +170,7 @@
+--- ref/drivers/net/net_init.c	Sat Jun 29 11:00:46 1996
++++ work/drivers/net/net_init.c	Wed Aug 21 10:55:59 1996
+@@ -181,6 +181,7 @@
  	dev->set_mac_address 	= eth_mac_addr;
  	dev->header_cache_bind 	= eth_header_cache_bind;
  	dev->header_cache_update= eth_header_cache_update;
@@ -13919,7 +13988,7 @@
  	dev->type		= ARPHRD_ETHER;
  	dev->hard_header_len 	= ETH_HLEN;
 --- ref/drivers/net/eql.c	Mon May  6 11:26:08 1996
-+++ work/drivers/net/eql.c	Mon Jun 10 17:36:35 1996
++++ work/drivers/net/eql.c	Wed Aug 21 10:56:01 1996
 @@ -248,6 +248,7 @@
  	dev->open		= eql_open;
  	dev->stop		= eql_close;
@@ -13929,7 +13998,7 @@
  	dev->get_stats		= eql_get_stats;
    
 --- ref/drivers/net/pi2.c	Fri Mar  1 06:50:45 1996
-+++ work/drivers/net/pi2.c	Mon Jun 10 17:36:37 1996
++++ work/drivers/net/pi2.c	Wed Aug 21 10:56:02 1996
 @@ -1414,6 +1414,7 @@
      dev->open = pi_open;
      dev->stop = pi_close;
@@ -13938,19 +14007,19 @@
      dev->hard_start_xmit = pi_send_packet;
      dev->get_stats = pi_get_stats;
  
---- ref/drivers/net/ppp.c	Wed May 29 06:32:38 1996
-+++ work/drivers/net/ppp.c	Mon Jun 10 17:36:38 1996
-@@ -399,6 +399,7 @@
+--- ref/drivers/net/ppp.c	Wed Jul 17 06:17:30 1996
++++ work/drivers/net/ppp.c	Thu Aug 29 12:16:26 1996
+@@ -398,6 +398,7 @@
  	dev->stop	      = ppp_dev_close;
  	dev->get_stats	      = ppp_dev_stats;
  	dev->do_ioctl	      = ppp_dev_ioctl;
-+	dev->ip_arp	      = ether_arp;
++	dev->ip_arp	      = NULL;
  	dev->addr_len	      = 0;
  	dev->tx_queue_len     = 10;
  	dev->type	      = ARPHRD_PPP;
---- ref/net/ipv4/arp.c	Wed Jun  5 13:42:27 1996
-+++ work/net/ipv4/arp.c	Mon Jun 10 17:36:38 1996
-@@ -2165,7 +2165,7 @@
+--- ref/net/ipv4/arp.c	Thu Aug  1 14:43:04 1996
++++ work/net/ipv4/arp.c	Wed Aug 21 10:56:06 1996
+@@ -2160,7 +2160,7 @@
   *	Handle an ARP layer I/O control request.
   */
  
@@ -13959,7 +14028,7 @@
  {
  	int err;
  	struct arpreq r;
-@@ -2176,12 +2176,7 @@
+@@ -2171,12 +2171,7 @@
  	{
  		case SIOCDARP:
  		case SIOCSARP:
@@ -13972,7 +14041,7 @@
  			memcpy_fromfs(&r, arg, sizeof(struct arpreq));
  			break;
  		case OLD_SIOCDARP:
-@@ -2370,6 +2365,47 @@
+@@ -2365,6 +2360,47 @@
  
  
  
@@ -14020,8 +14089,8 @@
  /*
   *	Called once on startup.
   */
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/atmlec.h	Wed Jul 31 18:20:21 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/atmlec.h	Wed Aug 21 11:13:56 1996
 @@ -0,0 +1,58 @@
 +/*
 + * 
@@ -14081,9 +14150,9 @@
 +        unsigned char receive;    /* 1= receive vcc, 0 = send_vcc */
 +};
 +#endif /* _ATMLEC_H_ */
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/lec.c	Tue Jul 30 18:43:49 1996
-@@ -0,0 +1,589 @@
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/lec.c	Wed Aug 21 11:42:09 1996
+@@ -0,0 +1,612 @@
 +/*
 + * lec.c: Lan Emulation driver 
 + * Marko Kiiskila carnil@cs.tut.fi
@@ -14108,15 +14177,19 @@
 +
 +#include "lec.h"
 +#include "lec_arpc.h"
++#include "tunable.h"
 +
 +#define DPRINTK(format,args...)
++/*
++#define DPRINTK printk
++*/
 +
 +struct atm_vcc *lecd = NULL;
 +
 +#define DUMP_PACKETS 0 /* 0 = None,
-+                       * 1 = 30 first bytes
-+                       * 2 = Whole packet
-+                       */
++                        * 1 = 30 first bytes
++                        * 2 = Whole packet
++                        */
 +
 +static int lec_open(struct device *dev);
 +static int lec_send_packet(struct sk_buff *skb, struct device *dev);
@@ -14175,6 +14248,7 @@
 +        struct lec_priv *priv = (struct lec_priv *)dev->priv;
 +        struct lecdatahdr_8023 *lec_h;
 +        struct atm_vcc *send_vcc;
++        unsigned char *nb;
 +#if DUMP_PACKETS > 0
 +        char buf[300];
 +        int i=0;
@@ -14240,21 +14314,43 @@
 +#endif /* DUMP_PACKETS > 0 */
 +                /* Send to right vcc */
 +                send_vcc = lec_arp_resolve(lec_h->h_dest);
++                DPRINTK("send_vcc:%p vcc_flags:%x\n",
++                        send_vcc, send_vcc?send_vcc->flags:0);
 +                if (!send_vcc || !(send_vcc->flags & ATM_VF_READY)) {    
 +                        if (priv)
 +                                priv->stats.tx_errors++;
++                        /*
 +                        DPRINTK("LEC:lec_send_packet: dropping ..\n");
 +                        dev_kfree_skb(skb, FREE_WRITE);
 +                        return 0;
++                        */
++                        DPRINTK("LEC:lec_send_packet: handing back...\n");
++                        dev->tbusy=1;
++                        return 1;
 +                } else {
 +#if DUMP_PACKETS > 0                    
 +                        printk("LEC:sending to vpi:%d vci:%d\n",
 +                                send_vcc->vpi, send_vcc->vci);
 +#endif /* DUMP_PACKETS > 0 */
 +                        /* Minimum ethernet-frame size */
-+                        if (skb->len <62)
-+                                skb->len = 62;
-+			atomic_add(skb->truesize,&send_vcc->tx_inuse);
++                        if (skb->len <62) {
++                                if (skb->truesize < 62) {
++                                        printk("LEC:data packet %ld / %d\n",
++                                               skb->len,skb->truesize);
++                                        nb=(unsigned char*)kmalloc(64, 
++                                                                   GFP_ATOMIC);
++                                        memcpy(nb,skb->data,skb->len);
++                                        kfree(skb->head);
++                                        skb->head = skb->data = nb;
++                                        skb->tail = nb+62;
++                                        skb->end = nb+64;
++                                        skb->len=62;
++                                        skb->truesize = 64;
++                                } else {
++                                        skb->len = 62;
++                                }
++                        }
++                        atomic_add(skb->truesize, &send_vcc->tx_inuse);
 +                        skb->atm.iovcnt = 0;
 +                        send_vcc->dev->ops->send(send_vcc, skb);
 +                        if (priv)
@@ -14396,8 +14492,10 @@
 +        struct lec_priv *priv = (struct lec_priv *)dev_lec.priv;
 +        struct atmlec_msg *mesg;
 +        int i;
-+        
++
++	atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
 +        mesg = (struct atmlec_msg *)skb->data;
++        DPRINTK("LEC: msg from zeppelin:%d\n", mesg->type);
 +        switch(mesg->type) {
 +        case l_set_mac_addr:
 +                for (i=0;i<6;i++) {
@@ -14465,14 +14563,6 @@
 +
 +        lec_arp_destroy();
 +
-+#if 0
-+        unregister_netdev(&dev_lec);
-+        /* Should we do this? */
-+        if (priv) {
-+                kfree_s(priv, sizeof(struct lec_priv));
-+                dev_lec.priv = NULL;
-+        }
-+#endif
 +        if (skb_peek(&vcc->recvq))
 +		printk("LEC lec_atm_close: closing with messages pending\n");
 +        while ((skb = skb_dequeue(&vcc->recvq))) 
@@ -14529,6 +14619,7 @@
 +	if (atm_addr)
 +		memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
 +
++	atomic_add(skb->truesize+ATM_PDU_OVHD, &lecd->rx_inuse);
 +	skb_queue_tail(&lecd->recvq, skb);
 +        wake_up(&lecd->sleep);
 +        return 0;
@@ -14601,6 +14692,7 @@
 +#endif /* DUMP_PACKETS > 0 */
 +        if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/
 +                DPRINTK("LEC: To daemon\n");
++                atomic_add(skb->truesize+ATM_PDU_OVHD, &vcc->rx_inuse);
 +                skb_queue_tail(&vcc->recvq, skb);
 +                wake_up(&vcc->sleep);
 +        } else { /* Data frame, queue to protocol handlers */
@@ -14673,8 +14765,8 @@
 +
 +        return 0;
 +}
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/lec.h	Wed Jul 31 19:34:38 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/lec.h	Thu Aug 29 13:59:48 1996
 @@ -0,0 +1,53 @@
 +/*
 + *
@@ -14729,9 +14821,9 @@
 +void lec_push(struct atm_vcc *vcc, struct sk_buff *skb);
 +#endif _LEC_H_
 +
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/lec_arpc.c	Thu Jul 11 13:11:57 1996
-@@ -0,0 +1,1090 @@
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/lec_arpc.c	Wed Aug 21 11:06:48 1996
+@@ -0,0 +1,1116 @@
 +#include <linux/types.h>
 +#include <linux/sched.h>
 +#include <linux/timer.h>
@@ -14744,7 +14836,11 @@
 +#include "lec.h"
 +#include "lec_arpc.h"
 +
++
 +#define DPRINTK(format,args...)
++/*
++#define DPRINTK printk
++*/
 +#define DEBUG_ARP_TABLE 0
 +
 +struct lec_arp_table *lec_arp_tables[LEC_ARP_TABLE_SIZE] =
@@ -14948,7 +15044,7 @@
 +                0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3],
 +                0xff&to_remove->mac_addr[4], 0xff&to_remove->mac_addr[5]);
 +
-+        dump_arp_table();
++       dump_arp_table();
 +        return 0;
 +}
 +
@@ -15158,7 +15254,7 @@
 +                                entry->next = to_remove->next;
 +                }
 +        lec_arp_clear_vccs(to_remove);
-+        kfree_s(to_remove, sizeof(struct lec_arp_table));
++        kfree(to_remove);
 +}
 +
 +/*
@@ -15187,7 +15283,7 @@
 +
 +        del_timer(&lec_arp_timer);
 +
-+        DPRINTK("lec_arp_check_expire\n");
++        DPRINTK("lec_arp_check_expire %d\n",lec_arp_lock_var);
 +        if (!lec_arp_lock_var) {
 +                lec_arp_lock();
 +                now = jiffies;
@@ -15199,6 +15295,8 @@
 +                                else
 +                                        time_to_check = lec_aging_time;
 +
++                                DPRINTK("About to expire: %lx - %lx > %lx\n",
++                                        now,entry->last_used, time_to_check);
 +                                if((now-entry->last_used > time_to_check) && 
 +                                   !(entry->flags & LEC_PERMANENT_FLAG)) {
 +                                        /* Remove entry */
@@ -15206,8 +15304,7 @@
 +                                        del_timer(&entry->timer);
 +                                        next = entry->next;      
 +                                        lec_arp_remove(entry);
-+                                        kfree_s(entry, 
-+                                                sizeof(struct lec_arp_table));
++                                        kfree(entry);
 +                                        entry = next;
 +                                } else {
 +                                        /* Something else */
@@ -15255,7 +15352,7 @@
 +                for(entry =lec_arp_tables[i];entry != NULL; entry=next) {
 +                        next = entry->next;
 +                        lec_arp_remove(entry);
-+                        kfree_s(entry, sizeof(struct lec_arp_table));
++                        kfree(entry);
 +                }
 +        }
 +        entry = lec_arp_empty_ones;
@@ -15263,7 +15360,7 @@
 +                next = entry->next;
 +                del_timer(&entry->timer);
 +                lec_arp_clear_vccs(entry);
-+                kfree_s(entry, sizeof(struct lec_arp_table));
++                kfree(entry);
 +                entry = next;
 +        }
 +        lec_arp_empty_ones = NULL;
@@ -15272,7 +15369,7 @@
 +                next = entry->next;
 +                del_timer(&entry->timer);
 +                lec_arp_clear_vccs(entry);
-+                kfree_s(entry, sizeof(struct lec_arp_table));
++                kfree(entry);
 +                entry = next;
 +        }
 +        lec_no_forward = NULL;
@@ -15299,7 +15396,7 @@
 +                        next = entry->next;
 +                        if (!(entry->flags & LEC_PERMANENT_FLAG)) {
 +                                lec_arp_remove(entry);
-+                                kfree_s(entry, sizeof(struct lec_arp_table));
++                                kfree(entry);
 +                        }
 +                }
 +        }
@@ -15342,7 +15439,8 @@
 +                   frame count is greater than the limit. If the limit has
 +                   not been reached, allow the caller to send packet to
 +                   BUS. */
-+                if (entry->packets_flooded < lec_maximum_unknown_frame_count) {
++                if (entry->status != ESI_FLUSH_PENDING &&
++                    entry->packets_flooded < lec_maximum_unknown_frame_count) {
 +                        entry->packets_flooded++;
 +                        DPRINTK("LEC_ARP: Flooding..\n");
 +                        return mcast_vcc;
@@ -15404,9 +15502,10 @@
 +                        next = entry->next;
 +                        if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
 +                            && (permanent || 
-+                                !(entry->flags & LEC_PERMANENT_FLAG)))
++                                !(entry->flags & LEC_PERMANENT_FLAG))) {
 +                                lec_arp_remove(entry);
-+                        kfree_s(entry, sizeof(struct lec_arp_table));
++                                kfree(entry);
++                        }
 +                        lec_arp_unlock();
 +                        return 0;
 +                }
@@ -15426,8 +15525,11 @@
 +        struct lec_arp_table *entry, *tmp;
 +        int i;
 +
++        DPRINTK("LEC:lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
++                mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],
++                mac_addr[4],mac_addr[5]);
++        dump_arp_table();
 +        lec_arp_lock();
-+
 +        if (lec_arp_empty_ones) {
 +                entry = lec_arp_empty_ones;
 +                if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) {
@@ -15453,7 +15555,7 @@
 +                                memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
 +                                tmp->vcc = entry->vcc;
 +                                tmp->old_push = entry->old_push;
-+                                kfree_s(entry, sizeof(struct lec_arp_table));
++                                kfree(entry);
 +                                entry=tmp;
 +                        } else {
 +                                entry->status = ESI_FORWARD_DIRECT;
@@ -15465,13 +15567,14 @@
 +                        else
 +                                entry->flags&=~LEC_REMOTE_FLAG;
 +                        lec_arp_unlock();
++                        DPRINTK("After update\n");
++                        dump_arp_table();
 +                        return;
 +                }
 +        }
 +        entry = lec_arp_find(mac_addr);
 +        if (!entry) {
 +                entry = make_entry(mac_addr);
-+                memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
 +                entry->status = ESI_UNKNOWN;
 +                lec_arp_put(entry);
 +                /* Temporary, changes before end of function */
@@ -15506,6 +15609,8 @@
 +                entry->status = ESI_VC_PENDING;
 +                send_to_lecd(l_svc_setup, NULL, atm_addr);
 +        }
++        DPRINTK("After update2\n");
++        dump_arp_table();
 +        lec_arp_unlock();
 +}
 +
@@ -15560,7 +15665,8 @@
 +                entry->timer.function = lec_arp_expire_vcc;
 +                entry->next = lec_no_forward;
 +                lec_no_forward = entry;
-+                lec_arp_unlock();
++                lec_arp_unlock();                
++		dump_arp_table();
 +                return;
 +        }
 +        DPRINTK("LEC_ARP:Attaching data direct, default:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
@@ -15581,7 +15687,7 @@
 +                                DPRINTK("LEC_ARP: Attaching data direct\n");
 +                                DPRINTK("Currently -> Vcc: %d, Rvcc:%d\n",
 +                                        entry->vcc?entry->vcc->vci:0,
-+                                        entry->recv_vcc?entry->recv_vcc:0);
++                                        entry->recv_vcc?entry->recv_vcc->vci:0);
 +                                found_entry=1;
 +                                del_timer(&entry->timer);
 +                                if (vcc) {
@@ -15618,6 +15724,7 @@
 +        }
 +        if (found_entry) {
 +                lec_arp_unlock();
++                DPRINTK("After vcc was added\n");
 +                dump_arp_table();
 +                return;
 +        }
@@ -15635,6 +15742,8 @@
 +        entry->timer.function = lec_arp_expire_vcc;
 +        add_timer(&entry->timer);
 +        lec_arp_unlock();
++        DPRINTK("After vcc was added\n");
++	dump_arp_table();
 +}
 +
 +void
@@ -15643,11 +15752,15 @@
 +        struct lec_arp_table *entry;
 +        int i;
 +  
++        DPRINTK("LEC:lec_flush_complete\n");
 +        for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
 +                for (entry=lec_arp_tables[i];entry!=NULL;entry=entry->next) {
 +                        if (memcmp(atm_addr, entry->atm_addr,ATM_ESA_LEN)==0 &&
 +                            entry->flush_tran_id == tran_id) {
++                                DPRINTK("entry->status:%d\n",entry->status);
 +                                entry->status = ESI_FORWARD_DIRECT;
++                                DPRINTK("LEC_ARP: Flushed\n");
++                                dump_arp_table();
 +                                return;
 +                        }
 +                }
@@ -15678,6 +15791,7 @@
 +                printk("LEC_ARP: Set_flush_tran_id: entry not found\n");
 +                return;
 +        }
++        DPRINTK("LEC: flush_tran_id:%lx\n",tran_id);
 +        entry->flush_tran_id = tran_id;
 +}
 +
@@ -15730,7 +15844,7 @@
 +                        next = entry->next;
 +                        if (vcc == entry->vcc) {
 +                                lec_arp_remove(entry);
-+                                kfree_s(entry, sizeof(struct lec_arp_table));
++                                kfree(entry);
 +                                if (mcast_vcc == vcc) {
 +                                        mcast_vcc = NULL;
 +                                }
@@ -15738,6 +15852,7 @@
 +                                /* Bus distribution closed */
 +                                mcast_vcc = NULL;
 +                                lec_arp_remove(entry);
++				kfree(entry);
 +                                lec_arp_unlock();
 +                                vcc->push(vcc, NULL);
 +                                return;
@@ -15748,7 +15863,7 @@
 +        while(entry && entry->vcc==vcc) {
 +                lec_arp_clear_vccs(entry);
 +                lec_arp_empty_ones=entry->next;
-+                kfree_s(entry, sizeof(struct lec_arp_table));
++                kfree(entry);
 +                entry=lec_arp_empty_ones;
 +        }
 +        for(;entry!=NULL;entry=next) {
@@ -15756,14 +15871,14 @@
 +                if (vcc == next->vcc) {
 +                        lec_arp_clear_vccs(next);
 +                        entry->next = next->next;
-+                        kfree_s(next, sizeof(struct lec_arp_table));
++                        kfree(next);
 +                }
 +        }
 +        entry=lec_no_forward;
 +        while(entry && entry->recv_vcc==vcc) {
 +                lec_arp_clear_vccs(entry);
 +                lec_no_forward=entry->next;
-+                kfree_s(entry, sizeof(struct lec_arp_table));
++                kfree(entry);
 +                entry=lec_no_forward;
 +        }
 +        for(;entry!=NULL;entry=next) {
@@ -15771,10 +15886,11 @@
 +                if (vcc == next->recv_vcc) {
 +                        lec_arp_clear_vccs(next);
 +                        entry->next = next->next;
-+                        kfree_s(next, sizeof(struct lec_arp_table));
++                        kfree(next);
 +                }
-+        }
++        }	
 +        lec_arp_unlock();
++	dump_arp_table();
 +}
 +
 +void
@@ -15789,11 +15905,12 @@
 +                del_timer(&entry->timer);
 +                memcpy(entry->mac_addr, hdr->h_source, ETH_ALEN);
 +                entry->status = ESI_FORWARD_DIRECT;
++                entry->last_used = jiffies;
 +                lec_arp_empty_ones = entry->next;
 +                /* We might have got an entry */
 +                if ((prev=lec_arp_find(hdr->h_source))) {
 +                        lec_arp_remove(prev);
-+                        kfree_s(prev, sizeof(struct lec_arp_table));
++                        kfree(prev);
 +                }
 +                lec_arp_put(entry);
 +                lec_arp_unlock();
@@ -15813,17 +15930,18 @@
 +        del_timer(&entry->timer);
 +        memcpy(entry->mac_addr, hdr->h_source, ETH_ALEN);
 +        entry->status = ESI_FORWARD_DIRECT;
++        entry->last_used = jiffies;
 +        prev->next = entry->next;
 +        if ((prev = lec_arp_find(hdr->h_source))) {
 +                lec_arp_remove(prev);
-+                kfree_s(prev, sizeof(struct lec_arp_table));
++                kfree(prev);
 +        }
 +        lec_arp_put(entry);
 +        lec_arp_unlock();  
 +}
 +
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/net/atm/lec_arpc.h	Wed Jul 31 19:34:38 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/net/atm/lec_arpc.h	Thu Aug 29 13:59:48 1996
 @@ -0,0 +1,104 @@
 +/*
 + * Lec arp cache
@@ -15929,8 +16047,8 @@
 +void lec_proc_info(char *buf);
 +
 +#endif
---- ref/include/net/route.h	Sun Jun  9 11:28:48 1996
-+++ work/include/net/route.h	Wed Jul 31 19:33:37 1996
+--- ref/include/net/route.h	Tue Aug 20 17:14:55 1996
++++ work/include/net/route.h	Thu Aug 29 13:58:43 1996
 @@ -26,6 +26,7 @@
  #define _ROUTE_H
  
@@ -15993,19 +16111,8 @@
  
  
  #endif	/* _ROUTE_H */
---- ref/include/net/sock.h	Sun Jun  9 11:25:41 1996
-+++ work/include/net/sock.h	Wed Jul 31 19:30:44 1996
-@@ -251,8 +251,8 @@
- 	unsigned char		max_ack_backlog;
- 	unsigned char		priority;
- 	unsigned char		debug;
--	unsigned short		rcvbuf;
--	unsigned short		sndbuf;
-+	unsigned long		rcvbuf;
-+	unsigned long		sndbuf;
- 	unsigned short		type;
- 	unsigned char		localroute;	/* Route locally only */
- #ifdef CONFIG_AX25
+--- ref/include/net/sock.h	Tue Aug 20 17:11:40 1996
++++ work/include/net/sock.h	Thu Aug 29 13:41:21 1996
 @@ -301,7 +301,13 @@
  	int			ip_mc_loop;		/* Loopback */
  	char			ip_mc_name[MAX_ADDR_LEN];/* Multicast device name */
@@ -16021,8 +16128,8 @@
  
  /*
   *	This part is used for the timeout functions (timer.c). 
---- /dev/null	Mon Jul 18 01:46:18 1994
-+++ work/include/linux/arequipa.h	Wed Jul 31 19:34:38 1996
+--- /dev/null	Thu Aug 29 17:08:20 1996
++++ work/include/linux/arequipa.h	Thu Aug 29 13:59:48 1996
 @@ -0,0 +1,45 @@
 +/* arequipa.h - Arequipa interface definitions */
 + 
@@ -16069,21 +16176,10 @@
 +#endif /* __KERNEL__ */
 +
 +#endif
---- ref/net/socket.c	Thu Jun  6 20:22:25 1996
-+++ work/net/socket.c	Mon Jun 10 18:30:51 1996
-@@ -778,7 +778,7 @@
- 		sock_release(newsock);
- 		return(-EINVAL);
- 	}
--	sock->file=current->files->fd[fd];
-+	newsock->file=current->files->fd[fd];
- 	
- 	if (upeer_sockaddr)
- 	{
---- ref/net/ipv4/tcp_input.c	Sun Jun  9 10:39:09 1996
-+++ work/net/ipv4/tcp_input.c	Mon Jun 10 17:36:44 1996
-@@ -33,6 +33,11 @@
- #include <linux/config.h>
+--- ref/net/ipv4/tcp_input.c	Thu Aug  1 14:25:59 1996
++++ work/net/ipv4/tcp_input.c	Wed Aug 21 10:56:28 1996
+@@ -36,6 +36,11 @@
+ #include <linux/random.h>
  #include <net/tcp.h>
  
 +#ifdef CONFIG_AREQUIPA
@@ -16094,7 +16190,7 @@
  /*
   *	Policy code extracted so it's now separate
   */
-@@ -415,6 +420,24 @@
+@@ -428,6 +433,24 @@
  			return;
  		}
  	}
@@ -16119,7 +16215,7 @@
  	skb_queue_head_init(&newsk->write_queue);
  	skb_queue_head_init(&newsk->receive_queue);
  	newsk->send_head = NULL;
-@@ -516,7 +539,7 @@
+@@ -529,7 +552,7 @@
  	 */
  
  	rt = ip_rt_route(newsk->opt && newsk->opt->srr ? newsk->opt->faddr : saddr, 0);
@@ -16128,7 +16224,7 @@
  	
  	if(rt!=NULL && (rt->rt_flags&RTF_WINDOW))
  		newsk->window_clamp = rt->rt_window;
-@@ -1771,6 +1794,12 @@
+@@ -1785,6 +1808,12 @@
  		skb->free = 1;
  		skb->saddr = daddr;
  		skb->daddr = saddr;
diff -ur --new-file old/atm/doc/usage.tex new/atm/doc/usage.tex
--- old/atm/doc/usage.tex	Wed Jul 31 18:25:35 1996
+++ new/atm/doc/usage.tex	Thu Aug 29 16:01:44 1996
@@ -1,7 +1,7 @@
 %%def%:=
 
 %:\begin{verbatim}
-%:Usage instructions  -  ATM on Linux, release 0.15 (pre-alpha)
+%:Usage instructions  -  ATM on Linux, release 0.16 (pre-alpha)
 %:-------------------------------------------------------------
 %:
 %:\end{verbatim}
@@ -38,14 +38,14 @@
 
 \title{ATM on Linux \\
   User's guide \\
-  Release 0.15 (pre-alpha)}
+  Release 0.16 (pre-alpha)}
 \author{Werner Almesberger \\
   {\tt werner.almesberger@lrc.di.epfl.ch} \\
   \\
   Laboratoire de R\'eseaux de Communication (LRC) \\
   EPFL, CH-1015 Lausanne, Switzerland}
  
-\date{July 31, 1996}
+\date{August 21, 1996}
 
 \begin{document}
 \maketitle
@@ -81,9 +81,9 @@
 In order to install this package, you need
 \begin{itemize}
   \item the package itself
-    \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.15.tar.gz}
-  \item the Linux kernel, version 2.0, e.g. from
-\url{ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.tar.gz}
+    \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.16.tar.gz}
+  \item the Linux kernel, version 2.0.14, e.g. from
+\url{ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.14.tar.gz}
   \item Perl, version 4 or 5
 \end{itemize}
 
@@ -96,13 +96,13 @@
 distribution:
 
 \begin{verbatim}
-tar xfz atm-0.15.tar.gz
+tar xfz atm-0.16.tar.gz
 \end{verbatim}
 
 and the kernel source:
 
 \begin{verbatim}
-tar xfz linux-2.0.tar.gz
+tar xfz linux-2.0.14.tar.gz
 \end{verbatim}
 
 Finally, you can extract the ATM-related patches:
@@ -129,6 +129,8 @@
   \item[\path{atm/ip/}] IP over ATM: \name{clip}, \name{atmarp}
   \item[\path{atm/arpd/}] ATMARP demon: \name{atmarpd}
   \item[\path{atm/led/}] LAN Emulation demon: \name{led}
+  \item[\path{atm/lane/}] LAN Emulation servers: \name{bus}, \name{lecs},
+    \name{les}
   \item[\path{atm/aqd/}] Arequipa demon: \name{arequipad}
   \item[\path{atm/debug/}] Debugging tools: \name{ed}, \name{en},
     \name{encopy}, \name{endump}, and \name{zndump}
@@ -928,7 +930,10 @@
 \# atmarp -s \meta{ip\_address} \meta{atm\_address}
 \end{command}
 
-There is also a \raw{temp} option for SVCs.
+There is also a (probably not very useful) \raw{temp} option for SVCs.
+All \raw{atmarp -s} commands also accept an option \raw{pcr \meta{value}}
+to change the connection to CBR (default is UBR) and to set the peak cell
+rate.
 
 \begin{command}
 \# atmarp -d \meta{ip\_address}
@@ -950,7 +955,8 @@
 Besides Classical IP over ATM, LAN Emulation (LANE) can be used to carry IP
 over ATM. LANE emulates the characteristics of legacy LAN technology,
 such as support for broadcasts. LANE client support is described in the
-file \path{atm/led/USAGE}.
+file \path{atm/led/USAGE}, LANE server support is described in
+\path{atm/lane/USAGE}.
 
 
 \subsection{Arequipa}
@@ -961,13 +967,16 @@
 should use Arequipa connections, the Arequipa demon has to be started:
 
 \begin{command}
-\# arequipad \[-b\] \[-d\] \[-n\]
+\# arequipad \[-b\] \[-d\] \[-l \meta{logfile}\] \[-n\]
 \end{command}
 
 \begin{description}
   \item[\raw{-b}] background. Run in a forked child process after initializing.
   \item[\raw{-d}] enables debugging output. By default, \name{arequipad} is
     very quiet.
+  \item[\raw{-l \meta{logfile}}] write diagnostic messages to the specified
+    file instead of to standard error. The special name \raw{syslog} is
+    used to send diagnostics to the system logger.
   \item[\raw{-n}] prints addresses in numeric format only, i.e. no address to
     name translation is attempted.
 \end{description}
diff -ur --new-file old/atm/doc/usage.txt new/atm/doc/usage.txt
--- old/atm/doc/usage.txt	Wed Jul 31 18:58:08 1996
+++ new/atm/doc/usage.txt	Thu Aug 29 16:17:44 1996
@@ -1,4 +1,4 @@
-Usage instructions  -  ATM on Linux, release 0.15 (pre-alpha)
+Usage instructions  -  ATM on Linux, release 0.16 (pre-alpha)
 -------------------------------------------------------------
 
 For updates of ATM on Linux, please check the Web page at  
@@ -17,9 +17,9 @@
 In order to install this package, you need 
 
   - the package itself  
-    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.15.tar.gz  
-  - the Linux kernel, version 2.0, e.g. from  
-    ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.tar.gz  
+    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.16.tar.gz  
+  - the Linux kernel, version 2.0.14, e.g. from  
+    ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.14.tar.gz  
   - Perl, version 4 or 5 
 
 
@@ -31,11 +31,11 @@
 all the files listed above there. Then extract the ATM on Linux 
 distribution:
 
-tar xfz atm-0.15.tar.gz
+tar xfz atm-0.16.tar.gz
 
 and the kernel source:
 
-tar xfz linux-2.0.tar.gz
+tar xfz linux-2.0.14.tar.gz
 
 Finally, you can extract the ATM-related patches:
 
@@ -56,6 +56,7 @@
   atm/ip/  IP over ATM: clip, atmarp 
   atm/arpd/  ATMARP demon: atmarpd 
   atm/led/  LAN Emulation demon: led 
+  atm/lane/  LAN Emulation servers: bus, lecs, les 
   atm/aqd/  Arequipa demon: arequipad 
   atm/debug/  Debugging tools: ed, en, encopy, endump, and zndump 
   atm/lib/  Libraries for applications and demons 
@@ -748,7 +749,9 @@
 
   # atmarp -s <ip_address> <atm_address>  
 
-There is also a  temp  option for SVCs.
+There is also a (probably not very useful)  temp  option for SVCs. All  
+atmarp -s  commands also accept an option  pcr <value>  to change the 
+connection to CBR (default is UBR) and to set the peak cell rate.
 
   # atmarp -d <ip_address>  
 
@@ -768,7 +771,7 @@
 Besides Classical IP over ATM, LAN Emulation (LANE) can be used to carry IP 
 over ATM. LANE emulates the characteristics of legacy LAN technology, such 
 as support for broadcasts. LANE client support is described in the file 
-atm/led/USAGE.
+atm/led/USAGE, LANE server support is described in atm/lane/USAGE.
 
 
 Arequipa
@@ -779,10 +782,13 @@
 parameters, etc.) to carry traffic between INET sockets. On a system that 
 should use Arequipa connections, the Arequipa demon has to be started:
 
-  # arequipad [-b] [-d] [-n]  
+  # arequipad [-b] [-d] [-l <logfile>] [-n]  
 
    -b   background. Run in a forked child process after initializing. 
    -d   enables debugging output. By default, arequipad is very quiet. 
+   -l <logfile>   write diagnostic messages to the specified file instead 
+    of to standard error. The special name  syslog  is used to send 
+    diagnostics to the system logger. 
    -n   prints addresses in numeric format only, i.e. no address to name 
     translation is attempted. 
 
diff -ur --new-file old/atm/ilmid/ilmid.c new/atm/ilmid/ilmid.c
--- old/atm/ilmid/ilmid.c	Fri Jun 21 13:27:54 1996
+++ new/atm/ilmid/ilmid.c	Wed Aug 21 11:34:05 1996
@@ -84,7 +84,6 @@
 	{
 	case RESTART:
 	  deleteNetPrefix();
-	  delete_nsap(itf);
 	  diag(COMPONENT, DIAG_DEBUG, "sending cold-start");
 	  diag(COMPONENT, DIAG_DEBUG, "sending get-next");
 	  send_message(fd, coldstart_message);
@@ -154,7 +153,7 @@
 			    if(in_message->data->a.get_response->error_status == NOERROR)
 			      {
 				diag(COMPONENT, DIAG_INFO, "ATM address registered");
-				add_nsap(itf, netprefix_oid, esi_oid);
+				update_nsap(itf, netprefix_oid, esi_oid);
 				poll_misses = 0;
 				new_state = POLL;
 			      }
diff -ur --new-file old/atm/ilmid/io.c new/atm/ilmid/io.c
--- old/atm/ilmid/io.c	Fri Jul 12 14:50:18 1996
+++ new/atm/ilmid/io.c	Wed Aug 21 11:34:06 1996
@@ -85,27 +85,10 @@
   return name;
 }
 
-void delete_nsap(int itf)
+void update_nsap(int itf, AsnOid *netprefix, AsnOid *esi)
 {
   struct atmif_sioc req;
-  int fd;
-  
-  if ((fd = socket(AF_ATMSVC, SOCK_DGRAM, 0)) < 0)
-    diag(COMPONENT, DIAG_FATAL, "socket: %s", strerror(errno));
-
-  req.number = itf;
-  req.arg = NULL;
-
-  if(ioctl(fd, ATM_RSTADDR, &req) < 0)
-    diag(COMPONENT, DIAG_FATAL, "ioctl ATM_RSTADDR: %s", strerror(errno));
-
-  close(fd);
-}
-
-void add_nsap(int itf, AsnOid *netprefix, AsnOid *esi)
-{
-  struct atmif_sioc req;
-  struct sockaddr_atmsvc addr;
+  struct sockaddr_atmsvc addr, ouraddr;
   int fd, m, n;
 
   addr.sas_family = AF_ATMSVC;
@@ -129,14 +112,41 @@
 
   if ((fd = socket(AF_ATMSVC, SOCK_DGRAM, 0)) < 0)
     diag(COMPONENT, DIAG_FATAL, "socket: %s", strerror(errno));
-
+  
   req.number = itf;
-  req.arg = &addr;
-  req.length = sizeof(addr);
+  req.arg = &ouraddr;
+  req.length = sizeof(ouraddr);
+
+  /* Try to get our address on that interface */
+
+  if (ioctl(fd, ATM_GETADDR, &req) <0)
+    diag(COMPONENT, DIAG_FATAL, "ioctl ATM_GETADDR: %s", strerror(errno));
 
-  if(ioctl(fd, ATM_ADDADDR, &req) < 0)
-    diag(COMPONENT, DIAG_FATAL, "ioctl ATM_ADDADDR: %s", strerror(errno));
+  n = 1;
+
+  for(m = 0; m < netprefix->octetLen; m++)
+     if(addr.sas_addr.prv[m] != ouraddr.sas_addr.prv[m])
+     {	n = 0;
+	break;
+     }
+
+  if ((req.length == 0) || (n == 0)) {
+  	  req.number = itf;
+  	  req.arg = NULL;
+  	  req.length = 0;
+
+  	  if(ioctl(fd, ATM_RSTADDR, &req) < 0)
+    	    diag(COMPONENT, DIAG_FATAL, "ioctl ATM_RSTADDR: %s", strerror(errno));
+
+	  req.number = itf;
+	  req.arg = &addr;
+	  req.length = sizeof(addr);
+	  
+	  if(ioctl(fd, ATM_ADDADDR, &req) < 0)
+	    diag(COMPONENT, DIAG_FATAL, "ioctl ATM_ADDADDR: %s", strerror(errno));
 
+	  diag(COMPONENT, DIAG_INFO, "ATM NSAP Address set on local host");
+  }	     	
   close(fd);
 
 }
diff -ur --new-file old/atm/ilmid/io.h new/atm/ilmid/io.h
--- old/atm/ilmid/io.h	Tue Feb  6 19:56:05 1996
+++ new/atm/ilmid/io.h	Wed Aug 21 11:34:06 1996
@@ -41,8 +41,7 @@
 #define MAX_ILMI_MSG 484
 
 AsnOid *get_esi(int fd);
-void add_nsap(int itf, AsnOid *netprefix, AsnOid *esi);
-void delete_nsap(int itf);
+void update_nsap(int itf, AsnOid *netprefix, AsnOid *esi);
 int wait_for_message(int fd, struct timeval *timeout);
 int read_message(int fd, Message *message);
 int send_message(int fd, Message *message);
diff -ur --new-file old/atm/ip/atmarp.c new/atm/ip/atmarp.c
--- old/atm/ip/atmarp.c	Tue Jul  9 13:12:07 1996
+++ new/atm/ip/atmarp.c	Thu Aug 29 11:43:36 1996
@@ -56,8 +56,10 @@
 {
     fprintf(stderr,"usage: %s -a\n",name);
     fprintf(stderr,"%6s %s -c [atmN]\n","",name);
-    fprintf(stderr,"%6s %s -s ip_addr [itf.]vpi.vci [temp] [null]\n","",name);
-    fprintf(stderr,"%6s %s -s ip_addr atm_addr [temp] [arpsrv]\n","",name);
+    fprintf(stderr,"%6s %s -s ip_addr [itf.]vpi.vci [pcr value] [temp] [null]"
+      "\n","",name);
+    fprintf(stderr,"%6s %s -s ip_addr atm_addr [pcr value] [temp] [arpsrv]\n",
+     "",name);
     fprintf(stderr,"%6s %s -d ip_addr [arpsrv]\n","",name);
     exit(1);
 }
@@ -144,23 +146,27 @@
 	memcpy(&((struct sockaddr_in *) &req.arp_pa)->sin_addr,hostent->h_addr,
 	  hostent->h_length);
     }
-    req.arp_flags = 0;
+    req.arp_flags = ATF_PERM;
     if (op == SIOCSARP) {
+	memset(&req.arp_qos,0,sizeof(req.arp_qos));
+	req.arp_qos.txtp.class = ATM_UBR;
 	for (i = optind+2; i < argc; i++)
-		if (!strcmp(argv[i],"term")) req.arp_flags |= ATF_PERM;
+		if (!strcmp(argv[i],"temp")) req.arp_flags &= ~ATF_PERM;
 		else if (!strcmp(argv[i],"null")) req.arp_flags |= ATF_NULL;
 		else if (!strcmp(argv[i],"arpsrv")) req.arp_flags |= ATF_ARPSRV;
+		else if (!strcmp(argv[i],"pcr")) {
+			if (++i >= argc) usage(argv[0]);
+			req.arp_qos.txtp.max_pcr = strtol(argv[i],&end,0);
+			if (*end) usage(argv[0]);
+		    }
 		else usage(argv[0]);
-	req.arp_flags ^= ATF_PERM;
+	req.arp_qos.txtp.max_sdu = RFC1483LLC_LEN+RFC1626_MTU;
+	req.arp_qos.rxtp = req.arp_qos.txtp;
 	if (text2atm(argv[optind+1],(struct sockaddr *) &req.arp_ha,
 	  sizeof(req.arp_ha),T2A_NAME) < 0) {
 	    fprintf(stderr,"%s: invalid ATM address\n",argv[optind+1]);
 	    return 1;
 	}
-	memset(&req.arp_qos,0,sizeof(req.arp_qos));
-	req.arp_qos.txtp.class = ATM_UBR;
-	req.arp_qos.txtp.max_sdu = RFC1483LLC_LEN+RFC1626_MTU;
-	req.arp_qos.rxtp = req.arp_qos.txtp;
     }
     if (op == SIOCDARP && optind+1 < argc) {
 	if (optind+2 < argc || strcmp(argv[optind+1],"arpsrv")) usage(argv[0]);
diff -ur --new-file old/atm/lane/COPYRIGHT.TUT new/atm/lane/COPYRIGHT.TUT
--- old/atm/lane/COPYRIGHT.TUT	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/COPYRIGHT.TUT	Sat Aug 10 14:03:24 1996
@@ -0,0 +1,21 @@
+/*
+ * Marko Kiiskila carnil@cs.tut.fi 
+ * 
+ * Tampere University of Technology - Telecommunications Laboratory
+ *
+ * Permission to use, copy, modify and distribute this
+ * software and its documentation is hereby granted,
+ * provided that both the copyright notice and this
+ * permission notice appear in all copies of the software,
+ * derivative works or modified versions, and any portions
+ * thereof, that both notices appear in supporting
+ * documentation, and that the use of this software is
+ * acknowledged in any publications resulting from using
+ * the software.
+ * 
+ * TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
+ * SOFTWARE.
+ * 
+ */
diff -ur --new-file old/atm/lane/Makefile new/atm/lane/Makefile
--- old/atm/lane/Makefile	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/Makefile	Thu Aug 29 12:33:16 1996
@@ -0,0 +1,47 @@
+#
+# Makefile
+# $Id: Makefile,v 1.26 1995/11/15 08:38:51 carnil Exp $
+
+#
+# Compilation options
+#
+
+CFLAGS = -ansi -pedantic -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs
+
+#
+#
+# The rules
+#
+#
+SYSPGMS =	les bus lecs
+LESBUSOBJS =	mem.o load.o units.o load_lex.o timers.o dump.o atm.o \
+		events.o lane.o
+LESOBJS =	$(LESBUSOBJS) packet.o connect.o db.c
+BUSOBJS =       $(LESBUSOBJS) connect_bus.o
+LECSOBJS =	lecs_db.o lecs_load.o lecs.o ldb.o mem_lecs.o atm_lecs.o
+OBJS =		$(LESOBJS) $(BUSOBJS) $(LECSOBJS)
+LDLIBS =	-latm
+
+include ../Rules.make
+
+load_lex.c : load_lex.l
+	$(LEX) -oload_lex.c load_lex.l
+
+lecs_db.c: lecs_db.l
+	$(LEX) -olecs_db.c lecs_db.l 
+
+les:	$(LESOBJS)
+	@echo "Linking $@"
+	@$(CC) $(LDFLAGS) -o $@ $(LESOBJS)
+
+bus:	$(BUSOBJS)
+	@echo "Linking $@"
+	@$(CC) $(LDFLAGS) -o $@ $(BUSOBJS)
+
+lecs:	$(LECSOBJS)
+	@echo "Linking $@"
+	@$(CC) $(LDFLAGS) -o $@ $(LECSOBJS) -latm
+
+clean:
+	rm -f $(SYSPGMS) *.o *.d *~ .*~ core *.bak *.tar* *.errs load_lex.c \
+	lecs_db.c *~
diff -ur --new-file old/atm/lane/USAGE new/atm/lane/USAGE
--- old/atm/lane/USAGE	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/USAGE	Sun Aug 18 23:00:10 1996
@@ -0,0 +1,109 @@
+/*
+ * Marko Kiiskila carnil@cs.tut.fi 
+ * 
+ * Tampere University of Technology - Telecommunications Laboratory
+ *
+ */
+
+LANE Service Package
+====================
+Lan Emulation Configuration Server, Lan Emulation Server and
+Broadcast and Unknown Server. Description
+of LAN-E can be found from ATM Forum's specification "LAN Emulation
+Over ATM - Version 1.0". 
+ftp://ftp.atmforum.com/pub/specs/af-lane-0021.000.ps.Z
+
+Usage:
+======
+Compile the package. This produces three executables lecs, les and bus.
+LES and BUS noth use same configuration file '.lanevars'. Fill in the 
+required fields in that file and start the servers.
+Configuration file for LECS is .lecs_conf
+
+Configuration file (.lanevars):
+===============================
+Has following variables for controlling VLAN and server operation:
+
+S1=Address of the LES. This address is used in ATM signalling.
+S2=Type of the emulated LAN. Valid values are "802.3" and "802.5".
+S3=Maximum frame size. Valid values are 1516, 4544, 9234 and 18190
+S4=Join Timeout. Time in seconds which LES waits for LE_JOIN_REQUEST 
+   before tearing down a connection.
+S5=Maximum frame Age. Currently not used.
+S6=Address of the BUS. This address is used in ATM signalling.
+ELANNAME= Name of the emulated LAN
+
+Most important variables are S1 and S6. When one is running LE service
+and LE client in same machine, care must be taken in choosing different
+ATM addresses for these entities. This is needed because SAPs for these
+entities must be different, and ATM address is the only way for this.
+Currently these variables must be given in format shown in example
+configuration file included in package, i.e.:
+
+S6=:47:00:23:00:00:00:03:03:00:01:00:02:01:00:20:ea:00:0a:e9:02 #viulu
+
+Configuration file (.lecs_conf):
+================================
+Includes definitions for LECS's ATM address and ELAN definitions for
+which LECS knows about. Look for example configuration file
+.lecs_conf for description of variables and syntax of these.
+
+Example scenario:
+=================
+
+--------             --------             --------
+|      |             |      |             |      |
+| Box1 |-------------|Switch|-------------| Box2 |
+|      |             |      |             |      |
+--------             --------             --------
+
+Box1 has ATM addresses A1, A2 and A3. Box2 has ATM address B1 and B2.
+A1 = LEC address in Box1
+A2 = LES address
+A3 = BUS address
+B1 = LECS address
+B2 = LEC address in Box2
+
+Start ATM signalling in both boxes. Switch is configures with IISP
+routes, because ilmid can only register one ATM address. 
+
+Another way is to modify signalling daemon's code.
+-----8<------
+                    if (walk->state == ls_same && atm_equal(&walk->addr,
+                      &msg->svc,0,0)) break;
+
+to
+
+                    if (walk->state == ls_same && atm_equal(&walk->addr,
+                      &msg->svc,(ATM_ESA_LEN-1)*8,AXE_WILDCARD)) break;
+
+(atm/sigd/kernel.c, near line 156)
+-----8<------
+
+After this it is possible to run ilmid if A1, A2 and A3 differ only in 
+selector byte of their ATM addresses. In this case IISP routes are
+not needed.
+
+.lanevars contains:
+[conn]
+S1=A2
+S6=A3
+
+
+.lecs_conf contains:
+#LECS address
+B1
+
+#ELAN definition
+[] 
+DEFAULT
+
+
+Start lecs, les and bus.
+
+Run LEC in Box1:
+zeppelin -c B1 -l A1 
+
+Run LEC in Box2:
+zeppelin -c B1 -l B2
+
diff -ur --new-file old/atm/lane/atm.c new/atm/lane/atm.c
--- old/atm/lane/atm.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/atm.c	Thu Aug  8 23:22:10 1996
@@ -0,0 +1,185 @@
+ /*
+ * ATM connection functions
+ *
+ * $Id: atm.c,v 1.3 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+/* System includes */
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <linux/atm.h>
+#include <linux/atmsap.h>
+#include <assert.h>
+
+/* Local includes */
+#include "atm.h"
+#include "load.h"
+#include "dump.h"
+#include "connect.h"
+#include "mem.h"
+
+/* Local protos */
+static void atm_init0(void);
+static void atm_init1(void);
+static void atm_dump(void);
+
+/* Static variables */
+static const char *rcsid="$Id: atm.c,v 1.3 1995/11/15 08:27:11 carnil Exp $";
+
+/* Data */
+#define QLEN 5
+
+const Unit_t atm_unit = {
+  "atm",
+  &atm_init0,
+  &atm_init1,
+  &atm_dump,
+  NULL
+};
+
+static void 
+atm_dump(void)
+{
+  ;
+}
+
+static void 
+atm_init0(void)
+{
+  ;
+}
+
+static void 
+atm_init1(void)
+{
+  set_var_str(&atm_unit, "version", rcsid);
+
+  Debug_unit(&atm_unit,"Initialized");
+}
+
+int 
+atm_create_socket(unsigned char codepoint, const AtmAddr_t *our_addr)
+{ 
+  struct sockaddr_atmsvc server;
+  struct atm_blli blli;
+  struct atm_qos qos;
+  int fd, ret;
+  int len = sizeof(server);
+
+  fd = socket(PF_ATMSVC, SOCK_DGRAM, ATM_AAL5);
+  if (fd <0) {
+    dump_error(&atm_unit,"socket");
+    return -1;
+  }
+
+  memset(&server, 0, len);
+  memset(&blli, 0, sizeof(blli));
+  memset(&qos, 0, sizeof(qos));
+  server.sas_family = AF_ATMSVC;
+  memcpy(server.sas_addr.prv, our_addr, ATM_ESA_LEN);
+  server.sas_addr.blli = &blli;
+  qos.txtp.class = ATM_UBR;
+  qos.txtp.max_sdu = 1516;
+  qos.rxtp.class = ATM_UBR;
+  qos.rxtp.max_sdu = 1516;
+
+  blli.l3_proto = ATM_L3_TR9577;
+  blli.l3.tr9577.ipi = NLPID_IEEE802_1_SNAP;
+  blli.l3.tr9577.snap[0] = 0x00;
+  blli.l3.tr9577.snap[1] = 0xa0;
+  blli.l3.tr9577.snap[2] = 0x3e;
+  blli.l3.tr9577.snap[3] = 0x00;
+  blli.l3.tr9577.snap[4] = codepoint;
+  
+  if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) {
+    dump_error(&atm_unit, "setsockopt(fd, SOL_ATM, SO_ATMQOS,...)");
+    close(fd);
+    return -1;
+  }
+  disp_sockaddr(&server);
+  ret = bind(fd, (struct sockaddr *)&server, len);
+  if (ret <0) {
+    dump_error(&atm_unit, "bind");
+    close(fd);
+    return -1;
+  }
+  ret = listen(fd, QLEN);
+  if (ret <0) {
+    dump_error(&atm_unit, "listen");
+    close(fd);
+    return -1;
+  }
+  return fd;
+}
+
+int
+atm_connect_back(const AtmAddr_t *our_addr, const Conn_t *conn,
+		 unsigned char codepoint)
+{
+  struct sockaddr_atmsvc address;
+  struct atm_blli blli;
+  struct atm_qos qos;
+  int fd, ret;
+  int len = sizeof(address);
+  
+  fd = socket(PF_ATMSVC, SOCK_DGRAM, ATM_AAL5);
+  if (fd <0) {
+    dump_error(&atm_unit,"socket");
+    return -1;
+  }
+  
+  memset(&qos, 0, sizeof(qos));
+  qos.txtp.class = ATM_UBR;
+  qos.txtp.max_sdu = 1516;
+  qos.rxtp.class = ATM_UBR;
+  qos.rxtp.max_sdu = 1516;
+
+  if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) {
+    dump_error(&atm_unit, "setsockopt(fd, SOL_ATM, SO_ATMQOS,...)");
+    close(fd);
+    return -1;
+  }
+
+  memset(&address, 0, len);
+  address.sas_family = AF_ATMSVC;
+  memcpy(address.sas_addr.prv, our_addr, sizeof(AtmAddr_t));
+
+  disp_sockaddr(&address);
+
+  ret = bind(fd, (struct sockaddr *)&address, len);
+  if (ret <0) {
+    dump_error(&atm_unit, "bind");
+    close(fd);
+    return -1;
+  }
+  memset(&address, 0, len);
+  ret = getpeername(conn->fd, (struct sockaddr*)&address, &len);
+  if (ret < 0) {
+    dump_error(&atm_unit, "getpeername");
+    close(fd);
+    return -1;
+  }
+  address.sas_addr.blli = &blli;
+  memset(&blli, 0, sizeof(blli));
+  blli.l3_proto = ATM_L3_TR9577;
+  blli.l3.tr9577.ipi = NLPID_IEEE802_1_SNAP;
+  blli.l3.tr9577.snap[0] = 0x00;
+  blli.l3.tr9577.snap[1] = 0xa0;
+  blli.l3.tr9577.snap[2] = 0x3e;
+  blli.l3.tr9577.snap[3] = 0x00;
+  blli.l3.tr9577.snap[4] = codepoint;
+  
+  disp_sockaddr(&address);
+
+  ret = connect(fd, (struct sockaddr*)&address,sizeof(struct sockaddr_atmsvc));
+  if (ret < 0) {
+    dump_error(&atm_unit, "connect");
+    close(fd);
+    return -1;
+  }
+  return fd;
+}
+
diff -ur --new-file old/atm/lane/atm.h new/atm/lane/atm.h
--- old/atm/lane/atm.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/atm.h	Thu Aug  8 23:22:19 1996
@@ -0,0 +1,40 @@
+/*
+ * ATM connection 
+ *
+ * $Id: atm.h,v 1.2 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+#ifndef ATM_H
+#define ATM_H
+
+/* System includes needed for types */
+#include <sys/types.h>
+ 
+/* Local includes needed for types */
+#include "units.h"
+#include "lane.h" 
+#include "connect.h"
+
+/* Type definitions */
+
+/* Codepoints */
+#define CONFIGURATION_DIRECT    0x01
+#define CONTROL_DIRECT          0x01
+#define CONTROL_DISTRIBUTE      0x01
+#define DATA_DIRECT_802_3       0x02
+#define DATA_DIRECT_802_5       0x03
+#define MULTICAST_SEND_802_3    0x04
+#define MULTICAST_FORWARD_802_3 0x04
+#define MULTICAST_SEND_802_5    0x05
+#define MULTICAST_FORWARD_802_5 0x05
+
+/* Global function prototypes */
+int atm_create_socket(unsigned char codepoint, const AtmAddr_t *our_addr);
+int atm_connect_back(const AtmAddr_t *our_addr, const Conn_t *conn,
+		     unsigned char codepoint);
+
+/* Global data */
+extern const Unit_t atm_unit;
+
+#endif
+
diff -ur --new-file old/atm/lane/atm_lecs.c new/atm/lane/atm_lecs.c
--- old/atm/lane/atm_lecs.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/atm_lecs.c	Sun Aug 18 22:19:47 1996
@@ -0,0 +1,78 @@
+ /*
+ * ATM connection functions
+ *
+ * $Id: atm.c,v 1.3 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+/* System includes */
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <linux/atm.h>
+#include <linux/atmsap.h>
+#include <assert.h>
+
+/* Local includes */
+#include "atm_lecs.h"
+
+/* Data */
+#define QLEN 5
+
+int 
+atm_create_socket(unsigned char codepoint, const unsigned char *our_addr)
+{ 
+  struct sockaddr_atmsvc server;
+  struct atm_blli blli;
+  struct atm_qos qos;
+  int fd, ret;
+  int len = sizeof(server);
+
+  fd = socket(PF_ATMSVC, SOCK_DGRAM, ATM_AAL5);
+  if (fd <0) {
+    perror("socket(PF_ATMSVC, ...)");
+    return -1;
+  }
+
+  memset(&server, 0, len);
+  memset(&blli, 0, sizeof(blli));
+  memset(&qos, 0, sizeof(qos));
+  server.sas_family = AF_ATMSVC;
+  if (our_addr)
+    memcpy(server.sas_addr.prv, our_addr, ATM_ESA_LEN);
+  server.sas_addr.blli = &blli;
+  qos.txtp.class = ATM_UBR;
+  qos.txtp.max_sdu = 1516;
+  qos.rxtp.class = ATM_UBR;
+  qos.rxtp.max_sdu = 1516;
+
+  blli.l3_proto = ATM_L3_TR9577;
+  blli.l3.tr9577.ipi = NLPID_IEEE802_1_SNAP;
+  blli.l3.tr9577.snap[0] = 0x00;
+  blli.l3.tr9577.snap[1] = 0xa0;
+  blli.l3.tr9577.snap[2] = 0x3e;
+  blli.l3.tr9577.snap[3] = 0x00;
+  blli.l3.tr9577.snap[4] = codepoint;
+  
+  if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) {
+    perror("setsockopt(fd, SOL_ATM, SO_ATMQOS,...)");
+    close(fd);
+    return -1;
+  }
+  ret = bind(fd, (struct sockaddr *)&server, len);
+  if (ret <0) {
+    perror("bind(fd, ...)");
+    close(fd);
+    return -1;
+  }
+  ret = listen(fd, QLEN);
+  if (ret <0) {
+    perror("listen(fd, QLEN)");
+    close(fd);
+    return -1;
+  }
+  return fd;
+}
+
+
diff -ur --new-file old/atm/lane/atm_lecs.h new/atm/lane/atm_lecs.h
--- old/atm/lane/atm_lecs.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/atm_lecs.h	Sun Aug 18 22:20:10 1996
@@ -0,0 +1,28 @@
+/*
+ * ATM connection 
+ *
+ * $Id: atm.h,v 1.2 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+#ifndef ATM_LECS_H
+#define ATM_LECS_H
+
+/* System includes needed for types */
+#include <sys/types.h>
+
+/* Codepoints */
+#define CONFIGURATION_DIRECT    0x01
+#define CONTROL_DIRECT          0x01
+#define CONTROL_DISTRIBUTE      0x01
+#define DATA_DIRECT_802_3       0x02
+#define DATA_DIRECT_802_5       0x03
+#define MULTICAST_SEND_802_3    0x04
+#define MULTICAST_FORWARD_802_3 0x04
+#define MULTICAST_SEND_802_5    0x05
+#define MULTICAST_FORWARD_802_5 0x05
+
+/* Global function prototypes */
+int atm_create_socket(unsigned char codepoint, const unsigned char *our_addr);
+
+#endif /* ATM_LECS_H */
+
diff -ur --new-file old/atm/lane/connect.c new/atm/lane/connect.c
--- old/atm/lane/connect.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/connect.c	Sun Aug 18 22:45:00 1996
@@ -0,0 +1,937 @@
+/*
+ * ATM connection wrapper
+ *
+ * $Id: connect.c,v 1.24 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+
+/* System includes */
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <linux/atm.h>
+#include <errno.h>
+
+/* Local includes */
+#include "mem.h"
+#include "lane.h"
+#include "dump.h"
+#include "load.h"
+#include "connect.h"
+#include "events.h"
+#include "db.h"
+#include "packet.h"
+#include "atm.h"
+
+/* Type definitions */
+
+/* Local function prototypes */
+static void conn_init0(void);
+static void conn_init1(void);
+static void conn_dump(void);
+static void conn_release(void);
+static const char *dump_conn_type(ConnType_t type);
+/*
+static void add_pvcs(void);
+*/
+static int data_handler(const Event_t *event, void *funcdata);
+static int timer_handler(const Event_t *event, void *funcdata);
+static void conn_main(void);
+
+static int join(const Conn_t *conn);
+static int join_ok(const Conn_t *conn);
+static int join_bad(const Conn_t *conn);
+static int join_close(const Conn_t *conn);
+static int join_expire(const Conn_t *conn);
+static int idle_bad(const Conn_t *conn);
+static int topology_request(const Conn_t *conn);
+
+static int register_req(const Conn_t *conn);
+static int unregister_req(const Conn_t *conn);
+
+static int arp_find(const Conn_t *conn);
+static int arp_forward_response(const Conn_t *conn);
+
+static int forward_flush_response(const Conn_t *conn);
+
+static int is_multicast(const LaneDestination_t *to_detect);
+static int proper_request(void);
+static Bool_t is_proxy(void);
+static int is_control(LaneControl_t *c);
+
+/* Data */
+#define BUFSIZE 256
+#define PORT 8621U
+
+const Unit_t conn_unit = {
+  "conn",
+  &conn_init0,
+  &conn_init1,
+  &conn_dump,
+  &conn_release
+};
+
+static Conn_t *connlist;
+
+extern Reg_t *reglist;
+
+extern Proxy_t *proxylist;
+
+extern Lecdb_t *leclist;
+
+LaneControl_t *control_packet;
+
+static const char *rcsid = "$Id: connect.c,v 1.24 1995/11/15 08:27:11 carnil Exp $";
+
+static State_t
+  /* CS_IDLE */
+  is_1 = { CE_SVC_OPEN, 0,  "Idle->Add_Party", join, CS_JOINING },
+  is_2 = { CE_SVC_OPEN, 0, "Idle->Idle", idle_bad, CS_IDLE },
+  *idle_state[] = { &is_1, &is_2, NULL },
+    
+  /* CS_JOINING */
+  js_1 = { CE_DATA, LE_JOIN_REQUEST, "Join->Oper", join_ok, CS_OPERATIONAL },
+    /*
+  js_2 = { CE_DATA, LE_JOIN_REQUEST, "Join->Add_P", join_ap_ok, CS_ADD_PARTY },
+  */
+  js_3 = { CE_DATA, LE_JOIN_REQUEST, "Join->Join", join_bad, CS_JOINING },
+  js_5 = { CE_SVC_CLOSE, 0, "Join->Idle", join_close, CS_IDLE },
+  js_6 = { CE_TIMER, 0, "Join->Idle", join_expire, CS_IDLE },
+  *join_state[] = { &js_1, &js_3, &js_5, &js_6, NULL },
+
+  /* CS_OPERATIONAL */
+  os_1 = { CE_DATA, LE_JOIN_REQUEST, "Oper->Oper JOIN", join_ok, CS_OPERATIONAL },
+  os_2 = { CE_DATA, LE_JOIN_REQUEST, "Oper->Join", join_bad, CS_JOINING },
+  os_3 = { CE_DATA, LE_REGISTER_REQUEST, "Oper->Oper REGISTER REQUEST", register_req, CS_OPERATIONAL },
+  os_4 = { CE_DATA, LE_UNREGISTER_REQUEST, "Oper->Oper UNREGISTER REQUEST", unregister_req, CS_OPERATIONAL },
+  os_5 = { CE_DATA, LE_ARP_REQUEST, "Oper->Oper ARP REQUEST", arp_find, CS_OPERATIONAL},
+  os_6 = { CE_DATA, LE_TOPOLOGY_REQUEST, "Oper->Oper TOPOLOGY REQUEST", topology_request, CS_OPERATIONAL },
+  os_7 = { CE_DATA, LE_ARP_RESPONSE, "Oper->Oper ARP RESPONSE FORWARD", arp_forward_response, CS_OPERATIONAL },
+  os_8 = { CE_DATA, LE_FLUSH_RESPONSE, "Oper->Oper FLUSH FORWARD", forward_flush_response, CS_OPERATIONAL },
+  os_9 = { CE_SVC_CLOSE, 0, "Oper->Idle", join_close, CS_IDLE },
+  *oper_state[] = { &os_1, &os_2, &os_3, &os_4, &os_5, &os_6, &os_7, &os_8,
+		      &os_9, NULL },
+
+  **transitions[CS_MAX + 1] = {
+    idle_state, join_state, oper_state
+  };
+
+extern int errno;
+
+/* Functions */
+
+/* Initialize local data */
+static void
+conn_init0(void)
+{
+  connlist = NULL;
+  reglist = NULL;
+  proxylist = NULL;
+  leclist = NULL;
+}
+
+/* Initialization for data that needs other units */
+static void
+conn_init1(void)
+{
+  set_var_str(&conn_unit, "version", rcsid);
+  conn_main();
+  add_event_handler(CE_DATA, &data_handler, "data_handler", NULL);
+  add_event_handler(CE_TIMER, &timer_handler, "timer_handler", NULL);
+  Debug_unit(&conn_unit, "Initialized.");
+}
+
+/* Dump status, local data etc. */
+static void
+conn_dump(void)
+{
+  const char *tmp;
+  const AtmAddr_t *addr;
+
+  Debug_unit(&conn_unit, "Dumping unit");
+  Debug_unit(&conn_unit, "Parameters:");
+  addr = get_var_addr(&conn_unit, "S1");
+  if (addr != NULL) {
+    Debug_unit(&conn_unit, "S1:");
+    dump_atmaddr(addr);
+  }
+  else {
+    Debug_unit(&conn_unit, "S1: not set");
+  }
+  tmp = get_var_str(&conn_unit, "S2");
+  if (tmp != NULL) {
+    Debug_unit(&conn_unit, "S2: %s", tmp);
+  } else {
+    Debug_unit(&conn_unit, "S2: not set", tmp);
+  }
+  Debug_unit(&conn_unit, "S3: %d", get_var_int(&conn_unit, "S3"));
+  Debug_unit(&conn_unit, "S4: %d", get_var_int(&conn_unit, "S4"));
+  Debug_unit(&conn_unit, "S5: %d", get_var_int(&conn_unit, "S5"));
+  addr = get_var_addr(&conn_unit, "S6");
+  if (addr != NULL) {
+    Debug_unit(&conn_unit, "S6:");
+    dump_atmaddr(addr);
+  }
+  else {
+    Debug_unit(&conn_unit, "S6: not set");
+  }
+  dump_conn(NULL);
+}
+
+/* Release allocated memory, close files etc. */
+static void
+conn_release(void)
+{
+  Conn_t *tmp;
+  Reg_t *rtmp;
+  Lecdb_t *ltmp;
+  Proxy_t *ptmp;
+  
+  Debug_unit(&conn_unit, "Releasing unit");
+  
+  for(tmp = connlist; tmp != NULL; tmp = tmp->next) {
+    connlist = tmp->next;
+    if (tmp->fd)
+      close(tmp->fd);
+    if (tmp->sfd)
+      close(tmp->sfd);
+    mem_free(&conn_unit, tmp);
+  }
+  for(rtmp = reglist; rtmp != NULL; rtmp = rtmp->next) {
+    reglist = rtmp->next;
+    mem_free(&conn_unit, rtmp);
+  }
+  for(ltmp = leclist; ltmp != NULL; ltmp = ltmp->next) {
+    leclist = ltmp->next;
+    mem_free(&conn_unit, ltmp);
+  }
+  for(ptmp = proxylist; ptmp != NULL; ptmp = ptmp->next) {
+    proxylist = ptmp->next;
+    mem_free(&conn_unit, ptmp);
+  }
+
+}
+
+/* Validates control packet from header */
+
+static int 
+is_control(LaneControl_t *c)
+{
+  if (c->marker == htons(LE_MARKER) &&
+      c->protocol == LE_PROTOCOL &&
+      c->version == LE_VERSION)
+    return 1;
+  else
+    return 0;
+}
+
+/* Used to detect if LaneDestination_t is
+   multicast address */
+static int 
+is_multicast(const LaneDestination_t *to_detect)
+{
+  if (to_detect->tag == htons(LANE_DEST_MAC)) {
+    return to_detect->a_r.mac_address[0] & 0x01;
+  } else if (to_detect->tag == htons(LANE_DEST_RD)) {
+    return to_detect->a_r.route.reserved[0] & 0x80;
+  } else
+  return 0;
+}
+
+/*
+ * Handle new connections or data arrival
+ * data points to Conn_t
+ */
+static int
+data_handler(const Event_t *event, void *funcdata)
+{
+  Conn_t *tmp, *newconn;
+  int fd, nbytes;
+  static char buffer[BUFSIZE];
+  LaneControl_t *ctmp;
+  struct sockaddr_atmsvc addr;
+
+  assert(event->data != NULL);
+  tmp = (Conn_t *)event->data;
+  dump_conn(tmp);
+  if (tmp->type == CT_MAIN) {
+    nbytes = sizeof(addr);
+    memset(&addr,0, nbytes);
+    fd = accept(tmp->fd, (struct sockaddr *)&addr, &nbytes);
+    if (fd <0) {
+      dump_error(&conn_unit, "accept");
+      if (errno == ENETRESET) {
+	Debug_unit(&conn_unit,"Restart. Sleeping 10 secs...");
+	sleep(10);
+	event_put(&conn_unit, CE_RESTART, NULL);
+      } else if (errno == EUNATCH) {
+	Debug_unit(&conn_unit,"Exiting...");
+	event_put(&conn_unit, CE_EXIT, NULL);
+      }
+      return -1;
+    }
+    newconn = conn_add(CT_SVC_CD, fd,0);
+    newconn->state = call_state(CE_SVC_OPEN, 0, newconn);
+  }
+  else {
+    /* tmp->fd or tmp->sfd ?*/
+    nbytes = read(tmp->active_fd, buffer, BUFSIZE);
+    if (nbytes < 0) {
+      dump_error(&conn_unit, "read");
+      if (errno == EUNATCH)
+	event_put(&conn_unit, CE_EXIT, NULL);
+      if (errno == ENETRESET) {
+	Debug_unit(&conn_unit, "Restart. Sleeping 10 secs...");
+	sleep(10);
+	event_put(&conn_unit, CE_RESTART, NULL);
+      }
+    } else if (nbytes == 0) {
+      /* EOF */
+      Debug_unit(&conn_unit, "EOF");
+      tmp->state = call_state(CE_SVC_CLOSE, 0, tmp);
+    } else {
+      buffer[nbytes] = '\0';
+      Debug_unit(&conn_unit, "Data: %2.2x %2.2x %2.2x", 
+		 0xff&buffer[0],0xff&buffer[1],0xff&buffer[2]);
+      ctmp = (LaneControl_t *)buffer;
+      if (is_control(ctmp) == 1) {
+	control_packet = (LaneControl_t*)buffer;
+	dump_control(ctmp);
+	tmp->proxy = is_proxy();
+	tmp->state = call_state(CE_DATA, ctmp->opcode, tmp);
+      } else
+	Debug_unit(&conn_unit,"Not a control_packet, discarding...");
+    }
+  }
+  mem_free(&conn_unit, event);
+  return 1;
+}
+
+static int
+timer_handler(const Event_t *event, void *funcdata)
+{
+  Conn_t *tmp;
+
+  assert(event->data != NULL);
+  tmp = (Conn_t *)event->data;
+  dump_conn(tmp);
+  tmp->state = call_state(CE_TIMER, 0, tmp);
+  return 1;
+}
+
+static const char *
+dump_conn_type(ConnType_t type)
+{
+  switch(type) {
+  case CT_NONE: return "None";
+  case CT_MAIN: return "Main listener";
+  case CT_PVC_CD: return "PVC Control Direct";
+  case CT_PVC_DD: return "PVC Data Direct";
+  case CT_SVC_CD: return "SVC Control Direct";
+  case CT_SVC_DD: return "SVC Data Direct";
+  default: return "Bad type";
+  }
+}
+
+void
+dump_conn(const Conn_t *connection)
+{
+  Conn_t *tmp;
+  
+  for(tmp = connlist; tmp != NULL; tmp = tmp->next) {
+    if (connection == NULL || tmp == connection) {
+      Debug_unit(&conn_unit, "fd %d sfd %d state %s type %s", tmp->fd, tmp->sfd, dump_conn_state(tmp->state), dump_conn_type(tmp->type));
+    }
+  }
+}
+
+Conn_t *
+conn_add(ConnType_t type, int fd, LecId_t pvc_lecid)
+{
+  Conn_t *tmp;
+  LecId_t lecid = 0;
+
+  if (type != CT_MAIN && type != CT_PVC_CD) {
+    /* Find next available LECID */
+    for (tmp = connlist; tmp != NULL; tmp = tmp->next){
+      if (lecid < tmp->lecid) {
+	lecid = tmp->lecid;
+      }
+    }
+    lecid++;
+  } else if (type == CT_MAIN) {
+    lecid = 0;
+  } else /* PVC */
+    lecid = pvc_lecid;
+  tmp = (Conn_t *)mem_alloc(&conn_unit, sizeof(Conn_t));
+  memset(tmp, 0, sizeof(*tmp));
+  tmp->fd = fd;
+  tmp->state = CS_IDLE;
+  tmp->lecid = lecid;
+  tmp->type = type;
+  tmp->next = connlist;
+  tmp->timer = timer_new(&conn_unit);
+  tmp->proxy = BL_FALSE;
+  connlist = tmp;
+
+  event_add_fd(fd, tmp); 
+
+  return tmp;
+}
+
+void
+conn_remove(const Conn_t *connection)
+{
+  Conn_t *tmp, *prev;
+
+  assert(connection != NULL);
+  prev = NULL;
+  tmp = connlist;
+  while(tmp) {
+    if (tmp == connection) {
+      if (prev != NULL) {
+	prev->next = tmp->next;
+      } else {
+	connlist = tmp->next;
+      }
+      if (connection->fd) {
+	close(connection->fd);
+	event_remove_fd(connection->fd);
+      }
+      if (connection->sfd) {
+	event_remove_fd(connection->sfd);
+	close(connection->sfd);
+      }
+      timer_free(&conn_unit, tmp->timer);
+      mem_free(&conn_unit, tmp);
+      return;
+    }
+    prev = tmp;
+    tmp = tmp->next;
+  }
+}
+
+void
+conn_set_active(void *data, int fd)
+{
+  Conn_t *tmp = (Conn_t *)data;
+
+  assert(tmp);
+  tmp->active_fd = fd;
+}
+
+static void
+conn_main(void)
+{
+  const AtmAddr_t *addr;
+  int main_conn;
+  const char *str;
+  int i;
+
+  addr = get_var_addr(&conn_unit, "S1");
+  if (addr == NULL) {
+    dump_printf(EL_ERROR, "S1 (LES Address) must be specified");
+    event_put(&conn_unit, CE_EXIT, NULL);
+  }
+  else {
+    str = get_var_str(&conn_unit,"S2");
+    if (str == NULL) {
+      set_var_str(&conn_unit, "S2", S2_default);
+    }
+    i = get_var_int(&conn_unit,"S3");
+    if (i == 0) {
+      set_var_int(&conn_unit,"S3", S3_default);
+    }
+    i = get_var_int(&conn_unit,"S4");
+    if (i == 0) {
+      set_var_int(&conn_unit,"S4", S4_default);
+    }
+    i = get_var_int(&conn_unit,"S5");
+    if (i == 0) {
+      set_var_int(&conn_unit,"S5", S5_default);
+    }
+    addr = get_var_addr(&conn_unit, "S6");
+    if (addr == NULL) {
+      dump_printf(EL_ERROR, "S6 (BUS Address) must be specified");
+      event_put(&conn_unit, CE_EXIT, NULL);
+    } else {
+      main_conn = atm_create_socket(CONTROL_DIRECT, 
+				    get_var_addr(&conn_unit, "S1"));
+      if (main_conn >= 0) {
+	(void)conn_add(CT_MAIN, main_conn,0);
+      }
+    }
+  }
+}
+
+
+ConnState_t
+call_state(EventType_t event, unsigned short opcode, Conn_t *conn)
+{
+  State_t **tmp;
+  unsigned int i = 0;
+  int ret;
+
+  Debug_unit(&conn_unit, "Call state");
+  assert(conn != NULL);
+  assert(conn->state <= CS_MAX);
+  tmp = transitions[conn->state];
+  for(; tmp[i] != NULL; i++) {
+    if (tmp[i]->event == event && htons(tmp[i]->opcode) == opcode) {
+      Debug_unit(&conn_unit, "Trying func %s", tmp[i]->descript);
+      ret = tmp[i]->func(conn);
+      if (ret != 0){
+	Debug_unit(&conn_unit, "Success");
+	return tmp[i]->nextstate;
+      }
+      else {
+	Debug_unit(&conn_unit, "Failed");
+      }
+    }
+    else {
+      Debug_unit(&conn_unit, "Skipping func %s", tmp[i]->descript);
+    }
+  }
+  return conn->state;
+}
+
+const char *
+dump_conn_state(ConnState_t state)
+{
+  switch(state) {
+  case CS_IDLE: return "Idle";
+  case CS_JOINING: return "Joining";
+  case CS_OPERATIONAL: return "Operational";
+  default: return "Bad state";
+  }
+}
+
+#define get_max_frame(a) ((a==LE_MAX_FRAME_1516)?1516:((a==LE_MAX_FRAME_4544)?4544:((a==LE_MAX_FRAME_9234)?9234:18190)))
+
+static int proper_request()
+{
+  if (control_packet != NULL &&
+
+      /* Target address is our address */
+      /* FI[S_ATM] == SV[S_ATM] */
+/*      memcmp((char *) &control_packet->target_addr, 
+	      (const char *) get_var_addr(&conn_unit,"S1"),
+	      sizeof(AtmAddr_t)) == 0  && */
+      
+      /* Lan type is unspecified or same as configured to this server */
+      /* FI[LAN Type] == "Unspecified" or FI[LAN Type] == S2 */
+      (control_packet->lan_type == LE_LAN_TYPE_UNSPECIFIED ||
+       strcmp(get_var_str(&conn_unit,"S2"),
+	      ((control_packet->lan_type ==
+		LE_LAN_TYPE_802_3)?"802.3":
+	       (control_packet->lan_type ==
+		LE_LAN_TYPE_802_5)?"802.5":"unspecified")) == 0) &&
+      
+      /* Max frame size is unspecified or FI[MAX MTU] >= S3 */
+      (control_packet->max_frame == LE_MAX_FRAME_UNSPECIFIED ||
+       get_var_int(&conn_unit, "S3") <=
+       get_max_frame(control_packet->max_frame))
+      /* TOADD: check for entry in REG-DB */
+      ) {
+    return 1;
+  }
+  return 0;
+}
+
+static Bool_t 
+is_proxy(void)
+{
+  if ((control_packet->flags & htons(LE_FLAG_PROXY)) == htons(LE_FLAG_PROXY))
+    return BL_TRUE;
+  else
+    return BL_FALSE;
+}
+
+/*
+ * State transition functions
+ */
+static int
+join(const Conn_t *conn)
+{
+  int timeout;
+  int rfd;
+
+  Debug_unit(&conn_unit, "Join called");
+  dump_conn(conn);
+  timeout = get_var_int(&conn_unit, "S4");
+  timer_alarm(&conn_unit, conn->timer, (unsigned)timeout, conn);
+  rfd=atm_connect_back(get_var_addr(&conn_unit, "S1"), 
+		       conn, CONTROL_DISTRIBUTE);
+  if (rfd<0) {
+    conn_remove(conn);
+    return 0;
+  }
+  conn->sfd=rfd;
+  event_add_fd(rfd, conn);
+  return 1;
+}
+
+static int
+join_ok(const Conn_t *conn)
+{
+  Reg_t *rtmp;
+  Lecdb_t *ltmp; 
+  const char *elanname;
+
+  Debug_unit(&conn_unit, "Join_ok called");  
+  dump_conn(conn);
+
+  if (control_packet != NULL &&
+      proper_request() == 1) {
+/*    dump_control(control_packet);*/
+
+    /* Do not accept control packets with lecid set to unknown value*/
+    if (control_packet->lecid != 0) {
+      Debug_unit(&conn_unit,"Lecid set");
+      ltmp = leciddb_find(control_packet->lecid);
+      if (!ltmp || memcmp(&ltmp->address, &control_packet->source_addr,
+			  sizeof(AtmAddr_t)) != 0) {
+	send_join_response(conn->fd, control_packet, conn->lecid,
+			   (unsigned int)LE_STATUS_BAD_LECID);
+	return 0;
+      }
+    }
+
+    /* Is lan destination address present? */
+    if (control_packet->source.tag != htons(LANE_DEST_NP)) {
+      rtmp = regdb_find_mac(control_packet->source);
+
+      /* Do not accept lan multicast address */
+      if (is_multicast(&control_packet->source)) {
+	Debug_unit(&conn_unit,"Destination lan address is multicast");
+	send_join_response(conn->fd, control_packet, conn->lecid,
+			   ((unsigned int)LE_STATUS_BAD_DEST));
+	return 0;
+      }
+
+      /* Duplicate registered Lan-destination, duplicate mac-address */
+      if (rtmp && memcmp(&rtmp->atm_address,&control_packet->source_addr, 
+			 sizeof(AtmAddr_t)) != 0) {
+	Debug_unit(&conn_unit,"Duplicate Destination lan, duplicate mac");
+	send_join_response(conn->fd, control_packet, conn->lecid,
+			   ((unsigned int)LE_STATUS_DUPLICATE_REG));
+	return 0;
+      }
+    }
+
+    /* Duplicate atm-address */
+    if ((ltmp =leciddb_find_atm(control_packet->source_addr)) != NULL &&
+	ltmp->lecid != conn->lecid) {
+      Debug_unit(&conn_unit,"Duplicate atmaddress");
+      send_join_response(conn->fd, control_packet, conn->lecid,
+			 ((unsigned int)LE_STATUS_DUPLICATE_ADDR));
+      return 0;
+    }
+    /* If we have elan-name, check it agaist the one in join request */
+    elanname = get_var_str(&conn_unit, "ELANNAME");
+    if (elanname) {
+      Debug_unit(&conn_unit, "Compare %s with %s",elanname, 
+		 control_packet->elan_name);
+      if ((strlen(elanname) != control_packet->elan_name_size) ||
+	  strncmp(elanname, control_packet->elan_name, 
+		  control_packet->elan_name_size)) {
+	/* Don't match */
+	Debug_unit(&conn_unit, "Invalid elan-name set");
+	send_join_response(conn->fd, control_packet, conn->lecid,
+			   ((unsigned int)LE_STATUS_NO_CONFIG));
+	return 0;
+      }
+    }
+    Debug_unit(&conn_unit,"Control_packet OK.");
+    /* Control_packet OK. */
+    if (leciddb_find(conn->lecid) == NULL) {
+      leciddb_add(conn->lecid,
+		  control_packet->source_addr, conn->fd);
+    }
+    if (control_packet->source.tag != htons(LANE_DEST_NP) && !rtmp) {
+/*      dump_addr(&control_packet->source); */
+      regdb_add(control_packet->source_addr, 
+		control_packet->source);
+    }
+    /* Send join response */
+    if ((conn->proxy == BL_TRUE || is_proxy() == BL_TRUE) &&
+	proxydb_find(conn->lecid) == NULL) {
+      proxydb_add((const Conn_t *)conn, conn->fd);
+    }
+    timer_ack(&conn_unit, conn->timer);
+    send_join_response(conn->fd, control_packet, conn->lecid,
+		       (unsigned short)LE_STATUS_SUCCESS);
+    return 1;
+  } 
+
+  return 0;
+}
+
+static int
+join_bad(const Conn_t *conn)
+{
+  Debug_unit(&conn_unit, "Join_bad called");
+  dump_conn(conn);
+
+  if (proper_request()==0) {
+    send_join_response(conn->sfd, control_packet, conn->lecid,
+		       (unsigned short)LE_STATUS_BAD_REQ);
+  }
+  return 1;
+}
+
+static int
+idle_bad(const Conn_t *conn)
+{
+  Debug_unit(&conn_unit, "Idle bad called");
+  dump_conn(conn);
+  conn_remove(conn);
+  return 1;
+}
+
+static int
+join_close(const Conn_t *conn)
+{
+  Lecdb_t *tmp;
+
+  Debug_unit(&conn_unit, "Join_close called");
+  dump_conn(conn);
+  Debug_unit(&conn_unit,"Trying to remove PROXY_DB entry");
+  if (proxydb_remove(conn) == 0)
+    Debug_unit(&conn_unit,"Removal of PROXY_DB entry failed");
+  else
+    Debug_unit(&conn_unit,"PROXY_DB entry removed");
+
+  tmp = leciddb_find(conn->lecid);
+  if (tmp) {
+    Debug_unit(&conn_unit, "Trying to remove REG_DB entry");
+    if (regdb_remove(tmp->address) == 0)
+      Debug_unit(&conn_unit, "Removal of REG_DB entry failed");
+    else
+      Debug_unit(&conn_unit, "REG_DB entry removed");
+  }
+/*  if (tmp) {
+    Debug_unit(&conn_unit,"Trying to close connection");
+    if (close(tmp->fd) < 0)
+      Debug_unit(&conn_unit,"Failed");
+    else
+      Debug_unit(&conn_unit,"Success");
+  }*/
+  Debug_unit(&conn_unit,"Trying to remove LECID-DB entry");
+  if (leciddb_remove(conn->lecid) == 0)
+    Debug_unit(&conn_unit,"Removal of LECID-DB entry failed");
+  else
+    Debug_unit(&conn_unit,"LECID-DB entry removed");
+  conn_remove(conn);
+  Debug_unit(&conn_unit,"Conn removed");
+  return 1;
+}
+
+static int
+join_expire(const Conn_t *conn)
+{
+  
+  Debug_unit(&conn_unit, "Join_expire called");
+  dump_conn(conn);
+
+  conn_remove(conn);
+  return 1;
+}
+
+static int
+register_req(const Conn_t *conn)
+{
+  Reg_t *tmp;
+  Lecdb_t *ltmp;
+
+  Debug_unit(&conn_unit, "Register_req called");
+  dump_conn(conn);
+  assert(control_packet != NULL);
+
+  /* If trying to register a multicast or broadcast address, reject */
+  if (is_multicast(&control_packet->source)) {
+    send_register_response(conn->sfd, control_packet,
+			   LE_STATUS_BAD_DEST, 1);
+    return 1;
+  }
+
+  /* Check lecid */
+  ltmp = leciddb_find(control_packet->lecid);
+  if (!ltmp) {
+    send_register_response(conn->sfd, control_packet,
+			   LE_STATUS_BAD_LECID, 1);
+    return 1;
+  }
+  tmp = regdb_find_mac(control_packet->source);
+  if (tmp == NULL) {
+    /* Unregistered MAC, registering... */
+    dump_addr(&control_packet->source);
+    dump_printf(EL_CONT,"\n");
+
+    regdb_add(control_packet->source_addr, control_packet->source);
+    send_register_response(conn->sfd, control_packet,
+			   LE_STATUS_SUCCESS, 1);
+  } else {
+    if (memcmp(&tmp->atm_address,&control_packet->source_addr, 
+	       sizeof(AtmAddr_t)) != 0) {
+      Debug_unit(&conn_unit, "MAC Address is bound to another ATM address");
+      send_register_response(conn->sfd, control_packet,
+			     LE_STATUS_DUPLICATE_REG, 1);
+    } else {
+      Debug_unit(&conn_unit,"Duplicate registeration");
+      send_register_response(conn->sfd, control_packet,
+			     LE_STATUS_SUCCESS, 1);
+    }
+  }
+  return 1;
+}
+
+static int
+unregister_req(const Conn_t *conn)
+{
+  Reg_t *tmp;
+  Lecdb_t *ltmp;
+
+  Debug_unit(&conn_unit, "Unregister_req called");
+  dump_conn(conn);
+  assert(control_packet != NULL);
+
+  /* Reject attempt to unregister multicast & broadcast address */
+
+  if (is_multicast(&control_packet->source)) {
+    send_register_response(conn->sfd, control_packet,
+			   LE_STATUS_BAD_DEST, 0);
+    return 1;
+  }
+  ltmp = leciddb_find(control_packet->lecid);
+  if (!ltmp) {
+    send_register_response(conn->sfd, control_packet,
+			   LE_STATUS_BAD_LECID, 0);
+    return 1;
+  }
+  tmp = regdb_find_mac(control_packet->source);
+  
+  if (tmp && (memcmp(&tmp->atm_address, &control_packet->source_addr, 
+		     sizeof(AtmAddr_t)) == 0)) {
+    /* Removing registered MAC adress */
+    regdb_remove(tmp->atm_address);
+    send_register_response(conn->sfd, control_packet,
+			   LE_STATUS_SUCCESS, 0);
+    return 1;
+  } else if (tmp) {
+    /* MAC was registered by another client */
+    send_register_response(conn->sfd, control_packet,
+			   LE_STATUS_BAD_DEST, 0);
+    return 1;
+  } 
+  /* MAC was not registered earlier */
+  send_register_response(conn->sfd, control_packet,
+			 LE_STATUS_SUCCESS, 0);
+  return 1;
+}
+
+static int
+arp_find(const Conn_t *conn)
+{
+  Reg_t *tmp;
+  Lecdb_t *ltmp;
+  
+  Debug_unit(&conn_unit, "Arp_find called");
+  dump_conn(conn);
+
+  Debug_unit(&conn_unit,"Arping for:");
+  dump_addr(&control_packet->target);
+  dump_printf(EL_CONT,"\n");
+
+  /* If requested multicast /broadcast address, respond with BUS address */
+  if (is_multicast(&control_packet->target)) {
+    tmp = mem_alloc(&conn_unit, sizeof(Reg_t));
+    memcpy(&tmp->atm_address, get_var_addr(&conn_unit, "S6"), 
+	   sizeof(AtmAddr_t));
+    Debug_unit(&conn_unit,"Arp for multicast address");
+    send_arp_response(conn->sfd, control_packet,
+		      LE_STATUS_SUCCESS, tmp);
+    return 1;
+  }
+
+  /* Check lecid */
+  ltmp = leciddb_find(control_packet->lecid);
+  if (!ltmp) {
+    send_arp_response(conn->sfd, control_packet,
+		      LE_STATUS_BAD_LECID, NULL);
+    return 1;
+  }
+  tmp = regdb_find_mac(control_packet->target);
+  if (tmp) {
+    Debug_unit(&conn_unit,"Address in databases");
+    /* Send response */
+    send_arp_response(conn->sfd, control_packet,
+		      LE_STATUS_SUCCESS,
+		      tmp);
+    return 1;
+  }
+  forward_arp_request(control_packet, proxylist);
+  return 1;
+}
+
+static int
+arp_forward_response(const Conn_t *conn)
+{
+  int a;
+  Conn_t *tmp;
+
+  Debug_unit(&conn_unit,"Arp forward response called");
+  dump_conn(conn);
+  /* We got response. Forward it to all */
+
+  for (tmp = connlist;tmp;tmp=tmp->next) {
+    if (tmp->sfd) {
+      a = send_control_frame(tmp->sfd, control_packet);
+      if (a == 0)
+	dump_error(&conn_unit, "Forward arp response write failed");
+    }
+  }
+  return 1;
+}
+
+static int
+forward_flush_response(const Conn_t *conn)
+{
+  int a;
+
+  Debug_unit(&conn_unit, "Forward_flush_response called");
+  dump_conn(conn);
+  for (conn = connlist; conn; conn=conn->next) {
+    if (conn->sfd) {
+      a = send_control_frame(conn->sfd, control_packet);
+      if (a == 0)
+	dump_error(&conn_unit, "Forward flush response failed");
+    }
+  } 
+  return 1;
+}
+
+static int
+topology_request(const Conn_t *conn)
+{
+  int a;
+
+  Debug_unit(&conn_unit, "Topology request called");
+  dump_conn(conn);
+
+  for(conn=connlist;conn;conn=conn->next) {
+    if (conn->sfd) {
+      a = send_control_frame(conn->sfd, control_packet);
+      if (a == 0)
+	dump_error(&conn_unit, "Topology request send failed");
+    }
+  }
+  return 1;
+}
diff -ur --new-file old/atm/lane/connect.h new/atm/lane/connect.h
--- old/atm/lane/connect.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/connect.h	Thu Aug  8 23:22:42 1996
@@ -0,0 +1,94 @@
+/*
+ * Connection management
+ *
+ * $Id: connect.h,v 1.11 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+#ifndef LANE_CONN_H
+#define LANE_CONN_H
+
+/* System includes needed for types */
+
+/* Local includes needed for types */
+#include "units.h"
+#include "lane.h"
+#include "timers.h"
+#include "load.h"
+#include "events.h"
+
+/* Type definitions */
+typedef enum {
+  CT_NONE, CT_MAIN, CT_PVC_CD, CT_PVC_DD, CT_SVC_CD, CT_SVC_DD, CT_BUS_CD
+} ConnType_t;
+
+typedef enum {
+  CS_IDLE, CS_JOINING, CS_OPERATIONAL
+} ConnState_t;
+
+#define CS_MAX CS_OPERATIONAL
+
+/* State vector SV */
+typedef struct _Conn_t {
+  int fd; /* Where we receive data */
+  int sfd; /* Where we send data */
+  int active_fd; /* Where select() said thingies are coming. BAD BAD way */
+  ConnState_t state;
+  LecId_t lecid;
+  ConnType_t type;
+  Bool_t proxy;
+  Timer_t *timer;
+  struct _Conn_t *next;
+} Conn_t;
+
+/* LECID -DB */
+typedef struct _Lecidb_t {
+  int fd;
+  AtmAddr_t address;
+  LecId_t lecid;
+  struct _Lecidb_t *next;
+} Lecdb_t;
+
+/* PROXY-DB */
+typedef struct _Proxy_t {
+  LecId_t lecid;
+  int fd;
+  struct _Proxy_t *next;
+} Proxy_t;
+
+/* REG-DB */
+typedef struct _Reg_t {
+  LaneDestination_t mac_address;
+  AtmAddr_t atm_address;
+  struct _Reg_t *next;
+} Reg_t;
+  
+/* Connection state machine */
+typedef struct {
+  EventType_t event;
+  unsigned short opcode;
+  const char *descript;
+  int (*func)(const Conn_t *conn);
+  ConnState_t nextstate;
+} State_t;
+
+/* Global function prototypes */
+void dump_conn(const Conn_t *connection);
+Conn_t *conn_add(ConnType_t type, int fd, LecId_t pvc_lecid);
+void conn_remove(const Conn_t *connection);
+ConnState_t call_state(EventType_t event, unsigned short opcode, Conn_t *conn);
+const char *dump_conn_state(ConnState_t state);
+const Conn_t* new_svc(const int fd);
+int delete_svc(const int fd, Conn_t *conn);
+void conn_set_active(void *data, int fd);
+
+/* Global data */
+extern const Unit_t conn_unit;
+
+/* Default values for S2-S5 */
+#define S2_default "unspecified"
+#define S3_default 1520
+#define S4_default 6
+#define S5_default 6
+
+#endif
+
diff -ur --new-file old/atm/lane/connect_bus.c new/atm/lane/connect_bus.c
--- old/atm/lane/connect_bus.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/connect_bus.c	Thu Aug  8 23:21:37 1996
@@ -0,0 +1,441 @@
+/*
+ * ATM connection wrapper
+ *
+ * $Id: connect_bus.c,v 1.1 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+
+/* System includes */
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <errno.h>
+
+/* Local includes */
+#include "mem.h"
+#include "lane.h"
+#include "dump.h"
+#include "load.h"
+#include "connect.h"
+#include "events.h"
+#include "atm.h"
+
+/* Type definitions */
+
+/* Local function prototypes */
+static void conn_init0(void);
+static void conn_init1(void);
+static void conn_dump(void);
+static void conn_release(void);
+static const char *dump_conn_type(ConnType_t type);
+
+static int data_handler(const Event_t *event, void *funcdata);
+static void conn_main(void);
+
+static int join(const Conn_t *conn);
+static int idle_bad(const Conn_t *conn);
+
+static int data_forward(const Conn_t *conn);
+static int join_close(const Conn_t *conn);
+
+/* Data */
+#define BUFSIZE 20000
+
+const Unit_t conn_unit = {
+  "conn",
+  &conn_init0,
+  &conn_init1,
+  &conn_dump,
+  &conn_release
+};
+
+static Conn_t *connlist;
+
+unsigned char *data_packet;
+unsigned int data_packet_size;
+
+static const char *rcsid = "$Id: connect_bus.c,v 1.1 1995/11/15 08:27:11 carnil Exp $";
+
+static State_t
+  /* CS_IDLE */
+  is_1 = { CE_SVC_OPEN, 0,  "Idle->Oper", join, CS_OPERATIONAL },
+  is_2 = { CE_SVC_OPEN, 0, "Idle->Idle", idle_bad, CS_IDLE },
+  *idle_state[] = { &is_1, &is_2, NULL },
+
+  /* CS_OPERATIONAL */
+  os_1 = { CE_DATA, 0, "Oper->Oper", data_forward, CS_OPERATIONAL },
+/*  os_2 = { CE_DATA, LE_FLUSH_REQUEST, "Active->Active", flush_request,
+	     CS_ACTIVE }, */
+  os_3 = { CE_SVC_CLOSE, 0, "Oper->Idle", join_close, CS_IDLE },
+  *operational_state[] = { &os_1, /*&as_2,*/ &os_3, NULL },
+
+  **transitions[CS_MAX + 1] = {
+    idle_state, NULL, operational_state
+  };
+
+extern int errno;
+
+/* Functions */
+
+/* Initialize local data */
+static void
+conn_init0(void)
+{
+  connlist = NULL;
+}
+
+/* Initialization for data that needs other units */
+static void
+conn_init1(void)
+{
+  set_var_str(&conn_unit, "version", rcsid);
+  conn_main();
+  add_event_handler(CE_DATA, &data_handler, "data_handler", NULL);
+  Debug_unit(&conn_unit, "Initialized.");
+}
+
+/* Dump status, local data etc. */
+static void
+conn_dump(void)
+{
+  const char *tmp;
+  const AtmAddr_t *addr;
+
+  Debug_unit(&conn_unit, "Dumping unit");
+  Debug_unit(&conn_unit, "Parameters:");
+  addr = get_var_addr(&conn_unit, "S1");
+  if (addr != NULL) {
+    Debug_unit(&conn_unit, "S1:");
+    dump_atmaddr(addr);
+  }
+  else {
+    Debug_unit(&conn_unit, "S1: not set");
+  }
+  tmp = get_var_str(&conn_unit, "S2");
+  if (tmp != NULL) {
+    Debug_unit(&conn_unit, "S2: %s", tmp);
+  }
+  else {
+    Debug_unit(&conn_unit, "S2: not set", tmp);
+  }
+  Debug_unit(&conn_unit, "S3: %d", get_var_int(&conn_unit, "S3"));
+  Debug_unit(&conn_unit, "S4: %d", get_var_int(&conn_unit, "S4"));
+  Debug_unit(&conn_unit, "S5: %d", get_var_int(&conn_unit, "S5"));
+  addr = get_var_addr(&conn_unit, "S6");
+  if (addr != NULL) {
+    Debug_unit(&conn_unit, "S6:");
+    dump_atmaddr(addr);
+  }
+  else {
+    Debug_unit(&conn_unit, "S6: not set");
+  }
+  dump_conn(NULL);
+}
+
+/* Release allocated memory, close files etc. */
+static void
+conn_release(void)
+{
+  Conn_t *tmp;
+  
+  Debug_unit(&conn_unit, "Releasing unit");
+  
+  for(tmp = connlist; tmp != NULL; tmp = tmp->next) {
+    connlist = tmp->next;
+    if (tmp->fd)
+      close(tmp->fd);
+    if (tmp->sfd)
+      close(tmp->sfd);
+    mem_free(&conn_unit, tmp);
+  }
+}
+
+/*
+ * Handle data arrival
+ * data points to Conn_t
+ */
+static int
+data_handler(const Event_t *event, void *funcdata)
+{
+  Conn_t *tmp, *newconn;
+  int fd, nbytes;
+  static char buffer[BUFSIZE];
+  struct sockaddr_atmsvc addr;
+
+  assert(event->data != NULL);
+  tmp = (Conn_t *)event->data;
+  dump_conn(tmp);
+  if (tmp->type == CT_MAIN) {
+    nbytes = sizeof(addr);
+    memset(&addr, 0,nbytes);
+    fd = accept(tmp->fd, (struct sockaddr *)&addr, &nbytes);
+    if (fd <0) {
+      dump_error(&conn_unit, "accept");
+      if (errno == ENETRESET) { /* Switch reseted? */
+	Debug_unit(&conn_unit,"Restart. Sleeping 10 secs...");
+	sleep(10);
+	event_put(&conn_unit, CE_RESTART, NULL);
+      } else if (errno == EUNATCH) { /* Probably signalling daemon was abruptly killed */
+	Debug_unit(&conn_unit,"Exiting...");
+	event_put(&conn_unit, CE_EXIT, NULL);
+      }
+      return -1;
+    }
+    newconn = conn_add(CT_SVC_CD, fd, 0);
+    newconn->state = call_state(CE_SVC_OPEN, 0, newconn);
+  }
+  else {
+    nbytes = read(tmp->active_fd, buffer, BUFSIZE);
+    if (nbytes < 0) {
+      dump_error(&conn_unit, "read");
+      if (errno == EUNATCH)
+	event_put(&conn_unit, CE_EXIT, NULL);
+      if (errno == ENETRESET) {
+	Debug_unit(&conn_unit, "Restart. Sleeping 10 secs...");
+	sleep(10);
+	event_put(&conn_unit, CE_RESTART, NULL);
+      }
+    } else if (nbytes == 0) {
+      /* EOF */
+      Debug_unit(&conn_unit, "EOF");
+      tmp->state = call_state(CE_SVC_CLOSE, 0, tmp);
+    } else {
+      buffer[nbytes] = '\0';
+      data_packet = (unsigned char *)buffer;
+      data_packet_size=nbytes;
+      tmp->state = call_state(CE_DATA, 0, tmp);
+    }
+  }
+  mem_free(&conn_unit, event);
+  return 1;
+}
+
+static const char *
+dump_conn_type(ConnType_t type)
+{
+  switch(type) {
+  case CT_NONE: return "None";
+  case CT_MAIN: return "Main listener";
+  case CT_PVC_CD: return "PVC Control Direct";
+  case CT_PVC_DD: return "PVC Data Direct";
+  case CT_SVC_CD: return "SVC Control Direct";
+  case CT_SVC_DD: return "SVC Data Direct";
+  default: return "Bad type";
+  }
+}
+
+void
+dump_conn(const Conn_t *connection)
+{
+  Conn_t *tmp;
+  
+  for(tmp = connlist; tmp != NULL; tmp = tmp->next) {
+    if (connection == NULL || tmp == connection) {
+      Debug_unit(&conn_unit, "fd %d sfd %d state %s type %s", tmp->fd, tmp->sfd, dump_conn_state(tmp->state), dump_conn_type(tmp->type));
+    }
+  }
+}
+
+Conn_t *
+conn_add(ConnType_t type, int fd, LecId_t dumb)
+{
+  Conn_t *tmp;
+
+  tmp = (Conn_t *)mem_alloc(&conn_unit, sizeof(Conn_t));
+  tmp->fd = fd;
+  tmp->sfd = 0;
+  tmp->state = CS_IDLE;
+  tmp->type = type;
+  tmp->next = connlist;
+  connlist = tmp;
+
+  event_add_fd(fd, tmp);
+  return tmp;
+}
+
+void
+conn_remove(const Conn_t *connection)
+{
+  Conn_t *tmp, *prev;
+
+  assert(connection != NULL);
+  prev = NULL;
+  tmp = connlist;
+  while(tmp) {
+    if (tmp == connection) {
+      if (prev != NULL) {
+	prev->next = tmp->next;
+      } else {
+	connlist = tmp->next;
+      }
+      if (connection->fd) {
+	close(connection->fd);
+	event_remove_fd(connection->fd);
+      }
+      if (connection->sfd) {
+	close(connection->sfd);
+	event_remove_fd(connection->sfd);
+      }
+      mem_free(&conn_unit, tmp);
+      return;
+    }
+    prev = tmp;
+    tmp = tmp->next;
+  }
+}
+
+void
+conn_set_active(void *data, int fd)
+{
+  Conn_t *tmp = (Conn_t *)data;
+
+  assert(tmp);
+  tmp->active_fd = fd;
+}
+
+static void
+conn_main(void)
+{
+  const AtmAddr_t *addr;
+  int main_conn;
+
+  addr = get_var_addr(&conn_unit, "S6");
+  if (addr == NULL) {
+    dump_printf(EL_ERROR, "S6 (BUS Address) must be specified");
+    event_put(&conn_unit, CE_EXIT, NULL);
+  } else {
+    main_conn = atm_create_socket(MULTICAST_SEND_802_3,
+				  get_var_addr(&conn_unit, "S6"));
+    if (main_conn >= 0) {
+      (void)conn_add(CT_MAIN, main_conn, 0);
+    }
+  }
+}
+
+ConnState_t
+call_state(EventType_t event, unsigned short opcode, Conn_t *conn)
+{
+  State_t **tmp;
+  unsigned int i = 0;
+  int ret;
+
+  Debug_unit(&conn_unit, "Call state");
+  assert(conn != NULL);
+  assert(conn->state <= CS_MAX);
+  tmp = transitions[conn->state];
+
+  for(; tmp[i] != NULL; i++) {
+    if (tmp[i]->event == event && tmp[i]->opcode == opcode) {
+      Debug_unit(&conn_unit, "Trying func %s", tmp[i]->descript);
+      ret = tmp[i]->func(conn);
+      if (ret != 0){
+	Debug_unit(&conn_unit, "Success");
+	return tmp[i]->nextstate;
+      }
+      else {
+	Debug_unit(&conn_unit, "Failed");
+      }
+    }
+    else {
+      Debug_unit(&conn_unit, "Skipping func %s", tmp[i]->descript);
+    }
+  }
+  return conn->state;
+}
+
+const char *
+dump_conn_state(ConnState_t state)
+{
+  switch(state) {
+  case CS_IDLE: return "Idle";
+  case CS_JOINING: return "Joining";
+  case CS_OPERATIONAL: return "Operational";
+  default: return "Bad state";
+  }
+}
+
+/*
+ * State transition functions
+ */
+static int
+join(const Conn_t *conn)
+{
+  int rfd;
+
+  Debug_unit(&conn_unit, "Join called");
+  dump_conn(conn);
+
+  rfd = atm_connect_back(get_var_addr(&conn_unit,"S6"),
+			 conn, MULTICAST_FORWARD_802_3);
+  if (rfd<0) { /* Calling back failed */
+    conn_remove(conn);
+    return 0;
+  } else { /* Success */
+    Debug_unit(&conn_unit, "Join successful");
+    conn->sfd = rfd;
+    event_add_fd(rfd, conn);
+    return 1;
+  }
+}
+
+static int
+idle_bad(const Conn_t *conn)
+{
+  Debug_unit(&conn_unit,"Idle_bad called");
+  dump_conn(conn);
+  conn_remove(conn);
+  return 1;
+}
+
+static int
+data_forward(const Conn_t *conn)
+{
+  Conn_t *tmp;
+  char packet_string[1024];
+  int rvalue;
+  int i;
+
+  Debug_unit(&conn_unit,"Data forward called");
+  dump_conn(conn);
+
+  for(tmp = connlist;tmp!=NULL;tmp=tmp->next) {
+    if (tmp->sfd >0 && tmp->type != CT_MAIN) {
+      rvalue=write(tmp->sfd, data_packet, data_packet_size);
+      if (rvalue<0) {
+	dump_error(&conn_unit, "data_forward,write");
+	dump_conn(tmp);
+      } else
+	Debug_unit(&conn_unit,"Forwarding to %d-%d bytes",tmp->sfd,
+		   data_packet_size);
+    }
+  }
+  Debug_unit(&conn_unit,"Sent packet :%ld bytes",data_packet_size);
+  for (i=0;i<data_packet_size && i < 83;i++) {
+    sprintf(&packet_string[3*i],"%2.2x ",0xff&data_packet[i]);
+  }
+  if (i==data_packet_size)
+    Debug_unit(&conn_unit,"Packet:->%s<-",packet_string);
+  else
+    Debug_unit(&conn_unit,"Packet:->%s->",packet_string);
+  Debug_unit(&conn_unit,"Returning from data forward");
+  return 1;
+}
+
+static int
+join_close(const Conn_t *conn)
+{
+
+  Debug_unit(&conn_unit,"Join_close called");
+
+  dump_conn(conn);
+  conn_remove(conn);
+  return 1;
+}
+
diff -ur --new-file old/atm/lane/db.c new/atm/lane/db.c
--- old/atm/lane/db.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/db.c	Thu Aug  8 23:23:02 1996
@@ -0,0 +1,266 @@
+/*
+ * Database handling functions
+ *
+ * $Id: db.c,v 1.3 1995/07/02 18:08:25 carnil Exp $
+ *
+ */
+
+/* System includes */
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/* Local includes */
+#include "mem.h"
+#include "lane.h"
+#include "dump.h"
+#include "load.h"
+#include "connect.h"
+#include "events.h"
+#include "db.h"
+
+Reg_t *reglist;
+
+Proxy_t *proxylist;
+
+Lecdb_t *leclist;
+
+/* Protos */
+
+/* Adds entry to PROXY-DB */
+void 
+proxydb_add(const Conn_t *conn, int fd)
+{
+  Proxy_t *tmp;
+
+  assert(conn != NULL);
+
+  Debug_unit(&conn_unit,"Proxydb_add");
+  tmp = (Proxy_t *) mem_alloc(&conn_unit, sizeof(Proxy_t));
+  tmp->lecid = conn->lecid;
+  tmp->fd = fd;
+  tmp->next = proxylist;
+  proxylist = tmp;
+  return;
+}
+
+/* Removes entry from PROXY-DB */
+int 
+proxydb_remove(const Conn_t *conn)
+{
+  Proxy_t *tmp, *tmp2;
+  
+  Debug_unit(&conn_unit,"Proxydb_remove");
+  if (proxylist == NULL) {
+    return 0;
+  }
+  
+  tmp = proxylist;
+  if (conn->lecid == tmp->lecid) {
+    proxylist =tmp->next;
+    mem_free(&conn_unit, tmp);
+    return 1;
+  }
+  tmp2 = tmp;
+  tmp = tmp->next;
+  
+  while(tmp) {
+    if (conn->lecid == tmp->lecid) {
+      tmp2->next = tmp->next;
+      mem_free(&conn_unit, tmp);
+      return 1;
+    }
+    tmp = tmp->next;
+  }
+  dump_error(&conn_unit,"Trying to remove unexisting entry from PROXY-DB");
+  return 0;
+}
+
+Proxy_t*
+proxydb_find(LecId_t to_find)
+{
+  Proxy_t *tmp;
+
+  tmp = proxylist;
+  while(tmp) {
+    if (to_find == tmp->lecid) {
+      Debug_unit(&conn_unit, "Proxy_t found");
+      return tmp;
+    }
+    tmp = tmp->next;
+  }
+  Debug_unit(&conn_unit,"Proxy_t not found from database");
+  return NULL;
+}
+
+/* Adds entry to LECID-DB */
+void 
+leciddb_add(LecId_t lecid, AtmAddr_t address, const int fd)
+{
+  Lecdb_t *tmp;
+
+  Debug_unit(&conn_unit, "Leciddb_add called");
+  tmp = (Lecdb_t *) mem_alloc(&conn_unit, sizeof(Lecdb_t));
+  tmp->fd = fd;
+  memcpy(&tmp->address, &address, sizeof(AtmAddr_t));
+  tmp->lecid = lecid;
+  tmp->next = leclist;
+  leclist = tmp;
+  return;
+}
+
+int leciddb_remove(LecId_t to_remove)
+{
+  Lecdb_t *tmp, *tmp2;
+
+  Debug_unit(&conn_unit,"Leciddb_remove");
+  if (leclist == NULL) {
+    return 0;
+  }
+
+  tmp = leclist;
+  if (to_remove == tmp->lecid) {
+    leclist =tmp->next;
+    mem_free(&conn_unit, tmp);
+    return 1;
+  }
+  tmp2 = tmp;
+  tmp = tmp->next;
+  
+  while(tmp) {
+    if (to_remove == tmp->lecid) {
+      tmp2->next = tmp->next;
+      mem_free(&conn_unit, tmp);
+      return 1;
+    }
+    tmp = tmp->next;
+  }
+  dump_error(&conn_unit,"Trying to remove unexisting entry from LECID-DB");
+  return 0;
+}
+
+/* Searches LECID-DB for entry */
+Lecdb_t *leciddb_find(LecId_t to_find)
+{
+  Lecdb_t *tmp;
+
+  tmp = leclist;
+  while(tmp) {
+    if (to_find == tmp->lecid) {
+      Debug_unit(&conn_unit, "Lecdb_t found");
+      return tmp;
+    }
+    tmp = tmp->next;
+  }
+  Debug_unit(&conn_unit,"Lecdb_t not found from database");
+  return NULL;
+}
+
+Lecdb_t *leciddb_find_atm(AtmAddr_t to_find)
+{
+  Lecdb_t *tmp;
+  
+  tmp = leclist;
+  while (tmp) {
+    if (memcmp(&to_find,&(tmp->address), sizeof(AtmAddr_t)) == 0) {
+      Debug_unit(&conn_unit, "Lecdb_t found");
+      return tmp;
+    }
+    tmp= tmp->next;    
+  }
+  Debug_unit(&conn_unit,"Lecid_t not found from database");
+  return NULL;
+}
+
+/* Adds entry to REG-DB */
+void regdb_add(AtmAddr_t aaddr, LaneDestination_t maddr)
+{
+  Reg_t *tmp;
+  
+  Debug_unit(&conn_unit,"Regdb_add");
+  tmp = (Reg_t *)mem_alloc(&conn_unit, sizeof(Reg_t));
+  memcpy(&tmp->mac_address, &maddr,sizeof(LaneDestination_t));
+  memcpy(&tmp->atm_address, &aaddr, sizeof(AtmAddr_t));
+  tmp->next = reglist;
+  reglist = tmp;
+  return;
+}
+
+/* Removes entry from REG-DB.
+   Returns 0 if entry is not found. 1 otherwise.
+*/
+int 
+regdb_remove(AtmAddr_t to_remove)
+{
+  Reg_t *tmp, *tmp2;
+
+  Debug_unit(&conn_unit,"Regdb_remove");
+  if (reglist == NULL) {
+    return 0;
+  }
+
+  tmp = reglist;
+  if (memcmp((char *)&to_remove, (char *)&tmp->atm_address, 
+	      sizeof(AtmAddr_t)) == 0) {
+    reglist =tmp->next;
+    mem_free(&conn_unit, tmp);
+    return 1;
+  }
+  tmp2 = tmp;
+  tmp = tmp->next;
+  
+  while(tmp) {
+    if (memcmp((char *)&to_remove, (char *)&tmp->atm_address, 
+		sizeof(AtmAddr_t)) == 0) {
+      tmp2->next = tmp->next;
+      mem_free(&conn_unit, tmp);
+      return 1;
+    }
+    tmp = tmp->next;
+  }
+  dump_error(&conn_unit,"Trying to remove unexisting entry from REG-DB");
+  return 0;
+}
+
+/* Finds entry from REG_DB by comparing mac address */
+Reg_t*
+regdb_find_mac(LaneDestination_t maddr)
+{
+  Reg_t *tmp;
+
+  tmp = reglist;
+  while (tmp) {
+
+    if((tmp->mac_address).tag == htons(LANE_DEST_MAC)) {
+      if (memcmp((char *)&(tmp->mac_address).a_r.mac_address, 
+		 (char *)&maddr.a_r.mac_address, 6) ==0) {
+	Debug_unit(&conn_unit, "MAC found from database");
+	return tmp;
+      }
+    }
+    else if ((tmp->mac_address).tag == htons(LANE_DEST_RD))
+      if (memcmp((char *)&(tmp->mac_address.a_r.route),
+		  (char *)&maddr.a_r.route, 
+		  4 + sizeof(unsigned short)) == 0) {
+	Debug_unit(&conn_unit, "MAC found from database");
+	return tmp;
+      }
+      else if (memcmp((char *)&(tmp->mac_address),
+		       (char *)&maddr, 
+		       sizeof(LaneDestination_t)) == 0) {
+	Debug_unit(&conn_unit, "MAC found from database");
+      return tmp;
+    }
+    tmp = tmp->next;
+  }
+  Debug_unit(&conn_unit, "MAC address not found from database");
+  return NULL;
+}
+
+
diff -ur --new-file old/atm/lane/db.h new/atm/lane/db.h
--- old/atm/lane/db.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/db.h	Thu Aug  8 23:23:11 1996
@@ -0,0 +1,25 @@
+/*
+ * Database handling functions
+ *
+ * $Id: db.h,v 1.3 1995/07/02 18:09:40 carnil Exp $
+ *
+ */
+#include <sys/types.h>
+
+#include "lane.h"
+#include "connect.h"
+
+/* Protos */
+void regdb_add(AtmAddr_t aaddr, LaneDestination_t maddr);
+int regdb_remove(AtmAddr_t to_remove);
+Reg_t *regdb_find_mac(LaneDestination_t maddr);
+
+void proxydb_add(const Conn_t *conn, int fd);
+int proxydb_remove(const Conn_t *conn);
+Proxy_t *proxydb_find(LecId_t to_find);
+
+Lecdb_t *leciddb_find(LecId_t to_find);
+Lecdb_t *leciddb_find_atm(AtmAddr_t to_find);
+void leciddb_add(LecId_t lecid, AtmAddr_t address, const int fd);
+int leciddb_remove(LecId_t to_remove);
+
diff -ur --new-file old/atm/lane/dump.c new/atm/lane/dump.c
--- old/atm/lane/dump.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/dump.c	Thu Aug  8 23:21:56 1996
@@ -0,0 +1,450 @@
+/*
+ * Debug packet dumper
+ *
+ * $Id: dump.c,v 1.16 1995/07/02 19:29:17 carnil Exp $
+ *
+ */
+
+/* System includes */
+#include <stdarg.h>
+#include <stdio.h>
+#include <assert.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h>
+
+#include <linux/atm.h>
+#include <linux/atmsap.h>
+
+/* Local includes */
+#include "dump.h"
+#include "lane.h"
+#include "load.h"
+#include "units.h"
+
+/* Local function prototypes */
+static void dump_init0(void);
+static void dump_init1(void);
+static void dump_dump(void);
+static void dump_release(void);
+
+/* Data */
+#define BUFSIZE 256
+
+static const char *rcsid = "$Id: dump.c,v 1.16 1995/07/02 19:29:17 carnil Exp $";
+
+const Unit_t dump_unit = {
+  "dump",
+  &dump_init0,
+  &dump_init1,
+  &dump_dump,
+  &dump_release
+};
+
+DumpType_t dump_type;
+static DumpType_t dump_open;
+
+static FILE *dump_filep;
+static const char *dump_filename = "/tmp/lane.log";
+static const char *dump_console = "/dev/console";
+
+/* Functions */
+static const char* dump_opcode_text(unsigned short opcode);
+static const char* dump_status_text(unsigned short status);
+static char* dump_maxframe(unsigned char size);
+static char* dump_lantype(unsigned char lantype);
+static void dump_atmtext(const AtmAddr_t addr);
+
+/* Initialize local data */
+static void
+dump_init0(void)
+{
+  dump_filep = NULL;
+  dump_open = dump_type;
+
+  switch (dump_open) {
+  case DT_NONE:
+  case DT_CMN_ERR:
+    break;
+  case DT_STDERR:
+    dump_filep = stderr;
+    break;
+  case DT_FILE:
+    dump_filep = fopen(dump_filename, "a");
+    if (dump_filep == NULL) {
+      dump_open = DT_STDERR;
+      dump_filep = stderr;
+      dump_printf(EL_WARN, "Cannot open log file %s", dump_filename);
+    }
+    break;
+  case DT_SYSLOG:
+    openlog("lane", LOG_PID | LOG_CONS, LOG_DAEMON);
+    break;
+  case DT_CONSOLE:
+    dump_filep = fopen(dump_console, "w");
+    if (dump_filep == NULL) {
+      dump_open = DT_STDERR;
+      dump_filep = stderr;
+      dump_printf(EL_WARN, "Cannot open console log");
+    }
+    break;
+  }
+  dump_printf(EL_DEBUG, "Log opened");
+}
+
+/* Initialization for data that needs other units */
+static void
+dump_init1(void)
+{
+  set_var_str(&dump_unit, "version", rcsid);
+  Debug_unit(&dump_unit, "Initialized.");
+}
+
+/* Dump status, local data etc. */
+static void
+dump_dump(void)
+{
+  static const char *dumptypes [] = {
+    "none", "standard error", "file", "syslog()", "cmn_err()", "/dev/console"
+  };
+
+  Debug_unit(&dump_unit, "Dumping to %s, filename: %s", dumptypes[dump_open],
+	     dump_filename);
+}
+
+/* Release allocated memory, close files etc. */
+static void
+dump_release(void)
+{
+  int flush_ret;
+
+  Debug_unit(&dump_unit, "Releasing unit");
+
+  dump_printf(EL_DEBUG, "Closing log file");
+
+  switch (dump_open) {
+  case DT_NONE:
+  case DT_CMN_ERR:
+    break;
+  case DT_STDERR:
+    flush_ret = fflush(stderr);
+    assert(flush_ret == 0);
+    break;
+  case DT_FILE:
+    if (fclose(dump_filep) != 0) {
+      dump_open = DT_STDERR;
+      dump_filep = stderr;
+      dump_printf(EL_WARN, "Cannot close log file %s", dump_filename);
+    }
+    break;
+  case DT_SYSLOG:
+    closelog();
+    break;
+  case DT_CONSOLE:
+      if (fclose(dump_filep) != 0) {
+      dump_open = DT_STDERR;
+      dump_filep = stderr;
+      dump_printf(EL_WARN, "Cannot close console log");
+    }
+    break;
+  }
+  dump_filep = NULL;
+  dump_open = DT_NONE;
+}
+
+static const int el_to_log[] = {
+  /* EL_CONT, EL_DEBUG, EL_NOTE, EL_WARN, EL_ERROR, EL_PANIC */
+  LOG_DEBUG, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, LOG_ERR, LOG_ALERT
+};
+
+static const char *el_prefix[] = {
+  /* EL_CONT, EL_DEBUG, EL_NOTE, EL_WARN, EL_ERROR, EL_PANIC */
+  "", "DEBUG: ", "NOTE: ", "WARNING: ", "ERROR: ", "PANIC: "
+};
+
+/* General printing function */
+void
+dump_printf(ErrorLevel_t level, const char *const format, ...)
+{
+  va_list args;
+  int printf_ret, flush_ret;
+  char buffer[BUFSIZE];
+
+  assert(level <= EL_PANIC);
+
+  switch (dump_open) {
+  case DT_CMN_ERR:
+  case DT_NONE:
+    return;
+  case DT_CONSOLE:
+  case DT_STDERR:
+  case DT_FILE:
+    va_start(args, format);
+    printf_ret = vsprintf(buffer, format, args);
+    assert(printf_ret > 0);
+    printf_ret = fprintf(dump_filep, "%s%s%s", el_prefix[level], buffer,
+			 level != EL_CONT? "\n" : "");
+    assert(printf_ret > 0);
+    va_end(args);
+    flush_ret = fflush(dump_filep);
+    assert(flush_ret == 0);
+    break;
+  case DT_SYSLOG:
+    va_start(args, format);
+    printf_ret = vsprintf(buffer, format, args);
+    assert(printf_ret > 0);
+    syslog(el_to_log[level], "%s", buffer);
+    va_end(args);
+    break;
+  }
+}
+
+/* Unit-specific debugging, can be enabled with variables */
+void
+Debug_unit(const Unit_t *unit, const char *const format, ...)
+{
+  va_list args;
+  char buffer[2048];
+  char buffer2[2048];
+  int sprintf_ret;
+
+#ifndef DEBUG
+  if (get_var_bool(unit, "debug") == BL_TRUE)  {
+#endif /* DEBUG */
+    sprintf_ret = sprintf(buffer, "%s: %s", unit->name, format);
+    assert(sprintf_ret > 0);
+
+    va_start(args, format);
+    sprintf_ret = vsprintf(buffer2, buffer, args);
+    assert(sprintf_ret > 0);
+    va_end(args);
+
+    dump_printf(EL_DEBUG, "%s", buffer2);
+#ifndef DEBUG
+  }
+#endif /* DEBUG */
+}
+
+void
+dump_error(const Unit_t *unit, const char *msg)
+{
+  Debug_unit(unit, "%s: %s", msg, strerror(errno));
+}
+
+
+/* Dumping functions, LANE address */
+void
+dump_addr(const LaneDestination_t *addr)
+{
+  assert(addr != NULL);
+  switch (ntohs(addr->tag)) {
+  case LANE_DEST_NP:
+    dump_printf(EL_CONT, "Not present");
+    break;
+    
+  case LANE_DEST_MAC:
+    dump_printf(EL_CONT, "MAC addr %2.2x.%2.2x.%2.2x.%2.2x.%2.2x.%2.2x",
+		addr->a_r.mac_address[0],addr->a_r.mac_address[1],
+		addr->a_r.mac_address[2],addr->a_r.mac_address[3],
+		addr->a_r.mac_address[4],addr->a_r.mac_address[5]
+		);
+    break;
+    
+  case LANE_DEST_RD:
+    dump_printf(EL_CONT, "Route Designator %4.4x", addr->a_r.route.designator);
+    break;
+  }
+}
+
+/* Dumping functions, ATM address */
+void
+dump_atmaddr(const AtmAddr_t *addr)
+{
+  int i;
+  char buffer[ATM_ADDR_LEN*3+2];
+
+  assert(addr != 0);
+
+  for (i = 0; i<ATM_ADDR_LEN; i++){
+    sprintf(&buffer[i*2], "%2.2x ", 0xff&(unsigned char)addr->addr[i]);
+  }
+
+  dump_printf(EL_DEBUG, "%s", buffer);
+}
+
+static void
+dump_atmtext(const AtmAddr_t addr)
+{
+  int i;
+  char buffer[ATM_ADDR_LEN*3+2];
+
+  for (i=0;i<ATM_ADDR_LEN;i++) {
+    sprintf(&buffer[i*2], "%2.2x ", 0xff&(unsigned char)addr.addr[i]);
+  }
+  dump_printf(EL_CONT, "%s", buffer);
+}
+
+/* Dumping functions, LANE control frame */
+static const char*
+dump_status_text(unsigned short status)
+{
+  switch (status) {
+  case LE_STATUS_SUCCESS :  return "Success";
+  case LE_STATUS_BAD_VERSION :  return "Version_Not_Supported";
+  case LE_STATUS_BAD_REQ :  return "Invalid_Parameters";
+  case LE_STATUS_DUPLICATE_REG :  return "Duplicate_LAN_Destination";
+  case LE_STATUS_DUPLICATE_ADDR :  return "Duplicate_ATM_Address";
+  case LE_STATUS_NO_RESOURCES :  return "Insufficient_Resources";
+  case LE_STATUS_NO_ACCESS :  return "Access_Denied";
+  case LE_STATUS_BAD_LECID :  return "Invalid_Request_ID";
+  case LE_STATUS_BAD_DEST :  return "Invalid_LAN_Destination";
+  case LE_STATUS_BAD_ADDR : return "Invalid_ATM_Address";
+  case LE_STATUS_NO_CONFIG : return "No_Configuration";
+  case LE_STATUS_CONFIG_ERROR : return "LE_Configuration_Error";
+  case LE_STATUS_NO_INFO : return "Insufficient_Information";
+  default : return "<Unknown Error Code>";
+  }
+}
+
+static const char*
+dump_opcode_text(unsigned short opcode)
+{
+  switch (opcode) {
+  case LE_CONFIGURE_REQUEST : return "LE_CONFIG_REQUEST";
+  case LE_CONFIGURE_RESPONSE : return "LE_CONFIG_RESPONSE";
+  case LE_JOIN_REQUEST : return "LE_JOIN_REQUEST";
+  case LE_JOIN_RESPONSE : return "LE_JOIN_RESPONSE";
+  case READY_QUERY : return "READY_QUERY";
+  case READY_IND : return "READY_INDICATION";
+  case LE_REGISTER_REQUEST : return "LE_REGISTER_REQUEST";
+  case LE_REGISTER_RESPONSE : return "LE_REGISTER_RESPONSE";
+  case LE_UNREGISTER_REQUEST : return "LE_UNREGISTER_REQUEST";
+  case LE_UNREGISTER_RESPONSE : return "LE_UNREGISTER_RESPONSE";
+  case LE_ARP_REQUEST : return "LE_ARP_REQUEST";
+  case LE_ARP_RESPONSE : return "LE_ARP_RESPONSE";
+  case LE_FLUSH_REQUEST : return "LE_FLUSH_REQUEST";
+  case LE_FLUSH_RESPONSE : return "LE_FLUSH_RESPONSE";
+  case LE_NARP_REQUEST : return "LE_NARP_REQUEST";
+  case LE_TOPOLOGY_REQUEST : return "LE_TOPOLOGY_REQUEST";
+  default :     return "<Unknown Opcode>";
+  }
+}
+
+static char*
+dump_lantype(unsigned char lantype)
+{
+  switch (lantype) {
+  case LE_LAN_TYPE_UNSPECIFIED:
+    return "Unspecified";
+  case LE_LAN_TYPE_802_3:
+    return "Ethernet/IEEE 802.3";
+  case LE_LAN_TYPE_802_5:
+    return "IEEE 802.5";
+  default:
+    return "<Unknown>";
+  }
+}
+
+static char*
+dump_maxframe(unsigned char size)
+{
+  switch (size) {
+  case LE_MAX_FRAME_UNSPECIFIED:
+    return "Unspecified";
+  case LE_MAX_FRAME_1516:
+    return "1516";
+  case LE_MAX_FRAME_4544:
+    return "4544";
+  case LE_MAX_FRAME_9234:
+    return "9234";
+  case LE_MAX_FRAME_18190:
+    return "18190";
+  default:
+    return "<Unknown>";
+  }
+}
+
+void
+dump_control(const LaneControl_t *c)
+{
+  dump_printf(EL_DEBUG, "\tMarker:\t0x%4.4hx\n\tProtocol:\t0x%2.2x\n\tVersion:\t0x%2.2x",
+	      ntohs(c->marker), c->protocol, c->version);
+  dump_printf(EL_CONT, "\tOpcode:\t\t%s\n\tStatus:\t\t%s\n\tTransactionID:\t0x%8.8x\n\t"
+	      "LECID:\t\t0x%4.4hx\n\tFlags:\t\t0x%4.4hx\n",
+	      dump_opcode_text(ntohs(c->opcode)), 
+	      dump_status_text(ntohs(c->status)),
+	      ntohl(c->transaction_id), ntohs(c->lecid), ntohs(c->flags));
+  switch(ntohs(c->opcode)) {
+  case LE_CONFIGURE_REQUEST:
+  case LE_CONFIGURE_RESPONSE:
+  case LE_JOIN_REQUEST:
+  case LE_JOIN_RESPONSE:
+    dump_printf(EL_CONT,"\tSource LAN:\t");
+    dump_addr(&c->source);
+    dump_printf(EL_CONT,"\n\tSource ATM:\t");
+    dump_atmtext(c->source_addr);
+    dump_printf(EL_CONT,"\n\tLan type:\t%s\n",dump_lantype(c->lan_type));
+    dump_printf(EL_CONT,"\tMax frame:\t%s\n",dump_maxframe(c->max_frame));
+    dump_printf(EL_CONT,"\tELAN name size:\t%d\n",c->elan_name_size);
+    if (c->elan_name_size>0) {
+      dump_printf(EL_CONT,"\nELAN name:\t%s\n",c->elan_name);
+    }
+    break;
+  case LE_ARP_REQUEST:
+  case LE_ARP_RESPONSE:
+    dump_printf(EL_CONT,"\tSource LAN:\t");
+    dump_addr(&c->source);
+    dump_printf(EL_CONT,"\n\tTarget LAN:\t");
+    dump_addr(&c->target);
+    dump_printf(EL_CONT,"\n\tSource ATM:\t");
+    dump_atmtext(c->source_addr);
+    dump_printf(EL_CONT,"\n\tTarget ATM:\t");
+    dump_atmtext(c->target_addr);
+    dump_printf(EL_CONT,"\n");
+    break;
+  case LE_FLUSH_REQUEST:
+  case LE_FLUSH_RESPONSE:
+    dump_printf(EL_CONT,"\tSource ATM:\t");
+    dump_atmtext(c->source_addr);
+    dump_printf(EL_CONT,"\n\tTarget ATM:\t");
+    dump_atmtext(c->target_addr);
+    dump_printf(EL_CONT,"\n");
+    break;
+  case LE_REGISTER_REQUEST:
+  case LE_REGISTER_RESPONSE:
+  case LE_UNREGISTER_REQUEST:
+  case LE_UNREGISTER_RESPONSE:
+    dump_printf(EL_CONT,"\tSource LAN:\t");
+    dump_addr(&c->source);
+    dump_printf(EL_CONT,"\n\tSource ATM:\t");
+    dump_atmtext(c->source_addr);
+    dump_printf(EL_CONT,"\n");
+    break;
+  }
+}
+
+void 
+disp_sockaddr(struct sockaddr_atmsvc *addr)
+{
+  int i;
+  dump_printf(EL_DEBUG,"Socket_address");
+  dump_printf(EL_CONT, "Sas_family:%d\n\tAddress:",addr->sas_family);
+  for(i=0;i<20;i++) {
+    dump_printf(EL_CONT,"%2.2x ",addr->sas_addr.prv[i]);
+  }
+  if (!addr->sas_addr.blli) {
+    dump_printf(EL_CONT,"No blli information\n");
+    fflush(stdout);
+  } else {
+    dump_printf(EL_CONT,"\nBlli:\n\t");
+    dump_printf(EL_CONT,"l2_proto:%d\n\t",addr->sas_addr.blli->l2_proto);
+    dump_printf(EL_CONT,"l3_proto:%d\n\t\t",addr->sas_addr.blli->l3_proto);
+    dump_printf(EL_CONT,"ipi:%x\tsnap:",addr->sas_addr.blli->l3.tr9577.ipi);
+    for(i=0;i<5;i++) {
+      dump_printf(EL_CONT,"%2.2x ",addr->sas_addr.blli->l3.tr9577.snap[i]);
+    }
+    dump_printf(EL_CONT,"\n");
+  }
+}
+
diff -ur --new-file old/atm/lane/dump.h new/atm/lane/dump.h
--- old/atm/lane/dump.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/dump.h	Thu Aug  8 23:23:24 1996
@@ -0,0 +1,47 @@
+/*
+ * Debug packet dumper
+ *
+ * $Id: dump.h,v 1.9 1994/11/29 13:29:49 asdf Exp $
+ *
+ */
+#ifndef LANE_DUMP_H
+#define LANE_DUMP_H
+
+/* System includes needed for types */
+#include <linux/atm.h>
+#include <linux/atmsap.h>
+
+/* Local includes needed for types */
+#include "units.h"
+#include "lane.h"
+
+/* Type definitions */
+/* Output destinations: no output, standard error, file, syslog() */
+typedef enum {
+  DT_NONE, DT_STDERR, DT_FILE, DT_SYSLOG, DT_CMN_ERR, DT_CONSOLE
+} DumpType_t;
+
+/* 
+ * Message type: continuation of another message, debug, notification only,
+ * warning, error, panic (causes abort())
+ */
+typedef enum {
+  EL_CONT, EL_DEBUG, EL_NOTE, EL_WARN, EL_ERROR, EL_PANIC
+} ErrorLevel_t;
+
+
+/* Global function prototypes */
+void dump_printf(ErrorLevel_t level, const char *const format, ...);
+void Debug_unit(const Unit_t *unit, const char *const format, ...);
+void dump_error(const Unit_t *unit, const char *msg);
+
+void dump_addr(const LaneDestination_t *addr);
+void dump_atmaddr(const AtmAddr_t *addr);
+void dump_control(const LaneControl_t *c);
+void disp_sockaddr(struct sockaddr_atmsvc *addr);
+
+/* Global data */
+extern const Unit_t dump_unit;
+extern DumpType_t dump_type;
+
+#endif
diff -ur --new-file old/atm/lane/events.c new/atm/lane/events.c
--- old/atm/lane/events.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/events.c	Thu Aug  8 23:23:42 1996
@@ -0,0 +1,383 @@
+/*
+ * Event handler
+ *
+ * $Id: events.c,v 1.16 1995/07/02 17:56:49 carnil Exp $
+ *
+ */
+
+
+/* System includes */
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+/* Local includes */
+#include "events.h"
+#include "load.h"
+#include "dump.h"
+#include "mem.h"
+#include "timers.h"
+#include "connect.h"
+
+/* Type definitions */
+typedef struct _EventList_t {
+  const Event_t *event;
+  struct _EventList_t *next;
+  struct _EventList_t *prev;
+} EventList_t;
+
+typedef struct _HFList_t {
+  const char *name;
+  HandlerFunc_t h;
+  void *funcdata;
+  struct _HFList_t *next;
+} HFList_t;
+
+typedef struct _FDList_t {
+  int fd;
+  void *data;
+  struct _FDList_t *next;
+} FDList_t;
+
+/* Local function prototypes */
+static void events_init0(void);
+static void events_init1(void);
+static void events_dump(void);
+static void events_release(void);
+static void event_get_fds(fd_set *dest);
+
+/* Data */
+static const char *rcsid="$Id: events.c,v 1.16 1995/07/02 17:56:49 carnil Exp $";
+
+const Unit_t events_unit = {
+  "events",
+  &events_init0,
+  &events_init1,
+  &events_dump,
+  &events_release
+};
+
+/*static mutex_t event_mutex;*/
+static EventList_t *eventhead, *eventtail;
+static HFList_t *handlers[CE_MAX + 1];
+static FDList_t *fdlist;
+
+/* Functions */
+
+/* Initialize local data */
+static void
+events_init0(void)
+{
+  unsigned int i;
+
+  eventhead = NULL;
+  eventtail = NULL;
+  for (i = 0; i <= CE_MAX; i++) {
+    handlers[i] = NULL;
+  }
+  fdlist = NULL;
+}
+
+/* Initialization for data that needs other units */
+static void
+events_init1(void)
+{
+  set_var_str(&events_unit, "version", rcsid);
+  Debug_unit(&events_unit, "Initialized.");
+}
+
+/* Dump status, local data etc. */
+static void
+events_dump(void)
+{
+  const EventList_t *tmp;
+  const HFList_t *htmp;
+  const FDList_t *ftmp;
+  unsigned int i;
+
+  for (tmp = eventhead; tmp != NULL; tmp = tmp->next) {
+    assert(tmp->event != NULL);
+    assert(tmp->event->unit != NULL);
+    assert(tmp->event->unit->name != NULL);
+    Debug_unit(&events_unit, "unit %s type %s data 0x%x", tmp->event->unit->name, dump_event_type(tmp->event->type), tmp->event->data);
+  }
+  for (i = 0; i <= CE_MAX; i++) {
+    for (htmp = handlers[i]; htmp != NULL; htmp = htmp->next) {
+      Debug_unit(&events_unit, "type %s func 0x%x name %s data 0x%x", dump_event_type(i), htmp->h, htmp->name, htmp->funcdata);
+    }
+  }
+  for (ftmp = fdlist; ftmp != NULL; ftmp = ftmp->next) {
+    Debug_unit(&events_unit, "polled fd %d", ftmp->fd);
+  }
+}
+
+/* Release allocated memory, close files etc. */
+static void
+events_release(void)
+{
+  unsigned int i;
+  HFList_t *htmp;
+  FDList_t *ftmp;
+  EventList_t *tmp;
+
+  /* Lock list */
+  for (tmp = eventhead; tmp != NULL; ) {
+    assert(eventhead->event != NULL);
+    assert(eventhead->event->unit != NULL);
+    assert(eventhead->event->unit->name != NULL);
+    Debug_unit(&events_unit, "discarding unread event, unit %s type %s data 0x%x", eventhead->event->unit->name, dump_event_type(eventhead->event->type), eventhead->event->data);
+    tmp = eventhead->next;
+    mem_free(&events_unit, eventhead->event);
+    mem_free(&events_unit, eventhead);
+    eventhead = tmp;
+  }
+  eventtail = NULL;
+  /* Unlock list */
+  for (i = 0; i <= CE_MAX; i++) {
+    for (htmp = handlers[i]; htmp != NULL; htmp = htmp->next) {
+      handlers[i] = htmp->next;
+      mem_free(&events_unit, htmp);
+    }
+  }
+  for (ftmp = fdlist; ftmp != NULL; ftmp = ftmp->next) {
+    printf("Closing:%d\n",ftmp->fd);
+    close(ftmp->fd);
+    fdlist = ftmp->next;
+    mem_free(&events_unit, ftmp);
+  }
+}
+
+void
+add_event_handler(EventType_t type, HandlerFunc_t func, const char *name, void *funcdata)
+{
+  HFList_t *tmp;
+
+  tmp = (HFList_t *)mem_alloc(&events_unit, sizeof(HFList_t));
+  tmp->name = name;
+  tmp->h = func;
+  tmp->funcdata = funcdata;
+  assert(type <= CE_MAX);
+  tmp->next = handlers[type];
+  
+  handlers[type] = tmp;
+}
+
+static const char *typetable[CE_MAX + 1] = {
+  "New SVC",
+  "SVC closed",
+  "Data arrived",
+  "Timer expired",
+  "Dump",
+  "Restart",
+  "Termination"
+};
+
+/* Return event type as string */
+const char *
+dump_event_type(EventType_t type)
+{
+  assert(type >= CE_SVC_CLOSE && type <= CE_MAX);
+  return typetable[type];
+}
+
+/* Get next event from queue */
+const Event_t *
+event_get_next(void)
+{
+  const Event_t *event = NULL;
+  EventList_t *tmplist;
+  const FDList_t *tmp;
+  int poll_ret;
+  Timer_t *soonest;
+  fd_set to_select;
+  struct timeval *rolex;
+
+  while (eventtail == NULL && sig_hup == 0 && 
+	 sig_usr1 == 0 && sig_alarm == 0 &&
+	 sig_usr2 == 0) {
+    /* No events waiting, sleep on select() or poll() */
+    if (fdlist != NULL) {
+      soonest = timer_find_soonest(&events_unit);
+      if (soonest != NULL) {
+	rolex = (struct timeval *)mem_alloc(&events_unit,
+					    sizeof(struct timeval));
+	rolex->tv_sec = soonest->alarm_time - time(NULL);
+	rolex->tv_usec = 0;
+	Debug_unit(&events_unit, "Sleeping %d s...", rolex->tv_sec);
+      }
+      else {
+	rolex = NULL;
+	Debug_unit(&events_unit, "Sleeping forever...");
+      }
+      event_get_fds(&to_select);
+      poll_ret = select(FD_SETSIZE, &to_select, NULL, NULL, rolex);
+      if (rolex)
+	mem_free(&events_unit,rolex);
+      Debug_unit(&events_unit, "Select: %d", poll_ret);
+      switch (poll_ret) {
+      case -1:
+	/* Error occurred */
+	dump_error(&events_unit, "select");
+	break;
+      case 0:
+	/* Timeout */
+	timer_ack(&events_unit, soonest);
+	event_put(&events_unit, CE_TIMER, soonest->data);
+	break;
+      default:
+	/* Data arrival / SVC creation */
+	Debug_unit(&events_unit,"fdlist:%d",fdlist);
+	for (tmp = fdlist; tmp != NULL; tmp = tmp->next) {
+	  dump_printf(EL_DEBUG,"FD:%d",tmp->fd);
+	  if (FD_ISSET(tmp->fd, &to_select)) {
+	    Debug_unit(&events_unit, "Event on fd %d", tmp->fd);
+	    conn_set_active(tmp->data, tmp->fd);
+	    event_put(&events_unit, CE_DATA, tmp->data);
+	  } 	  
+	}
+	break;
+      }
+    }
+    else {
+      Debug_unit(&events_unit, "No fds, restarting after 10 s");
+      sleep(10);
+      event_put(&events_unit, CE_RESTART, NULL);
+    }
+  }
+  if (sig_hup != 0) {
+      event_put(&events_unit, CE_RESTART, NULL);
+      sig_hup = 0;
+  }
+  if (sig_usr1 != 0) {
+      event_put(&events_unit, CE_DUMP, NULL);
+      sig_usr1 = 0;
+  }
+  if (sig_usr2 != 0) {
+      event_put(&events_unit, CE_EXIT, NULL);
+      sig_usr2 = 0;
+  }
+  if (sig_alarm != 0) {
+      event_put(&events_unit, CE_TIMER, NULL);
+      sig_alarm = 0;
+  }
+  Debug_unit(&events_unit, "get event %s", dump_event_type(eventtail->event->type));
+  /* Lock list */
+  event = eventhead->event;
+  if (eventhead->next != NULL) {
+    eventhead->next->prev = NULL;
+  }
+  else {
+    /* This was the last */
+    eventtail = NULL;
+  }
+  tmplist = eventhead;
+  eventhead = eventhead->next;
+  /* Unlock list */
+  mem_free(&events_unit, tmplist);
+  return event;
+}
+
+/* Add event to queue */
+void
+event_put(const Unit_t *unit, EventType_t type, void *data)
+{
+  Event_t *event;
+  EventList_t *tmplist;
+
+  Debug_unit(&events_unit, "unit %s puts event %s", unit->name, dump_event_type(type));
+  event = (Event_t *)mem_alloc(&events_unit, sizeof(Event_t));
+  event->unit = unit;
+  event->type = type;
+  event->data = data;
+
+  tmplist = (EventList_t *)mem_alloc(&events_unit, sizeof(EventList_t));
+  tmplist->event = event;
+  tmplist->next = NULL;
+  /* Lock list */
+  tmplist->prev = eventtail;
+
+  if (eventtail != NULL) {
+    eventtail->next = tmplist;
+  }
+  else {
+    /* This is the first one */
+    eventhead = tmplist;
+  }
+  eventtail = tmplist;
+  /* Unlock list */
+}
+
+/* Call handlers until one returns nonzero */
+int
+dispatch_handlers(const Event_t *event)
+{
+  int handled = 0;
+  const HFList_t *htmp;
+
+  assert(event != NULL);
+  for (htmp = handlers[event->type]; htmp != NULL; htmp = htmp->next) {
+    Debug_unit(&events_unit, "trying handler %s", htmp->name);
+    handled = (htmp->h(event, htmp->funcdata));
+    if (handled != 0) {
+      Debug_unit(&events_unit, "success.");
+      break;
+    }
+    else {
+      Debug_unit(&events_unit, "failed.");
+    }
+  }
+  return handled;
+}
+
+static void
+event_get_fds(fd_set *dest)
+{
+  FDList_t *tmp;
+
+  FD_ZERO(dest);
+
+  for(tmp = fdlist; tmp != NULL; tmp = tmp->next)
+    FD_SET(tmp->fd, dest);
+}
+
+void
+event_add_fd(int fd, void *data)
+{
+  FDList_t *tmp;
+
+  tmp = mem_alloc(&events_unit, sizeof(FDList_t));
+  tmp->fd = fd;
+  tmp->data = data;
+  tmp->next = fdlist;
+  fdlist = tmp;
+}
+
+void
+event_remove_fd(int fd)
+{
+  FDList_t *tmp, *prev = NULL;
+
+  for (tmp = fdlist; tmp != NULL; prev = tmp, tmp = tmp->next) {
+    if (tmp->fd == fd) {
+      break;
+    }
+  }
+
+  if (tmp == NULL) {
+    Debug_unit(&events_unit, "Could not find fd %d for removal", fd);
+    return;
+  }
+  else {
+    if (prev != NULL) {
+      prev->next = tmp->next;
+    }
+    else {
+      fdlist = tmp->next;
+    }
+    mem_free(&events_unit, tmp);
+  }
+}
diff -ur --new-file old/atm/lane/events.h new/atm/lane/events.h
--- old/atm/lane/events.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/events.h	Thu Aug  8 23:23:53 1996
@@ -0,0 +1,43 @@
+/*
+ * Event handler
+ *
+ * $Id: events.h,v 1.7 1994/11/10 15:19:38 asdf Exp $
+ *
+ */
+
+#ifndef EVENTS_H
+#define EVENTS_H
+/* System includes needed for types */
+
+/* Local includes needed for types */
+#include "units.h"
+
+/* Type definitions */
+typedef enum {
+  CE_SVC_OPEN, CE_SVC_CLOSE, CE_DATA, CE_TIMER, CE_DUMP, CE_RESTART, CE_EXIT
+} EventType_t;
+#define CE_MAX CE_EXIT
+
+typedef struct {
+  const Unit_t *unit;
+  EventType_t type;
+  void *data;
+} Event_t;
+
+/* Event handlers should return nonzero if they swallowed the event */
+typedef int (* HandlerFunc_t)(const Event_t *event, void *funcdata);
+
+/* Global function prototypes */
+void add_event_handler(EventType_t type, HandlerFunc_t func, const char *name, void *funcdata);
+const Event_t *event_get_next(void);
+void event_put(const Unit_t *unit, EventType_t type, void *data);
+const char *dump_event_type(EventType_t type);
+int dispatch_handlers(const Event_t *event);
+void event_add_fd(int fd, void *data);
+void event_remove_fd(int fd);
+
+/* Global data */
+extern const Unit_t events_unit;
+
+#endif
+
diff -ur --new-file old/atm/lane/lane.c new/atm/lane/lane.c
--- old/atm/lane/lane.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/lane.c	Thu Aug  8 23:24:13 1996
@@ -0,0 +1,225 @@
+/*
+ * Lan Emulation Server
+ *
+ * $Id: lane.c,v 1.21 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+
+/* System includes */
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+/* Local includes */
+#include "units.h"
+#include "load.h"
+#include "dump.h"
+#include "mem.h"
+#include "connect.h"
+#include "events.h"
+#include "timers.h"
+
+/* Type definitions */
+
+/* Local function prototypes */
+static void main_init1(void);
+static void parse_args(int argc, const char **argv);
+static void usage(void);
+static int dump_handler(const Event_t *event, void *funcdata);
+static int exit_handler(const Event_t *event, void *funcdata);
+
+/* Data */
+static const char *rcsid = "$Id: lane.c,v 1.21 1995/11/15 08:27:11 carnil Exp $";
+const Unit_t main_unit = {
+  "main",
+  NULL,
+  main_init1,
+  NULL,
+  NULL
+};
+
+static const char *progname;
+
+/* Functions */
+
+/* Initialization for data that needs other units */
+static void
+main_init1(void)
+{
+  set_var_str(&main_unit, "version", rcsid);
+  add_event_handler(CE_DUMP, &dump_handler, "dump_handler", NULL);
+  add_event_handler(CE_EXIT, &exit_handler, "exit_handler", NULL);
+  Debug_unit(&main_unit, "Initialized.");
+}
+
+/* Main loop */
+int
+main(int argc, const char **argv)
+{
+  short do_restart = 0;
+  const Event_t *event;
+  const Unit_t **units;
+
+  /* Debugging facility */
+  dump_type = DT_STDERR;
+
+  while (1) {
+    /* Call phase 0 initializers */
+    Debug_unit(&main_unit, "Calling phase 0 initializers");
+    FOR_ALL_UNITS(units) {
+      if ((*units)->init0 != NULL) {
+	Debug_unit(&main_unit, "Initializing %s", (*units)->name);
+	(*((*units)->init0))();
+      }
+    }
+
+    /* Get flags from command line */
+    parse_args(argc, argv);
+
+    /* Call phase 1 initializers */
+    Debug_unit(&main_unit, "Calling phase 1 initializers");
+    FOR_ALL_UNITS(units) {
+      if ((*units)->init1 != NULL) {
+	Debug_unit(&main_unit, "Initializing %s", (*units)->name);
+	(*((*units)->init1))();
+      }
+    }
+
+    do_restart = 0;
+
+    while (!do_restart) {
+      event = event_get_next();
+      if (dispatch_handlers(event) == 1) {
+	continue;
+      }
+      switch (event->type) {
+      case CE_RESTART:
+	do_restart = 1;
+	break;
+      case CE_EXIT:
+	break;
+      case CE_DUMP:
+	break;
+      case CE_SVC_OPEN:
+	break;
+      case CE_SVC_CLOSE:
+	break;
+      case CE_DATA:
+	break;
+      case CE_TIMER:
+	break;
+      }
+      mem_free(&main_unit, event);
+    }
+    /* Restart */
+    Debug_unit(&main_unit, "Releasing %d units", num_units);
+    FOR_ALL_UNITS_REV(units) {
+      if ((*units)->release != NULL) {
+	Debug_unit(&main_unit, "Releasing %s", (*units)->name);
+	(*((*units)->release))();
+      }
+    }
+  }
+  return 0;
+}
+
+/* Process CE_DUMP events */
+static int
+dump_handler(const Event_t *event, void *funcdata)
+{
+  const Unit_t **units;
+
+  mem_free(&main_unit, event);
+  FOR_ALL_UNITS(units) {
+    if ((*units)->dump != NULL) {
+      Debug_unit(&main_unit, "Dumping %s", (*units)->name);
+      (*((*units)->dump))();
+    }
+  }
+  return 1;
+}
+
+/* Process CE_EXIT events */
+static int
+exit_handler(const Event_t *event, void *funcdata)
+{
+  const Unit_t **units;
+
+  mem_free(&main_unit, event);
+  Debug_unit(&main_unit, "Releasing %d units", num_units);
+  FOR_ALL_UNITS_REV(units) {
+    if ((*units)->release != NULL) {
+      Debug_unit(&main_unit, "Releasing %s", (*units)->name);
+      (*((*units)->release))();
+    }
+  }
+  exit(0);
+}
+
+/*
+ * -dmodule sets debugging output of the module to true
+ * -mmodule sets memory debugging of the module to true
+ */
+static void
+parse_args(int argc, const char **argv)
+{
+  int i;
+  const Unit_t *unit, **units;
+  const char *arg;
+
+  progname = argv[0];
+  for (i = 1; i < argc; i++) {
+    arg = argv[i];
+    Debug_unit(&main_unit, "Arg %s", arg);
+    if (arg[0] == '-') {
+      switch (arg[1]) {
+      case 'd':
+	if (strcmp(&arg[2], "all") == 0) {
+	  FOR_ALL_UNITS(units) {
+	    set_var_bool(*units, "debug", BL_TRUE);
+	  }
+	}
+	else {
+	  unit = find_unit(&arg[2]);
+	  if (unit != NULL) {
+	    set_var_bool(unit, "debug", BL_TRUE);
+	  }
+	  else {
+	    dump_printf(EL_ERROR, "Unknown module name: %s", &arg[2]);
+	    usage();
+	  }
+	}
+	break;
+      case 'm':
+	if (strcmp(&arg[2], "all") == 0) {
+	  FOR_ALL_UNITS(units) {
+	    set_var_bool(*units, "memdebug", BL_TRUE);
+	  }
+	}
+	else {
+	  unit = find_unit(&arg[2]);
+	  if (unit != NULL) {
+	    set_var_bool(unit, "memdebug", BL_TRUE);
+	  }
+	  else {
+	    dump_printf(EL_ERROR, "Unknown module name: %s", &arg[2]);
+	    usage();
+	  }
+	}
+	break;
+      default:
+	usage();
+	return;
+      }
+    }
+  }
+}
+
+static void
+usage(void)
+{
+    dump_printf(EL_ERROR, "Usage:");
+    dump_printf(EL_ERROR, "%s [-dmodule]... [-mmodule]...", progname);
+    exit(1);
+}
+
diff -ur --new-file old/atm/lane/lane.h new/atm/lane/lane.h
--- old/atm/lane/lane.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/lane.h	Thu Aug  8 23:24:26 1996
@@ -0,0 +1,157 @@
+/*
+ * Global definitions header file
+ *
+ * $Id: lane.h,v 1.9 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+
+#ifndef LANE_H
+#define LANE_H
+
+/* System includes needed for types */
+#include <sys/types.h>
+
+/* Local includes needed for types */
+#include "units.h"
+
+
+/* Type definitions */
+typedef struct {
+  unsigned le_header : 16;
+  unsigned char destaddr[6];
+  unsigned char srcaddr[6];
+  unsigned type_len : 16;
+} LaneData_t;
+
+typedef struct {
+  long port;
+  long vpi;
+  long vci;
+} LaneVcc_t;
+
+#define LE_HEADER_MAX 0xefff
+
+typedef struct {
+  unsigned short tag;
+  union {
+    unsigned char mac_address[6];
+    struct route_designator {
+      unsigned char reserved[4];
+      unsigned short designator;
+    } route;
+  } a_r;
+} LaneDestination_t;
+
+#define LANE_DEST_NP 0x0000
+#define LANE_DEST_MAC 0x0001
+#define LANE_DEST_RD 0x0002
+
+typedef unsigned short LecId_t;
+#define LECID_MAX 0xfeff
+
+typedef struct {
+  unsigned char addr[20];
+} AtmAddr_t;
+#define ATM_ADDR_LEN (sizeof(AtmAddr_t))
+
+typedef struct lanedest_l {
+  LaneDestination_t *addr;
+  struct lanedest_l *next;
+} LaneDestList_t;
+
+typedef struct {
+  LaneVcc_t *pvc;
+  AtmAddr_t *address;
+  LecId_t lecid;
+  LaneDestList_t *destinations;
+} InitPvc_t;
+
+typedef struct {
+  unsigned marker : 16;
+  unsigned protocol : 8;
+  unsigned version : 8;
+  unsigned opcode : 16;
+  unsigned status : 16;
+  unsigned transaction_id : 32;
+  LecId_t lecid;
+  unsigned flags : 16;
+  LaneDestination_t source;
+  LaneDestination_t target;
+  AtmAddr_t source_addr;
+  unsigned lan_type : 8;
+  unsigned max_frame : 8;
+  unsigned reserved : 8;
+  unsigned elan_name_size : 8;
+  AtmAddr_t target_addr;
+  unsigned char elan_name[32];
+} LaneControl_t;
+
+typedef struct {
+  unsigned marker : 16;
+  unsigned protocol : 8;
+  unsigned version : 8;
+  unsigned opcode : 16;
+} LaneVccReady_t;
+
+/* Global function prototypes */
+
+/* Global data */
+#define LE_MARKER 0xff00
+#define LE_PROTOCOL 0x01
+#define LE_VERSION 0x01
+
+/* Opcodes */
+#define LE_CONFIGURE_REQUEST 0x0001
+#define LE_CONFIGURE_RESPONSE 0x0101
+#define LE_JOIN_REQUEST 0x0002
+#define LE_JOIN_RESPONSE 0x0102
+#define READY_QUERY 0x0003
+#define READY_IND 0x0103
+#define LE_REGISTER_REQUEST 0x0004
+#define LE_REGISTER_RESPONSE 0x0104
+#define LE_UNREGISTER_REQUEST 0x0005
+#define LE_UNREGISTER_RESPONSE 0x0105
+#define LE_ARP_REQUEST 0x0006
+#define LE_ARP_RESPONSE 0x0106
+#define LE_FLUSH_REQUEST 0x0007
+#define LE_FLUSH_RESPONSE 0x0107
+#define LE_NARP_REQUEST 0x0008
+#define LE_TOPOLOGY_REQUEST 0x0009
+
+/* Status codes */
+#define LE_STATUS_SUCCESS 0		/* Success */
+#define LE_STATUS_BAD_VERSION 1		/* Version not supported */
+#define LE_STATUS_BAD_REQ 2		/* Invalid request parameters */
+#define LE_STATUS_DUPLICATE_REG 4	/* Duplicate LAN registration */
+#define LE_STATUS_DUPLICATE_ADDR 5	/* Duplicate ATM address */
+#define LE_STATUS_NO_RESOURCES 6	/* Insufficient resources */
+#define LE_STATUS_NO_ACCESS 7		/* Access denied */
+#define LE_STATUS_BAD_LECID 8		/* Invalid requestor-id */
+#define LE_STATUS_BAD_DEST 9		/* Invalid LAN destination */
+#define LE_STATUS_BAD_ADDR 10		/* Invalid ATM address */
+#define LE_STATUS_NO_CONFIG 20		/* No configuration */
+#define LE_STATUS_CONFIG_ERROR 21	/* LE_CONFIGURE error */
+#define LE_STATUS_NO_INFO 22		/* Insufficient Information */
+#define LE_STATUS_MAX 22	
+
+/* Flags */
+#define LE_FLAG_REMOTE 0x0001
+#define LE_FLAG_PROXY 0x0080
+#define LE_FLAG_TOPOLOGY_CHANGE 0x0100
+
+/* Lan types */
+#define LE_LAN_TYPE_UNSPECIFIED 0x00
+#define LE_LAN_TYPE_802_3 0x01
+#define LE_LAN_TYPE_802_5 0x02
+
+/* Max frame sizes, mtus */
+#define LE_MAX_FRAME_UNSPECIFIED 0x00
+#define LE_MAX_FRAME_1516 0x01
+#define LE_MAX_FRAME_4544 0x02
+#define LE_MAX_FRAME_9234 0x03
+#define LE_MAX_FRAME_18190 0x04
+
+extern const Unit_t main_unit;
+
+#endif
+
diff -ur --new-file old/atm/lane/ldb.c new/atm/lane/ldb.c
--- old/atm/lane/ldb.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/ldb.c	Sun Aug 18 22:20:25 1996
@@ -0,0 +1,361 @@
+/*
+ *
+ * Configuration DB
+ *
+ * $Id$
+ *
+ */
+/* System includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <atm.h>
+#include <ctype.h>
+
+/* Local includes */
+#include "lecs.h"
+#include "ldb.h"
+#include "mem_lecs.h"
+
+/* Local protos */
+static void dump_elan(Elan_t *elan);
+static int valid_char(char test);
+static const char* get_type_string(char lan_type);
+static const char* get_max_frame_size_string(char max_frame);
+static const char* get_atm_addr_string(const unsigned char *addr);
+static void dump_elan(Elan_t *elan);
+static int match_addresses(Elan_t *elan, unsigned char *addr);
+
+/* Local data */
+static unsigned char *lecs_address =NULL;
+static Elan_t *elan_arr[32];
+static Elan_t *default_elan = NULL;
+static int no_elans=0;
+static char tmpbuffer[256];
+
+#define MIN(a,b) ((a<b)?a:b)
+#define COMP_NAME "LDB"
+
+Elan_t*
+new_elan(const char *name)
+{
+  elan_arr[no_elans] = (Elan_t *)mem_alloc(COMP_NAME, sizeof(Elan_t));
+  if (!elan_arr[no_elans]) {
+    return NULL;
+  }
+  memset(elan_arr[no_elans],0,sizeof(Elan_t));
+  elan_arr[no_elans]->elan_name_size = MIN(32, strlen(name));
+  strncpy(elan_arr[no_elans]->elan_name, name, 
+	  elan_arr[no_elans]->elan_name_size);
+  /* Default values */
+  elan_arr[no_elans]->type = LE_LAN_TYPE_UNSPECIFIED;
+  elan_arr[no_elans]->max_frame = LE_MAX_FRAME_UNSPECIFIED;
+  return elan_arr[no_elans++];
+}
+
+int
+add_les(Elan_t *elan, const char *addr)
+{  
+  struct sockaddr_atmsvc tmp;
+
+  assert(elan);
+  if (elan->les_addr[18] || 
+      elan->les_addr[17] ||
+      elan->les_addr[16] ||
+      elan->les_addr[15] ||
+      elan->les_addr[14] ||
+      elan->les_addr[13] ||
+      elan->les_addr[12]) {
+    printf("LES address already set for this ELAN!\n");
+    return 0;
+  }
+  
+  if (text2atm(addr,(struct sockaddr *)&tmp,sizeof(tmp),T2A_SVC|T2A_NAME)<0) {
+    return -1;
+  }
+  memcpy(elan->les_addr, tmp.sas_addr.prv, ATM_ESA_LEN);
+  return 0;
+}
+
+static int
+valid_char(char test)
+{
+  return ((test >= '0' && test <= '9') || (test >= 'a' || test <= 'f') ||
+	   (test >= 'A' && test <= 'F') || test == 'x' || test == 'X');
+}
+
+int 
+add_atm(Elan_t *elan, char *addr)
+{
+  char *tmp;
+  char *ch;
+  int pos=0;
+
+  ch = addr;
+
+  assert(elan && addr);
+  tmp = (char*)mem_alloc(COMP_NAME, ATM_ESA_LEN*2);
+  if (!tmp)
+    return -1;
+  memset(tmp,0,ATM_ESA_LEN*2);
+  while ((*ch)!='\0' && (*(ch+1))!='\0') {
+    if (!valid_char(*ch)) {
+      mem_free(COMP_NAME, tmp);
+      return -1;
+    }
+    if (*(ch+1) == '.' || *(ch+1) == ':' || *(ch+1) == '-') {
+      tmp[pos++] = '0';
+      tmp[pos++] = *ch;
+      ch+=2;
+    } else if (valid_char(*(ch+1))) {
+      tmp[pos++] = *ch;
+      tmp[pos++] = *(ch+1);
+      ch+=2;
+    } else {
+      mem_free(COMP_NAME, tmp);
+      return -1;
+    }
+    if (*ch == '.' || *ch == '-' || *ch == ':')
+      ch++;
+  }
+  if ((*ch) != '\0' && *(ch+1) == '\0') {
+    tmp[pos++] = '0';
+    tmp[pos++] = *ch;
+  }
+  if (pos<40) {
+    mem_free(COMP_NAME, tmp);
+    return -1;
+  }
+  elan->addresses[elan->no_addresses++] = tmp;
+  return 0;
+}
+
+void 
+set_default(Elan_t *elan)
+{
+  if (default_elan) {
+    printf("Warning! Default ELAN already set!\n");
+    return;
+  }
+  default_elan = elan;
+}
+
+static const char*
+get_type_string(char lan_type)
+{
+  switch (lan_type) {
+  case LE_LAN_TYPE_UNSPECIFIED:
+    return "<Unspecified>";
+  case LE_LAN_TYPE_802_3:
+    return "802.3";
+  case LE_LAN_TYPE_802_5:
+    return "802.5";
+  default:
+    return "UNKNOWN TYPE";
+  }
+}
+
+static const char*
+get_max_frame_size_string(char max_frame)
+{
+  switch (max_frame) {
+  case LE_MAX_FRAME_UNSPECIFIED:
+    return "<Unspecified>";
+  case LE_MAX_FRAME_1516:
+    return "1516";
+  case LE_MAX_FRAME_4544:
+    return "4544";
+  case LE_MAX_FRAME_9234:
+    return "9234";
+  case LE_MAX_FRAME_18190:
+    return "18190";
+  default:
+    return "UNKNOWN FRAME SIZE";
+  }
+}
+
+static const char*
+get_atm_addr_string(const unsigned char *addr)
+{
+  int i;
+
+  for(i=0;i<ATM_ESA_LEN-1;i++) {
+    sprintf(&tmpbuffer[i*3],"%2.2x.", addr[i]&0xff);
+  }
+  sprintf(&tmpbuffer[(ATM_ESA_LEN-1)*3],"%2.2x", addr[ATM_ESA_LEN-1]);
+  return tmpbuffer;
+}
+
+static void
+dump_elan(Elan_t *elan)
+{
+  int i;
+
+  printf("ELAN:%s (namelen:%d)\n",elan->elan_name, elan->elan_name_size);
+  fflush(stdout);
+  if (elan == default_elan) {
+    printf("\tDEFAULT ELAN\n");
+    fflush(stdout);
+  }
+  printf("\tMax frame size : %s\n", 
+	 get_max_frame_size_string(elan->max_frame));
+  fflush(stdout);
+  printf("\tELAN type      : %s\n", get_type_string(elan->type));
+  fflush(stdout);
+  printf("\tLES address    : %s\n", get_atm_addr_string(elan->les_addr));
+  fflush(stdout);
+  for(i=0;i<elan->no_addresses;i++)
+    printf("\t\t%s\n", elan->addresses[i]);
+  printf("\t------------------------\n");
+}
+
+void 
+dump_db(Elan_t *elan)
+{
+  int i;
+
+  if (elan) {
+    dump_elan(elan);
+    return;
+  }
+  printf("Dumping whole ELAN db\n");
+  if (lecs_address)
+    printf("LECS address: %s\n", get_atm_addr_string(lecs_address));
+  else
+    printf("LECS address not set\n");
+  for(i=0;i<no_elans;i++) {
+    dump_elan(elan_arr[i]);
+  }
+}
+
+void 
+set_lecs_addr(const char *addr)
+{
+  struct sockaddr_atmsvc tmp;
+
+  if (lecs_address) {
+    printf("Error: LECS address already set\n");
+  }
+  if (text2atm(addr,(struct sockaddr*)&tmp,sizeof(tmp),T2A_SVC|T2A_NAME)<0) {
+    printf("Couldn't get LECS address!\n");
+    return;
+  }
+  lecs_address=(unsigned char*)mem_alloc(COMP_NAME,ATM_ESA_LEN);
+  if (!lecs_address)
+    return;
+  memcpy(lecs_address, tmp.sas_addr.prv, ATM_ESA_LEN);
+}
+
+const unsigned char*
+get_lecs_addr(void)
+{
+  return lecs_address;
+}
+
+void
+reset_db(void)
+{
+  Elan_t *tmp;
+  int i,j;
+  
+  if (lecs_address) {
+    mem_free(COMP_NAME, lecs_address);
+    lecs_address = NULL;
+  }
+
+  for(i=0;i<no_elans;i++) {
+    tmp = elan_arr[i];
+    for(j=0;j<tmp->no_addresses;j++)
+      mem_free(COMP_NAME, tmp->addresses[j]);
+    mem_free(COMP_NAME,tmp);
+  }
+  no_elans=0;
+  default_elan=NULL;
+}
+
+static int
+match_addresses(Elan_t *elan, unsigned char *addr)
+{
+  int i,j,match=0;
+  unsigned char tmp;
+
+  for(i=0;i<elan->no_addresses && !match;i++) {
+    match=1;
+    for(j=0;j<ATM_ESA_LEN && match;j++) {
+      if (elan->addresses[i][j*2] == 'x' ||
+	  elan->addresses[i][j*2] == 'X') {
+	tmp = addr[j]&0xf0;
+      } else {
+	if (elan->addresses[i][j*2] >= '0' &&
+	    elan->addresses[i][j*2] <= '9') {
+	  tmp = (elan->addresses[i][j*2]-'0')<<4;
+	} else {
+	  tmp = (tolower(elan->addresses[i][j*2])-'a'+10)<<4;
+	}
+      }
+      if (elan->addresses[i][j*2+1] == 'x' ||
+	  elan->addresses[i][j*2+1] == 'X') {
+	tmp |= addr[j]&0xf;
+      } else {
+	if (elan->addresses[i][j*2+1] >= '0' &&
+	    elan->addresses[i][j*2+1] <= '9') {
+	  tmp |= 0xf&(elan->addresses[i][j*2+1]-'0');
+	} else {
+	  tmp |= 0xf&(tolower(elan->addresses[i][j*2+1])-'a'+10);
+	}
+      }
+
+      if (addr[j] != tmp)
+	match=0;
+    }
+  }
+  return match;
+}
+
+/*
+ * Rules in finding the LES address:
+ * 1. If elan_name matches exactly &&
+ *    there is an entry matching this ATM address for this ELAN.
+ *    If elan_name matches, but ATM address is not found, reject.
+ * 2. Search for first ELAN which matches in type, max_frame and
+ *    ATM address.
+ * 3. Return default elan
+ * 4. No match, reject.
+ */
+Elan_t*
+find_elan(unsigned char *lec_addr, const char type, 
+	  const char max_frame, const char *elan_name, 
+	  const short elan_name_size, unsigned short *reason)
+{
+  int pos;
+
+  *reason = LE_STATUS_SUCCESS;
+  for(pos=0;pos<no_elans;pos++) {
+    if (elan_name_size == elan_arr[pos]->elan_name_size &&
+	!memcmp(elan_name, elan_arr[pos]->elan_name, elan_name_size)) {      
+      if (match_addresses(elan_arr[pos], lec_addr)) {
+	return elan_arr[pos];
+      } else { 
+	*reason = LE_STATUS_NO_ACCESS;
+	return NULL;
+      }
+    }
+  }
+  for(pos=0;pos<no_elans;pos++) {
+    if ((max_frame == LE_MAX_FRAME_UNSPECIFIED ||
+	 elan_arr[pos]->max_frame == LE_MAX_FRAME_UNSPECIFIED ||
+	 max_frame == elan_arr[pos]->max_frame) &&
+	(type == LE_LAN_TYPE_UNSPECIFIED ||
+	 elan_arr[pos]->type == LE_LAN_TYPE_UNSPECIFIED ||
+	 type == elan_arr[pos]->type)) {
+      if (match_addresses(elan_arr[pos], lec_addr)) {
+	return elan_arr[pos];
+      }
+    }
+  }
+  if (default_elan)
+    return default_elan;  
+  *reason = LE_STATUS_NO_CONFIG;
+  return NULL;
+}
diff -ur --new-file old/atm/lane/ldb.h new/atm/lane/ldb.h
--- old/atm/lane/ldb.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/ldb.h	Tue Aug 13 16:19:29 1996
@@ -0,0 +1,37 @@
+/*
+ *
+ * Configuration DB
+ *
+ * $Id$
+ *
+ */
+#ifndef LDB_H
+#define LDB_H
+
+typedef struct {
+  char elan_name[32];
+  short elan_name_size;
+  int no_addresses;
+  char *addresses[256];
+  unsigned char les_addr[20];
+  char type; /* Unspecified, 802.3, 802.5 */
+  char max_frame; /* 1516, 4544, 9234, 18190 */
+} Elan_t;
+
+/* Protos */
+Elan_t *new_elan(const char *name);
+int add_les(Elan_t *elan, const char *addr);
+int add_atm(Elan_t *elan, char *addr);
+void set_default(Elan_t *elan);
+
+void set_lecs_addr(const char *addr);
+const unsigned char *get_lecs_addr(void);
+
+Elan_t *find_elan(unsigned char *lec_addr, const char type, 
+		  const char max_frame, const char *elan_name, 
+		  const short elan_name_size, unsigned short *reason);
+
+void dump_db(Elan_t *elan);
+
+void reset_db(void);
+#endif /* LDB_H */
diff -ur --new-file old/atm/lane/lecs.c new/atm/lane/lecs.c
--- old/atm/lane/lecs.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/lecs.c	Sun Aug 18 22:20:48 1996
@@ -0,0 +1,236 @@
+/*
+ *
+ * LECS main code
+ *
+ * $Id$
+ *
+ */
+
+/* Standard includes*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+/* ATM includes */
+#include <linux/atm.h>
+
+/* Local includes */
+#include "lecs_load.h"
+#include "ldb.h"
+#include "mem_lecs.h"
+#include "lecs.h"
+#include "atm_lecs.h"
+
+/* Protos */
+static void sig_reset(int foobar);
+static void sig_kill(int foobar);
+static void usage(const char *progname);
+int send_response(int fd, unsigned char *buffer, int len);
+
+/* Local data */
+#define COMP_NAME "MAIN"
+#define MAX_FD 32
+#define P_SIZE 1024
+static int stay_alive = 1;
+static int reset = 0;
+
+extern int errno;
+
+static void
+usage(const char *progname)
+{
+  printf("Usage: %s [-f configuration_file][-l listen_address][-d dump db]\n",
+	 progname);
+}
+
+static void
+sig_reset(int foobar)
+{
+  reset = 1;
+}
+
+static void
+sig_kill(int foobar)
+{
+  stay_alive = 0;
+}
+
+int 
+send_response(int fd, unsigned char *buffer, int len)
+{
+  LaneControl_t *dp;
+  Elan_t *elan;
+  unsigned short response;
+
+  if (len < sizeof(LaneControl_t))
+    return -1;
+
+  dp = (LaneControl_t *)buffer;
+
+  if (dp->marker != htons(LE_MARKER) ||
+      dp->protocol != LE_PROTOCOL ||
+      dp->version != LE_VERSION ||
+      dp->opcode != htons(LE_CONFIGURE_REQUEST)) {
+    return -1;
+  }
+  dp->opcode = htons(LE_CONFIGURE_RESPONSE);
+  elan = find_elan(dp->source_atm, dp->lan_type, dp->max_frame,
+		   (char*)dp->elan_name, dp->elan_name_size, &response);
+  if (!elan) {
+    dp->status = htons(response);
+  } else {
+    dp->status = htons(LE_STATUS_SUCCESS);
+    dp->lan_type = elan->type;
+    dp->max_frame = elan->max_frame;
+    memcpy(dp->elan_name, elan->elan_name, elan->elan_name_size);
+    dp->elan_name_size = elan->elan_name_size;
+    memcpy(dp->target_atm, elan->les_addr, ATM_ESA_LEN);
+  }
+  return write(fd, buffer, len);
+}
+
+void
+main(int argc, char **argv)
+{
+  int i =0;
+  char *config_file =NULL;
+  char *listen_addr = NULL;
+  int fd_arr[MAX_FD];
+  int no_fds=1;
+  int just_dump=0;
+  fd_set fds;
+  struct sockaddr_atmsvc client;
+  int len;
+  unsigned char buffer[P_SIZE];
+
+  while(i!=-1) {
+    i = getopt(argc, argv, "f:l:d");
+    switch(i) {
+    case 'd':
+      printf("Dumping databasefile\n");
+      just_dump=1;
+      break;
+    case 'f':
+      if (config_file) {
+	usage(argv[0]);
+	exit(-1);
+      }
+      config_file = (char*)mem_alloc(COMP_NAME, strlen(optarg)+1);
+      if (!config_file) {
+	exit(-1);
+      }
+      memcpy(config_file, optarg, strlen(optarg)+1);
+      break;
+    case 'l':
+      if (listen_addr) {
+	usage(argv[0]);
+	exit(-1);
+      }
+      listen_addr = (char*)mem_alloc(COMP_NAME, strlen(optarg)+1);
+      if (!listen_addr)
+	exit(-1);
+      memcpy(listen_addr, optarg, strlen(optarg)+1);
+      break;
+    case -1:
+      break;
+    default:
+      usage(argv[0]);
+      exit(-1);
+    }
+  }
+  /* Following gets run in the beginning or when lecs is restarted */
+  while (stay_alive) {
+
+    /* Read configuration file */
+    if (config_file) {
+      if (load_db(config_file)<0)
+	exit(-1);
+    } else {
+      if (load_db(DEFAULT_CONFIG)<0)
+	exit(-1);
+    }
+    if (just_dump) {
+      dump_db(NULL);
+      exit(0);
+    }
+
+    /* Reserve signals */
+    signal(SIGHUP, sig_reset);
+    signal(SIGINT, sig_kill);
+    signal(SIGQUIT, sig_kill);
+    signal(SIGABRT, sig_kill);
+    signal(SIGTERM, sig_kill);
+    signal(SIGSEGV, sig_kill);
+    
+    /* CHANGE: First parameter, then configuration file! */
+    fd_arr[0] = atm_create_socket(CONFIGURATION_DIRECT, 
+				  get_lecs_addr());
+    no_fds=1;
+    if (fd_arr[0] <0) {
+      stay_alive=0; /* No need to go on */
+    }
+    while(!reset && stay_alive) {
+      FD_ZERO(&fds);
+      for(i=0;i<no_fds;i++) {
+	FD_SET(fd_arr[i],&fds);
+      }
+      
+      if (select(MAX_FD, &fds, NULL, NULL, NULL)<0) {
+	perror("select(MAX_FD,...)");
+	stay_alive=0;
+      } else {
+	if (FD_ISSET(fd_arr[0],&fds)) { /* Incoming call */
+	  if (no_fds == MAX_FD) {
+	    close(fd_arr[1]); /* Oldest */
+	    memmove(&fd_arr[1], &fd_arr[2], sizeof(int)*(MAX_FD-2));
+	    no_fds--;
+	  }
+	  len = sizeof(client);
+	  fd_arr[no_fds] = accept(fd_arr[0], (struct sockaddr*)&client,
+				  &len);
+	  if (fd_arr[no_fds]<0) {
+	    if (errno==ENETRESET)
+	      reset=1;
+	    if (errno==EUNATCH)
+	      stay_alive=1;
+	  } else {
+	    no_fds++;
+	  }
+	}
+	for(i=1;i<no_fds;i++) {
+	  if (FD_ISSET(fd_arr[i],&fds)) {
+	    len = read(fd_arr[i], buffer, P_SIZE);
+	    if (len <0 && (errno == ENETRESET || errno == EUNATCH)) {
+	      reset=0;
+	    }
+	    if (len<=0) {
+	      close(fd_arr[i]);
+	      memmove(&fd_arr[i], &fd_arr[i+1], sizeof(int)*(--no_fds -i));
+	      i--;
+	    } else {
+	      if(send_response(fd_arr[i], buffer, len)<0) {
+		close(fd_arr[i]);
+		memmove(&fd_arr[i], &fd_arr[i+1], sizeof(int)*(--no_fds -i));
+	      }
+	    }
+	  }
+	}
+      }
+    }
+    /* This gets done if a signal has been caught, or if
+       network resets/becomes unavailable */
+    reset=0;
+    for(i=0;i<no_fds;i++)
+      close(fd_arr[i]);
+    no_fds=0;
+    reset_db();
+  }
+  exit(0);
+}
diff -ur --new-file old/atm/lane/lecs.h new/atm/lane/lecs.h
--- old/atm/lane/lecs.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/lecs.h	Mon Aug 12 20:19:44 1996
@@ -0,0 +1,101 @@
+/*
+ * Global definitions header file
+ *
+ * $Id: lane.h,v 1.9 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+
+#ifndef LECS_H
+#define LECS_H
+
+/* System includes needed for types */
+#include <sys/types.h>
+
+/* Type definitions */
+
+#define LANE_DEST_NP 0x0000
+#define LANE_DEST_MAC 0x0001
+#define LANE_DEST_RD 0x0002
+
+typedef struct {
+  unsigned marker : 16;
+  unsigned protocol : 8;
+  unsigned version : 8;
+  unsigned opcode : 16;
+  unsigned status : 16;
+  unsigned transaction_id : 32;
+  unsigned short lecid;
+  unsigned flags : 16;
+  unsigned char source_lan[8];
+  unsigned char target_lan[8];
+  unsigned char source_atm[20];
+  unsigned lan_type : 8;
+  unsigned max_frame : 8;
+  unsigned reserved : 8;
+  unsigned elan_name_size : 8;
+  unsigned char target_atm[20];
+  unsigned char elan_name[32];
+} LaneControl_t;
+
+/* Global function prototypes */
+
+/* Global data */
+#define LE_MARKER 0xff00
+#define LE_PROTOCOL 0x01
+#define LE_VERSION 0x01
+
+/* Opcodes */
+#define LE_CONFIGURE_REQUEST 0x0001
+#define LE_CONFIGURE_RESPONSE 0x0101
+#define LE_JOIN_REQUEST 0x0002
+#define LE_JOIN_RESPONSE 0x0102
+#define READY_QUERY 0x0003
+#define READY_IND 0x0103
+#define LE_REGISTER_REQUEST 0x0004
+#define LE_REGISTER_RESPONSE 0x0104
+#define LE_UNREGISTER_REQUEST 0x0005
+#define LE_UNREGISTER_RESPONSE 0x0105
+#define LE_ARP_REQUEST 0x0006
+#define LE_ARP_RESPONSE 0x0106
+#define LE_FLUSH_REQUEST 0x0007
+#define LE_FLUSH_RESPONSE 0x0107
+#define LE_NARP_REQUEST 0x0008
+#define LE_TOPOLOGY_REQUEST 0x0009
+
+/* Status codes */
+#define LE_STATUS_SUCCESS 0		/* Success */
+#define LE_STATUS_BAD_VERSION 1		/* Version not supported */
+#define LE_STATUS_BAD_REQ 2		/* Invalid request parameters */
+#define LE_STATUS_DUPLICATE_REG 4	/* Duplicate LAN registration */
+#define LE_STATUS_DUPLICATE_ADDR 5	/* Duplicate ATM address */
+#define LE_STATUS_NO_RESOURCES 6	/* Insufficient resources */
+#define LE_STATUS_NO_ACCESS 7		/* Access denied */
+#define LE_STATUS_BAD_LECID 8		/* Invalid requestor-id */
+#define LE_STATUS_BAD_DEST 9		/* Invalid LAN destination */
+#define LE_STATUS_BAD_ADDR 10		/* Invalid ATM address */
+#define LE_STATUS_NO_CONFIG 20		/* No configuration */
+#define LE_STATUS_CONFIG_ERROR 21	/* LE_CONFIGURE error */
+#define LE_STATUS_NO_INFO 22		/* Insufficient Information */
+#define LE_STATUS_MAX 22	
+
+/* Flags */
+#define LE_FLAG_REMOTE 0x0001
+#define LE_FLAG_PROXY 0x0080
+#define LE_FLAG_TOPOLOGY_CHANGE 0x0100
+
+/* Lan types */
+#define LE_LAN_TYPE_UNSPECIFIED 0x00
+#define LE_LAN_TYPE_802_3 0x01
+#define LE_LAN_TYPE_802_5 0x02
+
+/* Max frame sizes, mtus */
+#define LE_MAX_FRAME_UNSPECIFIED 0x00
+#define LE_MAX_FRAME_1516 0x01
+#define LE_MAX_FRAME_4544 0x02
+#define LE_MAX_FRAME_9234 0x03
+#define LE_MAX_FRAME_18190 0x04
+
+/* Default configuration file */
+#define DEFAULT_CONFIG ".lecs_conf"
+#endif
+
diff -ur --new-file old/atm/lane/lecs_db.h new/atm/lane/lecs_db.h
--- old/atm/lane/lecs_db.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/lecs_db.h	Mon Aug 12 22:31:20 1996
@@ -0,0 +1,30 @@
+/*
+ * 
+ * ELAN Configuration db load header
+ *
+ * $Id$
+ * 
+ */
+#ifndef LECS_DB_H
+#define LECS_DB_H
+
+#define ELAN_NAME 20
+#define ADDRESS_ATM 21
+#define ERROR 22
+#define LES_ADDR 23
+#define DEFAULT 24
+#define TYPE 25
+#define MAX_FRAME 26
+#define TYPE_ETHERNET 27
+#define TYPE_TR 28
+#define MF_1516 29
+#define MF_4544 30
+#define MF_9234 31
+#define MF_18190 32
+
+extern FILE *yyin;
+extern char *g_return;
+extern unsigned int g_lineno;
+
+int yylex(void);
+#endif /* LECS_DB_H */
diff -ur --new-file old/atm/lane/lecs_db.l new/atm/lane/lecs_db.l
--- old/atm/lane/lecs_db.l	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/lecs_db.l	Tue Aug 13 13:43:46 1996
@@ -0,0 +1,72 @@
+%{
+/*Standard includes*/
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Local includes */
+#include "lecs_load.h"
+#include "lecs_db.h"
+
+char *g_return;
+unsigned int g_lineno=1;
+%}
+C [a-zA-Z]
+H [0-9a-fA-F]
+
+%%
+[\t ]			{}
+
+\n			{g_lineno++;}
+
+\[{C}[a-zA-Z0-9\-_]*\] |
+\[\]			{
+                          g_return = (unsigned char*)
+			    malloc(strlen(yytext));
+			  strcpy(g_return, &yytext[1]);
+			  g_return[strlen(yytext)-2] = '\0';
+			  return ELAN_NAME;
+			}
+
+[Ll][Ee][Ss][\t ]?\:?\=?     	{ return LES_ADDR;}
+
+[Tt][Yy][Pp][Ee][\t ]?\:?\=?  { return TYPE;}
+
+802\_?3 |
+[Ee][Tt][Hh][Ee][Rr][Nn][Ee][Tt] { return TYPE_ETHERNET;}
+
+802\_?5 |
+[Tt][Oo][Kk][Ee][Nn]\_?[Rr][Ii][Nn][Gg] { return TYPE_TR;}
+
+[Mm][Aa][Xx]\_?[Ff][Rr][Aa][Mm][Ee][\t ]?\:?\=? {return MAX_FRAME;}
+
+[Dd][Ee][Ff][Aa][Uu][Ll][Tt] { return DEFAULT;}
+
+1516			{ return MF_1516; }
+4544			{ return MF_4544; }
+9234			{ return MF_9234; }
+18190			{ return MF_18190;}
+
+{H}[0-9a-fA-FxX\.\:\-]*	{
+			  g_return = (unsigned char*)
+			    malloc(strlen(yytext));
+			  strcpy(g_return, yytext);
+			  g_return[strlen(yytext)] = '\0';
+			  return ADDRESS_ATM;
+			}
+
+
+\#.*			{}
+
+.			{
+				int i;
+				while ((i = input())!='\n');
+				unput(i);
+				return ERROR;
+			}
+
+%%
+int 
+yywrap()
+{
+  return 1;
+}
diff -ur --new-file old/atm/lane/lecs_load.c new/atm/lane/lecs_load.c
--- old/atm/lane/lecs_load.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/lecs_load.c	Mon Aug 12 22:31:04 1996
@@ -0,0 +1,129 @@
+/*
+ *
+ * LECS configuration database loading
+ *
+ * $Id$
+ *
+ */
+
+/* System includes */
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Local includes */
+#include "lecs_load.h"
+#include "lecs_db.h"
+#include "ldb.h"
+#include "lecs.h"
+
+int
+load_db(const char *filename)
+{
+  int ret;
+  int readnew=1;
+  Elan_t *elan =NULL;
+
+  yyin = fopen(filename,"r");
+  if(!yyin) {
+    perror("fopen");
+    return -1;
+  }
+
+  while(1) {
+    if (readnew) 
+      ret = yylex();
+    readnew=1;
+
+    switch(ret) {
+    case ELAN_NAME:
+      elan = new_elan(g_return);
+      break;
+    case TYPE:
+      if (!elan) {
+	printf("No ELAN for TYPE; line %d\n", g_lineno);
+	break;
+      }
+      ret = yylex();
+      if (ret == TYPE_ETHERNET) {
+	elan->type = LE_MAX_FRAME_1516;
+      } else if (ret == TYPE_TR) {
+	elan->type = LE_LAN_TYPE_802_3;
+      } else {
+	printf("Invalid type; line %d\n", g_lineno);
+      }
+      break;
+    case TYPE_ETHERNET:
+    case TYPE_TR:
+      printf("Invalid type placement; line %d\n", g_lineno);
+      break;
+    case MAX_FRAME:
+      if (!elan) {
+	printf("No ELAN for Max frame size; line %d\n", g_lineno);
+	break;
+      }
+      ret = yylex();
+      switch (ret) {
+      case MF_1516:
+	elan->max_frame = LE_MAX_FRAME_1516;
+	break;
+      case MF_4544:
+	elan->max_frame = LE_MAX_FRAME_4544;
+	break;
+      case MF_9234:
+	elan->max_frame = LE_MAX_FRAME_9234;
+	break;
+      case MF_18190:
+	elan->max_frame = LE_MAX_FRAME_18190;
+	break;
+      default:
+	printf("Invalid max frame size %d\n", g_lineno);
+	break;
+      }
+      break;
+    case MF_1516:
+    case MF_4544:
+    case MF_9234:
+    case MF_18190:
+      printf("Invalid max frame size placement; line %d\n", g_lineno);
+      break;
+    case LES_ADDR:
+      if (!elan) {
+	printf("No ELAN for LES; line %d\n",g_lineno);
+	break;
+      }
+      ret = yylex();
+      if (ret != ADDRESS_ATM) {
+	printf("ATM address for LES missing; line %d; ret:%d\n",g_lineno,ret);
+	readnew=0;
+      } else
+	if (add_les(elan, g_return)<0) {
+	  printf("Couldn't read LES address; line %d\n", g_lineno);
+	}
+      break;
+    case ADDRESS_ATM:
+      if (!elan) {
+	set_lecs_addr(g_return);	
+	break;
+      }
+      if (add_atm(elan, g_return)<0)
+	printf("Couldn't read LEC address; line %d\n", g_lineno);
+      break;
+    case DEFAULT:
+      if (!elan) {
+	printf("No ELAN to set as a default; line %d\n",g_lineno);
+	break;
+      }
+      set_default(elan);
+      break;
+    case ERROR:
+      printf("Error reading database file; line %d\n", g_lineno);
+      while(ret==ERROR)
+	ret=yylex();
+      readnew=0;
+      break;
+    default:
+      fclose(yyin);
+      return 0;
+    }
+  }
+}
diff -ur --new-file old/atm/lane/lecs_load.h new/atm/lane/lecs_load.h
--- old/atm/lane/lecs_load.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/lecs_load.h	Sun Aug 11 23:10:22 1996
@@ -0,0 +1,13 @@
+/*
+ *
+ * LECS configuration database loading
+ *
+ * $Id$
+ *
+ */
+#ifndef LECS_LOAD_H
+#define LECS_LOAD_H
+
+int load_db(const char *filename);
+
+#endif
diff -ur --new-file old/atm/lane/load.c new/atm/lane/load.c
--- old/atm/lane/load.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/load.c	Thu Aug  8 23:24:43 1996
@@ -0,0 +1,602 @@
+/*
+ * Configuration file loader
+ *
+ * $Id: load.c,v 1.17 1995/07/02 17:55:16 carnil Exp $
+ *
+ */
+
+/* System includes */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <assert.h>
+#include <syslog.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+
+/* Local includes */
+#include "load.h"
+#include "lane.h"
+#include "units.h"
+#include "dump.h"
+#include "mem.h"
+#include "load_lex.h"
+
+/* Type definitions */
+typedef enum {
+  VT_INT, VT_STR, VT_BOOL, VT_ADDR, VT_PVC
+} VarType_t;
+
+typedef struct {
+  const Unit_t *unit;
+  const char *name;
+  VarType_t type;
+  union {
+    int intval;
+    const char *strval;
+    Bool_t boolval;
+    const AtmAddr_t *addrval;
+    const InitPvc_t *init;
+  } val_u;
+} Var_t;
+
+typedef struct _VarList_t {
+  Var_t *var;
+  struct _VarList_t *next;
+} VarList_t;
+
+/* Local function prototypes */
+static void load_init0(void);
+static void load_init1(void);
+static void load_dump(void);
+static void load_release(void);
+
+static Var_t *find_var(const Unit_t *unit, const char *varname);
+static void add_var(Var_t *var);
+static void load_vars(const char *filename);
+
+
+/* Data */
+#define BUFLEN 256
+static const char *rcsid = "$Id: load.c,v 1.17 1995/07/02 17:55:16 carnil Exp $";
+
+static VarList_t *varlist;
+static const char *var_file = ".lanevars";
+
+const Unit_t load_unit = {
+  "load",
+  &load_init0,
+  &load_init1,
+  &load_dump,
+  &load_release
+};
+
+/* Functions */
+
+/* Initialize local data */
+static void
+load_init0(void)
+{
+  varlist = NULL;
+}
+
+/* Initialization for data that needs other units */
+static void
+load_init1(void)
+{
+  set_var_str(&load_unit, "version", rcsid);
+  /*
+   * Load variables from file
+   * For example:
+   * [main]
+   * debug=True
+   * memdebug=True
+   * [conn]
+   * #S4, Join Timeout, s
+   * S4=60
+   */
+  load_vars(var_file);
+
+  Debug_unit(&load_unit, "Initialized.");
+}
+
+/* Dump status, local data etc. */
+static void
+load_dump(void)
+{
+  dump_vars(NULL);
+}
+
+/* Release allocated memory, close files etc. */
+static void
+load_release(void)
+{
+  VarList_t *tmp;
+  LaneDestList_t *ltmp, *ltmp2;
+
+  Debug_unit(&load_unit, "Releasing unit");
+  for (tmp = varlist; tmp != NULL;) {
+    Debug_unit(&load_unit, "Freeing var %s/%s", tmp->var->unit->name, tmp->var->name);
+    assert(tmp->var != NULL);
+    assert(tmp->var->name != NULL);
+    varlist = varlist->next;
+    if (tmp->var->type == VT_STR){
+      assert(tmp->var->val_u.strval != NULL);
+      mem_free(&load_unit, tmp->var->val_u.strval);
+    }
+    if (tmp->var->type == VT_ADDR){
+      assert(tmp->var->val_u.addrval != NULL);
+      mem_free(&load_unit, tmp->var->val_u.addrval);
+    }
+    if (tmp->var->type == VT_PVC){
+      assert(tmp->var->val_u.init != NULL);
+      assert(tmp->var->val_u.init->pvc != NULL);
+      mem_free(&load_unit, tmp->var->val_u.init->pvc);
+      assert(tmp->var->val_u.init->address != NULL);
+      mem_free(&load_unit, tmp->var->val_u.init->address);
+      ltmp = tmp->var->val_u.init->destinations;
+      while (ltmp != NULL) {
+	ltmp2 = ltmp->next;
+	assert(ltmp->addr != NULL);
+	mem_free(&load_unit, ltmp->addr);
+	mem_free(&load_unit, ltmp);
+	ltmp = ltmp2;
+      }
+      mem_free(&load_unit, tmp->var->val_u.init);
+    }
+    mem_free(&load_unit, tmp->var->name);
+    mem_free(&load_unit, tmp->var);
+    mem_free(&load_unit, tmp);
+    tmp = varlist;
+  }
+}
+
+static Var_t *
+find_var(const Unit_t *unit, const char *varname)
+{
+  VarList_t *tmp;
+
+  assert(unit != NULL);
+  assert(unit->name != NULL);
+  assert(varname != NULL);
+
+  for (tmp = varlist; tmp != NULL; tmp = tmp->next) {
+    assert(tmp->var != NULL);
+    assert(tmp->var->unit != NULL);
+    assert(tmp->var->unit->name != NULL);
+    assert(tmp->var->name != NULL);
+    if (strcmp(unit->name, tmp->var->unit->name) == 0 && strcmp(tmp->var->name, varname) == 0) {
+      break;
+    }
+  }
+  if (tmp) {
+    return tmp->var;
+  }
+  else {
+    return NULL;
+  }
+}
+
+/* Get or initialize variable */
+int
+get_var_int(const Unit_t *unit, const char *varname)
+{
+  const Var_t *tmp;
+
+  tmp = find_var(unit, varname);
+  if (tmp) {
+    assert(tmp->type == VT_INT);
+    return tmp->val_u.intval;
+  }
+  else {
+    return 0;
+  }
+}
+
+const InitPvc_t *get_var_vcc(const Unit_t *unit, const char *varname)
+{
+  const Var_t *tmp;
+
+  tmp=find_var(unit, varname);
+  if(tmp) {
+    assert(tmp->type == VT_PVC);
+    return tmp->val_u.init;
+  } else {
+    return NULL;
+  }
+}
+
+const char *
+get_var_str(const Unit_t *unit, const char *varname)
+{
+  const Var_t *tmp;
+
+  tmp=find_var(unit, varname);
+  if (tmp) {
+    assert(tmp->type == VT_STR);
+    return tmp->val_u.strval;
+  }
+  else {
+    return NULL;
+  }
+}
+
+Bool_t
+get_var_bool(const Unit_t *unit, const char *varname)
+{
+  const Var_t *tmp;
+
+  tmp = find_var(unit, varname);
+  if (tmp) {
+    assert(tmp->type == VT_BOOL);
+    return tmp->val_u.boolval;
+  }
+  else {
+    return BL_FALSE;
+  }
+}
+
+const AtmAddr_t *
+get_var_addr(const Unit_t *unit, const char *varname)
+{
+  const Var_t *tmp;
+
+  tmp = find_var(unit, varname);
+  if (tmp) {
+    assert(tmp->type == VT_ADDR);
+    return tmp->val_u.addrval;
+  }
+  else {
+    return NULL;
+  }
+}
+
+static void
+add_var(Var_t *var)
+{
+  VarList_t *tmpl;
+
+  tmpl = (VarList_t *)mem_alloc(&load_unit, sizeof(VarList_t));
+  tmpl->var = var;
+  tmpl->next = varlist;
+  varlist = tmpl;
+}
+
+/* Set or initialize variable */
+
+void 
+set_var_vcc(const Unit_t *unit, const char *varname, 
+	    const InitPvc_t *vcc)
+{
+  Var_t *tmp;
+  LaneDestList_t *ltmp, *ltmp2;
+
+  assert(unit != NULL && unit->name != NULL && varname != NULL);
+  tmp = find_var(unit, varname);
+  if (tmp == NULL) {
+    tmp = (Var_t *)mem_alloc(&load_unit, sizeof(Var_t));
+    tmp->unit = unit;
+    tmp->name = varname;
+    tmp->val_u.init = vcc;
+    tmp->type = VT_PVC;
+    add_var(tmp);
+  } else {
+    assert(tmp->type == VT_PVC);
+    mem_free(&load_unit, tmp->name);
+    tmp->name = varname;
+    assert(tmp->val_u.init->pvc != NULL);
+    mem_free(&load_unit, tmp->val_u.init->pvc);
+    assert(tmp->val_u.init->address != NULL);
+    mem_free(&load_unit, tmp->val_u.init->address);
+    ltmp = tmp->val_u.init->destinations;
+    while(ltmp != NULL) {
+      ltmp2 = ltmp->next;
+      assert(ltmp->addr != NULL);
+      mem_free(&load_unit, ltmp->addr);
+      mem_free(&load_unit, ltmp);
+      ltmp = ltmp2;
+    }
+    mem_free(&load_unit, tmp->val_u.init);
+    tmp->val_u.init = vcc;
+  }
+}
+
+void
+set_var_int(const Unit_t *unit, const char *varname, int intval)
+{
+  Var_t *tmp;
+
+  assert(unit != NULL && unit->name != NULL && varname != NULL);
+  tmp = find_var(unit, varname);
+  if (tmp == NULL) {
+    tmp = (Var_t *)mem_alloc(&load_unit, sizeof(Var_t));
+    tmp->unit = unit;
+    tmp->name = varname;
+    tmp->val_u.intval = intval;
+    tmp->type = VT_INT;
+    add_var(tmp);
+  }
+  else {
+    assert(tmp->type == VT_INT);
+    mem_free(&load_unit, tmp->name);
+    tmp->name = varname;
+    tmp->val_u.intval = intval;
+  }
+}
+
+void
+set_var_str(const Unit_t *unit, const char *varname, const char *strval)
+{
+  Var_t *tmp;
+
+  assert(unit != NULL && unit->name != NULL && varname != NULL);
+  tmp = find_var(unit, varname);
+  if (tmp == NULL) {
+    tmp = (Var_t *)mem_alloc(&load_unit, sizeof(Var_t));
+    tmp->unit = unit;
+    tmp->name = varname;
+    tmp->val_u.strval = strval;
+    tmp->type = VT_STR;
+    add_var(tmp);
+  } else {
+    assert(tmp->type == VT_STR);
+    mem_free(&load_unit, tmp->name);
+    tmp->name = varname;
+    mem_free(&load_unit, tmp->val_u.strval);
+    tmp->val_u.strval = strval;
+  }
+}
+
+
+void
+set_var_addr(const Unit_t *unit, const char *varname, const AtmAddr_t *addr)
+{
+  Var_t *tmp;
+
+  assert(unit != NULL && unit->name != NULL && varname != NULL);
+  tmp = find_var(unit, varname);
+  if (tmp == NULL) {
+    tmp = (Var_t *)mem_alloc(&load_unit, sizeof(Var_t));
+    tmp->unit = unit;
+    tmp->name = varname;
+    tmp->val_u.addrval = addr;
+    tmp->type = VT_ADDR;
+    add_var(tmp);
+  }
+  else {
+    assert(tmp->type == VT_ADDR);
+    mem_free(&load_unit, tmp->name);
+    tmp->name = varname;
+    mem_free(&load_unit, tmp->val_u.addrval);
+    tmp->val_u.addrval = addr;
+  }
+}
+
+void
+set_var_bool(const Unit_t *unit, const char *varname, Bool_t boolval)
+{
+  Var_t *tmp;
+
+  assert(unit != NULL && unit->name != NULL && varname != NULL);
+  tmp = find_var(unit, varname);
+  if (tmp == NULL) {
+    tmp = (Var_t *)mem_alloc(&load_unit, sizeof(Var_t));
+    tmp->unit = unit;
+    tmp->name = varname;
+    tmp->val_u.boolval = boolval;
+    tmp->type = VT_BOOL;
+    add_var(tmp);
+  }
+  else {
+    mem_free(&load_unit, tmp->name);
+    tmp->name = varname;
+    assert(tmp->type == VT_BOOL);
+    tmp->val_u.boolval = boolval;
+  }
+}
+
+void
+dump_vars(const Unit_t *unit)
+{
+  const VarList_t *tmp;
+  LaneDestList_t *ltmp;
+
+  Debug_unit(&load_unit, "Dumping variables");
+  for (tmp = varlist; tmp != NULL; tmp = tmp->next) {
+    assert(tmp->var != NULL);
+    assert(tmp->var->unit != NULL);
+    assert(tmp->var->unit->name != NULL);
+    assert(tmp->var->name != NULL);
+    if (unit == NULL || strcmp(unit->name, tmp->var->unit->name) == 0) {
+      switch (tmp->var->type) {
+      case VT_INT:
+	Debug_unit(&load_unit, "%s/%s = %d", tmp->var->unit->name, tmp->var->name, tmp->var->val_u.intval);
+	break;
+      case VT_STR:
+	Debug_unit(&load_unit, "%s/%s = \"%s\"", tmp->var->unit->name, tmp->var->name, tmp->var->val_u.strval);
+	break;
+      case VT_BOOL:
+	Debug_unit(&load_unit, "%s/%s = %s", tmp->var->unit->name, tmp->var->name, tmp->var->val_u.boolval == BL_TRUE? "True" : "False" );
+	break;
+      case VT_ADDR:
+	Debug_unit(&load_unit, "%s/%s =", tmp->var->unit->name, tmp->var->name);
+	dump_atmaddr(tmp->var->val_u.addrval);
+	break;
+      case VT_PVC:
+	Debug_unit(&load_unit,"%s/%s = %d,%d,%d with lecid:%d ",
+		   tmp->var->unit->name, 
+		   tmp->var->name, 
+		   tmp->var->val_u.init->pvc->port,
+		   tmp->var->val_u.init->pvc->vpi,
+		   tmp->var->val_u.init->pvc->vci,
+		   tmp->var->val_u.init->lecid);
+	dump_atmaddr(tmp->var->val_u.init->address);
+	ltmp = tmp->var->val_u.init->destinations;
+	while(ltmp) {
+	  dump_printf(EL_CONT,"\t");
+	  dump_addr(ltmp->addr);
+	  dump_printf(EL_CONT,"\n");
+	  ltmp = ltmp->next;
+	}
+	break;
+      }
+    }
+  }
+}
+
+void
+load_vars(const char *file)
+{
+  const Unit_t *curr_unit = NULL;
+
+  int ret;
+  char *varname;
+  InitPvc_t *pvc;
+  LaneDestList_t *ltmp;
+  int read_flag = 1;
+
+  assert(file != NULL);
+  Debug_unit(&load_unit, "Loading variables from file %s", file);
+  yyin = fopen(file, "r");
+  if (!yyin) {
+    Debug_unit(&load_unit, "Cannot open file %s: %s", file, strerror(errno));
+    return;
+  }
+  g_buf_index = 0;
+  do {
+    if (read_flag)
+      ret = yylex();
+    else
+      read_flag =1;
+    switch(ret) {
+    case END:
+      Debug_unit(&load_unit, "EOF");
+      break;
+    case UNIT:
+      Debug_unit(&load_unit, "Got unit %s", g_return.stringgi);
+      curr_unit = find_unit(g_return.stringgi);
+      if (curr_unit == NULL) {
+	Debug_unit(&load_unit, "Unknown unit %s", g_return.stringgi);
+      }
+      Debug_unit(&load_unit, "Got unit %s", g_return.stringgi);
+      mem_free(&load_unit,g_return.stringgi);
+      break;
+    case VARNAME:
+      varname = g_return.stringgi;
+      Debug_unit(&load_unit, "Got variable name %s", varname);
+      ret = yylex();
+      switch(ret) {
+      case STRING:
+	Debug_unit(&load_unit, "Variable is string: %s", g_return.stringgi);
+	set_var_str(curr_unit, varname, g_return.stringgi);
+	break;
+      case BOOLEAN:
+	Debug_unit(&load_unit, "Variable is boolean: %s", 
+		   g_return.bool==BL_TRUE?"True":"False");
+	set_var_bool(curr_unit, varname, g_return.bool);
+	break;
+      case INTEGER:
+	Debug_unit(&load_unit, "Variable is integer: %d", g_return.intti);
+	set_var_int(curr_unit, varname, g_return.intti);
+	break;
+      case ATMADDRESS:
+	Debug_unit(&load_unit, "Variable is atmaddress ");
+	dump_atmaddr(g_return.atmaddress);
+	set_var_addr(curr_unit, varname, g_return.atmaddress);
+	break;
+      case LANEDEST:
+	Debug_unit(&load_unit, "Invalid variable value for %s", varname);
+	mem_free(&load_unit, g_return.destaddr);
+	break;
+      case UNIT:
+	Debug_unit(&load_unit, "Invalid variable value for %s", varname);
+	mem_free(&load_unit, g_return.stringgi);
+	break;
+      case VCC:
+	Debug_unit(&load_unit, "Variable is vcc");
+	pvc = (InitPvc_t *)mem_alloc(curr_unit, sizeof(InitPvc_t));
+	pvc->pvc = (LaneVcc_t *)mem_alloc(curr_unit, sizeof(LaneVcc_t));
+	pvc->pvc->port = g_return.vcc.port;
+	pvc->pvc->vpi = g_return.vcc.vpi;
+	pvc->pvc->vci = g_return.vcc.vci;
+	pvc->address = NULL;
+	pvc->lecid = 0;
+	pvc->destinations = NULL;
+	ret = yylex();
+	if (ret != ATMADDRESS) {
+	  Debug_unit(&load_unit, "Invalid atm_address for pvc %d,%d,%d",
+		     pvc->pvc->port, pvc->pvc->vpi, pvc->pvc->vci);
+	  switch(ret) {
+	  case UNIT:
+	  case STRING:
+	  case VARNAME:
+	    mem_free(&load_unit, g_return.stringgi);
+	    break;
+	  case LANEDEST:
+	    mem_free(&load_unit, g_return.destaddr);
+	    break;
+	  }
+	} else {
+	  pvc->address = g_return.atmaddress;
+	}
+	ret = yylex();
+	if (ret != INTEGER) {
+	  Debug_unit(&load_unit, "Invalid lecid for pvc %d,%d,%d\n",
+		     pvc->pvc->port,pvc->pvc->vpi,pvc->pvc->vci);
+	  switch(ret) {
+	  case UNIT:
+	  case STRING:
+	  case VARNAME:
+	    mem_free(&load_unit, g_return.stringgi);
+	    break;
+	  case LANEDEST:
+	    mem_free(&load_unit, g_return.destaddr);
+	    break;
+	  case ATMADDRESS:
+	    mem_free(&load_unit, g_return.atmaddress);
+	    break;
+	  }
+	} else {
+	  pvc->lecid = g_return.intti;
+	}
+	while((ret=yylex())==LANEDEST) {
+	  ltmp=(LaneDestList_t *)mem_alloc(&load_unit, sizeof(LaneDestList_t));
+	  ltmp->addr = g_return.destaddr;
+	  ltmp->next = pvc->destinations;
+	  pvc->destinations = ltmp;
+	}
+	read_flag=0;
+	set_var_vcc(curr_unit, varname, pvc);
+	break;	
+      default:
+	Debug_unit(&load_unit, "Invalid variable value for %s", varname);
+	break;
+      }
+      break;
+    case STRING:
+      Debug_unit(&load_unit,"Invalid string placement %s",g_return.stringgi);
+      mem_free(&load_unit, g_return.stringgi);
+      break;
+    case ATMADDRESS:
+      Debug_unit(&load_unit, "Invalid atm address placement");
+      mem_free(&load_unit, g_return.atmaddress);
+      break;
+    case LANEDEST:
+      Debug_unit(&load_unit, "Invalid lane destination placement");
+      mem_free(&load_unit, g_return.destaddr);
+      break;
+    case INTEGER:
+      Debug_unit(&load_unit, "Invalid integer placement");
+      break;
+    default:
+      Debug_unit(&load_unit, "Invalid input");
+      break;
+    }
+  } while (ret != END);
+  if (fclose(yyin) != 0) {
+    Debug_unit(&load_unit, "Cannot close file %s: %s", file, strerror(errno));
+  }
+}
+
diff -ur --new-file old/atm/lane/load.h new/atm/lane/load.h
--- old/atm/lane/load.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/load.h	Thu Aug  8 23:25:04 1996
@@ -0,0 +1,42 @@
+/*
+ * Configuration file loader
+ *
+ * $Id: load.h,v 1.10 1995/07/02 17:55:16 carnil Exp $
+ *
+ */
+#ifndef LANE_LOAD_H
+#define LANE_LOAD_H
+
+/* System includes needed for types */
+
+/* Local includes needed for types */
+#include "units.h"
+#include "lane.h"
+
+/* Type definitions */
+typedef enum {
+  BL_FALSE=0, BL_TRUE
+} Bool_t;
+
+/* Global function prototypes */
+/* Get or initialize variable */
+int get_var_int(const Unit_t *unit, const char *varname);
+const char *get_var_str(const Unit_t *unit, const char *varname);
+Bool_t get_var_bool(const Unit_t *unit, const char *varname);
+const AtmAddr_t *get_var_addr(const Unit_t *unit, const char *varname);
+const InitPvc_t *get_var_vcc(const Unit_t *unit, const char *varname);
+
+/* Set or initialize variable */
+void set_var_int(const Unit_t *unit, const char *varname, int intval);
+void set_var_str(const Unit_t *unit, const char *varname, const char *strval);
+void set_var_bool(const Unit_t *unit, const char *varname, Bool_t boolval);
+void set_var_addr(const Unit_t *unit, const char *varname, const AtmAddr_t *addr);
+void set_var_vcc(const Unit_t *unit, const char *varname, const InitPvc_t *vcc);
+/* Dump variable definitions, NULL == all */
+void dump_vars(const Unit_t *unit);
+
+/* Global data */
+extern const Unit_t load_unit;
+
+#endif
+
diff -ur --new-file old/atm/lane/load_lex.h new/atm/lane/load_lex.h
--- old/atm/lane/load_lex.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/load_lex.h	Thu Aug  8 23:25:40 1996
@@ -0,0 +1,40 @@
+/*
+ * Configuration file loader, lex header
+ *
+ * $Id: load_lex.h,v 1.1 1995/07/02 17:54:46 carnil Exp $
+ *
+ */
+#ifndef __LOAD_LEX
+#define __LOAD_LEX
+
+#include <stdio.h>
+
+#include "lane.h"
+#include "load.h"
+
+#define UNIT 20
+#define BOOLEAN 21
+#define ATMADDRESS 22
+#define STRING 23
+#define INTEGER 24
+#define LANEDEST 25
+#define VARNAME 27
+#define VCC 28
+#define ERROR 26
+#define END 0
+
+typedef struct {
+  Bool_t bool;
+  int intti;
+  AtmAddr_t *atmaddress;
+  LaneDestination_t *destaddr;
+  char *stringgi;
+  LaneVcc_t vcc;
+} Ret_t;
+
+extern FILE *yyin;
+extern int g_buf_index;
+extern Ret_t g_return;
+
+int yylex(void);
+#endif
diff -ur --new-file old/atm/lane/load_lex.l new/atm/lane/load_lex.l
--- old/atm/lane/load_lex.l	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/load_lex.l	Fri Feb  2 08:15:53 1996
@@ -0,0 +1,121 @@
+%{
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "load_lex.h"
+#include "mem.h"
+#include "load.h"
+
+Ret_t g_return;
+char g_buf[256];
+int g_buf_index;
+
+char s_input(void);
+int s_unput(char);
+
+%}
+
+D [0-9]
+C [a-zA-Z]
+H [0-9a-fA-F]
+
+%%
+[\t\n ]		{}
+\"[^"]*\"      	{
+                 g_return.stringgi = mem_alloc(&load_unit, strlen(yytext));
+		 strcpy(g_return.stringgi,&yytext[1]);
+		 g_return.stringgi[strlen(yytext)-2] = '\0';
+		 return STRING;}
+\:.*		{int i;
+		 int hex;
+		 g_return.atmaddress = (AtmAddr_t *)
+		   mem_alloc(&load_unit, sizeof(AtmAddr_t));
+		 for(i=0;i<20;i++) {
+		   if(sscanf(&yytext[i*3],":%x",&hex) != 1)
+		     return ERROR;
+		   g_return.atmaddress->addr[i] = (unsigned char) hex;
+		 }
+		 return ATMADDRESS;
+	        }
+True	|
+true		{g_return.bool = BL_TRUE;
+		 return BOOLEAN;
+		}	
+False	|
+false		{g_return.bool = BL_FALSE;
+		 return BOOLEAN;
+		}
+\#.*		{}
+{H}{H}\;{H}{H}\;{H}{H}\;{H}{H}\;{H}{H}\;{H}{H}\;	{
+                 int i, hex;
+		 g_return.destaddr = (LaneDestination_t *)
+		   mem_alloc(&load_unit, sizeof(LaneDestination_t));
+		 for(i=0;i<5;i++) {
+		   if (sscanf(&yytext[i*3],"%x;",&hex) != 1)
+		     return ERROR;
+		   g_return.destaddr->a_r.mac_address[i] = hex;
+		 }	
+		 g_return.destaddr->tag = LANE_DEST_MAC;
+		 return LANEDEST;
+		}
+{D}+\,{D}+\,{D}+	{
+		 sscanf(yytext,"%ld,%ld,%ld",&g_return.vcc.port,
+			&g_return.vcc.vpi, &g_return.vcc.vci);
+		 return VCC;
+	        }
+{D}+		{int tmp;
+		 sscanf(yytext,"%d",&tmp);
+		 g_return.intti = tmp;
+		 return INTEGER;}
+\[{C}[a-zA-Z0-9]*\] {g_return.stringgi = mem_alloc(&load_unit, strlen(yytext));
+		 strcpy(g_return.stringgi,&yytext[1]);
+		 g_return.stringgi[strlen(yytext)-2] = '\0';
+		 return UNIT;}
+{C}[a-zA-Z0-9]*\=  {g_return.stringgi = mem_alloc(&load_unit, strlen(yytext));
+		 strcpy(g_return.stringgi,yytext);
+		 g_return.stringgi[strlen(yytext)-1] = '\0';
+		 return VARNAME;}
+\~              {return END;}
+.               {return ERROR;}
+%%
+/* Flex != lex
+#undef input
+#define input s_input
+#undef unput
+#define unput(c) s_unput(c)
+
+char s_input(void)
+{
+  int c;
+
+  if (g_buf_index <=0)
+    c = getc(g_fd);
+  else
+    c = g_buf[--g_buf_index];
+  if (c==EOF) {return '~';}
+  printf("%d :%c\n",c,c);
+  return c;
+}
+*/
+int yywrap()
+{
+  char c;
+
+  return 1;
+  c = input();
+  if (c == '~')
+    return 1;
+  else {
+    unput(c);
+    return 0;
+  }
+}
+/*
+int s_unput(char c)
+{
+  g_buf[g_buf_index++] = c;
+  return 1;
+}
+*/
+
+
diff -ur --new-file old/atm/lane/mem.c new/atm/lane/mem.c
--- old/atm/lane/mem.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/mem.c	Thu Aug  8 23:26:03 1996
@@ -0,0 +1,160 @@
+/*
+ * Memory allocation unit
+ *
+ * $Id: mem.c,v 1.13 1994/11/10 10:02:02 asdf Exp $
+ *
+ */
+
+/* System includes */
+#include <stdlib.h>
+#include <string.h>
+
+/* Local includes */
+#include "mem.h"
+#include "dump.h"
+#include "load.h"
+#include "units.h"
+
+/* Type definitions */
+typedef struct _MemList_t {
+  void *mem;
+  size_t memsize;
+  const Unit_t *unit;
+  struct _MemList_t *next;
+} MemList_t;
+
+/* Local function prototypes */
+static void mem_init0(void);
+static void mem_init1(void);
+static void mem_dump_all(void);
+static void mem_release(void);
+
+/* Data */
+static const char *rcsid = "$Id: mem.c,v 1.13 1994/11/10 10:02:02 asdf Exp $";
+
+static MemList_t *memlist;
+
+const Unit_t mem_unit = {
+  "memory",
+  &mem_init0,
+  &mem_init1,
+  &mem_dump_all,
+  &mem_release
+};
+
+static unsigned int alloccount, freecount;
+
+/* Functions */
+
+/* Initialize local data */
+static void
+mem_init0(void)
+{
+  memlist = NULL;
+  alloccount = 0;
+  freecount = 0;
+}
+
+/* Initialization for data that needs other units */
+static void
+mem_init1(void)
+{
+  set_var_str(&mem_unit, "version", rcsid);
+  Debug_unit(&mem_unit, "Initialized.");
+}
+
+/* Dump status, local data etc. */
+static void
+mem_dump_all(void)
+{
+  Debug_unit(&mem_unit, "Memory statistics:");
+  mem_dump(NULL);
+  Debug_unit(&mem_unit, "%d allocs, %d frees", alloccount, freecount);
+}
+
+/* Release allocated memory, close files etc. */
+static void
+mem_release(void)
+{
+  MemList_t *tmp;
+  Debug_unit(&mem_unit, "Releasing unit");
+
+  for (tmp = memlist; tmp != NULL; tmp = tmp->next) {
+    Debug_unit(&mem_unit, "memory not released: unit %s size %u ptr 0x%x", tmp->unit->name, tmp->memsize, tmp->mem);
+    mem_free(&mem_unit, tmp->mem);
+  }
+}
+
+/* Allocate memory for unit */
+void *
+mem_alloc(const Unit_t *unit, size_t nbytes)
+{
+  MemList_t *tmp;
+
+  alloccount++;
+  tmp = (MemList_t *)malloc(sizeof(MemList_t));
+  tmp->mem = malloc(nbytes);
+  tmp->memsize = nbytes;
+  tmp->unit = unit;
+  tmp->next = memlist;
+  memlist = tmp;
+  if (get_var_bool(unit, "memdebug") == BL_TRUE) {
+    Debug_unit(&mem_unit, "unit %s allocates size %u: ptr 0x%x", unit->name, nbytes, tmp->mem);
+  }
+  return tmp->mem;
+}
+
+/* Free memory block */
+void
+mem_free(const Unit_t *unit, const void *mem)
+{
+  MemList_t *tmp, *prev = NULL;
+  Bool_t debug;
+
+  freecount++;
+  debug = get_var_bool(unit, "memdebug");
+  if (debug == BL_TRUE) {
+    Debug_unit(&mem_unit, "unit %s frees ptr 0x%x", unit->name, mem);
+  }
+  for (tmp = memlist; tmp != NULL; prev = tmp, tmp = tmp->next) {
+    if (tmp->mem == mem) {
+      break;
+    }
+  }
+  /* Found a match? */
+  if (tmp) {
+    if (strcmp(tmp->unit->name, unit->name) != 0) {
+      Debug_unit(&mem_unit, "unit %s frees ptr 0x%x size %d allocated by unit %s", unit->name, tmp->mem, tmp->memsize, tmp->unit->name);
+    }
+    if (memlist == tmp) {
+      memlist = tmp->next;
+    }
+    if (prev != NULL) {
+      prev->next = tmp->next;
+    }
+    if (debug == BL_TRUE) {
+      Debug_unit(&mem_unit, "freeing %d bytes", tmp->memsize);
+    }
+    free(tmp->mem);
+    free(tmp);
+  }
+  else {
+    if (debug == BL_TRUE) {
+      Debug_unit(&mem_unit, "could not find block 0x%x for freeing", mem);
+    }
+  }
+}
+
+/* Dump memory allocation information about unit, NULL == all units */
+void
+mem_dump(const Unit_t *unit)
+{
+  MemList_t *tmp;
+
+  for (tmp = memlist; tmp != NULL; tmp = tmp->next) {
+    if (unit == NULL || strcmp(tmp->unit->name, unit->name) == 0) {
+      Debug_unit(&mem_unit, "unit %s size %u ptr 0x%x", tmp->unit->name, tmp->memsize, tmp->mem);
+    }
+  }
+}
+
diff -ur --new-file old/atm/lane/mem.h new/atm/lane/mem.h
--- old/atm/lane/mem.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/mem.h	Thu Aug  8 23:26:13 1996
@@ -0,0 +1,30 @@
+/*
+ * Memory allocation unit
+ *
+ * $Id: mem.h,v 1.7 1994/11/10 10:00:26 asdf Exp $
+ *
+ */
+
+#ifndef LANE_MEM_H
+#define LANE_MEM_H
+
+/* System includes needed for types */
+#include "sys/types.h"
+
+/* Local includes needed for types */
+#include "units.h"
+
+/* Type definitions */
+
+/* Global function prototypes */
+void *mem_alloc(const Unit_t *unit, size_t nbytes);
+void mem_free(const Unit_t *unit, const void *mem);
+
+/* Dump memory allocation info, NULL == all */
+void mem_dump(const Unit_t *unit);
+
+/* Global data */
+extern const Unit_t mem_unit;
+
+#endif
+
diff -ur --new-file old/atm/lane/mem_lecs.c new/atm/lane/mem_lecs.c
--- old/atm/lane/mem_lecs.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/mem_lecs.c	Sun Aug 18 22:21:49 1996
@@ -0,0 +1,88 @@
+/*
+ *
+ * Memory handling funcs
+ *
+ * $Id$
+ *
+ */
+/* System includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+/* Local includes */
+#include "mem_lecs.h"
+
+typedef struct _Mem_t {
+  size_t size;
+  void *start;
+  char *unit;
+  struct _Mem_t *next;
+} Mem_t;
+
+static Mem_t *memlist = NULL;
+
+void*
+mem_alloc(const char *unit, size_t nbytes)
+{
+  Mem_t *entry;
+
+  entry = (Mem_t *)malloc(sizeof(Mem_t));
+  if (!entry) {
+    perror("malloc");
+    return NULL;
+  }
+  entry->size = nbytes;
+  entry->unit = (char*)malloc(strlen(unit)+1);
+  if (!entry->unit) {
+    perror("malloc");
+    free(entry);
+    return NULL;
+  }
+  memcpy(entry->unit, unit, strlen(unit)+1);
+  entry->start = malloc(nbytes);
+  if (!entry->start) {
+    perror("malloc");
+    free(entry->unit);
+    free(entry);
+    return NULL;
+  }
+  entry->next = memlist;
+  memlist = entry;
+  return entry->start;
+}
+
+void 
+mem_free(const char *unit, const void *mem)
+{
+  Mem_t *tmp, *prev = NULL;
+
+  for (tmp=memlist;tmp;prev=tmp,tmp=tmp->next)
+    if (tmp->start == mem)
+      break;
+
+  if (tmp) { /* Found match */
+    if (memlist == tmp) {
+      memlist = tmp->next;
+    }
+    if (prev != NULL)
+      prev->next = tmp->next;
+    free(tmp->unit);
+    free(tmp->start);
+    free(tmp);
+  } else {
+    printf("Trying to free memory by %s, allocated by %s, size %d\n",
+	   unit, tmp->unit, tmp->size);
+  }
+}
+
+void 
+mem_dump(void)
+{
+  Mem_t *tmp;
+
+  printf("Dumping memory allocation\n");
+  for (tmp=memlist;tmp;tmp=tmp->next)
+    printf("%s : %d bytes from %p\n", tmp->unit, tmp->size, tmp->start);
+  printf("-------------------------\n");
+}
diff -ur --new-file old/atm/lane/mem_lecs.h new/atm/lane/mem_lecs.h
--- old/atm/lane/mem_lecs.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/mem_lecs.h	Sun Aug 18 22:21:40 1996
@@ -0,0 +1,19 @@
+/*
+ *
+ * Memory handling funcs
+ *
+ * $Id$
+ *
+ */
+
+#ifndef MEM_LECS_H
+#define MEM_LECS_H
+
+/* System includes */
+#include <sys/types.h>
+
+void *mem_alloc(const char *unit, size_t nbytes);
+void mem_free(const char *unit, const void *mem);
+
+void mem_dump(void);
+#endif /* MEM_LECS_H */
diff -ur --new-file old/atm/lane/packet.c new/atm/lane/packet.c
--- old/atm/lane/packet.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/packet.c	Sun Aug 18 22:13:34 1996
@@ -0,0 +1,123 @@
+/*
+ * Functions to send packets
+ *
+ * $Id: packet.c,v 1.4 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+
+/* System includes */
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+/* Local includes */
+#include "mem.h"
+#include "lane.h"
+#include "dump.h"
+#include "load.h"
+#include "connect.h"
+#include "events.h"
+#include "db.h"
+#include "packet.h"
+
+int
+forward_arp_request(LaneControl_t *to_forward, 
+		    Proxy_t *proxyl)
+{
+  Proxy_t *tmp;
+  int a;
+
+  Debug_unit(&conn_unit,"Forward_arp called");
+
+  tmp = proxyl;
+
+  while(tmp) {
+    a = write(tmp->fd, to_forward, sizeof(LaneControl_t));   
+    if (a == -1)
+      dump_error(&conn_unit, "Forward arp failed");
+    tmp = tmp->next;
+  }
+  return 1;
+}
+
+
+int
+send_arp_response(int fd, LaneControl_t *lc,
+		  unsigned int status, Reg_t *found)
+{
+  
+  Debug_unit(&conn_unit,"Send_arp_response called to %d",fd);
+
+  lc->opcode = htons(LE_ARP_RESPONSE);
+  lc->status = (unsigned short)htons((0xffff & status));
+
+  /* Clear the potential Remote flag */
+  if ((lc->flags & htons(LE_FLAG_REMOTE)) == htons(LE_FLAG_REMOTE)) {
+    lc->flags = (lc->flags ^ htons(LE_FLAG_REMOTE));
+  }
+  if (found) {
+    memcpy(&lc->target_addr,&found->atm_address, sizeof(lc->target_addr));
+  }
+  if (send_control_frame(fd, lc) == 0) {
+    dump_error(&conn_unit,"Send arp response failed");
+    return 0;
+  }
+  return 1;
+}
+
+int
+send_register_response(int fd, LaneControl_t *lc,
+		       unsigned int status, int reg)
+{
+
+  Debug_unit(&conn_unit,"Send_register_response called to %d",fd);
+  if (reg == 1)
+    lc->opcode = htons(LE_REGISTER_RESPONSE);
+  else
+    lc->opcode = htons(LE_UNREGISTER_RESPONSE);
+  lc->status = (unsigned short)htons(0xffff & status);
+
+  if (send_control_frame(fd, lc) == 0) {
+    dump_error(&conn_unit,"Send register response failed");
+    return 0;
+  }
+  return 1;
+}
+
+int
+send_join_response(int fd, LaneControl_t *lc, int lecid, 
+		   unsigned int status)
+{
+  Debug_unit(&conn_unit,"Send_join_response called to %d",fd);
+  lc->opcode = htons(LE_JOIN_RESPONSE);
+  lc->status = (unsigned short)htons(0xffff & status);
+  lc->lecid = lecid;
+
+  if (send_control_frame(fd, lc) == 0) {
+    dump_error(&conn_unit,"Send join response failed");
+    return 0;
+  }
+  return 1;
+}
+
+int
+send_control_frame(int fd, LaneControl_t *to_send)
+{
+  int a;
+
+  Debug_unit(&conn_unit,"Send control frame");
+  dump_control(to_send);
+  a = write(fd, to_send, sizeof(LaneControl_t));
+  if (a == -1) {
+    dump_error(&conn_unit,"Write error");
+    return 0;
+  }
+  return 1;
+}
+
+
diff -ur --new-file old/atm/lane/packet.h new/atm/lane/packet.h
--- old/atm/lane/packet.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/packet.h	Sun Aug 18 22:13:58 1996
@@ -0,0 +1,23 @@
+/*
+ * Database handling functions
+ *
+ * $Id: packet.h,v 1.4 1995/11/15 08:27:11 carnil Exp $
+ *
+ */
+
+#include "lane.h"
+#include "connect.h"
+
+/* Protos */
+int send_arp_response(int fd, LaneControl_t *lc,
+		      unsigned int status, Reg_t *found);
+
+int send_register_response(int fd, LaneControl_t *lc,
+			   unsigned int status, int reg);
+
+int send_join_response(int fd, LaneControl_t *lc, int lecid, 
+		       unsigned int status);
+
+int send_control_frame(int fd, LaneControl_t *to_send);
+int forward_arp_request(LaneControl_t *to_forward,
+			Proxy_t *proxyl);
diff -ur --new-file old/atm/lane/timers.c new/atm/lane/timers.c
--- old/atm/lane/timers.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/timers.c	Thu Aug  8 23:26:51 1996
@@ -0,0 +1,234 @@
+/*
+ * Timers and signals wrapper
+ *
+ * $Id: timers.c,v 1.9 1995/07/02 17:53:18 carnil Exp $
+ *
+ */
+
+/* System includes */
+#define _POSIX_SOURCE 1
+#include <unistd.h>
+#include <signal.h>
+#include <assert.h>
+#include <limits.h>
+
+/* Local includes */
+#include "timers.h"
+#include "load.h"
+#include "dump.h"
+#include "mem.h"
+
+/* Type definitions */
+typedef struct _TimerList_t {
+  Timer_t *timer;
+  struct _TimerList_t *next;
+} TimerList_t;
+
+/* Local function prototypes */
+static void timer_init0(void);
+static void timer_init1(void);
+static void timer_dump(void);
+static void timer_release(void);
+static void hup_handler(int nsig);
+static void usr1_handler(int nsig);
+static void usr2_handler(int nsig);
+static void alarm_handler(int nsig);
+
+/* Data */
+#define TIMER_MAX 65535
+
+static const char *rcsid="$Id: timers.c,v 1.9 1995/07/02 17:53:18 carnil Exp $";
+
+const Unit_t timer_unit = {
+  "timer",
+  &timer_init0,
+  &timer_init1,
+  &timer_dump,
+  &timer_release
+};
+
+static TimerList_t *timerlist;
+volatile int sig_hup, sig_usr1, sig_usr2, sig_alarm;
+
+/* Functions */
+
+/* Initialize local data */
+static void
+timer_init0(void)
+{
+  struct sigaction sig;
+
+  sig_hup = sig_usr1 = sig_usr2 = sig_alarm = 0;
+
+  sig.sa_handler = hup_handler;
+  sigemptyset(&sig.sa_mask);
+  sig.sa_flags = 0;
+  sigaction(SIGHUP, &sig, NULL);
+
+  sig.sa_handler = usr1_handler;
+  sigemptyset(&sig.sa_mask);
+  sig.sa_flags = 0;
+  sigaction(SIGUSR1, &sig, NULL);
+
+  sig.sa_handler = usr2_handler;
+  sigemptyset(&sig.sa_mask);
+  sig.sa_flags = 0;
+  sigaction(SIGUSR2, &sig, NULL);
+
+  sig.sa_handler = alarm_handler;
+  sigemptyset(&sig.sa_mask);
+  sig.sa_flags = 0;
+  sigaction(SIGALRM, &sig, NULL);
+
+  timerlist = NULL;
+}
+
+/* Initialization for data that needs other units */
+static void
+timer_init1(void)
+{
+  set_var_str(&timer_unit, "version", rcsid);
+  Debug_unit(&timer_unit, "Initialized.");
+}
+
+/* Dump status, local data etc. */
+static void
+timer_dump(void)
+{
+  TimerList_t *tmp;
+
+  for (tmp = timerlist; tmp != NULL; tmp = tmp->next) {
+    assert(tmp->timer != NULL);
+    assert(tmp->timer->unit != NULL);
+    assert(tmp->timer->unit->name != NULL);
+    Debug_unit(&timer_unit, "unit %s alarm %d data 0x%x", tmp->timer->unit->name, tmp->timer->alarm_time, tmp->timer->data);
+  }
+}
+
+/* Release allocated memory, close files etc. */
+static void
+timer_release(void)
+{
+  TimerList_t *tmp;
+
+  alarm(0);
+  for (tmp = timerlist; tmp != NULL; ) {
+    assert(tmp->timer != NULL);
+    assert(tmp->timer->unit != NULL);
+    assert(tmp->timer->unit->name != NULL);
+    Debug_unit(&timer_unit, "discarding timer, unit %s alarm %d data 0x%x", tmp->timer->unit->name, tmp->timer->alarm_time, tmp->timer->data);
+    tmp = timerlist->next;
+    mem_free(&timer_unit, timerlist->timer);
+    mem_free(&timer_unit, timerlist);
+    timerlist = tmp;
+  }
+}
+
+Timer_t *
+timer_new(const Unit_t *unit)
+{
+  Timer_t *timer;
+  TimerList_t *tmp;
+
+  timer = (Timer_t *)mem_alloc(&timer_unit, sizeof(Timer_t));
+  timer->alarm_time = INT_MAX;
+  timer->unit = unit;
+  tmp = (TimerList_t *)mem_alloc(&timer_unit, sizeof(TimerList_t *));
+  tmp->timer = timer;
+  tmp->next = timerlist;
+  timerlist = tmp;
+  timer_dump();
+  return (Timer_t *)timer;
+}
+
+void
+timer_free(const Unit_t *unit, Timer_t *timer)
+{
+  TimerList_t *tmp, *prev = NULL;
+
+  for (tmp = timerlist; tmp != NULL; tmp = tmp->next) {
+    assert(tmp->timer != NULL);
+    if (tmp->timer == timer) {
+      mem_free(&timer_unit, tmp->timer);
+      if (prev != NULL) {
+	prev->next = tmp->next;
+      }
+      else {
+	timerlist = tmp->next;
+      }
+      mem_free(&timer_unit, tmp);
+      return;
+    }
+    prev = tmp;
+  }
+}
+
+/* Delay for the specified period */
+void
+timer_alarm(const Unit_t *unit, Timer_t *timer, unsigned int nsecs, const void *data)
+{
+  assert (timer != NULL);
+  timer->data = data;
+  timer->alarm_time = time(NULL) + nsecs;
+}
+
+/* Acknowledge alarm */
+void
+timer_ack(const Unit_t *unit, Timer_t *timer)
+{
+  assert (timer != NULL);
+  timer->alarm_time = INT_MAX;
+}
+
+/* Find soonest timer expiration */
+Timer_t *
+timer_find_soonest(const Unit_t *unit)
+{
+  TimerList_t *tmp;
+  Timer_t *lowest = NULL;
+
+  for (tmp = timerlist; tmp != NULL; tmp = tmp->next ) {
+    assert(tmp->timer != NULL);
+    if (lowest == NULL || tmp->timer->alarm_time < lowest->alarm_time) {
+      lowest = tmp->timer;
+    }
+  }
+  if (lowest == NULL) {
+    return NULL;
+  }
+  Debug_unit(&timer_unit, "lowest: %d", lowest->alarm_time);
+  return lowest;
+}
+
+/* Handler for signal HUP, restart */
+static void
+hup_handler(int nsig)
+{
+  Debug_unit(&timer_unit, "Hup");
+  sig_hup = 1;
+}
+
+/* Handler for signal USR1, status dump */
+static void
+usr1_handler(int nsig)
+{
+  Debug_unit(&timer_unit, "Usr1");
+  sig_usr1 = 1;
+}
+
+/* Handler for signal INT, exit */
+static void
+usr2_handler(int nsig)
+{
+  Debug_unit(&timer_unit, "Int");
+  sig_usr2 = 1;
+}
+
+/* Handler for signal ALARM, timer expiration */
+static void
+alarm_handler(int nsig)
+{
+  Debug_unit(&timer_unit, "Alarm");
+  sig_alarm = 1;
+}
+
diff -ur --new-file old/atm/lane/timers.h new/atm/lane/timers.h
--- old/atm/lane/timers.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/timers.h	Thu Aug  8 23:27:04 1996
@@ -0,0 +1,36 @@
+/*
+ * Timers and signals wrapper
+ *
+ * $Id: timers.h,v 1.9 1995/07/05 21:06:37 carnil Exp $
+ *
+ */
+
+#ifndef TIMERS_H
+#define TIMERS_H
+
+/* System includes needed for types */
+#include <time.h>
+
+/* Local includes needed for types */
+#include "units.h"
+
+/* Type definitions */
+typedef struct {
+  const Unit_t *unit;
+  unsigned int alarm_time;
+  const void *data;
+} Timer_t;
+
+/* Global function prototypes */
+Timer_t *timer_new(const Unit_t *unit);
+void timer_free(const Unit_t *unit, Timer_t *timer);
+void timer_alarm(const Unit_t *unit, Timer_t *timer, unsigned int nsecs, const void *data);
+void timer_ack(const Unit_t *unit, Timer_t *timer);
+Timer_t *timer_find_soonest(const Unit_t *unit);
+
+/* Global data */
+extern const Unit_t timer_unit;
+extern volatile int sig_hup, sig_usr1, sig_usr2, sig_alarm;
+
+#endif
+
diff -ur --new-file old/atm/lane/units.c new/atm/lane/units.c
--- old/atm/lane/units.c	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/units.c	Thu Aug  8 23:27:18 1996
@@ -0,0 +1,59 @@
+/*
+ * Unitlist
+ *
+ * $Id: units.c,v 1.12 1995/06/21 18:55:37 carnil Exp $
+ *
+ */
+
+/* System includes */
+#include <assert.h>
+#include <string.h>
+
+/* Local includes */
+#include "units.h"
+#include "mem.h"
+#include "lane.h"
+#include "load.h"
+#include "dump.h"
+#include "connect.h"
+#include "timers.h"
+#include "events.h"
+#include "atm.h"
+
+/* Type definitions */
+
+/* Local function prototypes */
+
+/* Data */
+const Unit_t *unitlist[] = {
+  &dump_unit,
+  &mem_unit,
+  &load_unit,
+  &conn_unit,
+  &main_unit,
+  &timer_unit,
+  &events_unit,
+  &atm_unit,
+  NULL
+};
+
+const unsigned int num_units = sizeof(unitlist)/sizeof(Unit_t *)-1;
+
+/* Functions */
+const Unit_t *
+find_unit(const char *name)
+{
+  const Unit_t *tmp;
+  unsigned int i;
+
+  assert(name != NULL);
+  for (i = 0; unitlist[i] != NULL; i++) {
+    tmp = unitlist[i];
+    assert (tmp->name != NULL);
+    if (strcmp(tmp->name, name) == 0) {
+      return tmp;
+    }
+  }
+  return NULL;
+}
+
diff -ur --new-file old/atm/lane/units.h new/atm/lane/units.h
--- old/atm/lane/units.h	Thu Jan  1 01:00:00 1970
+++ new/atm/lane/units.h	Thu Aug  8 23:27:29 1996
@@ -0,0 +1,38 @@
+/*
+ * Unitlist
+ *
+ * $Id: units.h,v 1.6 1994/11/10 10:00:41 asdf Exp $
+ *
+ */
+#ifndef LANE_UNIT_H
+#define LANE_UNIT_H
+
+/* System includes needed for types */
+
+/* Local includes needed for types */
+
+/* Type definitions */
+typedef void (* VoidFunc_t)(void);
+
+typedef struct {
+  const char *name;
+  VoidFunc_t init0;
+  VoidFunc_t init1;
+  VoidFunc_t dump;
+  VoidFunc_t release;
+} Unit_t;
+
+/* Global function prototypes */
+/* Find unit */
+const Unit_t *find_unit(const char *name);
+
+/* Global data */
+extern const Unit_t *unitlist[];
+extern const unsigned int num_units;
+
+/* Enumerate units */
+#define FOR_ALL_UNITS(unit) for (unit = &unitlist[0]; *unit != NULL; unit++)
+#define FOR_ALL_UNITS_REV(unit) for (unit = &unitlist[num_units-1]; unit >= &unitlist[0]; unit--)
+
+#endif
+
diff -ur --new-file old/atm/led/Makefile new/atm/led/Makefile
--- old/atm/led/Makefile	Thu Jul 18 21:38:54 1996
+++ new/atm/led/Makefile	Tue Aug 20 20:39:17 1996
@@ -1,5 +1,5 @@
 LIBS=-latm
-OBJS=lec_arp.o lec_ctrl.o map.o le_disp.o g_event.o \
+OBJS=lec_arp.o lec_ctrl.o le_disp.o g_event.o \
    utils.o timers.o address.o conn.o main.o kernel_itf.o
 BOOTPGMS=zeppelin
 MANS=
diff -ur --new-file old/atm/led/USAGE new/atm/led/USAGE
--- old/atm/led/USAGE	Sun Jul  7 14:12:47 1996
+++ new/atm/led/USAGE	Sat Aug 10 13:58:44 1996
@@ -10,10 +10,14 @@
 Lan Emulation Daemon (LED) Zeppelin & kernel driver. Description
 of LAN-E can be found from ATM Forum's specification "LAN Emulation
 Over ATM - Version 1.0". 
+ftp://ftp.atmforum.com/pub/specs/af-lane-0021.000.ps.Z
 
 Usage:
+======
+In order to use LE one has to compile kernel with LANE support.
+
 zeppelin [-c LECS_address]|[-s LES_address] [-e esi] [-n VLAN_name]
-         [-m msg_mask]
+         [-m msg_mask] [-l listen_address]
 
 LECS_address: ATM address of Lan Emulation Configuration Server, if not
 set, Well-Known server address is used.
@@ -31,6 +35,8 @@
 setting global message mask. 0 = No messages, ffff = All messages.
 Purpose of different mask values is shown in source file g_event.h.
 
+listen_address: ATM address that zeppelin uses in signalling.
+
 e.g. 
 > zeppelin -c coral_lecs -n tut-lane1 &
 > ifconfig lec0 viulu.lane.tut.fi netmask 255.255.255.0
@@ -57,10 +63,10 @@
   /usr/local/bin/zeppelin -c coral_lecs -m 3
   sleep 30
 done
+----8<-----
 
-This is needed because zeppelin comes down in situations it can't handle.
-Wrapper scripts take care of the fact that LE gets up after this kind
-of situation.
+Wrapper scripts aren't really needed anymore. This is because demon
+code is becoming more stable and won't (hopefully) crash :)
 
 Known limitations:
 ------------------
diff -ur --new-file old/atm/led/addr_reg.h new/atm/led/addr_reg.h
--- old/atm/led/addr_reg.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/addr_reg.h	Tue Aug  6 16:33:07 1996
@@ -53,124 +53,6 @@
 *   06-Sep-95  TLR   Added special address allocation call.
 *
 * Description:   
-*   OVERVIEW OF ADDRESS REGISTRATION:
-*
-*   Before reading this file, it is assumed that the reader has read section
-*   5.8 of the UNI 3.0 specification (Address registration).  In this
-*   description the term Network Interface Card (NIC) is used for the
-*   "user-side" of the network interface.
-*
-*   Address registration is the process through which an end-node registers
-*   ATM addresses with the switch.  An ATM address is the concatenation of a
-*   network prefix, ESI (MAC address), and a selector.  Network prefixes are
-*   provided by the switch, ESI values are typically in a ROM on the NIC, and 
-*   the selector is an arbitrary value that can be chosen by the end-station.
-*   In this implementation, the selector is used to enable 256 ATM addresses
-*   to be derived from a single network prefix adn ESI concatenation.
-*
-*   All network communication between the address registration module and the 
-*   switch is done through SNMP messages (get, get-next, set, and traps).
-*
-*   When this module detects that the link has just come up, it sends out a
-*   "cold-start" trap to the switch. It then waits for up to 5 seconds for the
-*   switch to set a network prefix.  If this does not occur, this module again
-*   sends out a cold start trap. This process is repeated indefinitely.
-*
-*   While waiting for the switch to set the network prefix, address
-*   registration verifies that the switch's address table is empty.  If the 
-*   address table is not empty, then this module restarts and goes back and 
-*   sends a cold start trap [the check for the empty address table ensures that
-*   the switch processed the NIC's cold start trap].
-*  
-*   When the switch's address table is empty and the switch sets a network
-*   prefix on the NIC, then this module can register ATM addresses.
-*
-*   If the NIC receives a cold start trap from the switch, then this
-*   module must invalidate all network prefixes.  If the NIC receives an
-*   SNMP message that invalidates a network prefix, then this module must
-*   invalidate all registered ATM addresses that use that network prefix.
-*   The address registration module may register new ATM addresses
-*   immediately if there is a valid network prefix and an available ESI value.
-*
-*   HOW THE INTERFACE TO THIS MODULE WORKS:
-*
-*   The figure below shows a typical configuration in which this module is used.
-*   It shows a configuration in which two clients have registered with the 
-*   Address Registration module, and each client may be "called back" by the 
-*   Address Registration module.  There is one instantiation of the Address
-*   Registration module for each NIC in the system.
-*
-*   +-----------+    +------------+
-*   | Classical |    |    LAN     |
-*   |  TCP/IP   |    | Emulation  |
-*   +-----------+    +------------+
-*          |  ^          |  ^        ("|" means regular  call)
-*          v  :          v  :        (":" means callback call)
-*      +----------------------+
-*      | Address Registration |
-*      +----------------------+
-*                |  ^
-*                |  :
-*                v  :
-*              +-------+
-*              | SNMP  |
-*              | Agent |
-*              +-------+
-*
-*   Initially, the Address Registration module is initalized with a set of MAC
-*   addresses for the NIC.  Clients can subsequently register with the 
-*   Address Registration module and specify a callback routine that is called
-*   when ATM addresses are registered or deregistered.  After the client 
-*   registeration is complete, the client can begin registering ATM
-*   addresses with the switch.  If the registration of the ATM address
-*   completes successfully, the client is called back with the ATM address that
-*   was registered.  Note that the clients do not specify the ATM address
-*   but instead are given one.
-*
-*   If a client attempts to register addresses when the Address Registration
-*   module is not ready for this operation, the request is queued.  When the
-*   switch is ready to register addresses, this module completes the
-*   registration and executes a callback to the client.
-*
-*   If an address registration request is queued, there is no time limit until
-*   the request is completed.  It is possible that client may wait for a 
-*   long time before being given the requested address.  This is the mechanism
-*   by which clients are held off when there is no switch to talk to.  For 
-*   example, LAN Emulation will not attempt to communicate with a non-existent 
-*   switch because it will be blocked waiting for an ATM address.  Likewise,
-*   when a switch goes away, clients will have their ATM addresses invalidated
-*   and will be forced to wait for new ones.
-*
-*   The switch may register an additional network prefix at any time.  When this
-*   occurs, any future address registrations will use the newest network
-*   prefix.  Address registrations that are in progress and previously
-*   ATM addresses are not affected.
-*
-*   The switch may also deregister network prefixes at any time.  When this
-*   occurs, then all clients which have registered addresses using the
-*   deregistered network prefix are notified that they must re-register a 
-*   network address.  This must be done before the client sends any more 
-*   data using the invalidated ATM address.  If an ATM address using the
-*   deleted network prefix is has started the registration process but not yet 
-*   completed it, then the address registration fails and the client is
-*   notified via the callback.
-*
-*   The switch may send a cold-start trap at any time.  When this occurs, this
-*   module must invalidate all the network prefixes that the switch previously 
-*   set. Clients are notified that their ATM address are now invalid via the 
-*   callback.  If there are any address registrations in progress when the cold 
-*   start trap is in progress, then will automatically be retried when a 
-*   network prefix has been set.
-*
-*   This module must detect if the link goes down so that it can inform the
-*   switch that a "cold start" event has occured.  The clients are notified 
-*   that their ATM addresses are invalid via callback.
-*
-*   SNMP AGENT INTERFACE:
-*
-*   This module must interface with the SNMP agent to receive cold-start traps,
-*   generate messages to send to the switch, and to receive SNMP messages from
-*   the switch.
 *
 *   MANAGEMENT INTEFACE:
 *   
@@ -257,7 +139,7 @@
 *
 * Overview:
 *   Registers a client.  After a client is registered, it may register and 
-*   deregister ATM addresses.  A client can not be deregistered.  A client must
+*   deregister ATM addresses.  A client must
 *   register so that it can be told about changes in ATM addresses.
 *
 * Arguments:
@@ -291,6 +173,19 @@
                                  HANDLE             callback_handle,
                                  const char         *p_text,
                                  HANDLE            *p_client_handle); 
+/*
+ *   Deregisters a client.  
+ *
+ * Arguments:
+ *   client_handle - Handle to this client.
+ *                   
+ * Returns:
+ *   0   - Client is deregistered.
+ *   -1  - Client is NOT deregistered.
+ *
+ */                                              
+
+int addr_reg_client_deregister(HANDLE client_handle);
 
 /*++
 * ===========================
@@ -363,7 +258,8 @@
 
 int address_convert(char *parsestring, ADDR_ATM *atm_addr);
 int addr_getesi(unsigned char *mac_addr);
-
+int addr_getouratmaddr(struct sockaddr_atmsvc *addr);
+void addr_set_atm_addr(ADDR_ATM *set_to);
 
 
 
diff -ur --new-file old/atm/led/address.c new/atm/led/address.c
--- old/atm/led/address.c	Sun Jul  7 13:59:07 1996
+++ new/atm/led/address.c	Fri Aug 16 12:55:54 1996
@@ -26,7 +26,7 @@
  *
  * Client registration/query funcs used in Digital's code
  *
- * $Id: address.c,v 1.12 1996/07/07 11:51:47 carnil Exp carnil $
+ * $Id: address.c,v 1.13 1996/08/06 14:14:11 carnil Exp carnil $
  *
  */
 
@@ -55,6 +55,7 @@
 #include "codes.h"
 #include "g_event.h"
 #include "utl_os.h"
+#include "le_disp.h"
 
 #define EMOD MOD_ADDR_REG
 #define EINST "address.c"
@@ -71,6 +72,7 @@
   ADDR_ATM addr; /* ATM address for this client */  
   struct _client_t_ *next; 
   HANDLE my_timer; /* See that ATM address is maintained */
+  int notify;
 } Client_t;
 
 Client_t *Clientlist = NULL;
@@ -112,6 +114,7 @@
     }
     to_register->name[0] = '\0';
   }
+  to_register->notify=0;
   *p_client_handle = to_register;
   memset(&to_register->addr,0,sizeof(ADDR_ATM));
   to_register->next = Clientlist;
@@ -120,6 +123,21 @@
 			&to_register->my_timer);
 }
 
+int 
+addr_reg_client_deregister(HANDLE client_handle)
+{
+  Client_t *client = client_handle;
+
+  if (!client) {
+    EVENT(EM_NERR,("Address registration deregistering nonexisting client\n"));
+    return -1;
+  }
+  os_timer_dealloc(client->my_timer);
+  mem_free(EINST, client->name);
+  mem_free(EINST, client);
+  return 0;
+}
+
 STATUS 
 addr_reg_atm_addr_alloc(HANDLE client_handle)
 {
@@ -129,6 +147,7 @@
 
   client = (Client_t *)client_handle;
 
+  client->notify=1;
   addr_reg_timer_callback((HANDLE)client);
   return STATUS_K_SUCCESS;
 }
@@ -148,6 +167,14 @@
   return STATUS_K_SUCCESS;
 }
 
+void
+addr_set_atm_addr(ADDR_ATM *set_to)
+{
+  Client_t *client = Clientlist;
+
+  ATM_COPY(*set_to, client->addr);
+}
+
 int
 address_convert(char* parsestring, ADDR_ATM *atm_addr)
 {
@@ -184,92 +211,129 @@
 addr_reg_timer_callback(HANDLE context)
 {
   Client_t *client = (Client_t *)context;
-  struct sockaddr_atmsvc ouraddr;
+  unsigned char *buffer;
+  struct sockaddr_atmsvc *ouraddr;
   struct atmif_sioc req;
-  int s;
+  int s,i;
+  static int address_invalidated =0; /* If address is missing twice,
+					then act */
 
   EVENT(EM_DEBUG,("Addr_reg_timer_called\n"));
+  buffer = (unsigned char*)mem_alloc(EINST, 5*sizeof(struct sockaddr_atmsvc));
   req.number = 0;
-  req.arg = &ouraddr;
-  req.length = sizeof(ouraddr);
+  req.arg = buffer;
+  req.length = 5*sizeof(*ouraddr);
 
   /* Reset (or set) timer */
-  os_timer_set(client->my_timer, ADDR_TIMER_FREQ);
+  os_timer_set(client->my_timer, ADDR_TIMER_FREQ+1);
 
   s = socket(PF_ATMSVC, SOCK_DGRAM, 0);
   if (s<0) {
     EVENT(EM_NERR,("Socket failed:%s\n",strerror(errno)));
+    mem_free(EINST, buffer);
     return;
   }
   if (ioctl(s, ATM_GETADDR, &req) <0) {
     close(s);
     EVENT(EM_NERR,("Ioctl failed:%s\n",strerror(errno)));
+    mem_free(EINST, buffer);
     return;
   }
   close(s);
 
   if (req.length ==0 ) { /* No ATM address */
-    if (ATM_EQUAL_NULL(client->addr)) /* Address hasn't been registered 
-				       * and wasn't registered now */
+    if (ATM_EQUAL_NULL(client->addr)) {/* Address hasn't been registered 
+				        * and wasn't registered now */
+      mem_free(EINST, buffer);
       return;
-    EVENT(EM_NERR,("Address invalidated\n"));
-    client->callback(client->callback_handle, &client->addr,
-		     ADDR_REG_EVENT_ATM_ADDR_INVALIDATED);
-    ATM_COPY_NULL(client->addr);
-    return;
+    }
+    if (address_invalidated) { /* Twice is enough */
+      EVENT(EM_NERR,("Address invalidated\n"));
+      client->callback(client->callback_handle, &client->addr,
+		       ADDR_REG_EVENT_ATM_ADDR_INVALIDATED);
+      ATM_COPY_NULL(client->addr);
+      mem_free(EINST, buffer);
+      return;
+    } else {
+      address_invalidated = 1;
+      mem_free(EINST, buffer);
+      return;
+    }
   }
-
+  address_invalidated = 0;
   EVENT(EM_DEBUG,("We have address\n"));
-  if (!ATM_EQUAL_NULL(client->addr)){  /* Address has already been registered*/
-    if (client->addr.prefix[0] == ouraddr.sas_addr.prv[0] &&
-	client->addr.prefix[1] == ouraddr.sas_addr.prv[1] &&
-	client->addr.prefix[2] == ouraddr.sas_addr.prv[2] &&
-	client->addr.prefix[3] == ouraddr.sas_addr.prv[3] &&
-	client->addr.prefix[4] == ouraddr.sas_addr.prv[4] &&
-	client->addr.prefix[5] == ouraddr.sas_addr.prv[5] &&
-	client->addr.prefix[6] == ouraddr.sas_addr.prv[6] &&
-	client->addr.prefix[7] == ouraddr.sas_addr.prv[7] &&
-	client->addr.prefix[8] == ouraddr.sas_addr.prv[8] &&
-	client->addr.prefix[9] == ouraddr.sas_addr.prv[9] &&
-	client->addr.prefix[10] == ouraddr.sas_addr.prv[10] &&
-	client->addr.prefix[11] == ouraddr.sas_addr.prv[11] &&
-	client->addr.prefix[12] == ouraddr.sas_addr.prv[12] &&
-	client->addr.esi[0] == ouraddr.sas_addr.prv[13] &&
-	client->addr.esi[1] == ouraddr.sas_addr.prv[14] &&
-	client->addr.esi[2] == ouraddr.sas_addr.prv[15] &&
-	client->addr.esi[3] == ouraddr.sas_addr.prv[16] &&
-	client->addr.esi[4] == ouraddr.sas_addr.prv[17] &&
-	client->addr.esi[5] == ouraddr.sas_addr.prv[18] &&
-	client->addr.sel == ouraddr.sas_addr.prv[19])/*...and has stayed same*/
-      return;
+  if (!client->notify && !ATM_EQUAL_NULL(client->addr)){  /* Address has already been registered*/
+    EVENT(EM_DEBUG,("Old %s\n",disp_atm_text(client->addr)));
+    for(i=0;i < req.length/sizeof(struct sockaddr_atmsvc); i++) {
+      /* Possibility for several ATM addresses */   
+      ouraddr = (struct sockaddr_atmsvc*)buffer+i;
+      EVENT(EM_DEBUG,("Tested agaist %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
+		      ouraddr->sas_addr.prv[0],ouraddr->sas_addr.prv[1],
+		      ouraddr->sas_addr.prv[2],ouraddr->sas_addr.prv[3],
+		      ouraddr->sas_addr.prv[4],ouraddr->sas_addr.prv[5],
+		      ouraddr->sas_addr.prv[6],ouraddr->sas_addr.prv[7],
+		      ouraddr->sas_addr.prv[8],ouraddr->sas_addr.prv[9],
+		      ouraddr->sas_addr.prv[10],ouraddr->sas_addr.prv[11],
+		      ouraddr->sas_addr.prv[12],ouraddr->sas_addr.prv[13],
+		      ouraddr->sas_addr.prv[14],ouraddr->sas_addr.prv[15],
+		      ouraddr->sas_addr.prv[16],ouraddr->sas_addr.prv[17],
+		      ouraddr->sas_addr.prv[18],ouraddr->sas_addr.prv[19]));
+      if (client->addr.prefix[0] == ouraddr->sas_addr.prv[0] &&
+	  client->addr.prefix[1] == ouraddr->sas_addr.prv[1] &&
+	  client->addr.prefix[2] == ouraddr->sas_addr.prv[2] &&
+	  client->addr.prefix[3] == ouraddr->sas_addr.prv[3] &&
+	  client->addr.prefix[4] == ouraddr->sas_addr.prv[4] &&
+	  client->addr.prefix[5] == ouraddr->sas_addr.prv[5] &&
+	  client->addr.prefix[6] == ouraddr->sas_addr.prv[6] &&
+	  client->addr.prefix[7] == ouraddr->sas_addr.prv[7] &&
+	  client->addr.prefix[8] == ouraddr->sas_addr.prv[8] &&
+	  client->addr.prefix[9] == ouraddr->sas_addr.prv[9] &&
+	  client->addr.prefix[10] == ouraddr->sas_addr.prv[10] &&
+	  client->addr.prefix[11] == ouraddr->sas_addr.prv[11] &&
+	  client->addr.prefix[12] == ouraddr->sas_addr.prv[12] &&
+	  client->addr.esi[0] == ouraddr->sas_addr.prv[13] &&
+	  client->addr.esi[1] == ouraddr->sas_addr.prv[14] &&
+	  client->addr.esi[2] == ouraddr->sas_addr.prv[15] &&
+	  client->addr.esi[3] == ouraddr->sas_addr.prv[16] &&
+	  client->addr.esi[4] == ouraddr->sas_addr.prv[17] &&
+	  client->addr.esi[5] == ouraddr->sas_addr.prv[18] &&
+	  client->addr.sel == ouraddr->sas_addr.prv[19]) {
+	/*...and has stayed same*/
+	mem_free(EINST, buffer);
+	return;
+      }
+    }
     EVENT(EM_DEBUG,("... which is new one\n"));
     /* Hasn't stayed same. First invalidate previous, then register new. */
     client->callback(client->callback_handle, &client->addr,
 		     ADDR_REG_EVENT_ATM_ADDR_INVALIDATED);
   }
   EVENT(EM_DEBUG,("Register new one\n"));
-  client->addr.prefix[0] = ouraddr.sas_addr.prv[0];
-  client->addr.prefix[1] = ouraddr.sas_addr.prv[1];
-  client->addr.prefix[2] = ouraddr.sas_addr.prv[2];
-  client->addr.prefix[3] = ouraddr.sas_addr.prv[3];
-  client->addr.prefix[4] = ouraddr.sas_addr.prv[4];
-  client->addr.prefix[5] = ouraddr.sas_addr.prv[5];
-  client->addr.prefix[6] = ouraddr.sas_addr.prv[6];
-  client->addr.prefix[7] = ouraddr.sas_addr.prv[7];
-  client->addr.prefix[8] = ouraddr.sas_addr.prv[8];
-  client->addr.prefix[9] = ouraddr.sas_addr.prv[9];
-  client->addr.prefix[10] = ouraddr.sas_addr.prv[10];
-  client->addr.prefix[11] = ouraddr.sas_addr.prv[11];
-  client->addr.prefix[12] = ouraddr.sas_addr.prv[12];
-  client->addr.esi[0] = ouraddr.sas_addr.prv[13];
-  client->addr.esi[1] = ouraddr.sas_addr.prv[14];
-  client->addr.esi[2] = ouraddr.sas_addr.prv[15];
-  client->addr.esi[3] = ouraddr.sas_addr.prv[16];
-  client->addr.esi[4] = ouraddr.sas_addr.prv[17];
-  client->addr.esi[5] = ouraddr.sas_addr.prv[18];
-  client->addr.sel = ouraddr.sas_addr.prv[19];
+  client->notify=0;
+  ouraddr = (struct sockaddr_atmsvc *)buffer;
+  client->addr.prefix[0] = ouraddr->sas_addr.prv[0];
+  client->addr.prefix[1] = ouraddr->sas_addr.prv[1];
+  client->addr.prefix[2] = ouraddr->sas_addr.prv[2];
+  client->addr.prefix[3] = ouraddr->sas_addr.prv[3];
+  client->addr.prefix[4] = ouraddr->sas_addr.prv[4];
+  client->addr.prefix[5] = ouraddr->sas_addr.prv[5];
+  client->addr.prefix[6] = ouraddr->sas_addr.prv[6];
+  client->addr.prefix[7] = ouraddr->sas_addr.prv[7];
+  client->addr.prefix[8] = ouraddr->sas_addr.prv[8];
+  client->addr.prefix[9] = ouraddr->sas_addr.prv[9];
+  client->addr.prefix[10] = ouraddr->sas_addr.prv[10];
+  client->addr.prefix[11] = ouraddr->sas_addr.prv[11];
+  client->addr.prefix[12] = ouraddr->sas_addr.prv[12];
+  client->addr.esi[0] = ouraddr->sas_addr.prv[13];
+  client->addr.esi[1] = ouraddr->sas_addr.prv[14];
+  client->addr.esi[2] = ouraddr->sas_addr.prv[15];
+  client->addr.esi[3] = ouraddr->sas_addr.prv[16];
+  client->addr.esi[4] = ouraddr->sas_addr.prv[17];
+  client->addr.esi[5] = ouraddr->sas_addr.prv[18];
+  client->addr.sel = ouraddr->sas_addr.prv[19];
   client->callback(client->callback_handle,&client->addr, 
 		   ADDR_REG_EVENT_ATM_ADDR_ALLOCATED);
+  mem_free(EINST, buffer);
 }
 
 int 
@@ -292,9 +356,57 @@
   }
   return 0;
 }
+
+int
+addr_getouratmaddr(struct sockaddr_atmsvc *addr)
+{
+  Client_t *client;
+
+  client = Clientlist;
+
+  if (!client) {
+    EVENT(EM_SERR,("Addr_getouratmaddr, no ATM address!!!\n"));
+    return -1;
+  }
+  if (ATM_EQUAL_NULL(client->addr)) {
+    addr_reg_timer_callback(client);
+  }
+  if (ATM_EQUAL_NULL(client->addr)) {
+    EVENT(EM_SERR,("Addr_getouratmaddr, no ATM address!!!\n"));
+    return -1;
+  }
+  memset(addr,0,sizeof(*addr));
+  addr->sas_family = AF_ATMSVC;
+  addr->sas_addr.prv[0] = client->addr.prefix[0];
+  addr->sas_addr.prv[1] = client->addr.prefix[1];
+  addr->sas_addr.prv[2] = client->addr.prefix[2];
+  addr->sas_addr.prv[3] = client->addr.prefix[3];
+  addr->sas_addr.prv[4] = client->addr.prefix[4];
+  addr->sas_addr.prv[5] = client->addr.prefix[5];
+  addr->sas_addr.prv[6] = client->addr.prefix[6];
+  addr->sas_addr.prv[7] = client->addr.prefix[7];
+  addr->sas_addr.prv[8] = client->addr.prefix[8];
+  addr->sas_addr.prv[9] = client->addr.prefix[9];
+  addr->sas_addr.prv[10] = client->addr.prefix[10];
+  addr->sas_addr.prv[11] = client->addr.prefix[11];
+  addr->sas_addr.prv[12] = client->addr.prefix[12];
+  addr->sas_addr.prv[13] = client->addr.esi[0];
+  addr->sas_addr.prv[14] = client->addr.esi[1];
+  addr->sas_addr.prv[15] = client->addr.esi[2];
+  addr->sas_addr.prv[16] = client->addr.esi[3];
+  addr->sas_addr.prv[17] = client->addr.esi[4];
+  addr->sas_addr.prv[18] = client->addr.esi[5];
+  addr->sas_addr.prv[19] = client->addr.sel;
+  return 0;
+}
+
+
 /*
  *
  * $Log: address.c,v $
+ * Revision 1.13  1996/08/06 14:14:11  carnil
+ * Address handling moved to address.c from conn.c
+ *
  * Revision 1.12  1996/07/07 11:51:47  carnil
  * Address changes are noticed and notified
  *
diff -ur --new-file old/atm/led/atm.h new/atm/led/atm.h
--- old/atm/led/atm.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/atm.h	Tue Aug  6 16:33:07 1996
@@ -71,79 +71,6 @@
    UINT8    sel;     /* Selector                          */
    } ADDR_ATM;
 
-/* QOS_CLASS
- *
- *   General classes of Quality of Service for Virtual Channels.
- *
- *   QOS_CBR    - Constant Bit Rate.  The VC has a constant forward and backward
- *                cell rate defined (they may be different).
- *
- *   QOS_VBR    - Variable Bit Rate.  The VC has peak cell rate, sustainable
- *                cell rate, and burst tolerance parameters for both the
- *                forward and backward directions.
- *
- *   QOS_NORMAL - No specific parameters are set for the VC.
- *                Bandwidth is provided on an as-available basis.
- *                Congestion is managed by some traffic management
- *                scheme (or combination of schemes).
- */
-typedef enum
-   {
-   QOS_CBR,
-   QOS_VBR,
-   QOS_NORMAL
-   } QOS_CLASS;
-
-/* QOS Flow Control Schemes
- *
- *   The following macros define mask bits that may be used individually or in
- *   combinations to describe how traffic is managed on a QOS_NORMAL VC.
- *
- *   QOS_FLOW_UBR          - Flow is according to Unspecified Bit Rate.  There
- *                           is no flow control and congestion will result in
- *                           cell loss.
- *
- *   QOS_FLOW_ABR          - The ATM-Forum Standard Available Bit Rate scheme
- *                           is used in the VC endpoints to limit the data rate
- *                           to avoid congestion-induced cell loss.
- *
- *   QOS_FLOW_AN2          - The Digital Proprietary FLOWmaster credit-based
- *                           flow control scheme is in use between the local
- *                           entity and its direct peer.
- *
- *   QOS_FLOW_QFC          - The Quantum Flow Control credit-based flow control
- *                           scheme is in use on the VC
- *
- *   Valid combinations:
- *
- *       QOS_FLOW_ABR and QOS_FLOW_AN2
- *       QOS_FLOW_ABR and QOS_FLOW_QFC
- */
-#define QOS_FLOW_UBR  1
-#define QOS_FLOW_ABR  2
-#define QOS_FLOW_AN2  4
-#define QOS_FLOW_QFC  8
-
-/* QOS
- *
- *   Quality of Service parameters for a Virtual Channel.  This structure
- *   contains all of the information necessary to describe the characteristics
- *   of a VC.
- */
-typedef struct
-   {
-   QOS_CLASS   qos_class;
-   UINT16      qos_flow_style_mask;
-   UINT32      forw_peak_cell_rate;
-   UINT32      forw_sus_cell_rate;
-   UINT32      forw_burst_size;
-   UINT32      back_peak_cell_rate;
-   UINT32      back_sus_cell_rate;
-   UINT32      back_burst_size;
-   } QOS;
-
-#define QOS_COPY(from, to) (to) = (from)
-
 typedef union
    {
    struct
@@ -169,15 +96,6 @@
                             ((esi)[3] == 0xff) && \
                             ((esi)[4] == 0xff) && \
                             ((esi)[5] == 0xff))
-
-#define ESI_IS_MCAST(esi) ((esi)[0] & 0x01)
-
-#define ESI_EQUAL(a1, a2) (((a1)[5] == (a2)[5]) &&  \
-                           ((a1)[4] == (a2)[4]) &&  \
-                           ((a1)[3] == (a2)[3]) &&  \
-                           ((a1)[2] == (a2)[2]) &&  \
-                           ((a1)[1] == (a2)[1]) &&  \
-                           ((a1)[0] == (a2)[0]))
 
 #define ATM_COPY(from, to)               \
 	{                                     \
diff -ur --new-file old/atm/led/cm.h new/atm/led/cm.h
--- old/atm/led/cm.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/cm.h	Sat Aug 10 11:57:14 1996
@@ -36,7 +36,6 @@
 *   cm.h
 *   
 * Overview:
-*   This describes the management interface to the Connection Manager (CM).
 *
 * Authors:
 *   TLR - Theodore L. Ross
@@ -46,87 +45,8 @@
 *   17-Oct-94  TLR   Created.
 *   19-Jan-94  TLR   Added LAN Emulation map list hook.
 *
-* Description:
-*   This is the interface through which the CM is managed.  It enables
-*   instances of the the CM to be initialized at system start-up time (or any
-*   other time).
-*
-*   The CM provides connection management services on a per-adapter basis.
-*   Thus if there is more than one physical adapter in a system,
-*   there are multiple instantiations of the CM.  The management
-*   interface provides calls to create instantiations of the CM module.
-*
-* Future Extensions:
-*   This interface shall be extended with calls that allow management entities
-*   to access the internal state of a CM instance.
-*
-* Call Sequence Requirements:
-*
-*   Creation of instances of the CM is a two-step process.  First, each
-*   instance must be created using the cm_create call.  The instance must
-*   then be configured using the cm_config call.  This two-step process
-*   is needed because it breaks a circular dependency in the architecture (i.e.
-*   other module instances need the CM handle during creation and the handles
-*   of those module instances are needed during creation the CM instance).
-*
-*   The call sequence for each instance will look like the following:
-*
-*       <os_utilities created>..............OS Utilities are created.
-*
-*       cm_create...........................Create a CM module instance.  OS
-*                                           handle is passed so create routine
-*                                           can allocate memory.
-*
-*       <other module instances created>....Create other module instances using
-*                                           the CM handle from the
-*                                           cm_create.
-*
-*       cm_drv_config.......................Called during lower driver creation.
-*
-*       cm_svc_config.......................Called during SVC module creation.
-*
-*       cm_map_get..........................Called by the LAN Emulation Client
-*                                           (if it exists) to gain access to
-*                                           the CM's VC and ATM address lists.
 */
 
 typedef void (*LINK_CALLBACK) (HANDLE link_handle);
 
-
-/*++
-* ==============
-* = cm_map_get =
-* ==============
-*
-* Overview:
-*   Gets pointers to this CM instance's mapping lists (VC list and ATM address
-*   list).  This function is called by the LAN Emulation Client module during
-*   module creation.
-*
-* Arguments:
-*   cm_handle             - (IN)  Handle returned by cm_create.
-*   link_update_callback  - (IN)  Callback for MAC address link updates.
-*   link_remove_callback  - (IN)  Callback for MAC address link removal.
-*   callback_context      - (IN)  Context to be passed back with the callbacks.
-*   p_vc_list             - (OUT) VC List handle for this cm instance.
-*   p_atm_list            - (OUT) ATM Address List handle for this cm instance.
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   The cm_handle must be valid.
-*
-* Postconditions:
-*   None
---*/
-void cm_map_get(LINK_CALLBACK  link_update_callback,
-                LINK_CALLBACK  link_remove_callback,
-                HANDLE         callback_context,
-                HANDLE        *p_vc_list,
-                HANDLE        *p_atm_list);
-
-/*
- * Resets connections in cm module
- */
-void cm_reset(HANDLE sap_handle);
+void sig_reset(int a);
diff -ur --new-file old/atm/led/cm_sap.h new/atm/led/cm_sap.h
--- old/atm/led/cm_sap.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/cm_sap.h	Fri Aug  9 14:13:10 1996
@@ -112,41 +112,6 @@
 *
 *   User Data:
 *
-*     Packet transmit, receive calls, and transmit done callbacks contain a 
-*     "user_data" parameter.  The Connection Manager passes this parameter
-*     through and does not look at or modify it.  The user_data is a means of 
-*     communication between the SAP components and the AAL5 driver component.
-*     The description of the contents of the user data is outside of the scope
-*     of this interface specification, but since it is particularly relevant to
-*     SAP designers, a summary shall be described here.
-*
-*     The user data contains four fields:
-*
-*       LE_HEADER_VALID_FLAG....This flag is set if this is a transmit packet
-*                               from a LAN Emulation entity.  It instructs the
-*                               AAL5 driver to place the provided LAN Emulation
-*                               header on the front of the packet before
-*                               transmitting it.
-*
-*       LE_HEADER...............This is the actual 16-bit LAN Emulation header
-*                               that is prepended to the packet if the 
-*                               LE_HEADER_VALID_FLAG flag is set.
-*
-*       INTERNAL_FLAG...........This flag is set if the transmitted packet is
-*                               internally generated.  Internally generated
-*                               packets (i.e. LE-ARPs, ILMI packets, etc.)
-*                               are formatted differently from Operating System
-*                               packets and must be treated differently by the
-*                               AAL5 driver.
-*
-*       SAP_DATA................This 14-bit field is used only by the SAP
-*                               entity that transmits the packet.  It may be
-*                               read by the SAP when the transmit-done callback
-*                               returns the packet.  The SAP should
-*                               use this field to determine how to deallocate
-*                               the packet.  Note that internally generated
-*                               packets must be reclaimed differently than OS
-*                               generated packets.
 *
 *   AAL Data:
 *
@@ -155,102 +120,6 @@
 *     receive packet.  Refer to the definition of AAL_DATA in the "atm.h"
 *     header file.
 *
-* Call Sequence Requirements:
-*
-*   Since this interface is a registration interface, cm_sap_register must
-*   be called prior to calling any other CM function.  All other CM functions
-*   must be passed a valid SAP handle (which is returned from cm_sap_register).
-*
-*   Additionally, data packets may not be sent or received on this interface
-*   before a VC is established for that traffic.
-*
-* Example Usage Scenario (PVC only):
-*
-*   Callbacks are shown in parentheses.
-*
-*   cm_sap_register.....Before using the SAP interface, registration
-*                       must be completed.  If this SAP is only going to use
-*                       PVCs, it may clear the "accept_incoming" flag thus
-*                       telling the Connection Manager that it does not wish
-*                       to be offered incoming SVC connections.
-*
-*   cm_sap_pvc_setup....Before data can be exchanged over this interface,
-*                       a virtual channel must be established.  In this
-*                       case, a Permanent Virtual Channel (PVC) is being
-*                       created.  The SAP client provides the VCI of
-*                       the PVC.  It is assumed that the VPI will be zero.
-*
-*                       Note that in a PVC setup, the SAP chooses the VCI
-*                       of the new PVC.  This differs from SVC setup where the
-*                       VCI/VPI is chosen by the network.
-*
-*   (sap_vc_notify).....Some time later, the CM uses this callback to notify
-*                       the SAP that the PVC has been successfully set up.
-*
-*   cm_sap_xmt_vc.......Transmits a packet via the specified connection.  The
-*                       connection handle used is the same one returned by
-*                       the PVC setup call.  It is assumed that the rest of
-*                       the network (including the destination node) has been
-*                       setup to support this PVC.  If this is not the case,
-*                       the packet will not reach its destination.
-*
-*   (sap_rcv_callback)..A packet has been received on a VC bound to this
-*                       SAP (The VC became bound to this SAP during the
-*                       PVC setup).  This callback passes the packet to
-*                       the SAP along with its connection context.
-*
-*   cm_sap_pvc_teardown.When the SAP no longer needs the PVC, it uses
-*                       this call to remove the PVC and unbind it from
-*                       this SAP.
-*
-*   cm_sap_unregister...Cancel the registration with the CM.  After this
-*                       call completes, the SAP no longer exists from the
-*                       CM's perspective.
-*
-* Example Usage Scenario (with SVCs):
-*
-*   cm_sap_register.....Before using the SAP interface, registration must be
-*                       completed.  If this SAP client wishes to be offered
-*                       incoming SVC connections, it must set the
-*                       "accept_incoming" flag.
-*
-*   cm_sap_svc_setup....Request the setup of an SVC.  The caller provides the
-*                       ATM address of the desired destination and all of the
-*                       necessary parameters for the connection.
-*
-*   (sap_vc_notify).....Some time later, the CM uses this callback to notify
-*                       the SAP of the status of its SVC request.
-*
-*   cm_sap_xmt_atm......Once an SVC is set up for an ATM address, packets may
-*                       be sent to that ATM address.  The CM will look up the
-*                       ATM address in the mapping module to determine the
-*                       correct VC for transmission.  If the ATM address is
-*                       not associated with a valid VC, an error will be
-*                       returned.
-*
-*   cm_sap_xmt_vc.......Another way to transmit data is directly to the VC.
-*                       This is a faster way to transmit.  Generally this will
-*                       be used by the LAN Emulation Client since it will
-*                       already have the connection handle from its MAC
-*                       address lookup.
-*
-*   (sap_rcv)...........A packet has been received on a VC bound to this SAP.
-*                       The binding happens during SVC setup.
-*
-*   (sap_connect).......This callback is invoked when an incoming SVC request
-*                       is received.  The SAP now has the option to accept or
-*                       reject the call.
-*
-*                       When the CM receives an incoming connection request, it
-*                       offers this connection (via the sap_connect call
-*                       to each SAP in some arbitrary order.  The first SAP to
-*                       accept the connection gets the connection.  If none of
-*                       the matching SAPs accepts the connection, the CM
-*                       rejects the connection.
-*
-*   cm_sap_unregister...Cancel the registration.  This will automatically
-*                       close all SVCs and PVCs bound to this SAP.
-*
 */
 #ifndef CM_SAP_H
 #define CM_SAP_H
@@ -631,7 +500,6 @@
 *
 * Arguments:
 *   conn_handle     - (IN)  Connection handle of the SVC to be removed.
-*   p_release_info  - (IN)  Reason for this release.
 *              
 * Returns:
 *   STATUS_K_PENDING        - Success: Async operation has begun
@@ -642,8 +510,7 @@
 * Postconditions:
 *   None
 --*/
-STATUS cm_sap_svc_teardown (HANDLE        conn_handle,
-                            RELEASE_INFO *p_release_info);
+STATUS cm_sap_svc_teardown (HANDLE        conn_handle);
 
 /*++
 * =================
diff -ur --new-file old/atm/led/conn.c new/atm/led/conn.c
--- old/atm/led/conn.c	Sun Jul  7 20:47:57 1996
+++ new/atm/led/conn.c	Tue Aug 20 20:41:30 1996
@@ -25,7 +25,7 @@
  *
  * Connection forming/teardown & packet send/receive
  *
- * $Id: conn.c,v 1.25 1996/07/07 11:51:47 carnil Exp carnil $
+ * $Id: conn.c,v 1.26 1996/08/06 14:14:11 carnil Exp carnil $
  *
  */
 
@@ -41,6 +41,7 @@
 #include <errno.h>
 #include <assert.h>
 #include <netinet/in.h>
+#include <fcntl.h>
 
 /* Atm includes */
 
@@ -52,8 +53,6 @@
 #include "g_types.h"
 #include "cm_sap.h"
 #include "lec.h"
-#include "map.h"
-#include "map_data.h"
 #include "atm.h"
 #include "cm.h"
 #include "g_event.h"
@@ -63,6 +62,7 @@
 #include "le_disp.h"
 #include "kernel_itf.h"
 #include "lec_ctrl.h"
+#include "addr_reg.h"
 
 #define EMOD MOD_CM
 #define EINST "conn.c"
@@ -81,6 +81,7 @@
 			   */
 #define TRANSMITTED 1247  /* Packet transmitted, not notified */
 #define RELEASED 1248     /* Connection released */
+#define CONNECTING 1249   /* Non blocking socket, connecting */
 
 /* type */
 #define WEMADE 7
@@ -132,7 +133,6 @@
 			 long age_limit, CONN_INFO *info, Conn_t **p_conn);
 static Conn_t* conn_already_exists(unsigned char *atm_addr,Conn_t *current);
 
-
 STATUS 
 cm_sap_register(HANDLE sap_context, 
 		SAP_RCV_CALLBACK rcv_callback, 
@@ -194,7 +194,7 @@
 {
   Sap_client_t *sap, *curr;
   Sap_client_t *prev = NULL;
-  Conn_t *conn;
+  Conn_t *conn, *next;
 
   sap = (Sap_client_t *)sap_handle;
 
@@ -216,29 +216,29 @@
     prev->next = curr->next;    
   }
   /* Remove vcc's */
-  for(conn= connlist;conn!=NULL;conn=conn->next) {
+  for(conn= connlist;conn;conn=next) {
+    EVENT(EM_DEBUG,("Destroying:%p fd:%d type:%d\n",conn,conn->fd,conn->type));
+    next=conn->next;
     if (conn->type == KERNEL_SOCK) {
+      EVENT(EM_DEBUG,("Closing kernel socket\n"));
       close(conn->fd);
       list_remove_conn(conn);
+      mem_free(EINST, conn);
     }
   }
-  for(conn=connlist;conn!=NULL;conn=conn->next) {
+  for(conn=connlist;conn;conn=next) {
+    next=conn->next;
     close(conn->fd);
+    if (conn->conn_info)
+      mem_free(EINST, conn->conn_info);
+    close(conn->fd);
+    list_remove_conn(conn);
+    mem_free(EINST, conn);
   }
   mem_free(EINST, sap->p_sap_text);
   mem_free(EINST, sap);
 }
 
-void 
-cm_map_get(LINK_CALLBACK link_update_callback,
-	   LINK_CALLBACK link_remove_callback, HANDLE callback_context,
-	   HANDLE *p_vc_list, HANDLE *p_atm_list)
-{
-  EVENT(EM_ASSERT,("Cm_map_get\n"));
-  *p_vc_list = NULL;
-  *p_atm_list=NULL;
-}
-
 /* Don't check parameter current for atm address match */
 static Conn_t*
 conn_already_exists(unsigned char *atm_addr, Conn_t *current)
@@ -319,17 +319,19 @@
       /* Try to remove possible entry in kernel */
       lc_addr_delete(conn_context, p_conn_info->addr.sas_addr.prv);
     }
+    *p_conn_handle = NULL;
     return STATUS_K_RESOURCES;
   }
   /* Initialize address structs */
   memset(&us,0,sizeof(us));
-  if (get_ouratmaddr(s,&us) <0) {
+  if (addr_getouratmaddr(&us) <0) {
     if (is_data_direct(p_conn_info)) {
       /* Try to remove possible entry in kernel */
       lc_addr_delete(conn_context, p_conn_info->addr.sas_addr.prv);
     }
 
     close(s);
+    *p_conn_handle = NULL;
     return STATUS_K_ATM_RESOURCES;
   }
   
@@ -346,6 +348,7 @@
       lc_addr_delete(conn_context, p_conn_info->addr.sas_addr.prv);
     }
     close(s);
+    *p_conn_handle = NULL;
     return STATUS_K_ATM_RESOURCES;
   }
   
@@ -362,6 +365,7 @@
     }
 
     close(s);
+    *p_conn_handle = NULL;
     return STATUS_K_ATM_RESOURCES;
   }
 
@@ -391,15 +395,34 @@
 		  p_conn_info->addr.sas_addr.prv[19]&0xff));
 
   /* Try to connect */
+  if (is_data_direct(p_conn_info)) {
+    ret = fcntl(s, F_GETFL);
+    if (ret <0) {
+      EVENT(EM_SERR, ("fcntl(s, F_GETFL\n"));
+      lc_addr_delete(conn_context, p_conn_info->addr.sas_addr.prv);
+      close(s);
+      *p_conn_handle = NULL;
+    }
+    if (fcntl(s, F_SETFL, ret|O_NONBLOCK)<0) {
+      EVENT(EM_SERR, ("fcntl(s, F_SETFL, x&O_NONBLOCK)\n"));
+      lc_addr_delete(conn_context, p_conn_info->addr.sas_addr.prv);
+      close(s);
+      *p_conn_handle=NULL;
+      return STATUS_K_ATM_RESOURCES;
+    }
+  }
   ret = connect(s, (struct sockaddr *)&(p_conn_info->addr), 
 		sizeof(struct sockaddr_atmsvc));
-  if (ret<0) {
-    EVENT(EM_NERR,("connect error:%s\n",strerror(errno)));
+  if (ret<0 && errno != EINPROGRESS) {
+    EVENT(EM_NERR,("connect error:%d,%s\n",errno,strerror(errno)));
     if (is_data_direct(p_conn_info)) {
       /* Try to remove possible entry in kernel */
       lc_addr_delete(conn_context, p_conn_info->addr.sas_addr.prv);
     }
+    if (errno == ENETRESET)
+      sig_reset(0);    
     close(s);
+    *p_conn_handle = NULL;
     return STATUS_K_ATM_RESOURCES;
   }
 
@@ -410,16 +433,19 @@
   case 0x03:
     memcpy(ioc_data.atm_addr, p_conn_info->addr.sas_addr.prv, ATM_ESA_LEN);
     ioc_data.receive = 0;
+    EVENT(EM_DEBUG,("About to ioctl(s, ATMLEC_DATA, &ioc_data)\n"));
     if (ioctl(s, ATMLEC_DATA, &ioc_data)<0) {
       EVENT(EM_SERR,("Can't change socket into LE data socket:%s\n",
-		     strerror(errno)));
+		     strerror(errno)));      
       if (is_data_direct(p_conn_info)) {
 	/* Try to remove possible entry in kernel */
       lc_addr_delete(conn_context, p_conn_info->addr.sas_addr.prv);
       }
       close(s);
+      *p_conn_handle = NULL;
       return STATUS_K_ATM_RESOURCES;
     }
+    EVENT(EM_DEBUG,("ioctl done\n"));
     break;
   case 0x04:
   case 0x05:
@@ -431,6 +457,7 @@
 	lc_addr_delete(conn_context, p_conn_info->addr.sas_addr.prv);
       }
       close(s);
+      *p_conn_handle = NULL;
       return STATUS_K_ATM_RESOURCES;
     }
     break;
@@ -448,13 +475,17 @@
       lc_addr_delete(conn_context, p_conn_info->addr.sas_addr.prv);
     }
     close(s);
+    *p_conn_handle = NULL;
     return STATUS_K_RESOURCES;
   }
   conn->fd = s;
   conn->type = WEMADE;
 
   /* Connection was made. Must notify upper level later. */
-  conn->status = CONNECTED;
+  if (is_data_direct(p_conn_info))
+    conn->status = CONNECTING;
+  else
+    conn->status = CONNECTED;
 
   EVENT(EM_DEBUG,("Conn_handle %lx,fd:%d\n",(long)conn, s));
   *p_conn_handle = conn;
@@ -462,19 +493,20 @@
 }
 
 STATUS 
-cm_sap_svc_teardown(HANDLE conn_handle,
-		    RELEASE_INFO *p_release_info)
+cm_sap_svc_teardown(HANDLE conn_handle)
 {
   Conn_t *conn;
 
   EVENT(EM_DEBUG,("Cm_sap_svc_teardown %lx\n",(long)conn_handle));
   conn = (Conn_t *)conn_handle;
 
-  if (conn->conn_info) {
+  close(conn->fd);
+  /* Remove conn from list */
+  list_remove_conn(conn);
+  if (conn->conn_info)
     mem_free(EINST, conn->conn_info);
-    conn->conn_info = NULL;
-  }
-  conn->status = RELEASED;
+  mem_free(EINST,conn);
+
   return STATUS_K_SUCCESS;
 }
 
@@ -487,11 +519,10 @@
   Sap_client_t *sap;
   int ret;
 
-  EVENT(EM_DEBUG,("Cm_sap_xmt_vc\n"));
-
   /* Write data out */
   conn = (Conn_t *)conn_handle;
   sap = (Sap_client_t *)conn->sap_handle;
+  EVENT(EM_DEBUG,("Cm_sap_xmt_vc fd:%d len:%ld\n",conn->fd, length));
   ret=write(conn->fd, p_data, length);
 
   /* Tried to transmit packet */
@@ -532,13 +563,6 @@
   p_svc_conn_info->addr.sas_addr.blli = &(p_svc_conn_info->blli);
 }
 
-void 
-svc_release_info_make(int code, RELEASE_INFO *p_release_info)
-{
-  assert(p_release_info);
-}
-
-
 /* Callbacks for connections */
 void
 conn_call_callbacks(void)
@@ -580,6 +604,8 @@
       close(conn->fd);
       /* Remove conn from list */
       list_remove_conn(conn);
+      if (conn->conn_info)
+	mem_free(EINST, conn->conn_info);
       mem_free(EINST,conn);
       conn=c_tmp;
     } else {
@@ -617,20 +643,51 @@
   conn = connlist;
 
   if (EMASK & EM_DEBUG) {
-    buff = (char*)malloc(1024);
+    buff = (char*)mem_alloc(EINST,1024);
     ch = buff;
   }
   while (conn) {
-    if (EMASK & EM_DEBUG) {
-      ch = ch+sprintf(ch,"-%3d %s",conn->fd, conn_get_type_string(conn->type));
+    if (conn->status != CONNECTING) {
+      if (EMASK & EM_DEBUG) {
+	ch=ch+sprintf(ch,"-%3d %s",conn->fd, conn_get_type_string(conn->type));
+      }
+      FD_SET(conn->fd, fds);
     }
-    FD_SET(conn->fd, fds);
     conn = conn->next;
   }
   EVENT(EM_DEBUG,("conn_add_fds:%s\n",buff));
+  if (EMASK & EM_DEBUG) 
+    mem_free(EINST, buff);
   fflush(stdout);
 }
 
+void
+conn_get_connecting_fds(fd_set *fds)
+{
+  Conn_t *conn;
+  char *buff, *ch;
+
+  conn = connlist;
+
+  if (EMASK & EM_DEBUG) {
+    buff = (char*)mem_alloc(EINST, 1024);
+    ch = buff;
+  }
+  while (conn) {
+    if (conn->status == CONNECTING) {
+      if (EMASK & EM_DEBUG) {
+	ch=ch+sprintf(ch,"-%3d %s",conn->fd, conn_get_type_string(conn->type));
+      }
+      FD_SET(conn->fd, fds);
+    }
+    conn = conn->next;
+  }
+  EVENT(EM_DEBUG,("conn_add_connecting_fds:%s\n",buff));
+  if (EMASK & EM_DEBUG) 
+    mem_free(EINST, buff);
+  fflush(stdout);
+}
+  
 int
 conn_check_incoming(fd_set *fds)
 {
@@ -644,38 +701,43 @@
   struct sockaddr_atmsvc addr;
   Conn_t *to_add;
   struct atmlec_ioc ioc_data;
+  int reset = 0;
 
   conn = connlist;
-  
+
   while (conn) {
-    if (FD_ISSET(conn->fd, fds)) {
-      EVENT(EM_DEBUG,("Event in fd:%d\n",conn->fd));
-      if (conn->type == KERNEL_SOCK) { /* Message from kernel */
-	kernel_dispatch_handlers();
-      } else if (conn->type == LISTENING) { /* Incoming call */
-	EVENT(EM_EVENT,("Incoming call\n"));
-	if (list_add_conn(conn->sap_handle,
-			  NULL,
-			  0,
-			  NULL,
-			  &to_add)<0) {
-	  EVENT(EM_NERR,("list_conn_add failed\n"));
-	  continue;
-	}	       
-	sap = (Sap_client_t *)conn->sap_handle;
-	if (sap->svc_connect_callback(conn->conn_context,
-				      conn->conn_info, 
-				      to_add,
-				      &to_add->conn_context,
-				      &to_add->age_limit,
-				      &reject_reason) == FALSE) {
-	  /* What to do, if ... */
-	  assert(0);
-	}
+    if (FD_ISSET(conn->fd, fds) && conn->type == LISTENING){/* Incoming call */
+      EVENT(EM_EVENT,("Incoming call\n"));
+      if (list_add_conn(conn->sap_handle,
+			NULL,
+			0,
+			NULL,
+			&to_add)<0) {
+	EVENT(EM_NERR,("list_conn_add failed\n"));
+	continue;
+      }	       
+      sap = (Sap_client_t *)conn->sap_handle;
+      if (sap->svc_connect_callback(conn->conn_context,
+				    conn->conn_info, 
+				    to_add,
+				    &to_add->conn_context,
+				    &to_add->age_limit,
+				    &reject_reason) == FALSE) {
+	/* What to do, if ... */
+	len = sizeof(addr);
+	fd = accept(conn->fd, (struct sockaddr *)&addr, &len);
+	if (fd <0 && (errno == EUNATCH || errno == ENETRESET))
+	  sig_reset(42);
+	if (fd >=0)
+	  close(fd);
+	list_remove_conn(to_add);
+      } else {
 	len = sizeof(addr);
 	fd = accept(conn->fd, (struct sockaddr *)&addr, &len);
-	if (fd<0) {	  
+	if (fd<0) {
 	  EVENT(EM_NERR,("Accept failed:%s\n",strerror(errno)));
+	  if (errno == ENETRESET || errno == EUNATCH)
+	    sig_reset(42);
 	  list_remove_conn(to_add);
 	  sap->vc_notify_callback(to_add->conn_context,
 				  to_add,
@@ -731,7 +793,7 @@
 		  conn->conn_info->blli.l3.tr9577.snap[4] == 3) {
 		tmpconn = conn_already_exists(addr.sas_addr.prv, to_add);
 		if (tmpconn) {
-		  get_ouratmaddr(conn->fd, &addr);
+		  addr_getouratmaddr(&addr);
 		  if (memcmp(addr.sas_addr.prv, ioc_data.atm_addr, ATM_ESA_LEN)
 		      <0)
 		    ioc_data.receive = 1;
@@ -742,26 +804,46 @@
 	      } else
 		ioc_data.receive = 2; /* Multicast distribute */
 	      
+	      EVENT(EM_DEBUG,("About to ioctl(fd, ATMLEC_DATA, &ioc_data)\n"));
 	      if (ioctl(fd, ATMLEC_DATA, &ioc_data)<0) {
 		EVENT(EM_SERR,("Can't change socket into LE data socket:%s\n",
 			       strerror(errno)));
 	      }
+	      EVENT(EM_DEBUG,("ioctl done\n"));
 	    }
 	  }
 	}
+      }
+    }
+    conn = conn->next;
+  }
+  conn=connlist;
+  while (conn) {
+    if (FD_ISSET(conn->fd, fds)) {
+      EVENT(EM_DEBUG,("Event in fd:%d\n",conn->fd));
+      if (conn->type == KERNEL_SOCK) { /* Message from kernel */
+	kernel_dispatch_handlers();
+      } else if (conn->type == LISTENING) { /* Incoming call */
+      } else if (conn->status == CONNECTING) { /* Call is ready */
+	memset(&addr,0,sizeof(addr));
+	if (!connect(conn->fd, (struct sockaddr*)&addr,sizeof(addr))) {
+	  EVENT(EM_EVENT,("Nonblocking connect() :%s\n",strerror(errno)));
+	}
+	conn->status = CONNECTED;
       } else { /* Data coming in */
 	nbytes = read(conn->fd, buffer, BUFSIZE);
 	if (nbytes <0) {
 	  EVENT(EM_SERR,("Read failed on fd %d: %s\n",
 			 conn->fd,strerror(errno)));
-	  if (errno == EUNATCH || errno == ENOENT) 
-	    return -1;
+	  if (errno == EUNATCH || errno == ENOENT || errno == ENETRESET) 
+	    reset = -1;
 	  else {
 	    conn->status = RELEASED;
 	    EVENT(EM_EVENT, ("Closing connection\n"));
 	  }
 	} else if (nbytes==0) {
 	  /* EOF, connection closed */
+	  
 	  conn->status = RELEASED;
 	  EVENT(EM_EVENT,("Connection closed\n"));
 	} else {
@@ -782,7 +864,7 @@
     }
     conn = conn->next;
   }
-  return 0;
+  return reset;
 }
 
 int
@@ -834,7 +916,10 @@
     return -1;
   }
   
-  conn_info->addr.sas_family = AF_ATMSVC;
+  if (addr_getouratmaddr(&conn_info->addr)<0) {
+    close(fd);
+    return -1;
+  }
   conn_info->addr.sas_addr.blli = &conn_info->blli;
   conn_info->blli.l3_proto = ATM_L3_TR9577;
   conn_info->blli.l3.tr9577.ipi = NLPID_IEEE802_1_SNAP;
@@ -846,6 +931,10 @@
   conn_info->blli.l3.tr9577.snap[4] = (unsigned char)(0xff&blli_codepoint);
     
   len = sizeof(struct sockaddr_atmsvc);  
+
+  if (EMASK & EM_DEBUG)
+    disp_sockaddr(&conn_info->addr);
+  
   ret = bind(fd, (struct sockaddr *)&conn_info->addr, len);
   if (ret != 0) {
     EVENT(EM_NERR,("Bind failed: %s\n",strerror(errno)));
@@ -877,19 +966,6 @@
   return fd;
 }
 
-void 
-cm_reset(HANDLE sap_handle)
-{
-  Conn_t *conn, *next;
-
-  /* Remove vcc's */
-  for(conn=connlist;conn!=NULL;conn=next) {
-    next = conn->next;
-    close(conn->fd);
-    list_remove_conn(conn);
-  }
-}
-
 static int
 list_add_conn(HANDLE sap_handle, HANDLE conn_context, long age_limit, 
 	      CONN_INFO *info, Conn_t **p_conn)
@@ -923,13 +999,18 @@
 
   conn = (Conn_t *)conn_handle;
 
-  EVENT(EM_DEBUG,("Removing conn:%p previous:%p next:%p ", conn,
+  if (conn->next == NULL && conn->previous == NULL
+      && connlist != conn) return;
+  EVENT(EM_DEBUG,("Removing conn:%p fd:%d previous:%p next:%p ", conn, 
+		  conn->fd,
 		  conn->previous, conn->next));
   if (conn->previous) 
-    EVENT(EM_DEBUG,("Previous:%p, next:%p, previous:%p ", conn->previous,
+    EVENT(EM_DEBUG,("Previous:%p, fd:%d, next:%p, previous:%p ", conn->previous,
+		    conn->previous->fd,
 		    conn->previous->next, conn->previous->previous));
   if (conn->next)
-    EVENT(EM_DEBUG,("Next:%p, next:%p, previous:%p ",conn->next,
+    EVENT(EM_DEBUG,("Next:%p, fd:%d next:%p, previous:%p ",conn->next,
+		    conn->next->fd,
 		    conn->next->next, conn->next->previous));  
   if (conn->previous) {
     conn->previous->next = conn->next;
@@ -956,25 +1037,14 @@
   return fd;
 }
 
-int
-get_ouratmaddr(int s, struct sockaddr_atmsvc *addr)
-{
-  struct atmif_sioc req;
-
-  req.number = 0;
-  req.arg = addr;
-  req.length = sizeof(struct sockaddr_atmsvc);
-
-  if (ioctl(s, ATM_GETADDR, &req) <0) {
-    EVENT(EM_SERR,("ioctl ATM_GETADDR :%s",strerror(errno)));
-    return -1;
-  }
-  return 0;
-}
 
 /*
  *
  * $Log: conn.c,v $
+ * Revision 1.26  1996/08/06 14:14:11  carnil
+ * Cleaning up
+ * Address handling moved to address.c from conn.c
+ *
  * Revision 1.25  1996/07/07 11:51:47  carnil
  * Global msg mask
  *
diff -ur --new-file old/atm/led/conn.h new/atm/led/conn.h
--- old/atm/led/conn.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/conn.h	Thu Aug 15 23:16:25 1996
@@ -15,11 +15,12 @@
 
 void conn_call_callbacks(void);
 void conn_get_fds(fd_set *fds);
+void conn_get_connecting_fds(fd_set *fds);
 int conn_check_incoming(fd_set *fds);
 int conn_create_listensocket(HANDLE sap_context, HANDLE conn_context,
 			     unsigned short blli_codepoint,
-			     int max_cell_rate, HANDLE *p_conn_handle);
-int get_ouratmaddr(int s, struct sockaddr_atmsvc *addr);
+			     int max_cell_rate,
+			     HANDLE *p_conn_handle);
 int conn_set_kernel_socket(int fd);
 /*
 void conn_convert_to_data_vcc(HANDLE conn_handle);
@@ -28,6 +29,10 @@
 /*
  *
  * $Log: conn.h,v $
+ * Revision 1.2  1996/08/06 14:14:11  carnil
+ * Cleaning up
+ * Address handling moved to address.c from conn.c
+ *
  * Revision 1.1  1996/05/23 11:50:54  carnil
  * Initial revision
  *
diff -ur --new-file old/atm/led/g_event.h new/atm/led/g_event.h
--- old/atm/led/g_event.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/g_event.h	Tue Aug  6 16:33:08 1996
@@ -108,13 +108,9 @@
       {                                                                  \
       printf ("%s %s '%s': ", emodtext (EMOD), emasktext (mask), EINST); \
       printf text;                                                       \
-      }
+      fflush (stdout);    }
 
-/* Each module must do the following:  (CM Example provided)
- *
- *    #define EMOD  MOD_CM
- *    #define EINST p_cm->p_text
- *    #define EMASK p_cm->event_mask
+/* 
  *
  * example event:
  *
diff -ur --new-file old/atm/led/lec.h new/atm/led/lec.h
--- old/atm/led/lec.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/lec.h	Tue Aug  6 16:33:08 1996
@@ -36,9 +36,6 @@
 *   lec.h
 *   
 * Overview:
-*   This header file describes the interface to the LAN Emulation Client (LEC)
-*   module.  It is through this interface that network protocols join
-*   Emulated LANs (ELANs) and use their services.
 *
 * Authors:
 *   TLR - Theodore L. Ross
@@ -56,128 +53,6 @@
 *   codes.h    - Completion codes.
 *   atm.h      - ATM specific definitions and types.
 *
-* Description:
-*   This is the interface through which the LEC provides services to LAN
-*   Emulation users (typically protocols).  It is a registration style
-*   interface that allows multiple protocols to use the LEC simultaneously.
-*   Each user becomes a member of a separate ELAN.
-*
-*   When a user registers with the LEC, the user provides its desired ELAN
-*   characteristics (i.e. LAN type, maximum frame size, etc.).  When the
-*   network is available, the LEC joins an ELAN on behalf of the user.  If the
-*   network becomes unavailable, the ELAN membership is cancelled.  As long
-*   as the user remains registered, the LEC waits for the network to
-*   become available so it can rejoin on behalf of the user.
-*
-*   If possible, the LEC uses the services of a LAN Emulation Configuration
-*   Server (LECS) to determine which ELAN each of its registered users should
-*   join.  Each time a join is attempted, the LECS is contacted.  This is to
-*   allow failover mechanisms built into the LECS to function correctly.  If
-*   a LAN Emulation server fails, a backup server or backup ELAN can be
-*   contacted by each of the affected LECs.
-*
-* Call Sequence Requirements:
-*
-*   The following diagram depicts the call sequence constraints:  Functions
-*   with lesser indentation must be called before function with greater
-*   indentation.
-*
-*   - lec_create
-*     - lec_register
-*       - lec_set_filters
-*       - lec_get_filters
-*       - lec_mcast_add
-*       - lec_mcast_delete
-*       - lec_mcast_get
-*       - lec_xmt
-*       - lec_event_mask_set
-*       - lec_unregister
-*     - lec_destroy
-*
-* Example Usage Scenario:
-*
-*   Callbacks are shown in parentheses.
-*
-*   lec_create..............Called at initialization time to create this
-*                           instance of the LEC.
-*
-*   lec_register............A protocol is attempting to connect to the network
-*                           and uses this call to register with the LEC.
-*                           The "ELAN join" parameters are provided in the call.
-*                           In this case, the network is available and the
-*                           join process begins.
-*
-*                           Note that the registered user must assume that the
-*                           initial status of the network is "UNAVAILABLE".
-*                           Notification shall be provided when the join is
-*                           complete.
-*
-*   lec_set_filters.........The protocol uses this call to set multicast,
-*                           broadcast, and promiscuous filters.
-*
-*   lec_mcast_add...........The protocol uses this call to add multicast
-*                           addresses to the multicast address table.  This
-*                           is meaningful only if the multicast filter is
-*                           enabled.
-*
-*   (lec_event_callback)....The join process has successfully completed.  This
-*                           callback notifies the protocol that the network is
-*                           now available for use.
-*
-*   lec_xmt.................The protocol calls this function to transmit a
-*                           data packet on the network.  There are three
-*                           possible status values that this function may
-*                           return.
-*
-*                           If the function returns "SUCCESS", the protocol
-*                           may assume that the packet was transmitted and
-*                           that it is safe to deallocate or overwrite the
-*                           packet buffer.
-*
-*                           If the function returns "PENDING", the packet was
-*                           successfully queued for transmission but has not
-*                           yet been copied from the buffer.  The protocol
-*                           must not deallocate or overwrite the buffer until
-*                           a transmit-done notification is returned for that
-*                           buffer.
-*
-*                           If the transmit function returns "CONGESTED", the
-*                           packet was neither transmitted nor buffered.  This
-*                           indicates that there is congestion somewhere down
-*                           the line which is preventing this packet from being
-*                           transmitted.  The protocol has the option of
-*                           queueing the packet for retransmission or
-*                           discarding the packet.
-*
-*                           In the case of congestion, there is no notification
-*                           that the congestion has cleared.  If the protocol
-*                           chooses to queue the packet for retransmission, it
-*                           must retry that transmission at a later time.
-*
-*   (lec_xmt_done_callback).This callback notifies the protocol that a packet
-*                           that was queued for transmit has been successfully
-*                           copied from the buffer and that the buffer may be
-*                           deallocated or overwritten.  A pointer to the
-*                           buffer is provided in the callback.
-*
-*   (lec_rcv_callback)......This callback is invoked when a packet is received
-*                           from the network destined for this protocol.
-*
-*   (lec_event_callback)....If the network becomes unavailable for any reason,
-*                           the event callback is used to notify the protocol
-*                           that network services are no longer available.
-*
-*   (lec_event_callback)....The event callback is invoked when the network
-*                           has become available again and the re-join to the
-*                           ELAN has completed.
-*
-*   lec_unregister..........Once the registered protocol no longer needs to
-*                           use the network it may unregister.  The membership
-*                           with the ELAN is cancelled.
-*
-*   lec_destroy.............This call is used to destroy this instance of the
-*                           LEC.  This is called when software is unloaded from
-*                           a system or when a logical device is removed.
 */
 
 /*************************************************************************
@@ -389,597 +264,5 @@
 typedef void (*LEC_XMT_DONE_CALLBACK) (HANDLE  context,
                                        void   *p_packet);
 
-
-/*++
-* ==============
-* = lec_create =
-* ==============
-*
-* Overview:
-*   Creates a new instance of the LEC module.
-*
-* Arguments:
-*   os_handle       - (IN)  Handle for OS utilities.
-*   cm_handle       - (IN)  Handle for corresponding Connection Manager
-*                           instance.
-*   line_up_handle  - (IN)  Handle of associated line-up instance.
-*   p_text          - (IN)  Pointer to a descriptive text string.
-*   p_lec_handle    - (OUT) Handle for this LEC instance.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Success: See Postconditions.
-*   STATUS_K_RESOURCES  - Insufficient resources to complete registration.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The handle is valid.
-*
---*/
-STATUS lec_create (HANDLE   line_up_handle,
-                   char    *p_text,
-                   HANDLE  *p_lec_handle);
-
-/*++
-* ===============
-* = lec_destroy =
-* ===============
-*
-* Overview:
-*   Destroys an instance of the LEC module.
-*
-* Arguments:
-*   lec_handle   - (IN)  Handle returned by lec_create.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   The handle is valid.
-*
-* Postconditions:
-*   The handle is invalid.
-*
---*/
-void lec_destroy (HANDLE  lec_handle);
-
-/*++
-* ================
-* = lec_register =
-* ================
-*
-* Overview:
-*   Registers a new LEC user and begins a join to an Emulated LAN.  Note that
-*   before the join process can begin, the LEC must obtain a new ATM address
-*   via Address Registration.
-*
-* Arguments:
-*   lec_handle          - (IN)  Handle returned by lec_create.
-*   context             - (IN)  Context handle to be passed back in callbacks.
-*   addr_reg_handle     - (IN)  Handle of Address Registration module instance.
-*   event_callback      - (IN)  Address of event callback function.
-*   rcv_callback        - (IN)  Address of receive callback function.
-*   xmt_done_callback   - (IN)  Address of transmit done callback function.
-*   mac_addr            - (IN)  This station's MAC address.  If this address
-*                               is 00-00-00-00-00-00, the LEC module will
-*                               automatically generate a MAC address (from the
-*                               ESI field of its ATM address).
-*   lan_type            - (IN)  Requested LAN type.
-*   max_frame_size      - (IN)  Requested MTU size.
-*   p_elan_name         - (IN)  Name of preferred emulated LAN.
-*   init_method         - (IN)  Selected method of initialization.  See the
-*                               above description of INIT_METHOD.
-*   manual_atm_addr     - (IN)  Manually entered ATM address.  This is required
-*                               for some of the initialization methods that may
-*                               be chosen using init_method.  If the
-*                               init_method does not require a manual ATM
-*                               address, this argument will be ignored.
-*   proxy_flag          - (IN)  Proxy flag for this ELAN.
-*   lport_handle        - (IN)  Logical Port Handle.  Used by proxy LEC's to
-*                               identify the ELAN's logical port to the fast
-*                               path.
-*   p_text              - (IN)  Text constant which describes this instance.
-*   p_elan_handle       - (OUT) Handle that is unique to the new registered
-*                               ELAN.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Success: See Postconditions.
-*   STATUS_K_RESOURCES  - Insufficient resources to complete registration.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The handle is valid.
-*
-*   The status of the network must be assumed to be "NETWORK_UNAVAILABLE".
-*
---*/
-STATUS lec_register (HANDLE                 lec_handle,
-                     HANDLE                 context,
-                     HANDLE                 addr_reg_handle,
-                     LEC_EVENT_CALLBACK     event_callback,
-                     LEC_RCV_CALLBACK       rcv_callback,
-                     LEC_XMT_DONE_CALLBACK  xmt_done_callback,
-                     ESI                    mac_addr,
-                     LAN_TYPE               lan_type,
-                     LAN_MTU                max_frame_size,
-                     char                  *p_elan_name,
-                     INIT_METHOD            init_method,
-                     ADDR_ATM               manual_atm_addr,
-                     BOOLEAN                proxy_flag,
-                     HANDLE                 lport_handle,
-                     char                  *p_text,
-                     HANDLE                *p_elan_handle);
-
-
-/*++
-* ==================
-* = lec_deregister =
-* ==================
-*
-* Overview:
-*   Cancels registration with the LEC.  This registration client's Emulated
-*   LAN session will be canceled (or will not retry if the network is down).
-*
-* Arguments:
-*   elan_handle  - (IN) Handle returned by lec_register.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The handle is not valid.
-*
---*/
-void lec_deregister (HANDLE elan_handle);
-
-
-/*++
-* ======================
-* = lec_event_mask_set =
-* ======================
-*
-* Overview:
-*   Sets the event mask for events logged from this module instance.
-*
-* Arguments:
-*   elan_handle  - (IN) Handle returned by lec_register.
-*   mask         - (IN) New mask value.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-void lec_event_mask_set (HANDLE elan_handle,
-                         UINT32 event_mask);
-
-
-/*++
-* ====================
-* = lec_mac_addr_add =
-* ====================
-*
-* Overview:
-*   Adds an additional MAC address to be registered by the LEC.  This MAC
-*   address will become a local MAC address.  Once the registration is
-*   complete, all packets received with a Destination Address that macthes
-*   the MAC address will be received and passed up to the LEC's user.
-*
-* Arguments:
-*   elan_handle  - (IN) Handle returned by lec_register.
-*   mac_addr     - (IN) New MAC address.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Successful completion.  Address registration is in
-*                         process.
-*   STATUS_K_RESOURCES  - Insufficient resources to complete operation.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-STATUS lec_mac_addr_add (HANDLE elan_handle,
-                         ESI    mac_addr);
-
-
-/*++
-* ====================
-* = lec_mac_addr_del =
-* ====================
-*
-* Overview:
-*   Deletes (unregisters) a previously registered MAC address.
-*
-* Arguments:
-*   elan_handle  - (IN) Handle returned by lec_register.
-*   mac_addr     - (IN) MAC address to be deleted.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-void lec_mac_addr_del (HANDLE elan_handle,
-                       ESI    mac_addr);
-
-
-/*++
-* ===================
-* = lec_filters_set =
-* ===================
-*
-* Overview:
-*   Enable or disable reception of multicast and broadcast packets.
-*
-* Arguments:
-*   elan_handle    - (IN)  Handle returned by lec_register.
-*
-*   mcast_enb      - (IN)  Multicast enable flag.  If this is set, all
-*                          packets to multicast destinations shall be
-*                          received.  If it is cleared, only packets with
-*                          multicast destination addresses found in the
-*                          multicast address table shall be recieved.
-*
-*   bcast_enb      - (IN)  Broadcast enable flag.  If this flag is set, all
-*                          broadcast packets shall be received.  If it is
-*                          cleared, no broadcast packets shall be received.
-*
-*   prom_enb       - (IN)  Promiscuous mode enable.  If this flag is set,
-*                          all incoming packets shall be received.  This
-*                          overrides the settings of the mcast_enb and
-*                          bcast_enb flags.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The new filter settings immediately take effect.
-*
---*/
-void lec_filters_set (HANDLE  elan_handle,
-                      BOOLEAN mcast_enb,
-                      BOOLEAN bcast_enb,
-                      BOOLEAN prom_enb);
-
-
-/*++
-* ===================
-* = lec_filters_get =
-* ===================
-*
-* Overview:
-*   Gets the current settings of the receive packet filters.
-*
-* Arguments:
-*   elan_handle    - (IN)  Handle returned by lec_register.
-*   p_mcast_enb    - (OUT) Setting of multicast enable.
-*   p_bcast_enb    - (OUT) Setting of broadcast enable.
-*   p_prom_enb     - (OUT) Setting of promiscuous mode.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   Returned values reflect status of the filters that are in effect.
-*
---*/
-void lec_filters_get (HANDLE     elan_handle,
-                      BOOLEAN   *p_mcast_enb,
-                      BOOLEAN   *p_bcast_enb,
-                      BOOLEAN   *p_prom_enb);
-
-
-/*++
-* =================
-* = lec_mcast_add =
-* =================
-*
-* Overview:
-*   Adds a multicast 48-bit address to the multicast address table.  If this
-*   address is already in the table, its instance count shall be incremented.
-*
-* Arguments:
-*   elan_handle - (IN)  Handle returned by lec_register.
-*   addr        - (IN)  48-bit multicast address to be added.    
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Success: See Postconditions.
-*   STATUS_K_RESOURCES  - Insufficient resources to perform the operation.
-*                         Note that this may occur because host memory could
-*                         not be allocated or because an on-adapter multicast
-*                         address table is full.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   If the address was not previously in the table, it is added with an
-*   instance count of 1.
-*
-*   If the address was previously in the table, its instance count is 1
-*   greater than its previous value.
-*   
---*/
-STATUS lec_mcast_add (HANDLE  elan_handle,
-                      ESI     addr);
-
-/*++
-* ====================
-* = lec_mcast_delete =
-* ====================
-*
-* Overview:
-*   Deletes an instance of a multicast address from the multicast address
-*   table.
-*
-* Arguments:
-*   elan_handle  - (IN)  Handle returned by lec_register.
-*   addr         - (IN)  Multicast address to be deleted.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Success: See Postconditions.
-*   STATUS_K_NOT_FOUND  - No such address was found.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   If the address previously had an instance count of 2 or greater, the
-*   instance count is decremented by one.
-*
-*   If the address previously has an instance count of 1, the address has
-*   been deleted from the table.
-*
---*/
-STATUS lec_mcast_delete (HANDLE  elan_handle,
-                         ESI     addr);
-
-
-/*++
-* ==================
-* = lec_mcast_load =
-* ==================
-*
-* Overview:
-*   Clears and loads the multicast table in its entirety.
-*
-* Arguments:
-*   elan_handle    - (IN)  Handle returned by lec_register.
-*   table_size     - (IN)  Number of addresses in the table.
-*   addr_array     - (IN)  Address array.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The multicast address table contains the same addresses as the address
-*   array.  All instance counts are 1.
-*
---*/
-void lec_mcast_load (HANDLE   elan_handle,
-                     UINT32   table_size,
-                     ADDR_48  addr_array[]);
-
-
-/*++
-* =================
-* = lec_mcast_get =
-* =================
-*
-* Overview:
-*   Gets the contents of the multicast address table.
-*
-* Arguments:
-*   elan_handle    - (IN)  Handle returned by lec_register.
-*   array_size     - (IN)  Number of elements in array buffers.
-*   addr_array     - (IN)  Pointer to the address array.
-*   count_array    - (IN)  Pointer to the instance count array.
-*   p_addr_count   - (OUT) Number of addresses in multicast table.
-*                          Note that if this number is greater than array_size,
-*                          only array_size addresses have been copied into the
-*                          arrays.  The remaining (*p_addr_count - array_size)
-*                          entries are not copied.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   If array_size is zero, the pointers to both arrays need not be valid.
-*
-* Postconditions:
-*   MIN (array_size, *p_addr_count) entries have been copied into the two
-*   arrays.
-*
-*   For i from 0 to MIN (array_size, *p_addr_count) : p_count_array[i] is the
-*   instance count for the address in p_addr_array[i].
-*
---*/
-void lec_mcast_get (HANDLE   elan_handle,
-                    UINT32   array_size,
-                    ESI      addr_array[],
-                    UINT32   count_array[],
-                    UINT32  *p_addr_count);
-
-
-/*++
-* ===========
-* = lec_xmt =
-* ===========
-*
-* Overview:
-*   Requests the transmission of a packet to the Emulated LAN network.
-*
-* Arguments:
-*   elan_handle    - (IN)  Handle returned by lec_register.
-*   da             - (IN)  Destination address of the packet.
-*   p_pkt          - (IN)  Pointer to the packet to be transmitted.  The
-*                          format of this packet is not known to the LEC.
-*                          It simply sends the pointer down to the lower
-*                          driver.
-*   length         - (IN)  The length of the packet in bytes.
-*
-* Returns:
-*   STATUS_K_SUCCESS      - The packet was successfully transmitted.  The
-*                           buffer may be safely deallocated by the caller.
-*
-*   STATUS_K_PENDING      - The packet was successfully queued for
-*                           transmission.  The buffer may not be deallocated
-*                           until it is returned by the transmit-done callback.
-*
-*   STATUS_K_CONGESTED    - Packet was not transmitted due to congestion.
-*                           The transmit packet buffer is still intact
-*                           and may be buffered or dropped.
-*
-*   STATUS_K_FAILURE      - The network is not available.  The packet was not
-*                           transmitted and the packet buffer is still intact.
-*
-* Preconditions:
-*   None.
-*
-* Postconditions:
-*   None.
-*
---*/
-STATUS lec_xmt (HANDLE   elan_handle,
-                ESI      da,
-                void    *p_pkt,
-                UINT32   length);
-
-
-/*++
-* ================
-* = lec_attr_get =
-* ================
-*
-* Overview:
-*   Get a management attribute for an ELAN instance.  Refer to lec_mgt.h for
-*   a list of attribute IDs.
-*
-* Arguments:
-*   elan_handle       - (IN)  Handle returned by lec_register.
-*   attr_id           - (IN)  ID of attribute to be accessed.
-*   p_out_buffer      - (IN)  Pointer to the output buffer to be filled with
-*                             data.
-*   out_buffer_length - (IN)  Number of bytes writable in the output buffer.
-*   p_bytes_written   - (OUT) Number of bytes written.
-*
-* Returns:
-*   STATUS_K_SUCCESS       - Successful Completion.
-*   STATUS_K_ARG_2_BAD     - Invalid Attribute ID.
-*   STATUS_K_ARG_4_BAD     - Not enough space in output buffer.
-*   STATUS_K_NOT_FOUND     - Instance not found.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-STATUS lec_attr_get (HANDLE     elan_handle,
-                     UINT16     attr_id,
-                     void      *p_out_buffer,
-                     UINT16     out_buffer_length,
-                     UINT16    *p_bytes_written);
-
-/*++
-* =====================
-* = lec_attr_get_next =
-* =====================
-*
-* Overview:
-*   Get a management attribute for an ELAN instance.  Refer to lec_mgt.h for
-*   a list of attribute IDs.  This function gets the next instance of the
-*   attribute after the key supplied in the input buffer.
-*
-* Arguments:
-*   elan_handle       - (IN)  Handle returned by lec_register.
-*   attr_id           - (IN)  ID of attribute to be accessed.
-*   p_in_buffer       - (IN)  Pointer to input buffer containing search key
-*                             for get-next operation.
-*   in_buffer_length  - (IN)  Number of bytes in the input buffer.
-*   p_out_buffer      - (IN)  Pointer to the output buffer to be filled with
-*                             data.
-*   out_buffer_length - (IN)  Number of bytes writable in the output buffer.
-*   p_bytes_written   - (OUT) Number of bytes written.
-*
-* Returns:
-*   STATUS_K_SUCCESS       - Successful Completion.
-*   STATUS_K_ARG_2_BAD     - Invalid Attribute ID.
-*   STATUS_K_ARG_6_BAD     - Not enough space in output buffer.
-*   STATUS_K_NOT_FOUND     - Instance not found.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-STATUS lec_attr_get_next (HANDLE     elan_handle,
-                          UINT16     attr_id,
-                          void      *p_in_buffer,
-                          UINT16     in_buffer_length,
-                          void      *p_out_buffer,
-                          UINT16     out_buffer_length,
-                          UINT16    *p_bytes_written);
-
-/*++
-* ================
-* = lec_attr_set =
-* ================
-*
-* Overview:
-*   Set a management attribute for an ELAN instance.  Refer to lec_mgt.h for
-*   a list of attribute IDs.
-*
-* Arguments:
-*   elan_handle       - (IN)  Handle returned by lec_register.
-*   attr_id           - (IN)  ID of attribute to be accessed.
-*   p_in_buffer       - (IN)  Pointer to the input buffer that contains data
-*                             to be written.
-*   in_buffer_length  - (IN)  Number of bytes to be written.
-*
-* Returns:
-*   STATUS_K_SUCCESS       - Successful Completion.
-*   STATUS_K_FAILURE       - Operation Failed.
-*   STATUS_K_ARG_2_BAD     - Invalid Attribute ID.
-*   STATUS_K_ARG_5_BAD     - Not enough space in output buffer.
-*   STATUS_K_NOT_FOUND     - Instance not found.
-*   STATUS_K_NO_PRIVELEGE  - Attempted to write a Read-Only attribute.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-STATUS lec_attr_set (HANDLE     elan_handle,
-                     UINT16     attr_id,
-                     void      *p_in_buffer,
-                     UINT16     in_buffer_length);
 
 #endif /* LEC_H */
diff -ur --new-file old/atm/led/lec_arp.c new/atm/led/lec_arp.c
--- old/atm/led/lec_arp.c	Sun Jul  7 13:59:07 1996
+++ new/atm/led/lec_arp.c	Tue Aug 20 20:39:34 1996
@@ -24,7 +24,7 @@
 /*
  * Lec arp cache daemon part
  *
- * $Id: lec_arp.c,v 1.12 1996/07/07 11:51:47 carnil Exp carnil $
+ * $Id: lec_arp.c,v 1.13 1996/08/06 14:14:11 carnil Exp carnil $
  *
  */
 
@@ -45,10 +45,7 @@
 
 #include "af_lane.h"
 #include "cm.h"
-#include "map.h"
 #include "svc_info.h"
-#include "map_data.h"
-#include "lec_mgt.h"
 #include "lec.h"
 #include "lec_arp.h"
 
@@ -100,14 +97,14 @@
 {
   LA_ELAN_CONTEXT *p_elan;
   ADDR_ATM *to_pass;
-  MAP_ESI_RECORD dumb;
+  UINT32 dumb;
 
   to_pass = (ADDR_ATM*)mesg->content.normal.atm_addr;
 
   utl_list_traverse(lec_arp_context.elan_list, p_elan) {
     lec_arp_context.flush_xmt_callback(p_elan->lc_elan_handle, *to_pass,&dumb);
     kernel_sendmsg(l_flush_tran_id, mesg->content.normal.mac_addr,NULL,
-		   NULL, dumb.flush_tran_id);
+		   NULL, dumb);
   }
 }
 
@@ -201,19 +198,12 @@
   p_elan    = (LA_ELAN_CONTEXT *) la_elan_handle;
   p_context = (LA_CONTEXT      *) p_elan->la_handle;
   
-
   utl_list_delete(p_context->elan_list, p_elan);
   
   mem_free(EINST,p_elan);
 }
 
 void 
-la_event_mask_set(HANDLE la_elan_handle,
-		  UINT32 event_mask)
-{
-}
-
-void 
 la_config(HANDLE la_elan_handle, LAN_TYPE lan_type,
 	  BOOLEAN proxy_flag, UINT16 max_unknown_frame_count,
 	  UINT16 max_unknown_frame_time, UINT32 vcc_timeout,
@@ -238,12 +228,6 @@
   kernel_sendmsg(l_config, NULL, NULL, &conf_mesg, 0);
 }
 
-void 
-la_elan_reset(HANDLE la_elan_handle)
-{
-  kernel_sendmsg(l_reset, NULL, NULL, NULL, 0);
-}
-
 STATUS 
 la_perm_add(HANDLE la_elan_handle, ESI esi, ADDR_ATM addr_atm)
 {
@@ -268,6 +252,8 @@
 	      ADDR_ATM  addr_atm,
 	      BOOLEAN   remote_flag)
 {
+  EVENT(EM_DEBUG,("ARP update for %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
+		  esi[0],esi[1],esi[2],esi[3],esi[4],esi[5]));
   kernel_sendmsg(l_arp_update, (unsigned char *)esi,
 		 (unsigned char *)&addr_atm, NULL, remote_flag==TRUE?1:0);
 }
@@ -293,6 +279,9 @@
 /*
  *
  * $Log: lec_arp.c,v $
+ * Revision 1.13  1996/08/06 14:14:11  carnil
+ * Cleaning up
+ *
  * Revision 1.12  1996/07/07 11:51:47  carnil
  * Global msg_mask
  * Arp cache deletion by atm_address
diff -ur --new-file old/atm/led/lec_arp.h new/atm/led/lec_arp.h
--- old/atm/led/lec_arp.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/lec_arp.h	Tue Aug  6 16:33:08 1996
@@ -81,7 +81,6 @@
 *         - la_topology_change_set
 *         - la_vc_added
 *         - la_vc_deleted
-*       - la_event_mask_set
 *       - la_deregister
 *     - la_destroy
 *
@@ -398,30 +397,6 @@
 *   The la_elan_handle is not valid.
 --*/
 void la_deregister (HANDLE la_elan_handle);
-
-/*++
-* =====================
-* = la_event_mask_set =
-* =====================
-*
-* Overview:
-*   Sets this module's event reporting mask.
-*
-* Arguments:
-*   la_elan_handle  - (IN) Handle returned by la_register.
-*   event_mask      - (IN) New value of event_mask
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   The la_elan_handle is valid.
-*
-* Postconditions:
-*   None
---*/
-void la_event_mask_set (HANDLE la_elan_handle,
-                        UINT32 event_mask);
 
 /*++
 * =============
diff -ur --new-file old/atm/led/lec_ctrl.c new/atm/led/lec_ctrl.c
--- old/atm/led/lec_ctrl.c	Sun Jul  7 13:59:07 1996
+++ new/atm/led/lec_ctrl.c	Tue Aug 20 20:39:49 1996
@@ -81,39 +81,24 @@
 
 #include "af_lane.h"    /* ATM Forum LAN Emulation Definitions   */
 #include "cm.h"
-#include "map.h"        /* Mapping Module Interface              */
 #include "svc_info.h"   /* SVC Data Structures                   */
 #include "cm_sap.h"     /* CM SAP Interface                      */
 #include "addr_reg.h"   /* Address Registration Interface        */
-#include "map_data.h"
-#include "lec_mgt.h"
 #include "lec.h"        /* LAN Emulation Protocol Interface      */
 #include "lec_arp.h"    /* LEC_ARP Module Interface              */
 #include "lec_ctrl.h"   /* LEC_CTRL Module Interface             */
 #include "le_disp.h"
-#include "line_up.h"
 
 #define EMOD   MOD_LEC_CTRL
 #define EINST  "lec_ctrl.c"
 #include "emask.h"
 
-typedef struct _reg_dest
-   {
-   MAP_LIST_HDR       hdr;
-   ESI                mac_addr;
-   BOOLEAN            registered;
-   BOOLEAN            unregistering;
-   UINT32             tran_id;
-   } REG_DEST;
-
-static BOOLEAN reg_dest_destroy (HANDLE foobar,HANDLE dest_handle)
-{
-  REG_DEST  *p_dest;
-  
-  p_dest = (REG_DEST *) dest_handle;
-  os_mem_dealloc (dest_handle);
-  return TRUE;
-}
+typedef struct _reg_dest {
+  ESI                mac_addr;
+  BOOLEAN            registered;
+  BOOLEAN            unregistering;
+  UINT32             tran_id;
+} REG_DEST;
 
 /*  LEC_STATE
  *
@@ -132,7 +117,7 @@
   char           c5_elan_name[32]; /* For config request */
   UINT8          elan_name_size_join;   /* For join request */
   char           c5_elan_name_join[32]; /* For join request */
-  HANDLE         c6_my_mac_addr_list;
+  REG_DEST       c6_my_mac_addr; 
   UINT16         c7_control_timeout;
   ADDR_ATM       c9_les_atm_addr;
   UINT16         c10_max_unknown_frame_count;
@@ -237,10 +222,6 @@
  *  lecs_addr
  *    The ATM address of the LECS that is currently being contacted.
  *
- *  lecs_pvc
- *    Boolean flag indicating that the LECS is being contacted via well-known
- *    PVC.
- *
  *  skip_lecs
  *    Boolean flag that indicates that the LECS should not be contacted in the
  *    provecc of joining the emulated LAN.  Instead, it should be assumed that
@@ -250,11 +231,6 @@
  *  bus_addr
  *    The ATM Address of the BUS being contacted.
  *
- *  uni_version
- *    The UNI Version being supported by the connected switch (3.0 or 3.1).
- *    This is needed to properly set up SVC information elements.  This data
- *    is obtained from the UME.
- *
  *  max_cell_rate
  *    The maximum cell rate supported by the physical adapter.  This
  *    information is required to properly generate SVC information elements.
@@ -280,7 +256,6 @@
    {
    struct _lc_elan  *p_next;
    char             *p_text;
-   UINT32            event_mask;
    HANDLE            lc_handle;
    HANDLE            la_elan_handle;
    HANDLE            ld_elan_handle;
@@ -304,13 +279,11 @@
    UINT16            sm_timer_duration;
    LEC_STATE         lec_state;
    ADDR_ATM          lecs_addr;
-   BOOLEAN           lecs_pvc;
    INIT_METHOD       init_method;
    ADDR_ATM          bus_addr;
    HANDLE            reg_timer;
    SM_STATE_HISTORY  sm_state_history[SM_STATE_HISTORY_DEPTH];
    UINT8             sm_state_history_index;
-   UINT8             uni_version;
    UINT32            max_cell_rate;
    UINT32            current_tran_id;
    UINT8             vc_ready_mask;
@@ -321,10 +294,6 @@
    UINT32            ctrl_frames_rcvd;
    UINT32            arps_sent;
    UINT32            arps_rcvd;
-   UINT32            ucasts_sent_direct;
-   UINT32            ucasts_flooded;
-   UINT32            ucasts_discarded;
-   UINT32            nucasts_sent;
    } LC_ELAN_CONTEXT;
 
 SIMPLE_LIST (LC_ELAN_CONTEXT, ELAN_LIST);
@@ -440,11 +409,6 @@
   
   p_conn_info->addr.sas_family = AF_ATMSVC;
   
-  /* AAL Parameters. */
-  
-    /* Set AAL type to 5 */
-  
-  
     /* Set the forward and backward Max CPCS-SDU Size */
   switch(blli_codepoint) {
   case BLLI_CONTROL:
@@ -461,14 +425,6 @@
   default:
     EVENT(EM_ASSERT,("Unknown BLLI codepoint %x\n",blli_codepoint));
   }
-  if (p_elan->uni_version == UNI_3_0)
-    {
-      /* Set the mode field to 1 */
-    }
-
-      /* Set SCCS type to 0 */
-
-
   /* ATM User Cell Rate/ATM Traffic Descriptor. */
   p_conn_info->conqos.txtp.class = ATM_UBR;
   p_conn_info->conqos.rxtp.class = ATM_UBR;
@@ -477,26 +433,13 @@
   p_conn_info->conqos.txtp.max_pcr = p_elan->max_cell_rate;
   p_conn_info->conqos.rxtp.max_pcr = p_elan->max_cell_rate;
 
-  /* Broadband Bearer Capability. */
-
-      /* Set the bearer class to 16 */
-
-      /* Set the timing requirements to 0 */
-
-      /* Set the traffic type to 0 */
-
-      /* Set the user plane configuration to 'pmp' */
   if (pmp==TRUE) {
     /* Asdf */
   } else {
     /* Fdsa */
   }
-      /* Set the susceptability to clipping to 0 */
-
 
   /* Broadband Lower Layer Information. */
-
-    /* Set the BLLI to (hex) 6b.40.80.80.00.a0.3e.codepointhi.codepointlo */
   p_conn_info->blli.l3_proto = ATM_L3_TR9577;
   p_conn_info->blli.l3.tr9577.ipi = NLPID_IEEE802_1_SNAP;
   p_conn_info->blli.l3.tr9577.snap[0] = 0x00;
@@ -510,20 +453,7 @@
     for(i=0;i<5;i++) {
       printf("snap[%d] = 0x%2.2x\n",i,p_conn_info->blli.l3.tr9577.snap[i]);
     }
-  /* QoS Parameter. */
-
-      /* Set Qos class (forw and back) to 0 */
-
-
    /* Called Party Number. */
-
-      /* Set Plan ID to 2 */
-
-      /* Set the type to 0 */
-
-      /* Set the length to 20 */
-
-      /* Copy called_party into the conn_info */
   p_conn_info->addr.sas_addr.prv[0] = called_party.prefix[0];
   p_conn_info->addr.sas_addr.prv[1] = called_party.prefix[1];
   p_conn_info->addr.sas_addr.prv[2] = called_party.prefix[2];
@@ -545,15 +475,6 @@
   p_conn_info->addr.sas_addr.prv[18] = called_party.esi[5];
   p_conn_info->addr.sas_addr.prv[19] = called_party.sel;
    /* Calling Party Number. */
-
-      /* Set Plan ID to 2 */
-
-      /* Set the type to 0 */
-
-      /* Set the length to 20 */
-
-      /* Copy calling_party into the conn_info */
-
 }
 
 
@@ -709,7 +630,7 @@
 
    p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
 
-   utl_mem_zero (&frame, sizeof (LE_REG_FRAME));
+   memset(&frame, 0, sizeof (LE_REG_FRAME));
 
    if (reg)
       {
@@ -751,49 +672,38 @@
       }
    }
 
-static void reg_timer_handler (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   REG_DEST          *p_dest;
-   BOOLEAN            request_sent;
-   HANDLE             dest_handle;
-   STATUS             status;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   request_sent = FALSE;
-
-   /* Traverse the list of LAN destinations.  If there is an entry that has
-    * not been successfully registered, send a register-request to the LES on
-    * its behalf.  If there is an entry that is flagged as unregistering, send
-    * an unregister-request.
-    */
-   status = map_get_first (p_elan->lec_state.c6_my_mac_addr_list, &dest_handle);
-   while (status == STATUS_K_SUCCESS)
-      {
-      p_dest = (REG_DEST *) dest_handle;
-      if ((!p_dest->registered) && (!p_dest->unregistering))
-         {
-         reg_req_xmt (lc_elan_handle, p_dest, TRUE);
-         request_sent = TRUE;
-         }
-      if ((!p_dest->registered) && (p_dest->unregistering))
-         {
-         reg_req_xmt (lc_elan_handle, p_dest, FALSE);
-         request_sent = TRUE;
-         }
-
-      status = map_get_next (p_elan->lec_state.c6_my_mac_addr_list,
-                             p_dest->mac_addr,
-                             &dest_handle);
-      }
-
-   if (request_sent)
-      {
-      os_timer_set (p_elan->reg_timer,
-                    p_elan->lec_state.c7_control_timeout * 1000);
-      }
-   }
+static void 
+reg_timer_handler (HANDLE lc_elan_handle)
+{
+  LC_ELAN_CONTEXT   *p_elan;
+  BOOLEAN            request_sent;
+  
+  p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
+  
+  request_sent = FALSE;
+  
+  /* Our LAN address. If it has
+   * not been successfully registered, send a register-request to the LES.
+   * If it is flagged as unregistering, send
+   * an unregister-request.
+   */
+  if ((!p_elan->lec_state.c6_my_mac_addr.registered) && 
+      (!p_elan->lec_state.c6_my_mac_addr.unregistering)) {
+    reg_req_xmt (lc_elan_handle, 
+		 &p_elan->lec_state.c6_my_mac_addr, TRUE);
+    request_sent = TRUE;
+  }
+  if ((!p_elan->lec_state.c6_my_mac_addr.registered) && 
+      (p_elan->lec_state.c6_my_mac_addr.unregistering)) {
+    reg_req_xmt (lc_elan_handle, 
+		 &p_elan->lec_state.c6_my_mac_addr, FALSE);
+    request_sent = TRUE;
+  }
+  if (request_sent) {
+    os_timer_set (p_elan->reg_timer,
+		  p_elan->lec_state.c7_control_timeout * 1000);
+  }
+}
 
 /****************************************************************************
  *  State Machine Definitions
@@ -847,7 +757,6 @@
 static void act_ilmi_next_get       (HANDLE lc_elan_handle);
 static void act_lecs_svc_setup      (HANDLE lc_elan_handle);
 static void act_lecs_wsvc_setup     (HANDLE lc_elan_handle);
-static void act_lecs_pvc_setup      (HANDLE lc_elan_handle);
 static void act_config_req_xmt      (HANDLE lc_elan_handle);
 static void act_les_svc_setup       (HANDLE lc_elan_handle);
 static void act_join_req_xmt        (HANDLE lc_elan_handle);
@@ -857,6 +766,7 @@
 static void act_les_svc_teardown    (HANDLE lc_elan_handle);
 static void act_bus_svc_teardown    (HANDLE lc_elan_handle);
 static void act_timer_cancel        (HANDLE lc_elan_handle);
+static void act_ctrl_list_close     (HANDLE lc_elan_handle);
 
 #define TRAN(curr, in_event, next, act1, act2, act3)                       \
    {                                                                       \
@@ -975,10 +885,8 @@
    TRAN (S_LECS_SVC_WAIT,  E_LECS_SVC_RELEASE,    S_ILMI_WAIT,      act_timer_cancel,     act_ilmi_next_get,    NULL);
    TRAN (S_LECS_SVC_WAIT,  E_TIMEOUT_NORETRY,     S_ILMI_WAIT,      act_ilmi_next_get,    NULL,                 NULL);
    TRAN (S_LECS_WSVC_WAIT, E_LECS_SVC_READY,      S_CONFIG_WAIT,    act_timer_cancel,     act_config_req_xmt,   NULL);
-   TRAN (S_LECS_WSVC_WAIT, E_LECS_SVC_RELEASE,    S_LECS_PVC_WAIT,  act_timer_cancel,     act_lecs_pvc_setup,   NULL);
-   TRAN (S_LECS_WSVC_WAIT, E_TIMEOUT_NORETRY,     S_LECS_PVC_WAIT,  act_lecs_pvc_setup,   NULL,                 NULL);
-   TRAN (S_LECS_PVC_WAIT,  E_LECS_PVC_READY,      S_CONFIG_WAIT,    act_timer_cancel,     act_config_req_xmt,   NULL);
-   TRAN (S_LECS_PVC_WAIT,  E_TIMEOUT_NORETRY,     S_ILMI_WAIT,      act_ilmi_ld_1st_get,  NULL,                 NULL);
+   TRAN (S_LECS_WSVC_WAIT, E_LECS_SVC_RELEASE,    S_ILMI_WAIT,      act_timer_cancel,     act_ilmi_ld_1st_get,  NULL);
+   TRAN (S_LECS_WSVC_WAIT, E_TIMEOUT_NORETRY,     S_ILMI_WAIT,      act_ilmi_ld_1st_get,  NULL,                 NULL);
    TRAN (S_CONFIG_WAIT,    E_RCV_CONFIG_RSP,      S_LES_SVC_WAIT,   act_timer_cancel,     act_lecs_vc_teardown, act_les_svc_setup);
    TRAN (S_CONFIG_WAIT,    E_TIMEOUT_RETRY,       S_CONFIG_WAIT,    act_config_req_xmt,   NULL,                 NULL);
    TRAN (S_CONFIG_WAIT,    E_TIMEOUT_NORETRY,     S_ILMI_WAIT,      act_lecs_vc_teardown, act_ilmi_next_get,    NULL);
@@ -994,7 +902,7 @@
    TRAN (S_BUS_ARP_WAIT,   E_TIMEOUT_RETRY,       S_BUS_ARP_WAIT,   act_bus_arp_req_xmt,  NULL,                 NULL);
    TRAN (S_BUS_ARP_WAIT,   E_TIMEOUT_NORETRY,     S_ILMI_WAIT,      act_les_svc_teardown, act_ilmi_next_get,    NULL);
    TRAN (S_BUS_ARP_WAIT,   E_LES_SVC_RELEASE,     S_ILMI_WAIT,      act_timer_cancel,     act_ilmi_ld_1st_get,  NULL);
-   TRAN (S_BUS_SVC_WAIT,   E_BUS_SVC_READY,       S_OPERATIONAL,    act_timer_cancel,     NULL,                 NULL);
+   TRAN (S_BUS_SVC_WAIT,   E_BUS_SVC_READY,       S_OPERATIONAL,    act_timer_cancel,     act_ctrl_list_close,  NULL);
    TRAN (S_BUS_SVC_WAIT,   E_BUS_SVC_REL_NORM,    S_ILMI_WAIT,      act_timer_cancel,     act_les_svc_teardown, act_ilmi_next_get);
    TRAN (S_BUS_SVC_WAIT,   E_BUS_SVC_REL_ABNORM,  S_ILMI_WAIT,      act_timer_cancel,     act_les_svc_teardown, act_ilmi_next_get);
    TRAN (S_BUS_SVC_WAIT,   E_TIMEOUT_NORETRY,     S_ILMI_WAIT,      act_les_svc_teardown, act_ilmi_next_get,    NULL);
@@ -1051,7 +959,7 @@
    TRAN (S_BUS_ARP_WAIT,   E_TIMEOUT_RETRY,       S_BUS_ARP_WAIT,   act_bus_arp_req_xmt,  NULL,                 NULL);
    TRAN (S_BUS_ARP_WAIT,   E_TIMEOUT_NORETRY,     S_LES_SVC_WAIT,   act_les_svc_teardown, act_les_svc_setup,    NULL);
    TRAN (S_BUS_ARP_WAIT,   E_LES_SVC_RELEASE,     S_LES_SVC_WAIT,   act_timer_cancel,     act_les_svc_setup,    NULL);
-   TRAN (S_BUS_SVC_WAIT,   E_BUS_SVC_READY,       S_OPERATIONAL,    act_timer_cancel,     NULL,                 NULL);
+   TRAN (S_BUS_SVC_WAIT,   E_BUS_SVC_READY,       S_OPERATIONAL,    act_timer_cancel,     act_ctrl_list_close,  NULL);
    TRAN (S_BUS_SVC_WAIT,   E_BUS_SVC_REL_NORM,    S_LES_SVC_WAIT,   act_timer_cancel,     act_les_svc_teardown, act_les_svc_setup);
    TRAN (S_BUS_SVC_WAIT,   E_BUS_SVC_REL_ABNORM,  S_LES_SVC_WAIT,   act_timer_cancel,     act_les_svc_teardown, act_les_svc_setup);
    TRAN (S_BUS_SVC_WAIT,   E_TIMEOUT_NORETRY,     S_LES_SVC_WAIT,   act_les_svc_teardown, act_les_svc_setup,    NULL);
@@ -1212,24 +1120,6 @@
 * ================
 * = sm_timer_set =
 * ================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*
-* Arguments:
-*
-* Returns:
-*
-* Preconditions:
-*
-* Postconditions:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void sm_timer_set (HANDLE lc_elan_handle,
                           UINT16 duration,
@@ -1252,24 +1142,6 @@
 * ====================
 * = sm_timer_handler =
 * ====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*
-* Arguments:
-*
-* Returns:
-*
-* Preconditions:
-*
-* Postconditions:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void sm_timer_handler (HANDLE lc_elan_handle)
    {
@@ -1291,68 +1163,52 @@
       }
    }
 
+static void 
+act_ctrl_list_close(HANDLE lc_elan_handle)
+{
+  /*
+  cm_kill_ctrl_listens();
+  */
+}
+
 /*++
 * ====================
 * = act_atm_addr_req =
 * ====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
 * Description:
 *  Request a new ATM address from the Address-Registration Service.
-*
-* Issues:
-*   None
-*
 --*/
-static void act_atm_addr_req (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   STATUS             status;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   status = addr_reg_atm_addr_alloc (p_elan->addr_reg_client_handle);
-
-   assert ((status == STATUS_K_PENDING) || (status == STATUS_K_SUCCESS));
-   }
+static void 
+act_atm_addr_req (HANDLE lc_elan_handle)
+{
+  LC_ELAN_CONTEXT   *p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
+  STATUS             status;
+  
+  status = addr_reg_atm_addr_alloc (p_elan->addr_reg_client_handle);
+  
+  assert ((status == STATUS_K_PENDING) || (status == STATUS_K_SUCCESS));
+}
 
 /*++
 * =======================
 * = act_atm_addr_cancel =
 * =======================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
 * Description:
 *  Cancel registration of an ATM address.
-*
-* Issues:
-*   None
-*
 --*/
-static void act_atm_addr_cancel (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   (void) addr_reg_atm_addr_dealloc (p_elan->addr_reg_client_handle,
-                                     &p_elan->lec_state.c1_my_atm_addr); 
-   }
+static void 
+act_atm_addr_cancel (HANDLE lc_elan_handle)
+{
+  LC_ELAN_CONTEXT   *p_elan = (LC_ELAN_CONTEXT*) lc_elan_handle;
+  
+  (void) addr_reg_atm_addr_dealloc (p_elan->addr_reg_client_handle,
+				    &p_elan->lec_state.c1_my_atm_addr); 
+}
 
 /*++
 * =======================
 * = act_ilmi_ld_1st_get =
 * =======================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_ilmi_ld_1st_get (HANDLE lc_elan_handle)
    {
@@ -1387,18 +1243,11 @@
    assert (FALSE);
    }
 
+
 /*++
 * =====================
 * = act_ilmi_next_get =
 * =====================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_ilmi_next_get (HANDLE lc_elan_handle)
    {
@@ -1415,14 +1264,6 @@
 * ======================
 * = act_lecs_svc_setup =
 * ======================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_lecs_svc_setup (HANDLE lc_elan_handle)
    {
@@ -1451,13 +1292,6 @@
 * = act_lecs_wsvc_setup =
 * =======================
 *
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_lecs_wsvc_setup (HANDLE lc_elan_handle)
    {
@@ -1511,38 +1345,8 @@
 
 /*++
 * ======================
-* = act_lecs_pvc_setup =
-* ======================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
---*/
-static void act_lecs_pvc_setup (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 0);
-   }
-
-/*++
-* ======================
 * = act_config_req_xmt =
 * ======================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_config_req_xmt (HANDLE lc_elan_handle)
    {
@@ -1552,7 +1356,7 @@
 
    p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
 
-   utl_mem_zero (&frame, sizeof (LE_JOIN_FRAME));
+   memset(&frame, 0, sizeof (LE_JOIN_FRAME));
 
    lc_ctrl_hdr_make (lc_elan_handle, &frame.hdr, LE_CONFIG_REQ);
    frame.hdr.req_lec_id = hton16 (0);
@@ -1603,14 +1407,6 @@
 * =====================
 * = act_les_svc_setup =
 * =====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_les_svc_setup (HANDLE lc_elan_handle)
    {
@@ -1638,82 +1434,57 @@
 * ====================
 * = act_join_req_xmt =
 * ====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-static void act_join_req_xmt (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   LE_JOIN_FRAME      frame;
-   HANDLE             dest_handle;
-   REG_DEST          *p_dest;
-   STATUS             status;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   /* Mark all MAC addresses as unregistered so they will be re-registered
-    * with the ELAN we are now joining.
-    */
-   status = map_get_first (p_elan->lec_state.c6_my_mac_addr_list, &dest_handle);
-   while (status == STATUS_K_SUCCESS)
-      {
-      p_dest = (REG_DEST *) dest_handle;
-      p_dest->registered = FALSE;
-      status = map_get_next (p_elan->lec_state.c6_my_mac_addr_list,
-                             p_dest->mac_addr,
-                             &dest_handle);
-      }
-
-   utl_mem_zero (&frame, sizeof (LE_JOIN_FRAME));
-
-   p_elan->lec_state.c14_lec_id = 0;
-   lc_ctrl_hdr_make (lc_elan_handle, &frame.hdr, LE_JOIN_REQ);
-
-   frame.hdr.flags = p_elan->lec_state.c4_proxy_flag ?
-                     hton16 (LE_FLAG_PROXY) : 0;
-
-   /* If there are LAN destinations that need to be registered, pick the
-    * first one and place it in the Join frame to be implicitly registered.
-    */
-   status = map_get_first (p_elan->lec_state.c6_my_mac_addr_list, &dest_handle);
-   EVENT(EM_DEBUG,("Act_join_req_xmt, p_elan:%p, addr_list_get:%d\n",p_elan,status));
-   if (status == STATUS_K_SUCCESS)
-      {
-      p_dest                = (REG_DEST *) dest_handle;
-      p_dest->registered    = TRUE;
-      frame.src_lan_dst.tag = hton16 (TAG_MAC_ADDR);
-      ESI_COPY (p_dest->mac_addr, frame.src_lan_dst.mac_addr);
-      }
-
-   ATM_COPY (p_elan->lec_state.c1_my_atm_addr, frame.src_atm_addr);
+static void 
+act_join_req_xmt(HANDLE lc_elan_handle)
+{
+  LC_ELAN_CONTEXT   *p_elan;
+  LE_JOIN_FRAME      frame;
+  STATUS             status;
 
-   switch (p_elan->lec_state.c2_lan_type) {
-   case LAN_802_3 : 
-     frame.lan_type = 1;  
-     break;
-   case LAN_802_5 : 
-     frame.lan_type = 2;  
-     break;
-   default:
-     frame.lan_type = 1;
-   }
+  p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
+  
+  /* Mark MAC address as unregistered so it will be re-registered
+   * with the ELAN we are now joining.
+   */
+  p_elan->lec_state.c6_my_mac_addr.registered = FALSE;
 
-   switch (p_elan->lec_state.c3_lan_mtu) {
-   case MTU_UNSPEC: 
-     frame.max_frame_size = 0;  
-     break;
-   case MTU_1516  : frame.max_frame_size = 1;  break;
-   case MTU_4544  : frame.max_frame_size = 2;  break;
-   case MTU_9234  : frame.max_frame_size = 3;  break;
-   case MTU_18190 : frame.max_frame_size = 4;  break;
-   }
+  memset(&frame, 0, sizeof (LE_JOIN_FRAME));
+  
+  p_elan->lec_state.c14_lec_id = 0;
+  lc_ctrl_hdr_make (lc_elan_handle, &frame.hdr, LE_JOIN_REQ);
+  
+  frame.hdr.flags = p_elan->lec_state.c4_proxy_flag ?
+    hton16 (LE_FLAG_PROXY) : 0;
+  
+  p_elan->lec_state.c6_my_mac_addr.registered    = TRUE;
+  frame.src_lan_dst.tag = hton16 (TAG_MAC_ADDR);
+  ESI_COPY (p_elan->lec_state.c6_my_mac_addr.mac_addr, 
+	    frame.src_lan_dst.mac_addr);
 
+  ATM_COPY (p_elan->lec_state.c1_my_atm_addr, frame.src_atm_addr);
+  
+  switch (p_elan->lec_state.c2_lan_type) {
+  case LAN_802_3 : 
+    frame.lan_type = 1;  
+    break;
+  case LAN_802_5 : 
+    frame.lan_type = 2;  
+    break;
+  default:
+    frame.lan_type = 1;
+  }
+  
+  switch (p_elan->lec_state.c3_lan_mtu) {
+  case MTU_UNSPEC: 
+    frame.max_frame_size = 0;  
+    break;
+  case MTU_1516  : frame.max_frame_size = 1;  break;
+  case MTU_4544  : frame.max_frame_size = 2;  break;
+  case MTU_9234  : frame.max_frame_size = 3;  break;
+  case MTU_18190 : frame.max_frame_size = 4;  break;
+  }
+  
    frame.tlv_count      = 0;
 
    frame.elan_name_size = p_elan->lec_state.elan_name_size_join;   
@@ -1741,14 +1512,6 @@
 * =======================
 * = act_bus_arp_req_xmt =
 * =======================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_bus_arp_req_xmt (HANDLE lc_elan_handle)
    {
@@ -1758,7 +1521,7 @@
 
    p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
 
-   utl_mem_zero (&frame, sizeof (LE_ARP_FRAME));
+   memset(&frame, 0, sizeof (LE_ARP_FRAME));
 
    lc_ctrl_hdr_make (lc_elan_handle, &frame.hdr, LE_ARP_REQ);
 
@@ -1793,14 +1556,6 @@
 * =====================
 * = act_bus_svc_setup =
 * =====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_bus_svc_setup (HANDLE lc_elan_handle)
    {
@@ -1828,37 +1583,20 @@
 * ========================
 * = act_lecs_vc_teardown =
 * ========================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_lecs_vc_teardown (HANDLE lc_elan_handle)
    {
    LC_ELAN_CONTEXT   *p_elan;
-   RELEASE_INFO       release_info;
 
    p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
 
+   EVENT(EM_DEBUG,("LECS_VC_TEARDOWN :%p\n", p_elan->lecs_conn_handle));
    if (p_elan->lecs_conn_handle != NULL)
       {
-      if (p_elan->lecs_pvc)
-         {
-	   ; /* Not supported */
-         }
-      else
-         {
-         if (p_elan->link_state == LINK_SIG_UP)
-            {
-            svc_release_info_make (CAUSE_NORMAL, &release_info);
-            cm_sap_svc_teardown (p_elan->lecs_conn_handle,
-                                 &release_info);
-            }
-         }
+	if (p_elan->link_state == LINK_SIG_UP)
+	  {
+            cm_sap_svc_teardown (p_elan->lecs_conn_handle);
+	  }
 
       p_elan->lecs_conn_handle = NULL;
       }
@@ -1869,93 +1607,61 @@
 * ========================
 * = act_les_svc_teardown =
 * ========================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_les_svc_teardown (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   RELEASE_INFO       release_info;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   svc_release_info_make (CAUSE_NORMAL, &release_info);
-
-   if (p_elan->ctrl_direct_conn_handle != NULL)
-      {
-      if (p_elan->link_state == LINK_SIG_UP)
-         cm_sap_svc_teardown (p_elan->ctrl_direct_conn_handle,
-                              &release_info);
-      p_elan->ctrl_direct_conn_handle = NULL;
-      }
-
-   if (p_elan->ctrl_dist_conn_handle != NULL)
-      {
-      if (p_elan->link_state == LINK_SIG_UP)
-         cm_sap_svc_teardown (p_elan->ctrl_dist_conn_handle,
-                              &release_info);
-      p_elan->ctrl_dist_conn_handle = NULL;
-      }
-   }
+{
+  LC_ELAN_CONTEXT   *p_elan;
+  HANDLE teardown;
+  p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
+  
+  EVENT(EM_DEBUG,("LES_SVC_TEARDOWN :%p %p\n", 
+		  p_elan->ctrl_direct_conn_handle,
+		  p_elan->ctrl_dist_conn_handle));
+  
+  if (p_elan->ctrl_direct_conn_handle != NULL) {
+    teardown = p_elan->ctrl_direct_conn_handle;
+    p_elan->ctrl_direct_conn_handle = NULL;
+    cm_sap_svc_teardown (teardown);
+  }
+  
+  if (p_elan->ctrl_dist_conn_handle != NULL) {
+    teardown = p_elan->ctrl_dist_conn_handle;
+    p_elan->ctrl_dist_conn_handle = NULL;
+    cm_sap_svc_teardown (teardown);
+  }
+}
 
 /*++
 * ========================
 * = act_bus_svc_teardown =
 * ========================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_bus_svc_teardown (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   RELEASE_INFO       release_info;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   svc_release_info_make (CAUSE_NORMAL, &release_info);
-
-   if (p_elan->mcast_send_conn_handle != NULL)
-      {
-      if (p_elan->link_state == LINK_SIG_UP)
-         cm_sap_svc_teardown (p_elan->mcast_send_conn_handle,
-                              &release_info);
-      p_elan->mcast_send_conn_handle = NULL;
-      }
-
-   if (p_elan->mcast_rcv_conn_handle != NULL)
-      {
-      if (p_elan->link_state == LINK_SIG_UP)
-         cm_sap_svc_teardown (p_elan->mcast_rcv_conn_handle,
-                              &release_info);
-      p_elan->mcast_rcv_conn_handle = NULL;
-      }
-   }
+{
+  LC_ELAN_CONTEXT   *p_elan;
+  
+  p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
+  
+  EVENT(EM_DEBUG,("BUS_SVC_TEARDOWN :%p %p\n",
+		  p_elan->mcast_send_conn_handle,
+		  p_elan->mcast_rcv_conn_handle));
+  
+  if (p_elan->mcast_send_conn_handle != NULL) {
+    cm_sap_svc_teardown (p_elan->mcast_send_conn_handle);
+    p_elan->mcast_send_conn_handle = NULL;
+  }
+  
+  if (p_elan->mcast_rcv_conn_handle != NULL) {
+    cm_sap_svc_teardown (p_elan->mcast_rcv_conn_handle);
+    p_elan->mcast_rcv_conn_handle = NULL;
+  }
+}
 
 
 /*++
 * ====================
 * = act_timer_cancel =
 * ====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void act_timer_cancel (HANDLE lc_elan_handle)
    {
@@ -1974,24 +1680,6 @@
 * =====================
 * = addr_reg_callback =
 * =====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*
-* Arguments:
-*
-* Returns:
-*
-* Preconditions:
-*
-* Postconditions:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void addr_reg_callback (HANDLE               context,
                                ADDR_ATM            *p_atm_addr,
@@ -2025,24 +1713,6 @@
 * ==============
 * = lc_arp_xmt =
 * ==============
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*
-* Arguments:
-*
-* Returns:
-*
-* Preconditions:
-*
-* Postconditions:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void lc_arp_xmt (HANDLE   lc_elan_handle,
                         ESI      esi)
@@ -2053,7 +1723,7 @@
 
    p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
 
-   utl_mem_zero (&frame, sizeof (LE_ARP_FRAME));
+   memset(&frame, 0, sizeof (LE_ARP_FRAME));
 
    lc_ctrl_hdr_make (lc_elan_handle, &frame.hdr, LE_ARP_REQ);
 
@@ -2067,12 +1737,13 @@
 
    p_elan->arps_sent += 1;
 
-   status =  cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle,
-                            &frame,
-                            sizeof (frame),
-                            USER_DATA_INTERNAL,
-                            NULL);
-
+   if (p_elan->sm_state == S_OPERATIONAL) {
+     status =  cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle,
+			      &frame,
+			      sizeof (frame),
+			      USER_DATA_INTERNAL,
+			      NULL);
+   }
    if (status != STATUS_K_SUCCESS)
       p_elan->ctrl_xmt_failure_count += 1;
    else
@@ -2083,129 +1754,78 @@
 * ================
 * = lc_flush_xmt =
 * ================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*
-* Arguments:
-*
-* Returns:
-*
-* Preconditions:
-*
-* Postconditions:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void lc_flush_xmt (HANDLE    lc_elan_handle,
                           ADDR_ATM  addr_atm,
-                          HANDLE    esi_handle)
+                          HANDLE    flush_tran_id)
    {
    LC_ELAN_CONTEXT   *p_elan;
    LE_FLUSH_FRAME     frame;
    STATUS             status;
-   MAP_ESI_RECORD    *p_esi;
+   UINT32            *p_tran_id;
 
    p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-   p_esi  = (MAP_ESI_RECORD  *) esi_handle;
+   p_tran_id  = (UINT32 *)flush_tran_id;
 
-   utl_mem_zero (&frame, sizeof (LE_FLUSH_FRAME));
+   memset(&frame, 0, sizeof (LE_FLUSH_FRAME));
 
-   p_esi->flush_tran_id = lc_ctrl_hdr_make (lc_elan_handle,
-                                            &frame.hdr,
-                                            LE_FLUSH_REQ);
+   *p_tran_id = lc_ctrl_hdr_make (lc_elan_handle,
+				  &frame.hdr,
+				  LE_FLUSH_REQ);
 
    ATM_COPY (p_elan->lec_state.c1_my_atm_addr, frame.src_atm_addr);
    ATM_COPY (addr_atm,                         frame.target_atm_addr);
-
+   
    EVENT (EM_XDATA, ("Sending Flush Request for %s.\n",
           disp_atm_text (addr_atm)));
 
-   status =  cm_sap_xmt_vc (p_elan->mcast_send_conn_handle,
-                            &frame,
-                            sizeof (frame),
-                            USER_DATA_INTERNAL,
-                            NULL);
-
-   if (status != STATUS_K_SUCCESS)
-      p_elan->ctrl_xmt_failure_count += 1;
-   else
-      p_elan->ctrl_frames_sent += 1;
+   if (p_elan->sm_state == S_OPERATIONAL) {
+     status =  cm_sap_xmt_vc (p_elan->mcast_send_conn_handle,
+			      &frame,
+			      sizeof (frame),
+			      USER_DATA_INTERNAL,
+			      NULL);
+   }
+     if (status != STATUS_K_SUCCESS)
+       p_elan->ctrl_xmt_failure_count += 1;
+     else
+       p_elan->ctrl_frames_sent += 1;
    }
 
 /*++
 * ================
 * = lc_svc_setup =
 * ================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*
-* Arguments:
-*
-* Returns:
-*
-* Preconditions:
-*
-* Postconditions:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void lc_svc_setup (HANDLE    lc_elan_handle,
                           ADDR_ATM  addr_atm)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   CONN_INFO          conn_info;
-   HANDLE             unused_handle;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   lc_conn_info_make (lc_elan_handle,
-                      addr_atm,
-                      BLLI_DIRECT_802_3,
-                      FALSE,        /* point to point */
-                      &conn_info);
-
-   (void) cm_sap_svc_setup (p_elan->sap_handle,
-                            p_elan->direct_conn_context,
-                            &conn_info,
-                            p_elan->lec_state.c12_vcc_timeout,
-                            &unused_handle);   
-   }
+{
+  LC_ELAN_CONTEXT   *p_elan;
+  CONN_INFO          conn_info;
+  HANDLE             unused_handle;
+  
+  p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
+  
+  lc_conn_info_make (lc_elan_handle,
+		     addr_atm,
+		     BLLI_DIRECT_802_3,
+		     FALSE,        /* point to point */
+		     &conn_info);
+  
+  if (p_elan->sm_state == S_OPERATIONAL) {
+    (void) cm_sap_svc_setup (p_elan->sap_handle,
+			     p_elan->direct_conn_context,
+			     &conn_info,
+			     p_elan->lec_state.c12_vcc_timeout,
+			     &unused_handle);   
+  }
+}
 
 
 /*++
 * ====================
 * = lc_ready_ind_xmt =
 * ====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*
-* Arguments:
-*
-* Returns:
-*
-* Preconditions:
-*
-* Postconditions:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 static void lc_ready_ind_xmt (HANDLE   lc_elan_handle,
                               HANDLE   conn_handle)
@@ -2246,14 +1866,6 @@
 * =============
 * = lc_create =
 * =============
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 STATUS lc_create (HANDLE                line_up_handle,
                   ELAN_STATUS_CALLBACK  elan_status_callback,
@@ -2302,14 +1914,6 @@
 * ==============
 * = lc_destroy =
 * ==============
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 void lc_destroy (HANDLE  lc_handle)
    {
@@ -2351,14 +1955,6 @@
 * ===============
 * = lc_register =
 * ===============
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 STATUS lc_register (HANDLE       lc_handle,
                     HANDLE       ld_elan_handle,
@@ -2373,219 +1969,177 @@
                     HANDLE       lport_handle,
                     char        *p_text,
                     HANDLE      *p_lc_elan_handle)
-   {
-   LC_CONTEXT        *p_context;
-   LC_ELAN_CONTEXT   *p_elan;
-   REG_DEST          *p_dest;
-   STATUS             status;
-   int                i;
-
-   p_context = (LC_CONTEXT *) lc_handle;
-
-   /* Allocate Memory for this ELAN instance. */
-
-   p_elan = (LC_ELAN_CONTEXT *) os_mem_alloc (sizeof (LC_ELAN_CONTEXT));
-   if (p_elan == NULL)
-    {
-      return STATUS_K_RESOURCES;
-    }
-
-   EVENT(EM_DEBUG,("Lc_register, lc_handle:%p p_elan:%p\n",lc_handle, p_elan));
-
-   /* Initialize the fields of the elan block. */
-
-   p_elan->event_mask      = EM_DEFAULT;
-   p_elan->lc_handle       = lc_handle;
-   p_elan->ld_elan_handle  = ld_elan_handle;
-   p_elan->addr_reg_handle = addr_reg_handle;
-   p_elan->link_state      = LINK_DOWN;
-   p_elan->sm_state        = S_INITIAL;
-   p_elan->current_tran_id = 0x640305;
-   p_elan->vc_ready_mask   = 0;
-   p_elan->init_method     = init_method;
-   p_elan->p_text          = p_text;
-   p_elan->lport_handle    = lport_handle;
-
-   p_elan->sm_state_history_index = 0;
-   for (i = 0; i < SM_STATE_HISTORY_DEPTH; i++)
-      {
-      p_elan->sm_state_history[i].new_state = 0;
-      p_elan->sm_state_history[i].event     = 0;
-      }
-
-
-   if (init_method == INIT_MANUAL_LES)
-      {
-      ATM_COPY (manual_atm_addr, p_elan->lec_state.c9_les_atm_addr);
-      }
-
-   if (init_method == INIT_MANUAL_LECS)
-      {
-      ATM_COPY (manual_atm_addr, p_elan->lecs_addr);
-      }
-
-   /* Initialize the fields of the lec state. */
-
-   p_elan->lec_state.c2_lan_type    = lan_type;
-   p_elan->lec_state.c3_lan_mtu     = max_frame_size;
-   p_elan->lec_state.c4_proxy_flag  = proxy_flag;
-   p_elan->lec_state.elan_name_size = strlen (p_elan_name);
-   strncpy (p_elan->lec_state.c5_elan_name, p_elan_name, 32);
-   p_elan->lec_state.c7_control_timeout            = 10;
-   p_elan->lec_state.c10_max_unknown_frame_count   = 1;
-   p_elan->lec_state.c11_max_unknown_frame_time    = 1;
-   p_elan->lec_state.c12_vcc_timeout               = 1200;
-   p_elan->lec_state.c13_max_retry_count           = 2;
-   p_elan->lec_state.c17_aging_time                = 300;
-   p_elan->lec_state.c18_forward_delay_time        = 15;
-   p_elan->lec_state.c19_topology_change_flag      = FALSE;
-   p_elan->lec_state.c20_le_arp_response_time      = 1;
-   p_elan->lec_state.c21_flush_timeout             = 4;
-   p_elan->lec_state.c22_path_switching_delay      = 6;
-
-   p_elan->illegal_frame_rcv_count  = 0;
-   p_elan->ctrl_xmt_failure_count   = 0;
-   p_elan->illegal_transition_count = 0;
-   p_elan->ctrl_frames_sent         = 0;
-   p_elan->ctrl_frames_rcvd         = 0;
-   p_elan->arps_sent                = 0;
-   p_elan->arps_rcvd                = 0;
-   p_elan->ucasts_sent_direct       = 0;
-   p_elan->ucasts_flooded           = 0;
-   p_elan->ucasts_discarded         = 0;
-   p_elan->nucasts_sent             = 0;
-
-   status = map_list_alloc (sizeof (ESI),
-                            &p_elan->lec_state.c6_my_mac_addr_list);
-   if (status != STATUS_K_SUCCESS)
-      {
-      EVENT (EM_SERR, ("MAC Address List could not be allocated\n"));
-      os_mem_dealloc (p_elan);
-      return STATUS_K_RESOURCES;
-      }
-
-   /* If a MAC address has been supplied by the caller, add it to the
-    * destination list and flag it as not-registered.
-    */
-   if ((mac_addr[0] != 0) || (mac_addr[1] != 0) ||
-       (mac_addr[2] != 0) || (mac_addr[3] != 0) ||
-       (mac_addr[4] != 0) || (mac_addr[5] != 0))
-      {
-      p_dest = os_mem_alloc (sizeof (REG_DEST));
-      if (p_dest == NULL)
-         {
-         EVENT (EM_SERR, ("Registered Destination could not be allocated\n"));
-         map_list_dealloc (p_elan->lec_state.c6_my_mac_addr_list,
-                           &reg_dest_destroy, NULL);
-         os_mem_dealloc (p_elan);
-         return STATUS_K_RESOURCES;
-         }
-
-      ESI_COPY (mac_addr, p_dest->mac_addr);
-      p_dest->registered    = FALSE;
-      p_dest->unregistering = FALSE;
-      map_element_insert (p_elan->lec_state.c6_my_mac_addr_list,
-                          (HANDLE) p_dest);
-      }
-
-
-   /* Allocate the state machine timer. */
-
-   status = os_timer_alloc (sm_timer_handler,
-                            (HANDLE) p_elan,
-                            &p_elan->sm_timer);
-   if (status != STATUS_K_SUCCESS)
-      {
-      EVENT (EM_SERR, ("LC_ELAN SM timer could not be allocated\n"));
-      map_list_dealloc (p_elan->lec_state.c6_my_mac_addr_list,
-                        &reg_dest_destroy, NULL);
-      os_mem_dealloc (p_elan);
-      return STATUS_K_RESOURCES;
-      }
-
-   /* Allocate the address registration timer. */
-
-   status = os_timer_alloc (reg_timer_handler,
-                            (HANDLE) p_elan,
-                            &p_elan->reg_timer);
-   if (status != STATUS_K_SUCCESS)
-      {
-      EVENT (EM_SERR, ("LC_ELAN registration timer could not be allocated\n"));
-      os_timer_dealloc (p_elan->sm_timer);
-      map_list_dealloc (p_elan->lec_state.c6_my_mac_addr_list,
-                        &reg_dest_destroy, NULL);
-      os_mem_dealloc (p_elan);
-      return STATUS_K_RESOURCES;
-      }
-
-   /* Register with the Arp Cache module. */
+{
+  LC_CONTEXT        *p_context;
+  LC_ELAN_CONTEXT   *p_elan;
+  STATUS             status;
+  int                i;
+  
+  p_context = (LC_CONTEXT *) lc_handle;
+  
+  /* Allocate Memory for this ELAN instance. */
+  
+  p_elan = (LC_ELAN_CONTEXT *) os_mem_alloc (sizeof (LC_ELAN_CONTEXT));
+  
+  memset(p_elan, 0, sizeof(LC_ELAN_CONTEXT));
+  
+  if (p_elan == NULL) {
+    return STATUS_K_RESOURCES;
+  }
+  
+  EVENT(EM_DEBUG,("Lc_register, lc_handle:%p p_elan:%p\n",lc_handle, p_elan));
+  
+  /* Initialize the fields of the elan block. */
+  
+  p_elan->lc_handle       = lc_handle;
+  p_elan->ld_elan_handle  = ld_elan_handle;
+  p_elan->addr_reg_handle = addr_reg_handle;
+  p_elan->link_state      = LINK_DOWN;
+  p_elan->sm_state        = S_INITIAL;
+  p_elan->current_tran_id = 0x640305;
+  p_elan->vc_ready_mask   = 0;
+  p_elan->init_method     = init_method;
+  p_elan->p_text          = p_text;
+  p_elan->lport_handle    = lport_handle;
+  
+  p_elan->sm_state_history_index = 0;
+  for (i = 0; i < SM_STATE_HISTORY_DEPTH; i++) {
+    p_elan->sm_state_history[i].new_state = 0;
+    p_elan->sm_state_history[i].event     = 0;
+  }
+  
+  
+  if (init_method == INIT_MANUAL_LES) {
+    ATM_COPY (manual_atm_addr, p_elan->lec_state.c9_les_atm_addr);
+  }
+  
+  if (init_method == INIT_MANUAL_LECS) {
+    ATM_COPY (manual_atm_addr, p_elan->lecs_addr);
+  }
+  
+  /* Initialize the fields of the lec state. */
+  
+  p_elan->lec_state.c2_lan_type    = lan_type;
+  p_elan->lec_state.c3_lan_mtu     = max_frame_size;
+  p_elan->lec_state.c4_proxy_flag  = proxy_flag;
+  p_elan->lec_state.elan_name_size = strlen (p_elan_name);
+  strncpy(p_elan->lec_state.c5_elan_name, p_elan_name, 
+	  MIN(32, p_elan->lec_state.elan_name_size));
+  if (init_method == INIT_MANUAL_LES) {
+    p_elan->lec_state.elan_name_size_join = strlen (p_elan_name);
+    strncpy(p_elan->lec_state.c5_elan_name_join, p_elan_name, 
+	    MIN(32, p_elan->lec_state.elan_name_size_join));
+  }
+  p_elan->lec_state.c7_control_timeout            = 10;
+  p_elan->lec_state.c10_max_unknown_frame_count   = 1;
+  p_elan->lec_state.c11_max_unknown_frame_time    = 1;
+  p_elan->lec_state.c12_vcc_timeout               = 1200;
+  p_elan->lec_state.c13_max_retry_count           = 2;
+  p_elan->lec_state.c17_aging_time                = 300;
+  p_elan->lec_state.c18_forward_delay_time        = 15;
+  p_elan->lec_state.c19_topology_change_flag      = FALSE;
+  p_elan->lec_state.c20_le_arp_response_time      = 1;
+  p_elan->lec_state.c21_flush_timeout             = 4;
+  p_elan->lec_state.c22_path_switching_delay      = 6;
+  
+  p_elan->illegal_frame_rcv_count  = 0;
+  p_elan->ctrl_xmt_failure_count   = 0;
+  p_elan->illegal_transition_count = 0;
+  p_elan->ctrl_frames_sent         = 0;
+  p_elan->ctrl_frames_rcvd         = 0;
+  p_elan->arps_sent                = 0;
+  p_elan->arps_rcvd                = 0;
+  
+  /* If a MAC address has been supplied by the caller, add it to the
+   * destination list and flag it as not-registered.
+   */
+  if ((mac_addr[0] != 0) || (mac_addr[1] != 0) ||
+      (mac_addr[2] != 0) || (mac_addr[3] != 0) ||
+      (mac_addr[4] != 0) || (mac_addr[5] != 0)) {
+    ESI_COPY(mac_addr, p_elan->lec_state.c6_my_mac_addr.mac_addr);
+    p_elan->lec_state.c6_my_mac_addr.registered    = FALSE;
+    p_elan->lec_state.c6_my_mac_addr.unregistering = FALSE;
+  }
 
-   status = la_register (p_context->la_handle,
-                         (HANDLE) p_elan,
-                         p_elan->lport_handle,
-                         p_elan->p_text,
-                         &p_elan->la_elan_handle);
-   if (status != STATUS_K_SUCCESS)
-      {
-      EVENT (EM_SERR, ("la_register failed\n"));
-      os_timer_dealloc (p_elan->reg_timer);
-      os_timer_dealloc (p_elan->sm_timer);
-      map_list_dealloc (p_elan->lec_state.c6_my_mac_addr_list,
-                        &reg_dest_destroy, NULL);
-      os_mem_dealloc (p_elan);
-      return STATUS_K_RESOURCES;
-      }
+  /* Allocate the state machine timer. */
+  status = os_timer_alloc (sm_timer_handler,
+			   (HANDLE) p_elan,
+			   &p_elan->sm_timer);
+  if (status != STATUS_K_SUCCESS) {
+    EVENT (EM_SERR, ("LC_ELAN SM timer could not be allocated\n"));
+    os_mem_dealloc (p_elan);
+    return STATUS_K_RESOURCES;
+  }
+  
+  /* Allocate the address registration timer. */
+  
+  status = os_timer_alloc (reg_timer_handler,
+			   (HANDLE) p_elan,
+			   &p_elan->reg_timer);
+  if (status != STATUS_K_SUCCESS) {
+    EVENT (EM_SERR, ("LC_ELAN registration timer could not be allocated\n"));
+    os_timer_dealloc (p_elan->sm_timer);
+    os_mem_dealloc (p_elan);
+    return STATUS_K_RESOURCES;
+  }
 
-   la_config (p_elan->la_elan_handle,
-              p_elan->lec_state.c2_lan_type,
-              p_elan->lec_state.c4_proxy_flag,
-              p_elan->lec_state.c10_max_unknown_frame_count,
-              p_elan->lec_state.c11_max_unknown_frame_time,
-              p_elan->lec_state.c12_vcc_timeout,
-              p_elan->lec_state.c13_max_retry_count,
-              p_elan->lec_state.c17_aging_time,
-              p_elan->lec_state.c18_forward_delay_time,
-              p_elan->lec_state.c20_le_arp_response_time,
-              p_elan->lec_state.c21_flush_timeout,
-              p_elan->lec_state.c22_path_switching_delay);
-
-   /* Register as a client to the Address Registration module. */
-
-   status = addr_reg_client_register (p_elan->addr_reg_handle,
-                                      addr_reg_callback,
-                                      (HANDLE) p_elan,
-                                      "LAN Emulation Control",
-                                      &p_elan->addr_reg_client_handle);
-   if (status != STATUS_K_SUCCESS)
-      {
-      EVENT (EM_SERR, ("Address Registration Client register failed\n"));
-      la_deregister (p_elan->la_elan_handle);
-      os_timer_dealloc (p_elan->reg_timer);
-      os_timer_dealloc (p_elan->sm_timer);
-      map_list_dealloc (p_elan->lec_state.c6_my_mac_addr_list,
-                        &reg_dest_destroy, NULL);
-      os_mem_dealloc (p_elan);
-      return STATUS_K_RESOURCES;
+  /* Register with the Arp Cache module. */
+  
+  status = la_register (p_context->la_handle,
+			(HANDLE) p_elan,
+			p_elan->lport_handle,
+			p_elan->p_text,
+			&p_elan->la_elan_handle);
+  if (status != STATUS_K_SUCCESS) {
+    EVENT (EM_SERR, ("la_register failed\n"));
+    os_timer_dealloc (p_elan->reg_timer);
+    os_timer_dealloc (p_elan->sm_timer);
+    os_mem_dealloc (p_elan);
+    return STATUS_K_RESOURCES;
+  }
+  
+  la_config (p_elan->la_elan_handle,
+	     p_elan->lec_state.c2_lan_type,
+	     p_elan->lec_state.c4_proxy_flag,
+	     p_elan->lec_state.c10_max_unknown_frame_count,
+	     p_elan->lec_state.c11_max_unknown_frame_time,
+	     p_elan->lec_state.c12_vcc_timeout,
+	     p_elan->lec_state.c13_max_retry_count,
+	     p_elan->lec_state.c17_aging_time,
+	     p_elan->lec_state.c18_forward_delay_time,
+	     p_elan->lec_state.c20_le_arp_response_time,
+	     p_elan->lec_state.c21_flush_timeout,
+	     p_elan->lec_state.c22_path_switching_delay);
+  
+  /* Register as a client to the Address Registration module. */
+  
+  status = addr_reg_client_register (p_elan->addr_reg_handle,
+				     addr_reg_callback,
+				     (HANDLE) p_elan,
+				     "LAN Emulation Control",
+				     &p_elan->addr_reg_client_handle);
+   if (status != STATUS_K_SUCCESS) {
+     EVENT (EM_SERR, ("Address Registration Client register failed\n"));
+     la_deregister (p_elan->la_elan_handle);
+     os_timer_dealloc (p_elan->reg_timer);
+     os_timer_dealloc (p_elan->sm_timer);
+     os_mem_dealloc (p_elan);
+     return STATUS_K_RESOURCES;
       }
-
+   
    utl_list_add (p_context->elan_list, p_elan);
-
+   
    *p_lc_elan_handle = (HANDLE) p_elan;
+   EVENT(EM_DEBUG,("p_elan->les_svc_handles :%p %p\n",
+		   p_elan->ctrl_direct_conn_handle,
+		   p_elan->ctrl_dist_conn_handle));
    return STATUS_K_SUCCESS;
-   }
+}
 
 /*++
 * =================
 * = lc_deregister =
 * =================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 void lc_deregister (HANDLE lc_elan_handle)
    {
@@ -2599,6 +2153,7 @@
    p_elan->sm_state = S_DISABLED;
 
    os_timer_dealloc (p_elan->sm_timer);
+   os_timer_dealloc (p_elan->reg_timer);
 
    act_bus_svc_teardown (lc_elan_handle);
    act_les_svc_teardown (lc_elan_handle);
@@ -2606,6 +2161,8 @@
 
    status = addr_reg_atm_addr_dealloc (p_elan->addr_reg_client_handle,
                                        &p_elan->lec_state.c1_my_atm_addr);
+
+   addr_reg_client_deregister(p_elan->addr_reg_client_handle);
    
    la_deregister (p_elan->la_elan_handle);
 
@@ -2614,256 +2171,110 @@
    }
 
 /*++
-* =====================
-* = lc_event_mask_set =
-* =====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
---*/
-void lc_event_mask_set (HANDLE lc_elan_handle,
-                        UINT32 event_mask)
-   {
-   LC_ELAN_CONTEXT  *p_elan;
-
-   p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   p_elan->event_mask = event_mask;
-   la_event_mask_set (p_elan->la_elan_handle, event_mask);
-   }                           
-
-/*++
-* ===================
-* = lc_mac_addr_add =
-* ===================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
---*/
-STATUS lc_mac_addr_add (HANDLE lc_elan_handle,
-                        ESI    mac_addr)
-   {
-   LC_CONTEXT       *p_context;
-   LC_ELAN_CONTEXT  *p_elan;
-   REG_DEST         *p_dest;
-
-   p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
-   p_context = (LC_CONTEXT      *) p_elan->lc_handle;
-
-   p_dest = os_mem_alloc (sizeof (REG_DEST));
-   if (p_dest == NULL)
-      {
-      EVENT (EM_SERR, ("Registered Destination could not be allocated\n"));
-      return STATUS_K_RESOURCES;
-      }
-
-   ESI_COPY (mac_addr, p_dest->mac_addr);
-   p_dest->registered    = FALSE;
-   p_dest->unregistering = FALSE;
-   map_element_insert (p_elan->lec_state.c6_my_mac_addr_list, (HANDLE) p_dest);
-
-   /* Kick off Registration Protocol. */
-
-   os_timer_cancel (p_elan->reg_timer);
-   reg_req_xmt (lc_elan_handle, p_dest, TRUE);
-   os_timer_set (p_elan->reg_timer,
-                 p_elan->lec_state.c7_control_timeout * 1000);
-
-   return STATUS_K_SUCCESS;
-   }
-
-/*++
-* ===================
-* = lc_mac_addr_del =
-* ===================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
---*/
-void lc_mac_addr_del (HANDLE lc_elan_handle,
-                      ESI    mac_addr)
-   {
-   LC_ELAN_CONTEXT  *p_elan;
-   HANDLE            dest_handle;
-   REG_DEST         *p_dest;
-   STATUS            status;
-
-   p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   status = map_key_search (p_elan->lec_state.c6_my_mac_addr_list,
-                            mac_addr,
-                            &dest_handle);
-   if (status == STATUS_K_SUCCESS)
-      {
-      p_dest = (REG_DEST *) dest_handle;
-      p_dest->unregistering = TRUE;
-      os_timer_cancel (p_elan->reg_timer);
-      reg_req_xmt (lc_elan_handle, p_dest, FALSE);
-      os_timer_set (p_elan->reg_timer,
-                    p_elan->lec_state.c7_control_timeout * 1000);
-      }
-   }
-
-/*++
 * =========================
 * = lc_dest_is_registered =
 * =========================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-BOOLEAN lc_dest_is_registered (HANDLE  lc_elan_handle,
-                               ESI     dst_addr)
-   {
-   LC_ELAN_CONTEXT  *p_elan;
-   HANDLE            dest_handle;
-   REG_DEST         *p_dest;
-   STATUS            status;
-
-   p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   /* Traverse the list of registered MAC addresses looking for a match.
-    * If there is a matching entry that has been successfully registered,
-    * return TRUE.  Otherwise, return FALSE.
-    */
-   status = map_key_search (p_elan->lec_state.c6_my_mac_addr_list,
-                            dst_addr,
-                            &dest_handle);
-   if (status == STATUS_K_SUCCESS)
-      {
-      p_dest = (REG_DEST *) dest_handle;
-      if (p_dest->registered)
-         return TRUE;
-      }
+BOOLEAN 
+lc_dest_is_registered (HANDLE  lc_elan_handle,
+		       ESI     dst_addr)
+{
+  LC_ELAN_CONTEXT  *p_elan;
+  
+  p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
 
-   return FALSE;
-   }
+  /* If there is a matching entry that has been successfully registered,
+   * return TRUE.  Otherwise, return FALSE.
+   */
+  if (!memcmp(dst_addr, p_elan->lec_state.c6_my_mac_addr.mac_addr,
+	      sizeof(ESI)) &&
+      p_elan->lec_state.c6_my_mac_addr.registered)
+    return TRUE;
+  else
+    return FALSE;
+}
 
 /*++
 * =================
 * = lc_elan_reset =
 * =================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 void lc_elan_reset (HANDLE lc_elan_handle)
-   {
-   LC_CONTEXT        *p_context;
-   LC_ELAN_CONTEXT   *p_elan;
-
-   p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
-   p_context = (LC_CONTEXT      *) p_elan->lc_handle;
-
-   EVENT (EM_EVENT, ("LC_ELAN resetting\n"));
-
-   p_elan->sm_state = S_INITIAL;
-   p_context->elan_status_callback (p_elan->ld_elan_handle,
-                                    FALSE,
-                                    p_elan->lec_state.c3_lan_mtu,
-                                    p_elan->lec_state.c5_elan_name,
-                                    p_elan->lec_state.c14_lec_id);
-
-   act_bus_svc_teardown (lc_elan_handle);
-   act_les_svc_teardown (lc_elan_handle);
-   act_lecs_vc_teardown (lc_elan_handle);
-
-   p_elan->vc_ready_mask = 0;
-   cm_reset(p_elan->sap_handle);
-   
-   la_elan_reset (p_elan->la_elan_handle);
-
-   (void) addr_reg_atm_addr_dealloc (p_elan->addr_reg_client_handle,
-                                     &p_elan->lec_state.c1_my_atm_addr);
+{
+  LC_CONTEXT        *p_context;
+  LC_ELAN_CONTEXT   *p_elan;
+  
+  p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
+  p_context = (LC_CONTEXT      *) p_elan->lc_handle;
+  
+  EVENT (EM_EVENT, ("LC_ELAN resetting\n"));
+  
+  p_elan->sm_state = S_INITIAL;
+  p_context->elan_status_callback (p_elan->ld_elan_handle,
+				   FALSE,
+				   p_elan->lec_state.c3_lan_mtu,
+				   p_elan->lec_state.c5_elan_name,
+				   p_elan->lec_state.c14_lec_id);
+  
+  act_bus_svc_teardown (lc_elan_handle);
+  act_les_svc_teardown (lc_elan_handle);
+  act_lecs_vc_teardown (lc_elan_handle);
+  
+  p_elan->vc_ready_mask = 0;
+  /*
+    cm_reset(p_elan->sap_handle); 
+    la_elan_reset (p_elan->la_elan_handle);
+    */
+  (void) addr_reg_atm_addr_dealloc (p_elan->addr_reg_client_handle,
+				    &p_elan->lec_state.c1_my_atm_addr);
 
-   cm_sap_link_status_get (p_elan->sap_handle, &p_elan->link_state);
-   if (p_elan->link_state == LINK_SIG_UP)
-      {
-      line_up_uni_version_get (p_context->line_up_handle,
-                               &p_elan->uni_version);
-      sm_exec (lc_elan_handle, E_JOIN_START);
-      }
-   }
+  sig_reset(42);
+  /*  
+  cm_sap_link_status_get (p_elan->sap_handle, &p_elan->link_state);
+  if (p_elan->link_state == LINK_SIG_UP) {
+    sm_exec (lc_elan_handle, E_JOIN_START);
+  }
+  */
+}
 
 /*++
 * =================
 * = lc_join_start =
 * =================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 void lc_join_start (HANDLE  lc_elan_handle,
                     HANDLE  sap_handle,
                     HANDLE  direct_conn_context,
                     HANDLE  mcast_conn_context,
                     HANDLE  ctrl_conn_context)
-   {
-   LC_CONTEXT        *p_context;
-   LC_ELAN_CONTEXT   *p_elan;
-
-   p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
-   p_context = (LC_CONTEXT      *) p_elan->lc_handle;
-
-   p_elan->max_cell_rate   = (155200000 / 8) / 53;
-
-   p_elan->sap_handle            = sap_handle;
-   p_elan->direct_conn_context   = direct_conn_context;
-   p_elan->mcast_conn_context    = mcast_conn_context;
-   p_elan->ctrl_conn_context     = ctrl_conn_context;
-
-   cm_sap_link_status_get (p_elan->sap_handle, &p_elan->link_state);
-
-   if (p_elan->link_state == LINK_SIG_UP)
-      {
-      line_up_uni_version_get (p_context->line_up_handle,
-                               &p_elan->uni_version);
-      sm_exec (lc_elan_handle, E_JOIN_START);
-      }
-   }
+{
+  LC_CONTEXT        *p_context;
+  LC_ELAN_CONTEXT   *p_elan;
+  
+  p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
+  p_context = (LC_CONTEXT      *) p_elan->lc_handle;
+  
+  p_elan->max_cell_rate   = (155200000 / 8) / 53;
+  
+  p_elan->sap_handle            = sap_handle;
+  p_elan->direct_conn_context   = direct_conn_context;
+  p_elan->mcast_conn_context    = mcast_conn_context;
+  p_elan->ctrl_conn_context     = ctrl_conn_context;
+  
+  cm_sap_link_status_get (p_elan->sap_handle, &p_elan->link_state);
+  
+  if (p_elan->link_state == LINK_SIG_UP) {
+    sm_exec (lc_elan_handle, E_JOIN_START);
+  }
+  EVENT(EM_DEBUG,("p_elan->les_svc_handles :%p %p\n",
+		  p_elan->ctrl_direct_conn_handle,
+		  p_elan->ctrl_dist_conn_handle));  
+}
 
 /*++
 * ====================
 * = lc_sap_vc_notify =
 * ====================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 void lc_sap_vc_notify (HANDLE           conn_context,
                        HANDLE           conn_handle,
@@ -2926,10 +2337,7 @@
 	if (conn_handle == p_elan->lecs_conn_handle) {
 	  EVENT (EM_EVENT, ("Configuration Direct VCC Ready\n"));
 	  p_elan->vc_ready_mask |= READY_LECS;
-	  if (p_elan->lecs_pvc)
-	    sm_exec ((HANDLE) p_elan, E_LECS_PVC_READY);
-	  else
-	    sm_exec ((HANDLE) p_elan, E_LECS_SVC_READY);
+	  sm_exec ((HANDLE) p_elan, E_LECS_SVC_READY);
 	} else {
 	  assert (conn_handle == p_elan->ctrl_direct_conn_handle);
 	  EVENT (EM_EVENT, ("Control Direct VCC Ready\n"));
@@ -2996,14 +2404,6 @@
 * ==================
 * = lc_sap_connect =
 * ==================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 BOOLEAN lc_sap_connect (HANDLE       lc_elan_handle,
                         CONN_INFO   *p_conn_info,
@@ -3113,7 +2513,6 @@
 
       case STATUS_K_MISMATCH :
 
-         *p_reject_reason = REJECT_SAP_MISMATCH;
          return FALSE;
 
       case STATUS_K_REJECT :
@@ -3132,14 +2531,6 @@
 * ======================
 * = lc_sap_link_status =
 * ======================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 void lc_sap_link_status (HANDLE          lc_elan_handle,
                          ATM_LINK_STATE  link_state)
@@ -3181,23 +2572,16 @@
 * ==================
 * = lec_config_req =
 * ==================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_config_req (LC_ELAN_CONTEXT *p_elan,
-                            void            *p_packet,
-                            UINT32           length)
-   {
-   p_elan->illegal_frame_rcv_count += 1;
-   EVENT (EM_EVENT, ("Configure Request received - Illegal.\n"));
-   return;
-   }
+STATIC void 
+lec_config_req (LC_ELAN_CONTEXT *p_elan,
+		void            *p_packet,
+		UINT32           length)
+{
+  p_elan->illegal_frame_rcv_count += 1;
+  EVENT (EM_EVENT, ("Configure Request received - Illegal.\n"));
+  return;
+}
 
 /*++
 * =============
@@ -3212,845 +2596,628 @@
 *   None
 *
 --*/
-void tlv_parse (LC_ELAN_CONTEXT  *p_elan,
-                UINT8             buffer[],
-                UINT32            length,
-                UINT8            *p_tlv_index)
-   {
-   UINT32   tlv_type;
-   UINT8    tlv_length;
-   UINT8    tlv_value1;
-   UINT16   tlv_value2;
-   UINT32   tlv_value4;
-   UINT8    i;
-
-   if (length - *p_tlv_index < 5)
-      {
-      EVENT (EM_EVENT, ("TLV too short.\n"));
-      return;
-      }
-
-   /* Extract the tlv_type, length, and value from the buffer. */
+void 
+tlv_parse (LC_ELAN_CONTEXT  *p_elan,
+	   UINT8             buffer[],
+	   UINT32            length,
+	   UINT8            *p_tlv_index)
+{
+  UINT32   tlv_type;
+  UINT8    tlv_length;
+  UINT8    tlv_value1;
+  UINT16   tlv_value2;
+  UINT32   tlv_value4;
+  UINT8    i;
+  
+  if (length - *p_tlv_index < 5) {
+    EVENT (EM_EVENT, ("TLV too short.\n"));
+    return;
+  }
+  
+  /* Extract the tlv_type, length, and value from the buffer. */
+  
+  i = *p_tlv_index;
+  
+  tlv_type = (buffer [i]     << 24) |
+    (buffer [i + 1] << 16) |
+    (buffer [i + 2] << 8)  |
+    (buffer [i + 3]);
+  tlv_length = buffer[i + 4];
+  i += 5;
+  
+  if ((UINT32) (i + tlv_length) > length) {
+    EVENT (EM_EVENT, ("TLV value missing, type = %08lx.\n", tlv_type));
+    return;
+  }
 
-   i = *p_tlv_index;
+  tlv_value1 = 0;
+  tlv_value2 = 0;
+  tlv_value4 = 0;
+  
+  switch (tlv_length) {
+  case 1 :
+    tlv_value1   = buffer [i];
+    *p_tlv_index = i + 1;
+    break;
+    
+  case 2 :
+    tlv_value2   = (buffer [i] << 8) | buffer [i + 1];
+    *p_tlv_index = i + 2;
+    break;
+    
+  case 4 :
+    tlv_value4   = (buffer [i]     << 24) |
+      (buffer [i + 1] << 16) |
+      (buffer [i + 2] << 8 ) |
+      (buffer [i + 3]);
+    *p_tlv_index = i + 4;
+    break;
+  }
 
-   tlv_type = (buffer [i]     << 24) |
-              (buffer [i + 1] << 16) |
-              (buffer [i + 2] << 8)  |
-              (buffer [i + 3]);
-   tlv_length = buffer[i + 4];
-   i += 5;
+  /* Verify correct TVL lengths */
 
-   if ((UINT32) (i + tlv_length) > length)
-      {
-      EVENT (EM_EVENT, ("TLV value missing, type = %08lx.\n", tlv_type));
+  switch (tlv_type) {
+  case TLV_CTRL_TIMEOUT :
+  case TLV_MAX_UNKNOWN_COUNT :
+  case TLV_MAX_UNKNOWN_TIME :
+  case TLV_MAX_RETRY :
+  case TLV_FORW_DELAY_TIME :
+  case TLV_ARP_RSP_TIME :
+  case TLV_FLUSH_TIMEOUT :
+  case TLV_PATH_SWITCH_DELAY :
+  case TLV_LOCAL_SEG_ID :
+  case TLV_MCAST_VCC_TYPE :
+  case TLV_CONNECT_COMPLETION_TIMER :
+    if (tlv_length != 2) {
+      EVENT (EM_EVENT, ("Incorrect TLV length=%d for type=%08lx.\n",
+			tlv_length, tlv_type));
       return;
-      }
-
-   tlv_value1 = 0;
-   tlv_value2 = 0;
-   tlv_value4 = 0;
-
-   switch (tlv_length)
-      {
-      case 1 :
-         tlv_value1   = buffer [i];
-         *p_tlv_index = i + 1;
-         break;
-
-      case 2 :
-         tlv_value2   = (buffer [i] << 8) | buffer [i + 1];
-         *p_tlv_index = i + 2;
-         break;
-
-      case 4 :
-         tlv_value4   = (buffer [i]     << 24) |
-                        (buffer [i + 1] << 16) |
-                        (buffer [i + 2] << 8 ) |
-                        (buffer [i + 3]);
-         *p_tlv_index = i + 4;
-         break;
-      }
-
-   /* Verify correct TVL lengths */
-
-   switch (tlv_type)
-      {
-      case TLV_CTRL_TIMEOUT :
-      case TLV_MAX_UNKNOWN_COUNT :
-      case TLV_MAX_UNKNOWN_TIME :
-      case TLV_MAX_RETRY :
-      case TLV_FORW_DELAY_TIME :
-      case TLV_ARP_RSP_TIME :
-      case TLV_FLUSH_TIMEOUT :
-      case TLV_PATH_SWITCH_DELAY :
-      case TLV_LOCAL_SEG_ID :
-      case TLV_MCAST_VCC_TYPE :
-      case TLV_CONNECT_COMPLETION_TIMER :
-         if (tlv_length != 2)
-            {
-            EVENT (EM_EVENT, ("Incorrect TLV length=%d for type=%08lx.\n",
-                              tlv_length, tlv_type));
-            return;
-            }
-         break;
-
-      case TLV_VCC_TIMEOUT :
-      case TLV_AGING_TIME :
-      case TLV_MCAST_VCC_AVG_RATE :
-      case TLV_MCAST_VCC_PEAK_RATE :
-         if (tlv_length != 4)
-            {
-            EVENT (EM_EVENT, ("Incorrect TLV length=%d for type=%08lx.\n",
-                              tlv_length, tlv_type));
-            return;
-            }
-         break;
-      }
-
-   switch (tlv_type)
-      {
-      case TLV_CTRL_TIMEOUT :
-         p_elan->lec_state.c7_control_timeout = tlv_value2;
-         break;
-
-      case TLV_MAX_UNKNOWN_COUNT :
-         p_elan->lec_state.c10_max_unknown_frame_count = tlv_value2;
-         break;
-         
-      case TLV_MAX_UNKNOWN_TIME :
-         p_elan->lec_state.c11_max_unknown_frame_time = tlv_value2;
-         break;
-
-      case TLV_VCC_TIMEOUT :
-         p_elan->lec_state.c12_vcc_timeout = tlv_value4;
-         break;
-
-      case TLV_MAX_RETRY :
-         p_elan->lec_state.c13_max_retry_count = tlv_value2;
-         break;
-
-      case TLV_AGING_TIME :
-         p_elan->lec_state.c17_aging_time = tlv_value4;
-         break;
-
-      case TLV_FORW_DELAY_TIME :
-         p_elan->lec_state.c18_forward_delay_time = tlv_value2;
-         break;
-
-      case TLV_ARP_RSP_TIME :
-         p_elan->lec_state.c20_le_arp_response_time = tlv_value2;
-         break;
-
-      case TLV_FLUSH_TIMEOUT :
-         p_elan->lec_state.c21_flush_timeout = tlv_value2;
-         break;
-
-      case TLV_PATH_SWITCH_DELAY :
-         p_elan->lec_state.c22_path_switching_delay = tlv_value2;
-         break;
-
-      case TLV_LOCAL_SEG_ID :
-      case TLV_MCAST_VCC_TYPE :
-      case TLV_MCAST_VCC_AVG_RATE :
-      case TLV_MCAST_VCC_PEAK_RATE :
-      case TLV_CONNECT_COMPLETION_TIMER :
-      default :
-         EVENT (EM_EVENT, ("Unsupported TLV received, type=%08lx.\n",
-                           tlv_type))
-         break;
-      }
-   }
+    }
+    break;
+    
+  case TLV_VCC_TIMEOUT :
+  case TLV_AGING_TIME :
+  case TLV_MCAST_VCC_AVG_RATE :
+  case TLV_MCAST_VCC_PEAK_RATE :
+    if (tlv_length != 4) {
+      EVENT (EM_EVENT, ("Incorrect TLV length=%d for type=%08lx.\n",
+			tlv_length, tlv_type));
+      return;
+    }
+    break;
+  }
+  
+  switch (tlv_type) {
+  case TLV_CTRL_TIMEOUT :
+    p_elan->lec_state.c7_control_timeout = tlv_value2;
+    break;
+    
+  case TLV_MAX_UNKNOWN_COUNT :
+    p_elan->lec_state.c10_max_unknown_frame_count = tlv_value2;
+    break;
+    
+  case TLV_MAX_UNKNOWN_TIME :
+    p_elan->lec_state.c11_max_unknown_frame_time = tlv_value2;
+    break;
+    
+  case TLV_VCC_TIMEOUT :
+    p_elan->lec_state.c12_vcc_timeout = tlv_value4;
+    break;
+    
+  case TLV_MAX_RETRY :
+    p_elan->lec_state.c13_max_retry_count = tlv_value2;
+    break;
+    
+  case TLV_AGING_TIME :
+    p_elan->lec_state.c17_aging_time = tlv_value4;
+    break;
+    
+  case TLV_FORW_DELAY_TIME :
+    p_elan->lec_state.c18_forward_delay_time = tlv_value2;
+    break;
+    
+  case TLV_ARP_RSP_TIME :
+    p_elan->lec_state.c20_le_arp_response_time = tlv_value2;
+    break;
+    
+  case TLV_FLUSH_TIMEOUT :
+    p_elan->lec_state.c21_flush_timeout = tlv_value2;
+    break;
+    
+  case TLV_PATH_SWITCH_DELAY :
+    p_elan->lec_state.c22_path_switching_delay = tlv_value2;
+    break;
+    
+  case TLV_LOCAL_SEG_ID :
+  case TLV_MCAST_VCC_TYPE :
+  case TLV_MCAST_VCC_AVG_RATE :
+  case TLV_MCAST_VCC_PEAK_RATE :
+  case TLV_CONNECT_COMPLETION_TIMER :
+  default :
+    EVENT (EM_EVENT, ("Unsupported TLV received, type=%08lx.\n",
+		      tlv_type));
+    break;
+  }
+}
 
 /*++
 * ==================
 * = lec_config_rsp =
 * ==================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_config_rsp (LC_ELAN_CONTEXT *p_elan,
-                            void            *p_packet,
-                            UINT32           length)
-   {
-   LE_CONFIG_FRAME  *p_frame;
-   UINT8             buffer[1024];
-   UINT32            bytes_copied;
-   UINT8             tlv_index;
-
-   os_buff_hdr_copy (p_packet,
-                     length,
-                     buffer,
-                     length,
-                     &bytes_copied);
-
-   if (bytes_copied < sizeof (LE_CONFIG_FRAME))
-      {
-      EVENT (EM_EVENT, ("Received runt Config Response frame - %ld bytes.\n",
-                        length));
-      return;
-      }
-
-   p_frame = (LE_CONFIG_FRAME *) buffer;
-
-   if (p_frame->hdr.status != hton16 (LE_STATUS_SUCCESS))
-      {
-      EVENT (EM_EVENT, ("Received Config Response with error %d.\n",
-                        ntoh16 (p_frame->hdr.status)));
-      return;
-      }
-
-   switch (p_frame->max_frame_size)
-      {
-      case 1  : p_elan->lec_state.c3_lan_mtu = MTU_1516;     break;
-      case 2  : p_elan->lec_state.c3_lan_mtu = MTU_4544;     break;
-      case 3  : p_elan->lec_state.c3_lan_mtu = MTU_9234;     break;
-      case 4  : p_elan->lec_state.c3_lan_mtu = MTU_18190;    break;
-      default : break;
-      }
-
-   ATM_COPY (p_frame->target_atm_addr, p_elan->lec_state.c9_les_atm_addr);
-
-   switch(p_frame->lan_type) {
-   case 1:
-     p_elan->lec_state.c2_lan_type = LAN_802_3;
-     break;
-   case 2:
-     p_elan->lec_state.c2_lan_type = LAN_802_5;
-     break;
-   default:
-     break;
-   }
-
-   EVENT(EM_DEBUG,("Config response, elan_name:%s len:%d\n",
-		   p_frame->elan_name, p_frame->elan_name_size));
-   strncpy (p_elan->lec_state.c5_elan_name_join, p_frame->elan_name, 
-	    MIN(p_frame->elan_name_size,32));
-   p_elan->lec_state.elan_name_size_join = MIN(p_frame->elan_name_size, 32);
-
-   /* Parse TLVs */
+STATIC void 
+lec_config_rsp (LC_ELAN_CONTEXT *p_elan,
+		void            *p_packet,
+		UINT32           length)
+{
+  LE_CONFIG_FRAME  *p_frame;
+  UINT8             tlv_index;
+  
+  p_frame = (LE_CONFIG_FRAME *)p_packet;
 
-   tlv_index = sizeof (LE_CONFIG_FRAME);
-   while (tlv_index < length)
-      {
-      tlv_parse (p_elan, buffer, length, &tlv_index);
-      }
+  if (length < sizeof (LE_CONFIG_FRAME)) {
+    EVENT (EM_EVENT, ("Received runt Config Response frame - %ld bytes.\n",
+		      length));
+    return;
+  }
 
-       sm_exec ((HANDLE) p_elan, E_RCV_CONFIG_RSP);
-   }
+  if (p_frame->hdr.status != hton16 (LE_STATUS_SUCCESS)) {
+    EVENT (EM_EVENT, ("Received Config Response with error %d.\n",
+		      ntoh16 (p_frame->hdr.status)));
+    return;
+  }
+  
+  switch (p_frame->max_frame_size) {
+  case 1  : p_elan->lec_state.c3_lan_mtu = MTU_1516;     break;
+  case 2  : p_elan->lec_state.c3_lan_mtu = MTU_4544;     break;
+  case 3  : p_elan->lec_state.c3_lan_mtu = MTU_9234;     break;
+  case 4  : p_elan->lec_state.c3_lan_mtu = MTU_18190;    break;
+  default : break;
+  }
+  
+  ATM_COPY (p_frame->target_atm_addr, p_elan->lec_state.c9_les_atm_addr);
+  
+  switch(p_frame->lan_type) {
+  case 1:
+    p_elan->lec_state.c2_lan_type = LAN_802_3;
+    break;
+  case 2:
+    p_elan->lec_state.c2_lan_type = LAN_802_5;
+    break;
+  default:
+    break;
+  }
+   
+  EVENT(EM_DEBUG,("Config response, elan_name:%s len:%d\n",
+		  p_frame->elan_name, p_frame->elan_name_size));
+  strncpy (p_elan->lec_state.c5_elan_name_join, p_frame->elan_name, 
+	   MIN(p_frame->elan_name_size,32));
+  p_elan->lec_state.elan_name_size_join = MIN(p_frame->elan_name_size, 32);
+  
+  /* Parse TLVs */
+  
+  tlv_index = sizeof (LE_CONFIG_FRAME);
+  while (tlv_index < length) {
+    tlv_parse(p_elan, p_packet, length, &tlv_index);
+  }
+   
+   sm_exec ((HANDLE) p_elan, E_RCV_CONFIG_RSP);
+}
 
 /*++
 * ================
 * = lec_join_req =
 * ================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_join_req (LC_ELAN_CONTEXT *p_elan,
-                          void            *p_packet,
-                          UINT32           length)
-   {
-   p_elan->illegal_frame_rcv_count += 1;
-   EVENT (EM_EVENT, ("Join Request received - Illegal.\n"));
-   return;
-   }
+STATIC void 
+lec_join_req (LC_ELAN_CONTEXT *p_elan,
+	      void            *p_packet,
+	      UINT32           length)
+{
+  p_elan->illegal_frame_rcv_count += 1;
+  EVENT (EM_EVENT, ("Join Request received - Illegal.\n"));
+  return;
+}
 
 /*++
 * ================
 * = lec_join_rsp =
 * ================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_join_rsp (LC_ELAN_CONTEXT *p_elan,
-                          void            *p_packet,
-                          UINT32           length)
-   {
-   LE_JOIN_FRAME   frame;
-   UINT32          bytes_copied;
-
-   /* Copy the entire frame from the receive buffer to local memory. */
-
-   os_buff_hdr_copy (p_packet,
-                     length,
-                     &frame,
-                     sizeof (LE_JOIN_FRAME),
-                     &bytes_copied);
-   if (bytes_copied != sizeof (LE_JOIN_FRAME))
-      return;
-
-   /* Check the completion status of the frame.  If it isn't success, handle
-    * the error.
-    */
-   if (frame.hdr.status != ntoh16 (LE_STATUS_SUCCESS))
-      {
-      EVENT (EM_NERR, ("Join Request Rejected by LES. Error = %s.\n",
-             disp_status_text (ntoh16 (frame.hdr.status))));
-      return;
-      }
-
-   /* Get our new LEC_ID. */
-
-   p_elan->lec_state.c14_lec_id = ntoh16 (frame.hdr.req_lec_id);
-
-   /* Copy the joined ELAN type into our local state. */
-
-   switch (frame.lan_type)
-      {
-      case 1  : p_elan->lec_state.c2_lan_type = LAN_802_3;   break;
-      case 2  : p_elan->lec_state.c2_lan_type = LAN_802_5;   break;
-      default : return;
-      }
-
-   /* Copy the max frame size into our local state. */
+STATIC void 
+lec_join_rsp (LC_ELAN_CONTEXT *p_elan,
+	      void            *p_packet,
+	      UINT32           length)
+{
+  LE_JOIN_FRAME   *frame;
 
-   switch (frame.max_frame_size)
-      {
-      case 1  : p_elan->lec_state.c3_lan_mtu = MTU_1516;     break;
-      case 2  : p_elan->lec_state.c3_lan_mtu = MTU_4544;     break;
-      case 3  : p_elan->lec_state.c3_lan_mtu = MTU_9234;     break;
-      case 4  : p_elan->lec_state.c3_lan_mtu = MTU_18190;    break;
-      default : return;
-      }
+  frame = (LE_JOIN_FRAME *)p_packet;
+  if (length<sizeof(LE_JOIN_FRAME))
+    return;
+
+  /* Check the completion status of the frame.  If it isn't success, handle
+   * the error.
+   */
+  if (frame->hdr.status != ntoh16 (LE_STATUS_SUCCESS)) {
+    EVENT (EM_NERR, ("Join Request Rejected by LES. Error = %s.\n",
+		     disp_status_text (ntoh16 (frame->hdr.status))));
+    return;
+  }
+  
+  /* Get our new LEC_ID. */
+  
+  p_elan->lec_state.c14_lec_id = ntoh16 (frame->hdr.req_lec_id);
 
-   /* Copy the ELAN name into our local state. */
+  /* Copy the joined ELAN type into our local state. */
+  
+  switch (frame->lan_type) {
+  case 1  : p_elan->lec_state.c2_lan_type = LAN_802_3;   break;
+  case 2  : p_elan->lec_state.c2_lan_type = LAN_802_5;   break;
+  default : return;
+  }
 
-   p_elan->lec_state.elan_name_size = frame.elan_name_size;
-   utl_mem_copy (frame.elan_name,
-                 p_elan->lec_state.c5_elan_name,
-                 MIN (frame.elan_name_size, 32));
+  /* Copy the max frame size into our local state. */
+  
+  switch (frame->max_frame_size) {
+  case 1  : p_elan->lec_state.c3_lan_mtu = MTU_1516;     break;
+  case 2  : p_elan->lec_state.c3_lan_mtu = MTU_4544;     break;
+  case 3  : p_elan->lec_state.c3_lan_mtu = MTU_9234;     break;
+  case 4  : p_elan->lec_state.c3_lan_mtu = MTU_18190;    break;
+  default : return;
+  }
 
-   /* Provide the state machine with a received-join-response event. */
+  /* Copy the ELAN name into our local state. */
+  
+  p_elan->lec_state.elan_name_size = frame->elan_name_size;
+  memcpy(p_elan->lec_state.c5_elan_name, frame->elan_name,
+	 MIN (frame->elan_name_size, 32));
 
-   sm_exec ((HANDLE) p_elan, E_RCV_JOIN_RSP);
-   }
+  /* Provide the state machine with a received-join-response event. */
+  
+  sm_exec ((HANDLE) p_elan, E_RCV_JOIN_RSP);
+}
 
 /*++
 * ===================
 * = lec_ready_query =
 * ===================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_ready_query (LC_ELAN_CONTEXT *p_elan,
-                             HANDLE           conn_handle)
-   {
-   lc_ready_ind_xmt ((HANDLE) p_elan, conn_handle);
-   }
+STATIC void 
+lec_ready_query (LC_ELAN_CONTEXT *p_elan,
+		 HANDLE           conn_handle)
+{
+  lc_ready_ind_xmt ((HANDLE) p_elan, conn_handle);
+}
 
 /*++
 * =================
 * = lec_ready_ind =
 * =================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_ready_ind (LC_ELAN_CONTEXT *p_elan,
-                           HANDLE           conn_handle)
-   {
-   /* No Action Necessary. */
-   }
+STATIC void 
+lec_ready_ind (LC_ELAN_CONTEXT *p_elan,
+	       HANDLE           conn_handle)
+{
+  /* No Action Necessary. */
+}
 
 /*++
 * ===============
 * = lec_reg_req =
 * ===============
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_reg_req (LC_ELAN_CONTEXT *p_elan,
-                         void            *p_packet,
-                         UINT32           length)
-   {
-   p_elan->illegal_frame_rcv_count += 1;
-   EVENT (EM_EVENT, ("Registration Request received - Illegal.\n"));
-   return;
-   }
+STATIC void 
+lec_reg_req (LC_ELAN_CONTEXT *p_elan,
+	     void            *p_packet,
+	     UINT32           length)
+{
+  p_elan->illegal_frame_rcv_count += 1;
+  EVENT (EM_EVENT, ("Registration Request received - Illegal.\n"));
+  return;
+}
 
 /*++
 * ===============
 * = lec_reg_rsp =
 * ===============
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_reg_rsp (LC_ELAN_CONTEXT *p_elan,
-                         void            *p_packet,
-                         UINT32           length)
-   {
-   LE_REG_FRAME   frame;
-   UINT32         bytes_copied;
-   HANDLE         dest_handle;
-   REG_DEST      *p_dest;
-   STATUS         status;
-
-   /* Copy the entire frame from the receive buffer to local memory. */
-
-   os_buff_hdr_copy (p_packet,
-                     length,
-                     &frame,
-                     sizeof (LE_REG_FRAME),
-                     &bytes_copied);
-   if (bytes_copied != sizeof (LE_REG_FRAME))
-      return;
+STATIC void 
+lec_reg_rsp (LC_ELAN_CONTEXT *p_elan,
+	     void            *p_packet,
+	     UINT32           length)
+{
+  LE_REG_FRAME   *frame;
 
-   /* Check the completion status of the frame.  If it isn't success, handle
-    * the error.
-    */
-   if (frame.hdr.status != ntoh16 (LE_STATUS_SUCCESS))
-      {
-      EVENT (EM_NERR, ("Register Request Rejected by LES. Error = %s.\n",
-             disp_status_text (ntoh16 (frame.hdr.status))));
-      return;
-      }
+  frame = (LE_REG_FRAME *)p_packet;
 
-   /* Find the MAC address in our registered address list and mark it as
-    * successfully registered.
-    */
-   status = map_key_search (p_elan->lec_state.c6_my_mac_addr_list,
-                            frame.src_lan_dst.mac_addr,
-                            &dest_handle);
-   if (status == STATUS_K_SUCCESS)
-      {
-      p_dest = (REG_DEST *) dest_handle;
-      if (frame.hdr.tran_id == ntoh32 (p_dest->tran_id))
-         {
-         p_dest->registered = TRUE;
-         EVENT (EM_EVENT, ("MAC Address successfully registered.\n"))
-         }
-      }
-   }
+  if (length < sizeof(LE_REG_FRAME))
+    return;
+  
+  /* Check the completion status of the frame.  If it isn't success, handle
+   * the error.
+   */
+  if (frame->hdr.status != ntoh16 (LE_STATUS_SUCCESS)) {
+    EVENT (EM_NERR, ("Register Request Rejected by LES. Error = %s.\n",
+		     disp_status_text (ntoh16 (frame->hdr.status))));
+    return;
+  }
+
+  /* Mark MAC address as successfully registered.
+   */
+  
+  if (!memcmp(p_elan->lec_state.c6_my_mac_addr.mac_addr,
+	      frame->src_lan_dst.mac_addr, sizeof(ESI)) &&
+      ntoh32(frame->hdr.tran_id) == p_elan->lec_state.c6_my_mac_addr.tran_id){
+    p_elan->lec_state.c6_my_mac_addr.registered = TRUE;
+    EVENT (EM_EVENT, ("MAC Address successfully registered.\n"));
+  }
+}
 
 /*++
 * =================
 * = lec_unreg_req =
 * =================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_unreg_req (LC_ELAN_CONTEXT *p_elan,
-                           void            *p_packet,
-                           UINT32           length)
-   {
-   p_elan->illegal_frame_rcv_count += 1;
-   EVENT (EM_EVENT, ("Unregister Request received - Illegal.\n"));
-   return;
-   }
+STATIC void 
+lec_unreg_req (LC_ELAN_CONTEXT *p_elan,
+	       void            *p_packet,
+	       UINT32           length)
+{
+  p_elan->illegal_frame_rcv_count += 1;
+  EVENT (EM_EVENT, ("Unregister Request received - Illegal.\n"));
+  return;
+}
 
 /*++
 * =================
 * = lec_unreg_rsp =
 * =================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_unreg_rsp (LC_ELAN_CONTEXT *p_elan,
-                           void            *p_packet,
-                           UINT32           length)
-   {
-   LE_REG_FRAME   frame;
-   UINT32         bytes_copied;
-   HANDLE         dest_handle;
-   REG_DEST      *p_dest;
-   STATUS         status;
-
-   /* Copy the entire frame from the receive buffer to local memory. */
-
-   os_buff_hdr_copy (p_packet,
-                     length,
-                     &frame,
-                     sizeof (LE_REG_FRAME),
-                     &bytes_copied);
-   if (bytes_copied != sizeof (LE_REG_FRAME))
-      return;
-
-   /* Check the completion status of the frame.  If it isn't success, handle
-    * the error.
-    */
-   if (frame.hdr.status != ntoh16 (LE_STATUS_SUCCESS))
-      {
-      EVENT (EM_NERR, ("Unregister Request Rejected by LES. Error = %s.\n",
-             disp_status_text (ntoh16 (frame.hdr.status))));
-      return;
-      }
-
-   /* Find the MAC address in our registered address list and delete it. */
-
-   status = map_key_search (p_elan->lec_state.c6_my_mac_addr_list,
-                            frame.src_lan_dst.mac_addr,
-                            &dest_handle);
-   if (status == STATUS_K_SUCCESS)
-      {
-      p_dest = (REG_DEST *) dest_handle;
-      if (frame.hdr.tran_id == ntoh32 (p_dest->tran_id))
-         {
-         map_element_delete (p_elan->lec_state.c6_my_mac_addr_list, dest_handle);
-         EVENT (EM_EVENT, ("MAC Address successfully unregistered.\n"))
-         }
-      }
-   }
+STATIC void 
+lec_unreg_rsp (LC_ELAN_CONTEXT *p_elan,
+	       void            *p_packet,
+	       UINT32           length)
+{
+  LE_REG_FRAME   *frame;
+  
+  frame = (LE_REG_FRAME*)p_packet;
+  
+  if (length < sizeof (LE_ARP_FRAME))
+    return;
+  
+  /* Check the completion status of the frame.  If it isn't success, handle
+   * the error.
+   */
+  if (frame->hdr.status != ntoh16 (LE_STATUS_SUCCESS)) {
+    EVENT (EM_NERR, ("Unregister Request Rejected by LES. Error = %s.\n",
+		     disp_status_text (ntoh16 (frame->hdr.status))));
+    return;
+  }
+  
+  /* Delete MAC address */
+  
+  if (!memcmp(p_elan->lec_state.c6_my_mac_addr.mac_addr,
+	      frame->src_lan_dst.mac_addr, sizeof(ESI)) &&
+      ntoh32(frame->hdr.tran_id)==p_elan->lec_state.c6_my_mac_addr.tran_id) {
+    memset(&p_elan->lec_state.c6_my_mac_addr,0,sizeof(REG_DEST));
+    EVENT (EM_EVENT, ("MAC Address successfully unregistered.\n"));
+  }
+}
 
 /*++
 * ===============
 * = lec_arp_req =
 * ===============
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_arp_req (LC_ELAN_CONTEXT *p_elan,
-                         void            *p_packet,
-                         UINT32           length)
-   {
-   LE_ARP_FRAME   frame;
-   STATUS         status;
-   UINT32         user_data;
-   UINT32         bytes_copied;
-
-   /* If the LEC control state machine is not in the operational state, simply
-    * discard the receive packet.
-    */
-   if (p_elan->sm_state != S_OPERATIONAL)
-      return;
-
-   p_elan->arps_rcvd += 1;
-
-   /* Copy the entire ARP frame from the receive buffer into local memory. */
-
-   os_buff_hdr_copy (p_packet,
-                     length,
-                     &frame,
-                     sizeof (LE_ARP_FRAME),
-                     &bytes_copied);
-   if (bytes_copied != sizeof (LE_ARP_FRAME))
-      return;
-
-   switch (ntoh16 (frame.target_lan_dst.tag))
-      {
-      case TAG_NOT_PRESENT:
-         break;
-      case TAG_MAC_ADDR:
-         if (lc_dest_is_registered ((HANDLE) p_elan,
-                                    frame.target_lan_dst.mac_addr))
-            {
-            frame.hdr.op_code = hton16 (LE_ARP_RSP);
-            frame.hdr.status  = hton16 (LE_STATUS_SUCCESS);
-            frame.hdr.flags   = hton16 (0);        /* Clear Remote Flag */
-            ATM_COPY (p_elan->lec_state.c1_my_atm_addr,
-                      frame.target_atm_addr);
-            user_data = USER_DATA_INTERNAL;
-            status = cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle,
-                                   (void *) &frame,
-                                   sizeof (LE_ARP_FRAME),
-                                   user_data,
-                                   NULL);
-            return;
-            }
-
-         break;
-      case TAG_ROUTE_DESC:
-         break;
+STATIC void 
+lec_arp_req (LC_ELAN_CONTEXT *p_elan,
+	     void            *p_packet,
+	     UINT32           length)
+{
+  LE_ARP_FRAME   *frame;
+  STATUS         status;
+  UINT32         user_data;
+  
+  /* If the LEC control state machine is not in the operational state, simply
+   * discard the receive packet.
+   */
+  if (p_elan->sm_state != S_OPERATIONAL)
+    return;
+  
+  p_elan->arps_rcvd += 1;
+  
+  frame = (LE_ARP_FRAME*)p_packet;
+  if (length < sizeof (LE_ARP_FRAME))
+    return;
+  
+  switch (ntoh16 (frame->target_lan_dst.tag)) {
+  case TAG_NOT_PRESENT:
+    break;
+  case TAG_MAC_ADDR:
+    if (lc_dest_is_registered ((HANDLE) p_elan,
+			       frame->target_lan_dst.mac_addr))
+      {
+	frame->hdr.op_code = hton16 (LE_ARP_RSP);
+	frame->hdr.status  = hton16 (LE_STATUS_SUCCESS);
+	frame->hdr.flags   = hton16 (0);        /* Clear Remote Flag */
+	ATM_COPY (p_elan->lec_state.c1_my_atm_addr,
+		  frame->target_atm_addr);
+	user_data = USER_DATA_INTERNAL;
+	status = cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle,
+				(void *) frame,
+				sizeof (LE_ARP_FRAME),
+				user_data,
+				NULL);
+	return;
       }
-   }
+    
+    break;
+  case TAG_ROUTE_DESC:
+    break;
+  }
+}
 
 /*++
 * ===============
 * = lec_arp_rsp =
 * ===============
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_arp_rsp (LC_ELAN_CONTEXT *p_elan,
-                         void            *p_packet,
-                         UINT32           length)
-   {
-   LE_ARP_FRAME   frame;
-   UINT32         bytes_copied;
-   STATUS status;
-   HANDLE dummy;
-
-   os_buff_hdr_copy (p_packet,
-                     length,
-                     &frame,
-                     sizeof (LE_ARP_FRAME),
-                     &bytes_copied);
-
-   if (bytes_copied != sizeof (LE_ARP_FRAME))
-      return;
-
-   if (frame.hdr.status == ntoh16 (LE_STATUS_SUCCESS))
-      {
-      switch (ntoh16 (frame.target_lan_dst.tag))
-         {
-         case TAG_NOT_PRESENT:
-            break;
-         case TAG_MAC_ADDR:
-
-            if ((ESI_IS_BCAST (frame.target_lan_dst.mac_addr)) &&
-                (p_elan->sm_state == S_BUS_ARP_WAIT))
-               {
-               ATM_COPY (frame.target_atm_addr, p_elan->bus_addr);
-               sm_exec ((HANDLE) p_elan, E_RCV_BUS_ARP_RSP);
-               }
-            else
-               {
-          EVENT (EM_RDATA, ("Received LE-ARP response for: %02x-%02x-%02x-%02x-%02x-%02x\n",
-             frame.target_lan_dst.mac_addr[0],
-             frame.target_lan_dst.mac_addr[1],
-             frame.target_lan_dst.mac_addr[2],
-             frame.target_lan_dst.mac_addr[3],
-             frame.target_lan_dst.mac_addr[4],
-             frame.target_lan_dst.mac_addr[5]));
-	  status = map_key_search(p_elan->lec_state.c6_my_mac_addr_list,
-				  frame.target_lan_dst.mac_addr, 
-				  &dummy);
-	  if (status != STATUS_K_SUCCESS) 		     
-	    la_arp_update (p_elan->la_elan_handle,
-			   frame.target_lan_dst.mac_addr,
-			   frame.target_atm_addr,
-			   (ntoh16(frame.hdr.flags) &
-			    LE_FLAG_REMOTE_ADDR) ? TRUE : FALSE);
-               }
-            break;
-         case TAG_ROUTE_DESC:
-            break;
-         }
+STATIC void 
+lec_arp_rsp (LC_ELAN_CONTEXT *p_elan,
+	     void            *p_packet,
+	     UINT32           length)
+{
+  LE_ARP_FRAME  *frame;
+  
+  frame = (LE_ARP_FRAME *)p_packet;
+  
+  if (length < sizeof (LE_ARP_FRAME))
+    return;
+  
+  if (frame->hdr.status == ntoh16 (LE_STATUS_SUCCESS)) {
+    switch (ntoh16 (frame->target_lan_dst.tag)) {
+    case TAG_NOT_PRESENT:
+      break;
+    case TAG_MAC_ADDR:
+      
+      if ((ESI_IS_BCAST (frame->target_lan_dst.mac_addr)) &&
+	  (p_elan->sm_state == S_BUS_ARP_WAIT)) {
+	ATM_COPY (frame->target_atm_addr, p_elan->bus_addr);
+	sm_exec ((HANDLE) p_elan, E_RCV_BUS_ARP_RSP);
+      } else {
+	EVENT (EM_RDATA, ("Received LE-ARP response for: %02x-%02x-%02x-%02x-%02x-%02x\n",
+			  frame->target_lan_dst.mac_addr[0],
+			  frame->target_lan_dst.mac_addr[1],
+			  frame->target_lan_dst.mac_addr[2],
+			  frame->target_lan_dst.mac_addr[3],
+			  frame->target_lan_dst.mac_addr[4],
+			  frame->target_lan_dst.mac_addr[5]));
+	if (memcmp(p_elan->lec_state.c6_my_mac_addr.mac_addr,
+		   frame->target_lan_dst.mac_addr, 
+		   sizeof(ESI))) {
+	  la_arp_update (p_elan->la_elan_handle,
+			 frame->target_lan_dst.mac_addr,
+			 frame->target_atm_addr,
+			 (ntoh16(frame->hdr.flags) &
+			  LE_FLAG_REMOTE_ADDR) ? TRUE : FALSE);
+	}
       }
-
-   return;
-   }
+      break;
+    case TAG_ROUTE_DESC:
+      break;
+    }
+  }  
+  return;
+}
 
 /*++
 * =================
 * = lec_flush_req =
 * =================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_flush_req (LC_ELAN_CONTEXT *p_elan,
-                           void            *p_packet,
-                           UINT32           length)
-   {
-   LE_FLUSH_FRAME  frame;
-   UINT32          user_data;
-   STATUS          status;
-   UINT32          bytes_copied;
-
-   os_buff_hdr_copy (p_packet,
-                     length,
-                     &frame,
-                     sizeof (LE_FLUSH_FRAME),
-                     &bytes_copied);
-
-   if (bytes_copied != sizeof (LE_FLUSH_FRAME))
-      return;
-
-   EVENT(EM_DEBUG,("Received flush request, my atmaddr:%s, for :%s\n",
-		   disp_atm_text(p_elan->lec_state.c1_my_atm_addr),
-		   disp_atm_text(frame.target_atm_addr)));
-   if (ATM_EQUAL (p_elan->lec_state.c1_my_atm_addr, frame.target_atm_addr))
-      {
-      EVENT (EM_RDATA, ("Received Flush Request, Responding.\n"));
-      frame.hdr.op_code = hton16 (LE_FLUSH_RSP);
-      frame.hdr.status  = hton16 (LE_STATUS_SUCCESS);
-      user_data = USER_DATA_INTERNAL;
-      status = cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle,
-                             (void *) &frame,
-                             sizeof (LE_FLUSH_FRAME),
-                             user_data,
-                             NULL);
-      if (status != STATUS_K_SUCCESS)
-         {
-         p_elan->ctrl_xmt_failure_count += 1;
-         }
-      else
-         {
-         p_elan->ctrl_frames_sent += 1;
-         }
-      }
-
-   return;
-   }
+STATIC void 
+lec_flush_req (LC_ELAN_CONTEXT *p_elan,
+	       void            *p_packet,
+	       UINT32           length)
+{
+  LE_FLUSH_FRAME *frame;
+  UINT32          user_data;
+  STATUS          status;
+
+  frame = (LE_FLUSH_FRAME *)p_packet;
+
+  if (length < sizeof (LE_FLUSH_FRAME))
+    return;
+
+  EVENT(EM_DEBUG,("Received flush request, my atmaddr:%s, for :%s\n",
+		  disp_atm_text(p_elan->lec_state.c1_my_atm_addr),
+		  disp_atm_text(frame->target_atm_addr)));
+  if (ATM_EQUAL (p_elan->lec_state.c1_my_atm_addr, frame->target_atm_addr)) {
+    EVENT (EM_RDATA, ("Received Flush Request, Responding.\n"));
+    frame->hdr.op_code = hton16 (LE_FLUSH_RSP);
+    frame->hdr.status  = hton16 (LE_STATUS_SUCCESS);
+    user_data = USER_DATA_INTERNAL;
+    status = cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle,
+			    (void *) frame,
+			    sizeof (LE_FLUSH_FRAME),
+			    user_data,
+			    NULL);
+    if (status != STATUS_K_SUCCESS) {
+      p_elan->ctrl_xmt_failure_count += 1;
+    } else {
+      p_elan->ctrl_frames_sent += 1;
+    }
+  }  
+  return;
+}
 
 /*++
 * =================
 * = lec_flush_rsp =
 * =================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_flush_rsp (LC_ELAN_CONTEXT *p_elan,
-                           void            *p_packet,
-                           UINT32           length)
-   {
-   LE_FLUSH_FRAME frame;
-   UINT32         bytes_copied;
-
-   os_buff_hdr_copy (p_packet,
-                     length,
-                     &frame,
-                     sizeof (LE_FLUSH_FRAME),
-                     &bytes_copied);
+STATIC void 
+lec_flush_rsp(LC_ELAN_CONTEXT *p_elan,
+	      void            *p_packet,
+	      UINT32           length)
+{
+  LE_FLUSH_FRAME *frame;
 
-   if (bytes_copied != sizeof (LE_FLUSH_FRAME))
-      return;
+  frame = (LE_FLUSH_FRAME *)p_packet;
 
-   if ((frame.hdr.status == ntoh16 (LE_STATUS_SUCCESS)) &&
-       (ATM_EQUAL (p_elan->lec_state.c1_my_atm_addr, frame.src_atm_addr)))
-      {
-      EVENT (EM_RDATA, ("Received flush response.\n"));
-      la_flush_complete (p_elan->la_elan_handle,
-                         frame.target_atm_addr,
-                         ntoh32 (frame.hdr.tran_id));
-      }
-
-   return;
-   }
+  if (length < sizeof (LE_FLUSH_FRAME))
+    return;
+  
+  if ((frame->hdr.status == ntoh16 (LE_STATUS_SUCCESS)) &&
+      (ATM_EQUAL (p_elan->lec_state.c1_my_atm_addr, frame->src_atm_addr))) {
+    EVENT (EM_RDATA, ("Received flush response.\n"));
+    la_flush_complete(p_elan->la_elan_handle,
+		      frame->target_atm_addr,
+		      ntoh32 (frame->hdr.tran_id));
+  }  
+  return;
+}
 
 /*++
 * ================
 * = lec_narp_req =
 * ================
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_narp_req (LC_ELAN_CONTEXT *p_elan,
-                          void            *p_packet,
-                          UINT32           length)
-   {
-   }
+STATIC void 
+lec_narp_req (LC_ELAN_CONTEXT *p_elan,
+	      void            *p_packet,
+	      UINT32           length)
+{
+}
 
 /*++
 * ===============
 * = lec_top_req =
 * ===============
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
-STATIC void lec_top_req (LC_ELAN_CONTEXT *p_elan,
-                         void            *p_packet,
-                         UINT32           length)
-   {
-   LE_TOPOLOGY_FRAME frame;
-   UINT32            bytes_copied;
-
-   os_buff_hdr_copy (p_packet,
-                     length,
-                     &frame,
-                     sizeof (LE_TOPOLOGY_FRAME),
-                     &bytes_copied);
-
-   if (bytes_copied != sizeof (LE_TOPOLOGY_FRAME))
-      return;
+STATIC void 
+lec_top_req (LC_ELAN_CONTEXT *p_elan,
+	     void            *p_packet,
+	     UINT32           length)
+{
+  LE_TOPOLOGY_FRAME *frame;
+  
+  frame = (LE_TOPOLOGY_FRAME*)p_packet;
 
-   la_topology_change_set (p_elan->la_elan_handle,
-                           (ntoh16 (frame.hdr.flags) &
-                            LE_FLAG_TOPOLOGY_CHANGE) ? TRUE : FALSE);
+  if (length < sizeof (LE_TOPOLOGY_FRAME))
+    return;
 
-   return;
-   }
+  la_topology_change_set (p_elan->la_elan_handle,
+			  (ntoh16(frame->hdr.flags) &
+			   LE_FLAG_TOPOLOGY_CHANGE) ? TRUE : FALSE);
+  
+  return;
+}
 
 /*++
 * ==============
 * = lc_sap_rcv =
 * ==============
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Description:
-*
-* Issues:
-*   None
-*
 --*/
 void lc_sap_rcv (HANDLE     conn_context,
                  HANDLE     conn_handle,
@@ -4058,83 +3225,73 @@
                  UINT32     user_data,
                  AAL_DATA  *p_aal_data,
                  void     **pp_packet)
-   {
-     LE_READY_HDR       hdr;
-   LEC_CONN_CONTEXT  *p_conn;
-   LC_ELAN_CONTEXT   *p_elan;
-   UINT32             bytes_copied;
-    /* Convert handles to structure pointers. */
-
+{
+  LE_READY_HDR      *hdr;
+  LEC_CONN_CONTEXT  *p_conn;
+  LC_ELAN_CONTEXT   *p_elan;
+  /* Convert handles to structure pointers. */
+  
    p_conn = (LEC_CONN_CONTEXT *) conn_context;
-   p_elan = (LC_ELAN_CONTEXT  *) p_conn->lc_elan_handle;
+   p_elan = (LC_ELAN_CONTEXT  *) p_conn->lc_elan_handle;   
+   hdr = (LE_READY_HDR *)*pp_packet;
 
-   /* Copy the LE Ctrl header up to the op-code from the received packet.
-    * This is the maximum we can copy because the frame may be a READY_IND
-    * or a READY_QUERY which has the op-code as its last element.
-    */
-   os_buff_hdr_copy (*pp_packet,
-                     length,
-                     &hdr,
-                     sizeof (LE_READY_HDR),
-                     &bytes_copied);
-   if (bytes_copied != sizeof (LE_READY_HDR))
-      return;
+   if (length < sizeof (LE_READY_HDR))
+     return;
 
    /* Check the marker and protocol fields.  If they are inappropriate for
     * a LEC control frame, discard the frame.
     */
-   if ((hdr.marker   != ntoh16 (LE_CTRL_MARKER)) ||
-       (hdr.protocol != LE_CTRL_PROTOCOL))
-      return;
+   if ((hdr->marker   != ntoh16 (LE_CTRL_MARKER)) ||
+       (hdr->protocol != LE_CTRL_PROTOCOL))
+     return;
 
    /* Check the version field, discard if it does not match. */
 
-   if (hdr.version != LE_CTRL_VERSION)
-      return;
+   if (hdr->version != LE_CTRL_VERSION)
+     return;
 
    p_elan->ctrl_frames_rcvd += 1;
 
    /* Dispatch to the the appropriate handler for the op-code. */
 
-   switch (ntoh16 (hdr.op_code))
-      {
-      case LE_CONFIG_REQ : 
-         lec_config_req  (p_elan, *pp_packet, length);   break;
-      case LE_CONFIG_RSP :
-         lec_config_rsp  (p_elan, *pp_packet, length);   break;
-      case LE_JOIN_REQ :
-         lec_join_req    (p_elan, *pp_packet, length);   break;
-      case LE_JOIN_RSP :
-         lec_join_rsp    (p_elan, *pp_packet, length);   break;
-      case READY_QUERY :
-         lec_ready_query (p_elan, conn_handle);          break;
-      case READY_IND :
-         lec_ready_ind   (p_elan, conn_handle);          break;
-      case LE_REGISTER_REQ :
-         lec_reg_req     (p_elan, *pp_packet, length);   break;
-      case LE_REGISTER_RSP :
-         lec_reg_rsp     (p_elan, *pp_packet, length);   break;
-      case LE_UNREGISTER_REQ :
-         lec_unreg_req   (p_elan, *pp_packet, length);   break;
-      case LE_UNREGISTER_RSP :
-         lec_unreg_rsp   (p_elan, *pp_packet, length);   break;
-      case LE_ARP_REQ :
-         lec_arp_req     (p_elan, *pp_packet, length);   break;
-      case LE_ARP_RSP :
-         lec_arp_rsp     (p_elan, *pp_packet, length);   break;
-      case LE_FLUSH_REQ :
-	 lec_flush_req   (p_elan, *pp_packet, length);   break;
-      case LE_FLUSH_RSP :
-         lec_flush_rsp   (p_elan, *pp_packet, length);   break;
-      case LE_NARP_REQ :
-         lec_narp_req    (p_elan, *pp_packet, length);   break;
-      case LE_TOPOLOGY_REQ :
-         lec_top_req     (p_elan, *pp_packet, length);   break;
-      default:
-         break;
-      }
-   return;
+   switch (ntoh16 (hdr->op_code)) {
+   case LE_CONFIG_REQ : 
+     lec_config_req  (p_elan, *pp_packet, length);   break;
+   case LE_CONFIG_RSP :
+     lec_config_rsp  (p_elan, *pp_packet, length);   break;
+   case LE_JOIN_REQ :
+     lec_join_req    (p_elan, *pp_packet, length);   break;
+   case LE_JOIN_RSP :
+     lec_join_rsp    (p_elan, *pp_packet, length);   break;
+   case READY_QUERY :
+     lec_ready_query (p_elan, conn_handle);          break;
+   case READY_IND :
+     lec_ready_ind   (p_elan, conn_handle);          break;
+   case LE_REGISTER_REQ :
+     lec_reg_req     (p_elan, *pp_packet, length);   break;
+   case LE_REGISTER_RSP :
+     lec_reg_rsp     (p_elan, *pp_packet, length);   break;
+   case LE_UNREGISTER_REQ :
+     lec_unreg_req   (p_elan, *pp_packet, length);   break;
+   case LE_UNREGISTER_RSP :
+     lec_unreg_rsp   (p_elan, *pp_packet, length);   break;
+   case LE_ARP_REQ :
+     lec_arp_req     (p_elan, *pp_packet, length);   break;
+   case LE_ARP_RSP :
+     lec_arp_rsp     (p_elan, *pp_packet, length);   break;
+   case LE_FLUSH_REQ :
+     lec_flush_req   (p_elan, *pp_packet, length);   break;
+   case LE_FLUSH_RSP :
+     lec_flush_rsp   (p_elan, *pp_packet, length);   break;
+   case LE_NARP_REQ :
+     lec_narp_req    (p_elan, *pp_packet, length);   break;
+   case LE_TOPOLOGY_REQ :
+     lec_top_req     (p_elan, *pp_packet, length);   break;
+   default:
+     break;
    }
+   return;
+}
 
 void 
 lc_addr_delete(HANDLE lc_elan_handle, unsigned char *atm_addr)
diff -ur --new-file old/atm/led/lec_ctrl.h new/atm/led/lec_ctrl.h
--- old/atm/led/lec_ctrl.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/lec_ctrl.h	Tue Aug  6 16:33:08 1996
@@ -78,7 +78,6 @@
 *       - lc_join_start
 *         - (ELAN_STATUS_CALLBACK)
 *           - lc_addr_resolve
-*       - lc_event_mask_set
 *       - lc_deregister
 *     - lc_destroy
 *
@@ -311,83 +310,6 @@
 --*/
 void lc_deregister (HANDLE lc_elan_handle);
 
-
-/*++
-* =====================
-* = lc_event_mask_set =
-* =====================
-*
-* Overview:
-*
-* Arguments:
-*   lc_elan_handle  - (IN) Handle returned by lc_register.
-*   event_mask      - (IN) New value of log event mask.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-void lc_event_mask_set (HANDLE lc_elan_handle,
-                        UINT32 event_mask);
-
-
-/*++
-* ===================
-* = lc_mac_addr_add =
-* ===================
-*
-* Overview:
-*   Registers a new destination address with the LES.  Note that MAC address
-*   registration is asynchronous and does not take effect immediately.  This
-*   routine begins the registration process.  There is no notification to the
-*   caller that registration is complete.  It simply takes effect when the
-*   registration process completes.
-*
-* Arguments:
-*   lc_elan_handle  - (IN) Handle returned by lc_register.
-*   mac_addr        - (IN) New LAN destination for this elan instance.
-*
-* Returns:
-*   STATUS_K_SUCCESS - Successful Completion (registration is in process)
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-STATUS lc_mac_addr_add (HANDLE lc_elan_handle,
-                        ESI    mac_addr);
-
-/*++
-* ===================
-* = lc_mac_addr_del =
-* ===================
-*
-* Overview:
-*   Deregisters a registered destination address with the LES.
-*
-* Arguments:
-*   lc_elan_handle  - (IN) Handle returned by lc_register.
-*   mac_addr        - (IN) LAN destination to be deregistered.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-void lc_mac_addr_del (HANDLE lc_elan_handle,
-                      ESI    mac_addr);
-
 /*++
 * =========================
 * = lc_dest_is_registered =
@@ -539,7 +461,6 @@
 --*/
 void lc_sap_link_status (HANDLE          lc_elan_handle,
                          ATM_LINK_STATE  link_state);
-
 
 /* 
  * Forwards address deletion request to lec_arp module.
diff -ur --new-file old/atm/led/lec_mgt.h new/atm/led/lec_mgt.h
--- old/atm/led/lec_mgt.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/lec_mgt.h	Thu Jan  1 01:00:00 1970
@@ -1,127 +0,0 @@
-/*************************************************************************
-  (c) Copyright.  Digital Equipment Corporation, 1995.  All Rights
-  Reserved.
-
-  Permission is hereby granted to use, copy, modify, or enhance this 
-  software freely, as long as the foregoing copyright of Digital Equipment
-  Corporation and this notice are retained on the software.  This 
-  software may not be distributed or sublicensed for a fee.  Digital      
-  makes this software available "AS IS" and without warranties of any
-  kind.  
- *************************************************************************/
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Tampere University of Technology - Telecommunications Laboratory
- *
- * Permission to use, copy, modify and distribute this
- * software and its documentation is hereby granted,
- * provided that both the copyright notice and this
- * permission notice appear in all copies of the software,
- * derivative works or modified versions, and any portions
- * thereof, that both notices appear in supporting
- * documentation, and that the use of this software is
- * acknowledged in any publications resulting from using
- * the software.
- * 
- * TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
- * SOFTWARE.
- * 
- */
-
-/*
-* Module Name:
-*   lec_mgt.h
-*   
-* Overview:
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*
-* Dependencies:
-*   types.h    - Generally used type definitions.
-*   codes.h    - Completion codes.
-*   atm.h      - ATM specific definitions and types.
-*
-* Description:
-*
-* Call Sequence Requirements:
-*
-*/
-
-/*************************************************************************
- * Types that are specific to this interface.                            *
- *************************************************************************/
-
-#define  ATTR_C1_MY_ATM_ADDR            1001  /* R  */
-#define  ATTR_C2_LAN_TYPE               1002  /* R  */
-#define  ATTR_C3_LAN_MTU                1003  /* R  */
-#define  ATTR_C4_PROXY_FLAG             1004  /* R  */
-#define  ATTR_C5_ELAN_NAME              1005  /* R  */
-#define  ATTR_C6_LOCAL_ESI              1006  /* R  */
-#define  ATTR_C7_CONTROL_TIMEOUT        1008  /* RW */
-#define  ATTR_C8_LOCAL_RD               1009  /* -- */
-#define  ATTR_C9_LES_ATM_ADDR           1010  /* R  */
-#define  ATTR_C10_MAX_UF_COUNT          1011  /* RW */
-#define  ATTR_C11_MAX_UF_TIME           1012  /* RW */
-#define  ATTR_C12_VCC_TIMEOUT           1013  /* RW */
-#define  ATTR_C13_MAX_RETRY_COUNT       1014  /* RW */
-#define  ATTR_C14_LEC_ID                1015  /* R  */
-#define  ATTR_C16_LEARP_CACHE           1017  /* R  */
-#define  ATTR_C17_AGING_TIME            1019  /* RW */
-#define  ATTR_C18_FORW_DELAY_TIME       1020  /* RW */
-#define  ATTR_C19_TOPOLOGY_CHANGE_FLAG  1021  /* RW */
-#define  ATTR_C20_LEARP_RSP_TIME        1022  /* RW */
-#define  ATTR_C21_FLUSH_TIMEOUT         1023  /* RW */
-#define  ATTR_C22_PATH_SWITCH_DELAY     1024  /* RW */
-#define  ATTR_SM_STATE                  1025  /* R  */
-#define  ATTR_SM_STATE_HISTORY          1026  /* R  */
-#define  ATTR_BUS_ATM_ADDR              1027  /* R  */
-#define  ATTR_ILLEGAL_CTRL_FRAMES_RVCD  1028  /* R  */
-#define  ATTR_CTRL_XMT_FAILURES         1029  /* R  */
-#define  ATTR_ILLEGAL_TRANSITIONS       1030  /* R  */
-#define  ATTR_UCASTS_SENT_DIRECT        1031  /* R  */
-#define  ATTR_UCASTS_FLOODED            1032  /* R  */
-#define  ATTR_UCASTS_DISCARDED          1033  /* R  */
-#define  ATTR_NUCASTS_SENT              1034  /* R  */
-#define  ATTR_BUS_FRAMES_RCVD           1035  /* R  */
-#define  ATTR_DIRECT_FRAMES_RCVD        1036  /* R  */
-#define  ATTR_RCV_FRAMES_DISCARDED      1037  /* R  */
-#define  ATTR_ECHOS_SUPPRESSED          1038  /* R  */
-#define  ATTR_CTRL_FRAMES_SENT          1039  /* R  */
-#define  ATTR_CTRL_FRAMES_RCVD          1040  /* R  */
-#define  ATTR_LEARPS_SENT               1041  /* R  */
-#define  ATTR_LEARPS_RCVD               1042  /* R  */
-#define  ATTR_LEARP_SET                 1043  /* W  */
-#define  ATTR_LEARP_DELETE              1044  /* W  */
-
-
-typedef struct
-   {
-   ESI         esi;
-   UINT16      esi_status;
-   BOOLEAN     remote_flag;
-   BOOLEAN     permanent_flag;
-   UINT32      arp_age;
-   ADDR_ATM    addr_atm;
-   UINT16      atm_status;
-   UINT32      vcc_count;
-   UINT32      esi_count;
-   UINT32      vc_id;
-   UINT16      vc_flags;
-   UINT32      age_limit;
-   UINT32      idle_time;
-   } LEARP_CACHE_ENTRY;
-
-typedef struct
-   {
-   ESI         esi;
-   ADDR_ATM    addr_atm;
-   BOOLEAN     permanent_flag;
-   } LEARP_SET;
-
diff -ur --new-file old/atm/led/line_up.h new/atm/led/line_up.h
--- old/atm/led/line_up.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/line_up.h	Thu Jan  1 01:00:00 1970
@@ -1,136 +0,0 @@
-/*************************************************************************
-  (c) Copyright.  Digital Equipment Corporation, 1995.  All Rights
-  Reserved.
-
-  Permission is hereby granted to use, copy, modify, or enhance this 
-  software freely, as long as the foregoing copyright of Digital Equipment
-  Corporation and this notice are retained on the software.  This 
-  software may not be distributed or sublicensed for a fee.  Digital      
-  makes this software available "AS IS" and without warranties of any
-  kind.  
- *************************************************************************/
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Tampere University of Technology - Telecommunications Laboratory
- *
- * Permission to use, copy, modify and distribute this
- * software and its documentation is hereby granted,
- * provided that both the copyright notice and this
- * permission notice appear in all copies of the software,
- * derivative works or modified versions, and any portions
- * thereof, that both notices appear in supporting
- * documentation, and that the use of this software is
- * acknowledged in any publications resulting from using
- * the software.
- * 
- * TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
- * SOFTWARE.
- * 
- */
-
-/*++
-* Module Name:
-*   line_up.h
-*
-* Abstract:
-*   This file is the interface to the line-up functionality.  Line-up is when
-*   both ends of a link agree to the values to use on the link.
-*
-* Authors:
-*   DMW - Douglas M. Washabaugh
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description
-*   10-Feb-95  DMW   Created.
-*   15-May-95  TLR   Added Event Reporting Support.
-*    3-Aug-95  TLR   Added uni-version call.
-*
-* Description:
-*   The line-up process starts as soon as this module receives a link-up 
-*   notification from the ilmi_io module.  Line-up uses ILMI to read remote MIB
-*   attributes (DEC MIB and ATM MIB) and cache their values.  Basically, 
-*   this module is a database that initializes itself when the link comes up.  
-*
-*   Once this is complete, the connection manager is called to notify it that
-*   line-up is complete.  The connection manager propagates this line-up 
-*   indication to all interested parties.
-*
-*   When the interested parties receive the line-up indication, they
-*   can either use the dec_mib or atm_mib routines to read remote objects, 
-*   or they can directly call this module.  However, since this module requires
-*   SNMP names, the indirect calls to dec_mib and atm_mib are simpler.
-*
-*   The values which are used on the link depend upon the values on the local
-*   side and the remote side of the link.  For instance, Digital FLOWmaster
-*   flow-control is used only if both sides can support it.  It is up to 
-*   each entity to determine the actual value used on the link.  It is also 
-*   the responsibility of the entity to verify the correctness of the values.
-*
-*   If the link goes down, then no values are available until the line-up
-*   has run and completed.
-*
-* Call Sequence:
-*   - line_up_create
-*      - line_up_event_mask_set
-*      - line_up_get
-*      - line_up_destroy
-*
-* Call Scenario:
-*
-*   - line_up_create ............... Driver calls this to create an instance.
-*
-*   - line_up_link_status_change ... Called by ilmi_io to notify that the link
-*                                    is now available.
-*
-*   - <call to connection mgr>   ... The link up process has completed, and now
-*                                    line-up calls the connection manager.
-*                                    The connection manager notifies all 
-*                                    interested parties.
-*
-*   - line_up_get .................. Interested parties call to get values.
-*   -  : : : : : : : : : :  ........ Other values.
-*   - line_up_get  ................. Last value.
-*
-*
-*   - line_up_destroy .............. The device/adapter is no longer being used.
-*
-* Issues:
-*   none
---*/
-
-/*++
-* ===========================
-* = line_up_uni_version_get =
-* ===========================
-*
-* Overview:
-*   This function returns the UNI version that is being used on the physical
-*   port.
-*
-* Arguments:
-*   line_up_handle  - (IN)  The handle returned by line_up_create.
-*   p_uni_version   - (OUT) The version number of the UNI supported.
-*                           (see defines below)
-*
-* Returns:
-*   STATUS_K_SUCCESS           - Refer to postconditions.
-*   STATUS_K_FAILURE           - UNI Version is unknown (not 3.0).
-*   STATUS_K_NOT_READY         - Line-up has not yet completed.
-*
-* Preconditions:
-*   none
-*
-* Postconditions:
-*   The uni version is returned.
---*/                                              
-#define UNI_3_0   0x30
-#define UNI_3_1   0x31
-#define UNI_4_0   0x40
-
-STATUS line_up_uni_version_get (HANDLE  line_up_handle,
-                                UINT8  *p_uni_version);
-
diff -ur --new-file old/atm/led/main.c new/atm/led/main.c
--- old/atm/led/main.c	Sun Jul  7 13:59:07 1996
+++ new/atm/led/main.c	Tue Aug 20 20:41:40 1996
@@ -25,7 +25,7 @@
  *
  * Initialization, main loop
  * 
- * $Id: main.c,v 1.18 1996/07/07 11:51:47 carnil Exp carnil $
+ * $Id: main.c,v 1.19 1996/08/06 14:14:11 carnil Exp carnil $
  */
 
 /* Global includes */
@@ -46,9 +46,9 @@
 #include "lec_ctrl.h"
 #include "utl_os.h"
 #include "g_event.h"
-#include "map.h"
 #include "addr_reg.h"
 #include "le_disp.h"
+#include "cm.h"
 
 /* Local incs */
 #include "conn.h"
@@ -81,21 +81,9 @@
  *
  *  bus_conn_context.......Connection Context for BUS VCCs.
  *
- *  mcast_list.............Handle for the multicast address list.  This list is
- *                         managed by the mapping module.
- *
- *  elan_up................This flag indicates whether or not the ELAN is fully
- *                         joined and ready for network traffic.
- *
  *  lec_id.................LEC_ID of this LEC in the ELAN.  Used in the LAN
  *                         emulation header for data packets.
  *
- *  mcast_enb..............Multicast enable flag.
- *
- *  bcast_enb..............Briadcast enable flag.
- *
- *  prom_enb...............Promiscuous mode enable flag.
- *
  *  lec_event_callback.....Callback for ELAN events.
  *
  *  lec_rcv_callback.......Callback for received packets.
@@ -106,7 +94,6 @@
 typedef struct _ld_elan {
   struct _ld_elan        *p_next;
   char                   *p_text;
-  UINT32                  event_mask;
   HANDLE                  lec_handle;
   HANDLE                  client_context;
   HANDLE                  lc_elan_handle;
@@ -115,19 +102,10 @@
   LEC_CONN_CONTEXT        direct_conn_context;
   LEC_CONN_CONTEXT        mcast_conn_context;
   LEC_CONN_CONTEXT        ctrl_conn_context;
-  HANDLE                  mcast_list;
-  BOOLEAN                 elan_up;
   UINT16                  lec_id;
-  BOOLEAN                 mcast_enb;
-  BOOLEAN                 bcast_enb;
-  BOOLEAN                 prom_enb;
   LEC_EVENT_CALLBACK      lec_event_callback;
   LEC_RCV_CALLBACK        lec_rcv_callback;
   LEC_XMT_DONE_CALLBACK   lec_xmt_done_callback;
-  UINT32                  bus_frames_rcvd;
-  UINT32                  direct_frames_rcvd;
-  UINT32                  rcv_frames_discarded;
-  UINT32                  echos_suppressed;
 } LD_ELAN_CONTEXT;
 
 /*
@@ -150,6 +128,7 @@
 } LD_CONTEXT;
 
 int stay_alive =1;
+int reset=0;
 
 #define EMOD   MOD_LEC_DATA
 #define EINST  "main.c"
@@ -174,6 +153,13 @@
 sig_die(int a)
 {
   stay_alive = 0;
+  reset = 1;
+}
+
+void
+sig_reset(int a)
+{
+  reset = 1;  
 }
 
 static void 
@@ -322,12 +308,14 @@
   STATUS status;
 
   fd_set fds;
+  fd_set efds;
   int poll_ret =0;
   struct timeval *timeout;
   HANDLE current_timer;
+  ADDR_ATM *listen_address = NULL;
 
   while(poll_ret != -1) {
-    poll_ret = getopt(argc, argv, "c:e:n:s:m:");
+    poll_ret = getopt(argc, argv, "c:e:n:s:m:l:");
     switch(poll_ret) {
     case 'c':
       if (atm_set) {
@@ -378,6 +366,15 @@
       }
       EVENT(EM_MSG,("Message mask set to %lx\n",EMASK));
       break;
+    case 'l':
+      listen_address = (ADDR_ATM*)mem_alloc(EINST, sizeof(ADDR_ATM));
+      if (address_convert(optarg, listen_address)<0) {
+	EVENT(EM_SERR,("Invalid ATM listen address\n"));
+	usage(argv[0]);
+	exit(-1);
+      }
+      EVENT(EM_MSG,("Our ATM address: %s\n", disp_atm_text(*listen_address)));
+      break;
     case -1:
       break;
     default:
@@ -392,242 +389,254 @@
     } 
     EVENT(EM_MSG,("LEC ESI:%s\n",disp_esi_text(mac_addr)));
   }
-  /* Reserve signals */
-  signal(SIGHUP, sig_die);
-  signal(SIGINT, sig_die);
-  signal(SIGQUIT, sig_die);
-  signal(SIGABRT, sig_die);
-  signal(SIGTERM, sig_die);
-  signal(SIGSEGV, sig_die);
-
-  /* Allocate storage for the data context.  Return failure status if memory
-   * could not be allocated.
-   */
-
-  p_context = (LD_CONTEXT *) os_mem_alloc (sizeof (LD_CONTEXT));
+  while (stay_alive) {
 
-  if (p_context == NULL)
-    return STATUS_K_RESOURCES;
+    /* Reserve signals */
+    signal(SIGHUP, sig_reset);
+    signal(SIGINT, sig_die);
+    signal(SIGQUIT, sig_die);
+    signal(SIGABRT, sig_die);
+    signal(SIGTERM, sig_die);
+    signal(SIGSEGV, sig_die);
     
-  /* Initialize the list of ELANs. */
-  
-  utl_list_init (p_context->elan_list);
-  
-  if (kernel_init(mac_addr)<0) {
-    EVENT(EM_SERR,("Kernel interface creation failed, exiting..."));
-    return STATUS_K_RESOURCES;
-  }
-
-  /* Create an instance of the LEC_CTRL module.  If there is an error, back
-   * out of our previous operations and return failure status.
-   */
-  status = lc_create (line_up_handle,
-		      elan_status_callback,
-		      &p_context->lc_handle);
-  if (status != STATUS_K_SUCCESS) {
-    os_mem_dealloc (p_context);
-    return STATUS_K_RESOURCES;
-  }
-  
-  /* Return the lec handle with success status. */
-  /*
-   *p_lec_handle = (HANDLE) p_context;
-   return STATUS_K_SUCCESS;
-  */
-
-  /* Allocate memory for a new ELAN context.  If the allocation fails, return
-   * error status.
-   */
-  p_elan = (LD_ELAN_CONTEXT *)os_mem_alloc(sizeof (LD_ELAN_CONTEXT));
-  if (p_elan == NULL) {
-    os_mem_dealloc (p_context);
-    return STATUS_K_RESOURCES;
-  }
-  memset(p_elan,0, sizeof(LD_ELAN_CONTEXT));
+    /* Allocate storage for the data context.  Return failure status if memory
+     * could not be allocated.
+     */
 
-  p_elan->event_mask = EM_DEFAULT;
-  p_elan->p_text     = p_text;
-  
-  /* Initialize the ELAN context's neighbor handles. */
-  
-  p_elan->lec_handle     = (HANDLE)p_context;
-  p_elan->client_context = callback_context;
-  p_elan->lan_type       = lan_type;
-  
-  p_elan->bus_frames_rcvd       = 0;
-  p_elan->direct_frames_rcvd    = 0;
-  p_elan->rcv_frames_discarded  = 0;
-  p_elan->echos_suppressed      = 0;
-  
-  /* Store the callback addresses in the ELAN context. */
-  
-  p_elan->lec_event_callback    = lec_event_callback;
-  p_elan->lec_rcv_callback      = lec_rcv_callback;
-  p_elan->lec_xmt_done_callback = lec_xmt_done_callback;
-  
-  /* Set the "up" state to false since the ELAN has not been joined yet. */
-  
-  p_elan->elan_up   = FALSE;
-  
-  /* Initialize the multicast, broadcast, and promiscuous enables. */
-  
-  p_elan->mcast_enb = FALSE;
-  p_elan->bcast_enb = FALSE;
-  p_elan->prom_enb  = FALSE;
-  
-  /* Allocate the multicast address list.  If there is an error, back out of
-   * our operations thus far and return error status.
-   */
-  status = map_list_alloc(sizeof (ADDR_48),
-			  &p_elan->mcast_list);
-  if (status != STATUS_K_SUCCESS) {
-    EVENT (EM_SERR, ("Failed to allocate multicast list.\n"));
-    os_mem_dealloc(p_elan);
-    os_mem_dealloc(p_context);
-    return STATUS_K_RESOURCES;
-  }
-  
-  /* Register with the LEC_CTRL module to cause it to allocate an
-   * ELAN instance.  If there is an error, back out of our operations so
-   * far and return error status.
-   */
-  status = lc_register (p_context->lc_handle,
-			(HANDLE) p_elan,
-			addr_reg_handle,
-			mac_addr,
-			lan_type,
-			max_frame_size,
-			p_elan_name,
-			init_method,
-			manual_atm_addr,
-			proxy_flag,
-			lport_handle,
-			p_text,
-			&p_elan->lc_elan_handle);
-  if (status != STATUS_K_SUCCESS) {
-    EVENT (EM_SERR, ("Failed to register lec_ctrl instance.\n"));
-    map_list_dealloc (p_elan->mcast_list,
-		      NULL, NULL);
-    os_mem_dealloc (p_elan);
-    os_mem_dealloc (p_context);
-    return STATUS_K_RESOURCES;
-  }
+    p_context = (LD_CONTEXT *) os_mem_alloc (sizeof (LD_CONTEXT));
+    
+    if (p_context == NULL)
+      return STATUS_K_RESOURCES;
+    
+    /* Initialize the list of ELANs. */
+    
+    utl_list_init (p_context->elan_list);
+    
+    if (kernel_init(mac_addr)<0) {
+      EVENT(EM_SERR,("Kernel interface creation failed, exiting...\n"));
+      return STATUS_K_RESOURCES;
+    }
+    
+    /* Create an instance of the LEC_CTRL module.  If there is an error, back
+     * out of our previous operations and return failure status.
+     */
+    status = lc_create (line_up_handle,
+			elan_status_callback,
+			&p_context->lc_handle);
+    if (status != STATUS_K_SUCCESS) {
+      os_mem_dealloc (p_context);
+      return STATUS_K_RESOURCES;
+    }
+        
+    /* Allocate memory for a new ELAN context.  If the allocation fails, return
+     * error status.
+     */
+    p_elan = (LD_ELAN_CONTEXT *)os_mem_alloc(sizeof (LD_ELAN_CONTEXT));
+    if (p_elan == NULL) {
+      os_mem_dealloc (p_context);
+      return STATUS_K_RESOURCES;
+    }
+    memset(p_elan,0, sizeof(LD_ELAN_CONTEXT));
+    
+    p_elan->p_text     = p_text;
+    
+    /* Initialize the ELAN context's neighbor handles. */
+    
+    p_elan->lec_handle     = (HANDLE)p_context;
+    p_elan->client_context = callback_context;
+    p_elan->lan_type       = lan_type;
+    
+    /* Store the callback addresses in the ELAN context. */
+    
+    p_elan->lec_event_callback    = lec_event_callback;
+    p_elan->lec_rcv_callback      = lec_rcv_callback;
+    p_elan->lec_xmt_done_callback = lec_xmt_done_callback;
+    
+    /* Register with the LEC_CTRL module to cause it to allocate an
+     * ELAN instance.  If there is an error, back out of our operations so
+     * far and return error status.
+     */
+    status = lc_register (p_context->lc_handle,
+			  (HANDLE) p_elan,
+			  addr_reg_handle,
+			  mac_addr,
+			  lan_type,
+			  max_frame_size,
+			  p_elan_name,
+			  init_method,
+			  manual_atm_addr,
+			  proxy_flag,
+			  lport_handle,
+			  p_text,
+			  &p_elan->lc_elan_handle);
+    if (status != STATUS_K_SUCCESS) {
+      EVENT (EM_SERR, ("Failed to register lec_ctrl instance.\n"));
+      os_mem_dealloc (p_elan);
+      os_mem_dealloc (p_context);
+      return STATUS_K_RESOURCES;
+    }
 
-  /* Pre-initialize the data-direct and BUS connection context blocks. */
-  
-  p_elan->direct_conn_context.ld_elan_handle = (HANDLE) p_elan;
-  p_elan->direct_conn_context.lc_elan_handle = p_elan->lc_elan_handle;
-  p_elan->direct_conn_context.conn_type      = LEC_DIRECT;
-  
-  p_elan->mcast_conn_context.ld_elan_handle  = (HANDLE) p_elan;
-  p_elan->mcast_conn_context.lc_elan_handle  = p_elan->lc_elan_handle;
-  p_elan->mcast_conn_context.conn_type       = LEC_MCAST;
-  
-  p_elan->ctrl_conn_context.ld_elan_handle   = (HANDLE) p_elan;
-  p_elan->ctrl_conn_context.lc_elan_handle   = p_elan->lc_elan_handle;
-  p_elan->ctrl_conn_context.conn_type        = LEC_CTRL;
-  
-  /* Add the ELAN context to the ELAN list in the module context. */
-  
-  utl_list_add (p_context->elan_list, p_elan);
+    /* Pre-initialize the data-direct and BUS connection context blocks. */
+    
+    p_elan->direct_conn_context.ld_elan_handle = (HANDLE) p_elan;
+    p_elan->direct_conn_context.lc_elan_handle = p_elan->lc_elan_handle;
+    p_elan->direct_conn_context.conn_type      = LEC_DIRECT;
+  
+    p_elan->mcast_conn_context.ld_elan_handle  = (HANDLE) p_elan;
+    p_elan->mcast_conn_context.lc_elan_handle  = p_elan->lc_elan_handle;
+    p_elan->mcast_conn_context.conn_type       = LEC_MCAST;
+    
+    p_elan->ctrl_conn_context.ld_elan_handle   = (HANDLE) p_elan;
+    p_elan->ctrl_conn_context.lc_elan_handle   = p_elan->lc_elan_handle;
+    p_elan->ctrl_conn_context.conn_type        = LEC_CTRL;
+    
+    /* Add the ELAN context to the ELAN list in the module context. */
+    
+    utl_list_add (p_context->elan_list, p_elan);
   
-  /* Register with the CM as a SAP.  This is the Data-SAP for this ELAN.
-   * Again, back out if there is an error.
-   */
-  status = cm_sap_register(p_elan->lc_elan_handle,
-			   ld_rcv_callback,
-			   lc_sap_vc_notify,
-			   lc_sap_connect,
-			   lc_sap_link_status,
-			   ld_xmt_done_callback,
-			   "LAN Emulation Convergence",
-			   &p_elan->sap_handle);
-  if (status != STATUS_K_SUCCESS) {
-    EVENT(EM_SERR, ("Failed to register as an NSAP client.\n"));
-    lc_deregister(p_elan->lc_elan_handle);
-    map_list_dealloc(p_elan->mcast_list,
-		     NULL,NULL);
-    os_mem_dealloc(p_elan);
-    os_mem_dealloc(p_context);
-    return STATUS_K_RESOURCES;
-  }
+    /* Register with the CM as a SAP.  This is the Data-SAP for this ELAN.
+     * Again, back out if there is an error.
+     */
+    status = cm_sap_register(p_elan->lc_elan_handle,
+			     ld_rcv_callback,
+			     lc_sap_vc_notify,
+			     lc_sap_connect,
+			     lc_sap_link_status,
+			     ld_xmt_done_callback,
+			     "LAN Emulation Convergence",
+			     &p_elan->sap_handle);
+    if (status != STATUS_K_SUCCESS) {
+      EVENT(EM_SERR, ("Failed to register as an NSAP client.\n"));
+      lc_deregister(p_elan->lc_elan_handle);
+      os_mem_dealloc(p_elan);
+      os_mem_dealloc(p_context);
+      return STATUS_K_RESOURCES;
+    }
+    
+    if (listen_address) {
+      addr_set_atm_addr(listen_address);
+    }
 
+    /*
+      Create listen sockets. LES / BUS will have different addresses.
+      -> no clash.
+      */
+    if (conn_create_listensocket(p_elan->sap_handle,
+				 p_elan->lc_elan_handle,
+				 BLLI_CONTROL,
+				 (155200000 / 8) / 53, 
+				 NULL)<0) {
+      EVENT(EM_NERR,("Creating Control blli codepoint failed\n"));
+      return STATUS_K_ATM_RESOURCES;
+    }
+    if (conn_create_listensocket(p_elan->sap_handle,
+				 p_elan->lc_elan_handle,
+				 BLLI_BUS_802_3,
+				 (155200000 / 8) / 53, 
+				 NULL)<0) {
+      EVENT(EM_NERR, ("Creating Bus 802_3 blli codepoint failed\n"));
+      return STATUS_K_ATM_RESOURCES;
+    }
+    
+    if (conn_create_listensocket(p_elan->sap_handle,
+				 p_elan->lc_elan_handle,
+				 BLLI_DIRECT_802_3,
+				 (155200000 / 8) / 53, 
+				 NULL)<0) {
+      EVENT(EM_NERR, ("Creating Data direct 802_3 blli codepoint failed\n"));
+      return STATUS_K_ATM_RESOURCES;
+    }	  
+
+    /* Registration is complete.  Notify the LEC_CTRL module that it may begin
+     * the ELAN join.
+     */
+    lc_join_start (p_elan->lc_elan_handle,
+		   p_elan->sap_handle,
+		   (HANDLE) &p_elan->direct_conn_context,
+		   (HANDLE) &p_elan->mcast_conn_context,
+		   (HANDLE) &p_elan->ctrl_conn_context);
 
-  /* Registration is complete.  Notify the LEC_CTRL module that it may begin
-   * the ELAN join.
-   */
-  lc_join_start (p_elan->lc_elan_handle,
-		 p_elan->sap_handle,
-		 (HANDLE) &p_elan->direct_conn_context,
-		 (HANDLE) &p_elan->mcast_conn_context,
-		 (HANDLE) &p_elan->ctrl_conn_context);
-
-  /*
-    Create listen sockets. LES / BUS will have different addresses.
-    -> no clash.
-   */
-  if (conn_create_listensocket(p_elan->sap_handle,
-			       p_elan->lc_elan_handle,
-			       BLLI_CONTROL,
-			       (155200000 / 8) / 53, NULL)<0) {
-    EVENT(EM_NERR,("Creating Control blli codepoint failed\n"));
-    return STATUS_K_ATM_RESOURCES;
-  }
-  if (conn_create_listensocket(p_elan->sap_handle,
-			       p_elan->lc_elan_handle,
-			       BLLI_BUS_802_3,
-			       (155200000 / 8) / 53, NULL)<0) {
-    EVENT(EM_NERR, ("Creating Bus 802_3 blli codepoint failed\n"));
-    return STATUS_K_ATM_RESOURCES;
-  }
 
-  if (conn_create_listensocket(p_elan->sap_handle,
-			       p_elan->lc_elan_handle,
-			       BLLI_DIRECT_802_3,
-			       (155200000 / 8) / 53, NULL)<0) {
-    EVENT(EM_NERR, ("Creating Data direct 802_3 blli codepoint failed\n"));
-    return STATUS_K_ATM_RESOURCES;
-  }	  
-  /* Notify about new connections */
-  conn_call_callbacks();
-
-  while(stay_alive) {
-    EVENT(EM_DEBUG,("Checking for new event\n"));
-    current_timer = timer_find_soonest();
-    timeout = timer_get_expiration(current_timer);
-    if (timeout) {
-      EVENT(EM_DEBUG,("Sleeping %d secs....\n",timeout->tv_sec));
-    } else {
-      EVENT(EM_DEBUG,("No timers pending...\n"));
-    }
-    if (!timeout || (timeout->tv_sec!=0 && timeout->tv_usec!=0)) {
-      FD_ZERO(&fds);
-      conn_get_fds(&fds);
-      poll_ret = select(FD_SETSIZE, &fds, NULL, NULL, timeout);
-      if (poll_ret < 0) {
-	perror("select");
-      } else if (poll_ret >0) {
-	if (conn_check_incoming(&fds)<0) {
-	  stay_alive=0;
+    /* Notify about new connections */
+    conn_call_callbacks();
+    
+    while(!reset && stay_alive) {
+      EVENT(EM_DEBUG,("Checking for new event\n"));
+      current_timer = timer_find_soonest();
+      timeout = timer_get_expiration(current_timer);
+      if (timeout) {
+	EVENT(EM_DEBUG,("Sleeping %d secs....\n",timeout->tv_sec));
+      } else {
+	EVENT(EM_DEBUG,("No timers pending...\n"));
+      }
+      if (!reset && (!timeout || (timeout->tv_sec!=0 && timeout->tv_usec!=0))){
+	FD_ZERO(&fds);
+	conn_get_fds(&fds);
+	FD_ZERO(&efds);
+	conn_get_connecting_fds(&efds);
+	poll_ret = select(FD_SETSIZE, &fds, NULL, &efds, timeout);
+	EVENT(EM_DEBUG,("Selected .....\n\n\n"));
+	if (poll_ret < 0) {
+	  perror("select");
+	} else if (poll_ret >0) {
+	  EVENT(EM_DEBUG,("RESET:%d\n",reset));
+	  if (conn_check_incoming(&fds)<0) {
+	    reset=1;
+	  }
+	  conn_check_incoming(&efds);
 	}
+      } else
+	poll_ret =0;
+      if (poll_ret ==0 && current_timer) { /* Timeout */
+	timer_call_callback(current_timer);
       }
-    } else
-      poll_ret =0;
-    if (poll_ret ==0 && current_timer) { /* Timeout */
-      timer_call_callback(current_timer);
+      EVENT(EM_DEBUG,("About to handle callbacks\n"));
+      conn_call_callbacks();
+      EVENT(EM_DEBUG,("Callbacks handled\n"));
+    }
+    if (reset && stay_alive) {
+      EVENT(EM_NERR,("Resetting...\n"));
+      /* Deregister with the Connection Manager. */
+      cm_sap_unregister(p_elan->sap_handle);
+
+      sleep(6);
+      /* Deregister the LEC_CTRL instance for this ELAN.  This will in turn
+       * deregister the le-arp instance.
+       */
+      lc_deregister(p_elan->lc_elan_handle);
+
+      /* Remove this data block from the LEC instance's list of ELANs. */
+      utl_list_delete (p_context->elan_list, p_elan);
+
+      /* Deallocate the ELAN context data block. */
+      
+      os_mem_dealloc(p_elan);
+      
+      /* Request the destruction of the LEC_CTRL module instance. */
+      
+      lc_destroy(p_context->lc_handle);
+      
+      /* Deallocate the memory for the LEC context data block. */
+      
+      os_mem_dealloc(p_context);
+
+#if 0
+      /* Now we should be able to restart from empty table? */
+      mem_usage();
+      timer_usage();
+#endif
+      reset = 0;
     }
-    EVENT(EM_DEBUG,("About to handle callbacks\n"));
-    conn_call_callbacks();
-    EVENT(EM_DEBUG,("Callbacks handled\n"));
   }
-  cm_sap_unregister(p_elan->sap_handle);
-  lc_destroy(p_context->lc_handle);
   return STATUS_K_SUCCESS; 
 }
 
 /*
  *
  * $Log: main.c,v $
+ * Revision 1.19  1996/08/06 14:14:11  carnil
+ * Reset handling
+ *
  * Revision 1.18  1996/07/07 11:51:47  carnil
  * Global_msgmask
  *
diff -ur --new-file old/atm/led/map.c new/atm/led/map.c
--- old/atm/led/map.c	Sun Jul  7 13:59:07 1996
+++ new/atm/led/map.c	Thu Jan  1 01:00:00 1970
@@ -1,819 +0,0 @@
-/*************************************************************************
-  (c) Copyright.  Digital Equipment Corporation, 1995.  All Rights
-  Reserved.
-
-  Permission is hereby granted to use, copy, modify, or enhance this 
-  software freely, as long as the foregoing copyright of Digital Equipment
-  Corporation and this notice are retained on the software.  This 
-  software may not be distributed or sublicensed for a fee.  Digital      
-  makes this software available "AS IS" and without warranties of any
-  kind.  
- *************************************************************************/
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Tampere University of Technology - Telecommunications Laboratory
- *
- * Permission to use, copy, modify and distribute this
- * software and its documentation is hereby granted,
- * provided that both the copyright notice and this
- * permission notice appear in all copies of the software,
- * derivative works or modified versions, and any portions
- * thereof, that both notices appear in supporting
- * documentation, and that the use of this software is
- * acknowledged in any publications resulting from using
- * the software.
- * 
- * TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
- * SOFTWARE.
- * 
- */
-
-/*
-* Module Name:
-*   map.c
-*   
-* Overview:
-*   This file implements the mapping module.  A map list is implemented as a
-*   doubly linked ring.  The search algorithm is linear search with reordering.
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   18-Jan-95  TLR   Created.
-*   23-Jan-95  TLR   Updated with inputs from team review.
-*    6-Mar-95  TLR   Fixed a bug in the key_search routine.
-*/
-
-#ifdef _DEBUG
-#define STATIC
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#else
-#define STATIC static
-#define assert(expr)
-#endif
-
-/* Include General Headers. */
-
-#include "g_types.h"      /* General Purpose Types      */
-#include "codes.h"      /* Return Status Codes        */
-#include "utl.h"        /* General Purpose Utilities  */
-#include "utl_os.h"     /* Operating System Utilities */
-
-/* Include Headers for Mapping Module Interfaces. */
-
-#include "map.h"
-
-#define MAX_KEY   100
-
-/****************************************************************************
- *  Internal Data Structures
- ****************************************************************************/
-
-/* MAP_LIST
- *
- *  This structure describes a map list.
- *
- *  p_head......Pointer to the head element in the list.  This is the first
- *              element in the linear search order.
- *
- *  p_tail......Pointer to the tail element in the list.  This is the last
- *              element in the linear search order.
- *
- *  size........Number of elements in the list.
- *
- *  key_length..The length of the search key field in bytes.
- *
- */
-typedef struct _map_list
-   {
-   MAP_LIST_HDR  *p_head;
-   MAP_LIST_HDR  *p_tail;
-   UINT32         size;
-   UINT8          key_length;
-   UINT8          thread_count;
-   } MAP_LIST;
-
-
-/****************************************************************************
- *  Doubly linked list macros
- ****************************************************************************/
-
-/*++
-* ========================
-* = link_to_head (MACRO) =
-* ========================
-*
-* Overview:
-*   Places an element onto the head of a doubly linked list.
-*
-* Arguments:
-*   list        - List to be modified.
-*   p_element   - Pointer to element to be added to the list.
-*              
-* Returns:
-*   Not Applicable
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The element pointed to by p_element is at the head of the list.
-*
-*   The size of the list is one greater than before the macro call.
-*
-* Description:
-*   Place the new element at the head of the list.  The old head element
-*   (if there was one) becomes the second element.  The list structure must
-*   remain well-formed (i.e. all of the pointers are correct and the size
-*   mmeber of the list structure is equal to the number of elements in the
-*   list).
-*
-*   The first step is to initialize the links of the element to insert. The
-*   next step depends upon whether the list was previously empty or not.  If
-*   the list was previously empty, then the tail of the list is set to point
-*   to the new element.  Otherwise, the element that was the old head must
-*   have its previous link set to point to the new element.
-*
-*   The final step is to set the head of the list to point to the new element,
-*   and to increment the count of elements in the list.
-*
-* Issues:
-*   None
-*
---*/
-#define link_to_head(list,p_element)             \
-   {                                             \
-   (p_element)->p_prev = NULL;                   \
-   (p_element)->p_next = (list)->p_head;         \
-                                                 \
-   if ((list)->p_head == NULL)                   \
-      {                                          \
-      (list)->p_tail = (p_element);              \
-      assert ((list)->size == 0);                \
-      }                                          \
-   else                                          \
-      (list)->p_head->p_prev = (p_element);      \
-                                                 \
-   (list)->p_head      = (p_element);            \
-   (list)->size       += 1;                      \
-   }
-
-/*++
-* ==================
-* = unlink (MACRO) =
-* ==================
-*
-* Overview:
-*   Unlinks an element from a list, leaving the list intact.
-*
-* Arguments:
-*   list        (IN) List to be modified.
-*   p_element   (IN) Pointer to the element to be removed from the list.
-*              
-* Returns:
-*   Not Applicable
-*
-* Preconditions:
-*   The element pointed to by p_element is a member of the list.
-*
-* Postconditions:
-*   The element pointed to by p_element is not a member of the list.
-*
-*   The size of the list is one less than before the macro call.
-*
-* Description:
-*   Wherever the element is in the list, it is removed from the list and
-*   the elements neighbors (previous and next) are list are "reconnected".
-*   To reconnect a list, the "next" link of the previous element must be set
-*   to the next element.  Similiarly, the "prev" link of the next element must
-*   be set to point to the previous element.
-*
-*   The list must remain well-formed.  Note that nothing is deleted, an element
-*   is simply dis-associated with the list.
-*
-*   The first steps are to update the head and tail of the list.  The head 
-*   must be updated only if the element was the head, and the tail must be
-*   updated if the element was the tail (note that for a list of size 1, the 
-*   element can be both the head and the tail).
-*
-*   The final step is to reconnect the list, as described above.
-*   The assertion states that either the list is has at least one element,
-*   or the list is empty and that the head and tail pointers are NULL.
-*
-* Issues:
-*   None
-*
---*/
-#define unlink(list,p_element)                                      \
-   {                                                                \
-   if ((list)->p_head == (p_element))                               \
-      (list)->p_head = (p_element)->p_next;                         \
-                                                                    \
-   if ((list)->p_tail == (p_element))                               \
-      (list)->p_tail = (p_element)->p_prev;                         \
-                                                                    \
-   if ((p_element)->p_prev != NULL)                                 \
-      (p_element)->p_prev->p_next = (p_element)->p_next;            \
-                                                                    \
-   if ((p_element)->p_next != NULL)                                 \
-      (p_element)->p_next->p_prev = (p_element)->p_prev;            \
-                                                                    \
-   (list)->size -= 1;                                               \
-   assert (((list)->size > 0) ||                                    \
-           (((list)->size == 0) &&                                  \
-            ((list)->p_head == NULL) && ((list)->p_tail == NULL))); \
-   }
-
-
-/****************************************************************************
- *  Function Implementations
- ****************************************************************************/
-
-/*++
-* ==================
-* = map_list_alloc =
-* ==================
-*
-* Description:
-*   Allocate a MAP_LIST descriptor and initialize its fields to represent
-*   an empty list.
-*
-* Issues:
-*   None
-*
---*/
-STATUS map_list_alloc (UINT8     key_length,
-                       HANDLE   *p_list_handle)
-   {
-   MAP_LIST    *p_map;
-
-   /* Allocate a MAP_LIST descriptor for the new list.  If memory allocation
-    * fails, return error status.
-    */
-   p_map = (MAP_LIST*) os_mem_alloc (sizeof (MAP_LIST));
-   if (p_map == NULL)
-      return STATUS_K_RESOURCES;
-
-   /* Initialize the list elements to make an empty list. */
-
-   p_map->p_head     = NULL;
-   p_map->p_tail     = NULL;
-   p_map->size       = 0;
-
-   /* Store the key length in the descriptor block. */
-
-   p_map->key_length   = key_length;
-   p_map->thread_count = 0;
-
-   /* Convert the address of the descriptor block to a handle and return it
-    * to the caller with success status.
-    */
-   *p_list_handle = (HANDLE) p_map;
-   return STATUS_K_SUCCESS;
-   }
-
-/*++
-* ====================
-* = map_list_dealloc =
-* ====================
-*
-* Description:
-*   Iteratively request the deletion of each element in the list then
-*   deallocate the list descriptor.
-*
-* Issues:
-*   None
-*
---*/
-void map_list_dealloc (HANDLE          list_handle,
-                       MAP_CALLBACK    destroy_callback,
-                       HANDLE          parameter)
-   {
-   MAP_LIST       *p_map;
-   MAP_LIST_HDR   *p_ptr, *p_save;
-
-   /* Obtain a pointer to the MAP_LIST descriptor block. */
-
-   p_map = (MAP_LIST*) list_handle;
-   p_map->thread_count += 1;
-
-   /* Traverse the list in its entirety calling the destroy callback for each
-    * entry in the list.
-    */
-   p_ptr = p_map->p_head;
-   while (p_ptr != NULL)
-      {
-      /* Save the p_next pointer before destroying the entry. */
-
-      p_save = p_ptr->p_next;
-      (void) destroy_callback ((HANDLE) p_ptr, parameter);
-      p_ptr  = p_save;
-      }
-
-   /* Deallocate the memory used for the descriptor block. */
-
-   os_mem_dealloc (p_map);
-   }
-
-/*++
-* ======================
-* = map_element_insert =
-* ======================
-*
-* Description:
-*   Link the element represented by the element_handle onto the head of the
-*   list.
-*
-* Issues:
-*   None
-*
---*/
-void map_element_insert (HANDLE    list_handle,
-                         HANDLE    element_handle)
-   {
-   MAP_LIST       *p_map;
-   MAP_LIST_HDR   *p_element;
-
-   /* Convert the list handle to a pointer to a MAP_LIST descriptor. */
-
-   p_map = (MAP_LIST*) list_handle;
-   p_map->thread_count += 1;
-
-   /* Convert the element handle to a pointer to a MAP_LIST_HDR.  Note that
-    * the actual element structure is larger than a MAP_LIST_HDR structure but
-    * this function doesn't care about what's beyond the header.
-    */
-   p_element = (MAP_LIST_HDR*) element_handle;
-
-   /* Link the new element to the head of the list. */
-
-   link_to_head (p_map, p_element);
-   p_map->thread_count -= 1;
-   }
-
-/*++
-* ======================
-* = map_element_delete =
-* ======================
-*
-* Description:
-*   Unlink the element represented by element_handle from the list.  No memory
-*   is deallocated by this function.
-*
-* Issues:
-*   None
-*
---*/
-void map_element_delete (HANDLE list_handle,
-                         HANDLE element_handle)
-   {
-   MAP_LIST       *p_map;
-   MAP_LIST_HDR   *p_element;
-
-   /* Convert the list handle to a pointer to a MAP_LIST descriptor. */
-
-   p_map = (MAP_LIST*) list_handle;
-   p_map->thread_count += 1;
-
-   /* Convert the element handle to a pointer to a MAP_LIST_HDR.  Note that
-    * the actual element structure is larger than a MAP_LIST_HDR structure but
-    * this function doesn't care about what's beyond the header.
-    */
-   p_element = (MAP_LIST_HDR*) element_handle;
-
-   /* Unlink the element from the list. */
-
-   unlink (p_map, p_element);
-   p_map->thread_count -= 1;
-   }
-
-/*++
-* =====================
-* = map_list_size_get =
-* =====================
-*
-* Description:
-*   Return the size parameter of the list.
-*
-* Issues:
-*   None
-*
---*/
-UINT32 map_list_size_get (HANDLE list_handle)
-   {
-   MAP_LIST *p_map;
-
-   p_map = (MAP_LIST *) list_handle;
-
-   return p_map->size;
-   }
-
-/*++
-* ==================
-* = map_key_search =
-* ==================
-*
-* Description:
-*   Linearly search the list for an element that has a key field that is
-*   identical to the provided search key.  If a matching element is found
-*   ensure that it is left on the head of the list.
-*
-* Issues:
-*   None
-*
---*/
-STATUS map_key_search (HANDLE   list_handle,
-                       void    *p_key,
-                       HANDLE  *p_element_handle)
-   {
-   MAP_LIST       *p_map;
-   MAP_LIST_HDR   *p_element;
-   INT8            index;
-	UINT8          *search_key;
-   UINT8          *test_key;
-   BOOLEAN         found;
-
-   /* Obtain a pointer to a MAP_LIST descriptor from the list handle. */
-
-   p_map = (MAP_LIST*) list_handle;
-   p_map->thread_count += 1;
-
-   /* Cast the address of the search key to a pointer to a byte. */
-
-   search_key = (UINT8*) p_key;
-
-   /* Iterate linearly through the list searching for a matching key. */
-
-   p_element = p_map->p_head;
-   found     = FALSE;
-   while (p_element != NULL)
-      {
-      /* Cast the address of the key in the list element to a pointer to a
-       * byte.
-       */
-      test_key = (UINT8*) ((unsigned long) p_element + sizeof (MAP_LIST_HDR));
-
-      /* Search the key byte by byte from the rear forward.  This is done
-       * because it is assumed that the keys (network addresses) will have
-       * their unique octets right justified.  This is to make mismatches
-       * fail more quickly and therefore more efficiently.
-       */
-		index = p_map->key_length - 1;
-      found = TRUE;
-      while ((found) && (index >= 0))
-         {
-         if (search_key[index] != test_key[index])
-            found = FALSE;
-         index -= 1;
-         }
-
-      /* If a matching element has been found, stop the search. */
-
-      if (found)
-         break;
-
-      /* Go to the next element in the list. */
-
-      p_element = p_element->p_next;
-      }
-
-   if (found)
-      {
-      /* If a matching element was found, return the pointer to that element
-       * in the form of a handle.
-       */
-      *p_element_handle = (HANDLE) p_element;
-
-      /* If the found element is not on the head of the list, unlink it from
-       * its current location and place it at the head of the list.
-       */
-		if ((p_element != p_map->p_head) && (p_map->thread_count == 1))
-         {
-         unlink       (p_map, p_element);
-         link_to_head (p_map, p_element);
-         }
-
-      /* Return success status. */
-
-      p_map->thread_count -= 1;
-      return STATUS_K_SUCCESS;
-      }
-
-	/* If a matching element was not found, return error status. */
-
-   p_map->thread_count -= 1;
-   return STATUS_K_NOT_FOUND;
-   }
-
-
-/*++
-* =========================
-* = map_key_search_offset =
-* =========================
-*
-* Description:
-*   Linearly search the list for an element that has a key field that is
-*   identical to the provided search key.  If a matching element is found
-*   ensure that it is left on the head of the list.
-*
-* Issues:
-*   None
-*
---*/
-STATUS map_key_search_offset (HANDLE   list_handle,
-										void    *p_key,
-										UINT32   offset,
-										INT8     len,
-										HANDLE  *p_element_handle)
-	{
-	MAP_LIST       *p_map;
-	MAP_LIST_HDR   *p_element;
-	INT8            index;
-	UINT8          *search_key;
-	UINT8          *test_key;
-	BOOLEAN         found;
-
-	/* Obtain a pointer to a MAP_LIST descriptor from the list handle. */
-
-	p_map = (MAP_LIST*) list_handle;
-	p_map->thread_count += 1;
-
-	/* Cast the address of the search key to a pointer to a byte. */
-
-	search_key = (UINT8*) p_key;
-
-	/* Iterate linearly through the list searching for a matching key. */
-
-	p_element = p_map->p_head;
-	found     = FALSE;
-	while (p_element != NULL)
-		{
-		/* Cast the address of the key in the list element to a pointer to a
-		 * byte.
-		 */
-		test_key = (UINT8*) ((unsigned long) p_element +
-									 sizeof (MAP_LIST_HDR) +
-									 offset);
-
-		/* Search the key byte by byte from the rear forward.  This is done
-		 * because it is assumed that the keys (network addresses) will have
-		 * their unique octets right justified.  This is to make mismatches
-		 * fail more quickly and therefore more efficiently.
-		 */
-		index = len - 1;
-		found = TRUE;
-		while ((found) && (index >= 0))
-			{
-			if (search_key[index] != test_key[index])
-				found = FALSE;
-			index -= 1;
-			}
-
-		/* If a matching element has been found, stop the search. */
-
-		if (found)
-			break;
-
-		/* Go to the next element in the list. */
-
-		p_element = p_element->p_next;
-		}
-
-	if (found)
-		{
-		/* If a matching element was found, return the pointer to that element
-		 * in the form of a handle.
-		 */
-		*p_element_handle = (HANDLE) p_element;
-
-		/* If the found element is not on the head of the list, unlink it from
-		 * its current location and place it at the head of the list.
-		 */
-		if ((p_element != p_map->p_head) && (p_map->thread_count == 1))
-			{
-			unlink       (p_map, p_element);
-			link_to_head (p_map, p_element);
-			}
-
-		/* Return success status. */
-
-		p_map->thread_count -= 1;
-		return STATUS_K_SUCCESS;
-		}
-
-	/* If a matching element was not found, return error status. */
-
-	p_map->thread_count -= 1;
-	return STATUS_K_NOT_FOUND;
-	}
-
-/*++
-* =====================
-* = map_list_traverse =
-* =====================
-*
-* Description:
-*   Traverse the list and invoke a callback for each element of the list.
-*   If the callback returns BOOLEAN FALSE, stop traversing the list.
-*
-* Issues:
-*   The callback must not do a lookup on this list.  The reordering of the
-*   elements might lead to unpredictable behavior during traversal.
-*
---*/
-void map_list_traverse (HANDLE         list_handle,
-                        MAP_CALLBACK   traverse_callback,
-                        HANDLE         parameter)
-   {
-   MAP_LIST       *p_map;
-   MAP_LIST_HDR   *p_element, *p_save;
-   BOOLEAN         cont;
-
-   /* Obtain a pointer to a MAP_LIST descriptor from the list handle. */
-
-   p_map = (MAP_LIST*) list_handle;
-   p_map->thread_count += 1;
-
-   /* Traverse the list, calling the traverse_callback for each element. */
-
-   p_element = p_map->p_head;
-   while (p_element != NULL)
-      {
-      /* Save the next pointer before invoking the callback.  This is in
-       * case the callback deletes the element.
-       */
-      p_save = p_element->p_next;
-
-      /* If the callback returns FALSE, stop iterating through the list. */
-
-      cont = traverse_callback ((HANDLE) p_element, parameter);
-      if (!cont) break;
-
-      /* Go to the next element in the list. */
-
-      p_element = p_save;
-      }
-
-   p_map->thread_count -= 1;
-   }
-
-#define COMPARE_LT   1
-#define COMPARE_EQ   2
-#define COMPARE_GT   4
-#define COMPARE_LE   (COMPARE_LT | COMPARE_EQ)
-#define COMPARE_GE   (COMPARE_GT | COMPARE_EQ)
-
-static UINT32 compare_multiple (UINT8  *p_arg1,
-                                UINT8  *p_arg2,
-                                UINT8   key_length)
-   {
-   int      i;
-
-   for (i = 0; i < key_length; i++)
-      {
-      if (p_arg1[i] > p_arg2[i])
-         return COMPARE_GT;
-      if (p_arg1[i] < p_arg2[i])
-         return COMPARE_LT;
-      }
-   return COMPARE_EQ;
-   }
-
-
-/*++
-* =================
-* = map_get_first =
-* =================
-*
-* Description:
-*   If the list is empty, return NOT_FOUND.  Otherwise, find the entry with
-*   the lowest numerical key.
-*
-* Issues:
-*
---*/
-STATUS map_get_first (HANDLE   list_handle,
-                      HANDLE  *p_member_handle)
-   {
-   MAP_LIST       *p_map;
-   MAP_LIST_HDR   *p_element, *p_lowest;
-   UINT8           temp[MAX_KEY], *p_key;
-   int             i;
-
-   /* Obtain a pointer to a MAP_LIST descriptor from the list handle. */
-
-   p_map = (MAP_LIST*) list_handle;
-
-   /* Handle the case in which the list is empty. */
-
-   if (p_map->size == 0)
-      return STATUS_K_NOT_FOUND;
-
-   /* Set temporary key to greatest possible value. */
-
-   for (i = 0; i < MAX_KEY; i++)
-      temp[i] = 0xFF;
-
-   /* Initialize pointers for list traversal. */
-
-   p_element = p_map->p_head;
-   p_lowest  = p_element;
-
-   while (p_element != NULL)
-      {
-      p_key = (UINT8 *) ((unsigned long) p_element +
-                         sizeof (MAP_LIST_HDR));
-      if (compare_multiple (temp,
-                            p_key,
-                            p_map->key_length) & COMPARE_GT)
-         {
-         p_lowest = p_element;
-         utl_mem_copy (p_key, temp, p_map->key_length);
-         }
-
-      p_element = p_element->p_next;
-      }
-
-   *p_member_handle = (HANDLE) p_lowest;
-   return STATUS_K_SUCCESS;
-   }
-
-/*++
-* ================
-* = map_get_next =
-* ================
-*
-* Description:
-*   If the list is empty, return NOT_FOUND.  Otherwise, find the entry with
-*   the lowest numerical key which is greater than the supplied key.
-*
-* Issues:
-*
---*/
-STATUS map_get_next (HANDLE  list_handle,
-                     void   *p_key,
-                     HANDLE *p_member_handle)
-   {
-   MAP_LIST       *p_map;
-   MAP_LIST_HDR   *p_element, *p_lowest;
-   UINT8          *p_member_key;
-
-   /* Obtain a pointer to a MAP_LIST descriptor from the list handle. */
-
-   p_map = (MAP_LIST*) list_handle;
-
-   /* Handle the case in which the list is empty. */
-
-   if (p_map->size == 0)
-      return STATUS_K_NOT_FOUND;
-
-   /* Initialize pointers for list traversal. */
-
-   p_element = p_map->p_head;
-   p_lowest  = NULL;
-
-   /* Traverse the list looking for the next greater element. */
-
-   while (p_element != NULL)
-      {
-      p_member_key = (UINT8 *) ((unsigned long) p_element +
-                                 sizeof (MAP_LIST_HDR));
-      if (compare_multiple (p_member_key,
-                            p_key,
-                            p_map->key_length) & COMPARE_GT)
-         {
-         /* If we get here, we have an "eligible" entry which is greater
-          * than the supplied key.  Check to see if it's either the first
-          * eligible entry or less than the previous least.
-          */
-         if ((p_lowest == NULL) ||
-             (compare_multiple (p_member_key,
-                                (UINT8 *) ((unsigned long) p_lowest +
-                                           sizeof (MAP_LIST_HDR)),
-                                p_map->key_length) & COMPARE_LT))
-            {
-            p_lowest = p_element;
-            }
-         }
-
-      p_element = p_element->p_next;
-      }
-
-   if (p_lowest == NULL)
-      {
-      return STATUS_K_NOT_FOUND;
-      }
-   else
-      {
-      *p_member_handle = (HANDLE) p_lowest;
-      return STATUS_K_SUCCESS;
-      }
-   }
-
diff -ur --new-file old/atm/led/map.h new/atm/led/map.h
--- old/atm/led/map.h	Sun Jul  7 13:59:07 1996
+++ new/atm/led/map.h	Thu Jan  1 01:00:00 1970
@@ -1,446 +0,0 @@
-/*************************************************************************
-  (c) Copyright.  Digital Equipment Corporation, 1995.  All Rights
-  Reserved.
-
-  Permission is hereby granted to use, copy, modify, or enhance this 
-  software freely, as long as the foregoing copyright of Digital Equipment
-  Corporation and this notice are retained on the software.  This 
-  software may not be distributed or sublicensed for a fee.  Digital      
-  makes this software available "AS IS" and without warranties of any
-  kind.  
- *************************************************************************/
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Tampere University of Technology - Telecommunications Laboratory
- *
- * Permission to use, copy, modify and distribute this
- * software and its documentation is hereby granted,
- * provided that both the copyright notice and this
- * permission notice appear in all copies of the software,
- * derivative works or modified versions, and any portions
- * thereof, that both notices appear in supporting
- * documentation, and that the use of this software is
- * acknowledged in any publications resulting from using
- * the software.
- * 
- * TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
- * SOFTWARE.
- * 
- */
-
-/*
-* Module Name:
-*   map.h
-*   
-* Overview:
-*   This describes the interface to the Mapping Module.  This module provides
-*   a high-speed store and lookup function.  It contains only the details
-*   needed to perform the storage and lookup functions.  It is not concerned
-*   with the details of how they will be used.
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   17-Jan-95  TLR   Created.
-*   23-Jan-95  TLR   Updated with inputs from team review.
-*   22-Sep-95  TLR   Added get-first and get-next calls.
-*
-* Description:
-*   This module provides a general purpose storage and lookup service.  The
-*   user of this service must define a structure that contains the data fields
-*   to be stored.  The structure must conform to two requirements:
-*
-*       1. The first member of the structure must be of type MAP_LIST_HDR,
-*
-*       2. The second member of the structure must be the search key that will
-*          be used when searching the list.
-*
-*   The following is a template structure:
-*
-*       typedef struct
-*          {
-*          MAP_LIST_HDR     list_hdr;
-*          ADDR_ATM         addr;
-*          -- Additional storage elements go here.
-*          } LIST_ELEMENT;
-*
-*   In this example, the 'addr' member is used as a search key.  If the list
-*   is implemented as a hash table or an ordered list or tree, the search key
-*   is also used for element insertion.
-*
-*   The length of the key is specified for each allocated list at the time the
-*   list is allocated.
-*
-*   Note that in the function prototypes, a handle is used to refer to
-*   an element in the list.  This element is of the type defined above.
-*   The handle must be cast from a pointer to the element.  For example:
-*
-*       LIST_ELEMENT    *p_elt;
-*
-*       map_list_add (list1, (HANDLE) p_elt);
-*
-* Call Sequence Requirements:
-*   The only requirement is that for a given list, the map_list_alloc be called
-*   prior to any other call.
-*
-*   - map_list_alloc
-*     - map_list_add
-*     - map_list_delete
-*     - map_list_lookup
-*     - map_list_traverse
-*     - map_list_dealloc
-*
-*/
-
-/*************************************************************************
- * Types that are specific to this interface.                            *
- *************************************************************************/
-
-/* MAINTENANCE TIP
- *
- *  The following structure contains members that are specific to the list
- *  implementation.  They have to appear here due to shortcomings of the C
- *  programming language.  If the list implementation is changed, this
- *  structure must also be changed.
- */
-typedef struct _hdr
-   {
-   struct _hdr    *p_next;
-   struct _hdr    *p_prev;
-   } MAP_LIST_HDR;
-
-
-/*************************************************************************
- * Function Prototypes for this interface.                               *
- *************************************************************************/
-
-/*++
-* ================
-* = MAP_CALLBACK =
-* ================
-*
-* Overview:
-*   This is the function prototype for list callbacks.  There are cases in
-*   which list operations must make a callback for each member of the list.
-*
-* Arguments:
-*   element_handle    - (IN)  Handle that refers to a member of the list.
-*   parameter         - (IN)  General purpose handle provided by the caller.
-*
-* Returns:
-*   General purpose boolean flag.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-typedef BOOLEAN (*MAP_CALLBACK) (HANDLE element_handle,
-                                 HANDLE parameter);
-
-
-/*++
-* ==================
-* = map_list_alloc =
-* ==================
-*
-* Overview:
-*   Allocates an empty map list.
-*
-* Arguments:
-*   os_handle        - (IN)  Handle required by the utl_os module.
-*   key_length       - (IN)  Length in bytes of the search key for this list.
-*   p_list_handle    - (OUT) Map handle describing new map list.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - The list was successfully created.
-*   STATUS_K_RESOURCES  - There were insufficient resources to create the list.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   p_list_handle refers to an empty list.
---*/
-STATUS map_list_alloc (UINT8     key_length,
-                       HANDLE   *p_list_handle);
-
-
-/*++
-* ====================
-* = map_list_dealloc =
-* ====================
-*
-* Overview:
-*   Deallocates a map list.  For each member of the list, a callback is called
-*   which must properly delete and deallocate the stored element.
-*
-*   The boolean return value from the callback is ignored by this function.
-*
-* Arguments:
-*   list_handle         - (IN) Handle returned by map_list_alloc.
-*   destroy_callback    - (IN) Address of callback routine to destroy members
-*                              of the list.  If this callback address is NULL,
-*                              no callback will be invoked.
-*   parameter           - (IN) Generic parameter to be passed to the callback.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The map_handle is invalid.
---*/
-void map_list_dealloc (HANDLE          list_handle,
-                       MAP_CALLBACK    destroy_callback,
-                       HANDLE          parameter);
-
-
-/*++
-* ======================
-* = map_element_insert =
-* ======================
-*
-* Overview:
-*   Adds an element to a map list.
-*
-* Arguments:
-*   list_handle     - (IN)  Handle returned by map_list_alloc.
-*   member_handle   - (IN)  Handle of element to add.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   The new element is not a member of the list.
-*
-* Postconditions:
-*   The new element is a member of the list.   
---*/
-void map_element_insert (HANDLE    list_handle,
-                         HANDLE    member_handle);
-
-
-/*++
-* ======================
-* = map_element_delete =
-* ======================
-*
-* Overview:
-*   Deletes an element from a map list.  Note that this function does not
-*   destroy or deallocate anything, it simply removes an entry from the list.
-*
-* Arguments:
-*   list_handle     - (IN)  Handle returned by map_list_alloc.
-*   member_handle   - (IN)  Handle of element to be deleted.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   The element is a member of the list.
-*
-* Postconditions:
-*   The element is not a member of the list.
---*/
-void map_element_delete (HANDLE list_handle,
-                         HANDLE member_handle);
-
-
-/*++
-* =====================
-* = map_list_size_get =
-* =====================
-*
-* Overview:
-*   Returns the number of elements in the list.
-*
-* Arguments:
-*   list_handle     - (IN)  Handle returned by map_list_alloc.
-*
-* Returns:
-*   The list size in number of elements.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-UINT32 map_list_size_get (HANDLE list_handle);
-
-/*++
-* ==================
-* = map_key_search =
-* ==================
-*
-* Overview:
-*   Searches the list for an element containing a key.  If a matching element
-*   is found, the handle of that member is returned.
-*
-* Arguments:
-*   list_handle     - (IN)  Handle returned by map_list_alloc.
-*
-*   p_key           - (IN)  Pointer to the key to be searched for.  The length
-*                           of this key is the length that was
-*                           specified when the list was allocated.
-*
-*   p_member_handle - (OUT) If the search was successful, this is the handle
-*                           of the found member.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Search was successful, member handle is valid.
-*   STATUS_K_NOT_FOUND  - Search failed, member handle is not valid.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-STATUS map_key_search (HANDLE   list_handle,
-							  void    *p_key,
-							  HANDLE  *p_member_handle);
-
-/*++
-* =========================
-* = map_key_search_offset =
-* =========================
-*
-* Overview:
-*   Searches the list for an element containing a key.  If a matching element
-*   is found, the handle of that member is returned. This function is similar
-*   to map_key_search, the only difference being that in this function the
-*   offset and length into the structure to be searched is specified.
-*
-* Arguments:
-*   list_handle     - (IN)  Handle returned by map_list_alloc.
-*
-*   p_key           - (IN)  Pointer to the key to be searched for.  The length
-*                           of this key is the length that was
-*                           specified when the list was allocated.
-*	 offset          - (IN)  offset into the structure being searched.
-*	 len             - (IN)  Length of the key.
-*   p_member_handle - (OUT) If the search was successful, this is the handle
-*                           of the found member.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Search was successful, member handle is valid.
-*   STATUS_K_NOT_FOUND  - Search failed, member handle is not valid.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-
-STATUS map_key_search_offset (HANDLE   list_handle,
-										void    *p_key,
-										UINT32   offset,
-										INT8     len,
-										HANDLE  *p_member_handle);
-
-/*++
-* =====================
-* = map_list_traverse =
-* =====================
-*
-* Overview:
-*   Traverses an entire list, calling the callback for every element in the
-*   list.
-*
-*   For example, this function might be used to update an age timer in each
-*   member of a list.
-*
-*   The boolean return value from the callback is used to continue or stop the
-*   traversal.  If the return value is TRUE, the traversal continues.  If it is
-*   FALSE, the traversal stops.  This feature allows for a slow but general
-*   list search.  This might be useful if it is necessary to search with a key
-*   other than the specified search key.
-*
-*   Note that this routine provides a fast and efficient traversal of the list.
-*   The get-first/get-next traversal method may not be as efficient for some
-*   map list implementations.
-*
-* Arguments:
-*   list_handle         - (IN)  Handle returned by map_list_alloc.
-*   traverse_callback   - (IN)  Callback to be invoked for each member.
-*   parameter           - (IN)  Generic parameter to be passed to the callback.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-void map_list_traverse (HANDLE         list_handle,
-                        MAP_CALLBACK   traverse_callback,
-                        HANDLE         parameter);
-
-/*++
-* =================
-* = map_get_first =
-* =================
-*
-* Overview:
-*   Locate and return the handle of the "first" member of the map list.  The
-*   "first" element is defined to be the one with the numerically lowest key.
-*
-* Arguments:
-*   list_handle         - (IN)  Handle returned by map_list_alloc.
-*   p_member_handle     - (OUT) Handle of first member if found.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Successful completion, *p_member_handle is valid.
-*   STATUS_K_NOT_FOUND  - The list is empty and has no first member.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-STATUS map_get_first (HANDLE   list_handle,
-                      HANDLE  *p_member_handle);
-
-/*++
-* ================
-* = map_get_next =
-* ================
-*
-* Overview:
-*   Locate and return the handle of the "next" member of the map list.  The
-*   "next" element is defined to be the one with the key that is numerically
-*   closest to (and greater than) the provided key.
-*
-* Arguments:
-*   list_handle         - (IN)  Handle returned by map_list_alloc.
-*   p_member_handle     - (OUT) Handle of next member if found.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Successful completion, *p_member_handle is valid.
-*   STATUS_K_NOT_FOUND  - There is no "next" entry.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-STATUS map_get_next (HANDLE  list_handle,
-                     void   *p_key,
-                     HANDLE *p_member_handle);
-
-
diff -ur --new-file old/atm/led/map_data.h new/atm/led/map_data.h
--- old/atm/led/map_data.h	Sun Jul  7 13:59:08 1996
+++ new/atm/led/map_data.h	Thu Jan  1 01:00:00 1970
@@ -1,378 +0,0 @@
-/*************************************************************************
-  (c) Copyright.  Digital Equipment Corporation, 1995.  All Rights
-  Reserved.
-
-  Permission is hereby granted to use, copy, modify, or enhance this 
-  software freely, as long as the foregoing copyright of Digital Equipment
-  Corporation and this notice are retained on the software.  This 
-  software may not be distributed or sublicensed for a fee.  Digital      
-  makes this software available "AS IS" and without warranties of any
-  kind.  
- *************************************************************************/
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Tampere University of Technology - Telecommunications Laboratory
- *
- * Permission to use, copy, modify and distribute this
- * software and its documentation is hereby granted,
- * provided that both the copyright notice and this
- * permission notice appear in all copies of the software,
- * derivative works or modified versions, and any portions
- * thereof, that both notices appear in supporting
- * documentation, and that the use of this software is
- * acknowledged in any publications resulting from using
- * the software.
- * 
- * TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
- * SOFTWARE.
- * 
- */
-
-/*
-* Module Name:
-*   map_data.h
-*   
-* Overview:
-*   This file defines the records stored in the address to VC mapping.  It is
-*   concerned only with the VC and ATM lists.
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   16-Feb-95  TLR   Created.
-*   14-Oct-95  TLR   Updated VC_RECORD to handle buffer pools.
-*
-* Description:
-*
-*/
-
-/*************************************************************************
- * Types that are specific to this interface.                            *
- *************************************************************************/
-
-/* ESI_Status
- *
- *   This enumerated type lists the status values that are contained in
- *   48-bit address entries.
- *
- *      ESI_ARP_PENDING.....There is no ATM address associated with this
- *                          48-bit address.  The LE-ARP protocol is in
- *                          progress.
- *
- *      ESI_VC_PENDING......There is a valid ATM address associated with this
- *                          48-bit address but there is no VC set up to that
- *                          ATM address.  The signaling protocol is in process.
- *
- *      ESI_FLUSH_START.....There is a valid ATM address and VC associated
- *                          with this 48-bit address.  No packets have been
- *                          sent on this data direct VC for this address yet
- *                          so the LEC must initiate the flush protocol.
- *
- *      ESI_FLUSH_PENDING...The LEC has been notified of the FLUSH_START
- *                          status and it is assumed that the flush protocol is
- *                          in process.
- *
- *      ESI_FORWARD_DIRECT..Either the Path Switching Delay (C22) has elapsed
- *                          or the LEC has notified the Mapping that the flush
- *                          protocol has completed.  In either case, it is
- *                          safe to forward packets to this address via the
- *                          data direct VC.
- *
- *                          With regard to flushing, the LEC has the option of
- *                          participating in the flush protocol or simply
- *                          waiting until the Path Switching Delay elapses.
- *                          If the LEC chooses not to send a flush request,
- *                          the esi_status will transition from
- *                          ESI_FLUSH_PENDING to ESI_FORWARD_DIRECT
- *                          automatically after the delay has passed.
- */
-#ifndef MAP_DATA_H
-#define MAP_DATA_H
-#include "utl.h"
-
-typedef enum
-   {
-   ESI_UNKNOWN,
-   ESI_ARP_PENDING,
-   ESI_VC_PENDING,
-   ESI_FLUSH_PENDING,
-   ESI_FORWARD_DIRECT
-   } ESI_STATUS;
-
-/* ATM_Status
- *
- *   This enumerated type lists the ATM status values that are contained in
- *   ATM address entries.
- *
- *      ATM_NOVC........There is no VC associated with this ATM address and 
- *                      Signaling must be initiated in order to get a VC.
- *
- *      ATM_PENDING.....There is no VC associated with this ATM address and
- *                      Signaling is in the process of getting a VC for this
- *                      address.
- *
- *      ATM_VALID.......There is a valid and open VC associated with this
- *                      ATM address.
- *
- *      ATM_FAIL........Either the VC open failed or the SVC was released for
- *                      a reason other than "normal-unspecified".
- *
- */
-typedef enum {
-  ATM_NOVC,
-  ATM_PENDING,
-  ATM_VALID,
-  ATM_FAIL
-} ATM_STATUS;
-
-/* VC_Flags definitions
- *
- * The vc_flags field of the MAP_VC_RECORD has the following structure:
- *
- *      15                              6   5          3   2          0
- *    +-----------------------------------+--------------+--------------+
- *    |             FLAGS                 |  PHY_STATE   |  SVC_STATE   |
- *    +-----------------------------------+--------------+--------------+
- *
- * Both PHY_STATE and SVC_STATE can have the following values:
- *
- *    VC_STATE_CLOSED   - PHY: The driver has not been notified of the VC,
- *                        SVC: The signaling protocol has not begun or has
- *                             completed with a release.
- *
- *    VC_STATE_OPENING  - PHY: The driver has been given a vc_setup request
- *                             and the request is pending (i.e. the driver
- *                             has not yet called the vc_setup_cfm routine).
- *                        SVC: The signaling protocol is in progress.
- *
- *    VC_STATE_OPEN     - PHY: The VC is open at the driver.
- *                        SVC: The signaling protocol completed successfully.
- *
- *    VC_STATE_CLOSING  - PHY: The driver has been given a vc_teardown request
- *                             and the request if pending (i.e. the driver
- *                             has not yet called the vc_teardown_cfm routine).
- *                        SVC: <not used>
- *
- * The following flags are in the FLAGS field:
- *
- *    VC_FLAG_NOTIFICATION_REQUIRED - The bound NSAP client requires
- *                                    notification of completed VC setup or
- *                                    teardown/setup-failure.
- *
- *    VC_FLAG_VC_ID_PRESENT         - The vc_id field is valid for an SVC.
- *                                    This is used during the signaling
- *                                    protocol because the vc_id becomes known
- *                                    at differing points in the protocol
- *                                    exchange depending on the direction of
- *                                    the call and the implementation of the
- *                                    switch.
- *
- *    VC_FLAG_CALLING_PARTY         - This end-station is the calling party
- *                                    for an SVC.
- *
- *    VC_FLAG_PVC                   - The VC is a PVC (Permanent VC).
- *
- *    VC_FLAG_RVC                   - The VC is an RVC (Digital Resilient VC).
- *
- */
-
-#define VC_SVC_STATE_MASK  0x0007
-#define VC_PHY_STATE_MASK  0x0038
-
-#define VC_SVC_STATE(flags)   ((flags) & VC_SVC_STATE_MASK)
-#define VC_PHY_STATE(flags)  (((flags) & VC_PHY_STATE_MASK) >> 3)
-
-#define VC_SVC_STATE_SET(flags, state)                \
-    {                                                 \
-    (flags) = ((flags) & ~VC_SVC_STATE_MASK) | state; \
-    }
-
-#define VC_PHY_STATE_SET(flags, state)                       \
-    {                                                        \
-    (flags) = ((flags) & ~VC_PHY_STATE_MASK) | (state << 3); \
-    }
-
-#define VC_FLAGS_INIT      (0x0000 | VC_STATE_CLOSED | (VC_STATE_CLOSED << 3))
-
-#define VC_STATE_CLOSED    1
-#define VC_STATE_OPENING   2
-#define VC_STATE_OPEN      3
-#define VC_STATE_CLOSING   4
-#define VC_STATE_FAIL      5
-
-#define VC_FLAG_NOTIFICATION_REQUIRED  0x0040
-#define VC_FLAG_VC_ID_PRESENT          0x0080
-#define VC_FLAG_CALLING_PARTY          0x0100
-#define VC_FLAG_PVC                    0x0200
-#define VC_FLAG_RVC                    0x0400
-
-#define VC_CALLING_PARTY(flags) \
-   ((BOOLEAN) ((flags & VC_FLAG_CALLING_PARTY) ? TRUE : FALSE))
-
-typedef struct _handle
-   {
-   struct _handle *p_next;
-   HANDLE          handle;
-   } HANDLE_RECORD;
-
-SIMPLE_LIST (HANDLE_RECORD, HANDLE_LIST);
-
-/* MAP_VC_RECORD
- *
- *   This structure is the user-visible part of a Virtual Channel entry.
- *   The VC table is composed of a list of these structures.
- *
- *   vc_id.............The VC_ID of the Virtual Channel.  This is an
- *                     opaque type which represents a VCI and a VPI
- *                     value to be used on the network.  VC_IDs are
- *                     supplied by the signaling module and are used
- *                     by the adapter hardware to derive a VCI and VPI.
- *
- *   conn_id...........The connection ID of the VC.  This is the handle
- *                     used by the Signaling stack to uniquely identify VCs.
- *                     This handle is generated by the Signaling module.
- *
- *   vc_status.........The current status of this VC.  See the above
- *                     definition of the VC_STATUS type for the possible
- *                     values.
- *
- *   xmt_queue.........The transmit queue identifier specifies which
- *                     transmit queue to use when transmitting data
- *                     on this VC.  It is assumed that ATM adapters
- *                     generally support multiple transmit and receive
- *                     queues.
- *
- *   rcv_queue.........The receive queue identifier specifies which
- *                     receive queue to use when data is received
- *                     on this VC.
- *
- *   sap_handle........Each VC must be bound to a Service Access Point
- *                     (SAP).  This value contains the binding for this
- *                     VC entry.  The sap_handle is generated by the
- *                     Connection Manager.
- *
- *                     When a packet is received, its VC_ID is looked
- *                     up in the VC tables.  Once the VC_ID is found,
- *                     this sap_handle is used to forward the packet
- *                     up to the next higher level.
- *
- *   map_lec_handle....This handle identifies the LEC entry in the mapping
- *                     that is associated with this VC.  This handle is
- *                     generated by the Mapping module.
- *
- *   conn_context......When a SAP creates a VC, it supplies a connection
- *                     context.  This context is then passed up to the SAP
- *                     along with every packet received on the VC.
- *
- *   requested_params..When a VC is opened, parameters are requested for
- *                     that VC.  This field contains the parameters that
- *                     were originally requested for this VC.
- *
- *   actual_params.....Because of numerical resolution issues and
- *                     variance in the availability of network
- *                     resources, the actual parameters granted to a VC
- *                     may be somewhat different from those requested.
- *                     This field contains the actual parameters that the
- *                     VC is operating with.
- *
- *   permanent_flag....This boolean flag is set if this is an SVC and it is
- *                     not to be removed to make room for opening SVCs.
- *
- *   xmt_packet_count..Number of Packets transmitted on this VC since it
- *                     was opened.
- *
- *   rcv_packet_count..Number of Packets received on this VC since it was
- *                     opened.
- */
-typedef struct
-   {
-   MAP_LIST_HDR   hdr;
-   UINT32         vc_id;
-   CALL_ID        call_provider_id;
-   CALL_ID        call_user_id;
-   UINT16         vc_flags;
-   HANDLE         xmt_pool_context;
-   HANDLE         rcv_pool_context;
-   HANDLE         sap_handle;
-   HANDLE         conn_context;
-   HANDLE         atm_link;
-   HANDLE         spare;
-   ADDR_ATM       calling_party;        /* See ATMF sec 8.1.11 */
-   UINT32         xmt_packet_count;
-   UINT32         rcv_packet_count;
-   QOS            requested_qos;
-   QOS            actual_qos;
-   UINT32         idle_time;
-   UINT32         age_limit;
-   } MAP_VC_RECORD;
-
-/* MAP_ATM_RECORD
- *
- *   This structure is the user-visible part of an ATM address entry.
- *   The ATM address table is composed of lists of these structures.
- */
-typedef struct
-   {
-   MAP_LIST_HDR   hdr;
-   ADDR_ATM       addr;
-   ATM_STATUS     atm_status;
-   HANDLE         active_vc_link;
-   HANDLE_LIST    vc_link_list;
-   HANDLE_LIST    esi_link_list;
-   } MAP_ATM_RECORD;
-
-/* AGE_REF
- *
- *  Age Reference.  This structure refers to a 48-bit address record, may be
- *  stored in a doubly linked list, and contains fields needed for the arp
- *  refresh and retry event queues.
- *
- *  p_event_queue   - Pointer to the event queue in which this strucure is
- *                    stored.  If this is not an element in an event queue,
- *                    this pointer MUST be NULL.  This pointer is used when
- *                    age references are unlinked from event queues.  It is
- *                    critical that the age reference be removed from the
- *                    queue of which it is a member.
- *
- *  delta_time      - Delta time used to schedule this age event in the event
- *                    queue.  It signifies how long after the previous event
- *                    this event is to be scheduled.
- *
- *  arp_retries     - Number of times an arp retry has been attempted on
- *                    behalf of this 48-bit address.  This is used to limit
- *                    the number of retries that will be attempted.
- */
-typedef struct age_ref
-   {
-   struct age_ref      *p_next;
-   struct age_ref      *p_prev;
-   struct event_tag    *p_event_queue;
-   HANDLE               esi_handle;
-   UINT32               delta_time;
-   UINT8                arp_retries;
-   } AGE_REF;
-
-typedef struct
-   {
-   MAP_LIST_HDR   hdr;
-   ESI            esi;
-   ESI_STATUS     esi_status;
-   HANDLE         atm_link;
-   HANDLE         vc_link;
-   HANDLE         la_elan_handle;
-   AGE_REF       *p_age_ref;
-   BOOLEAN        remote_flag;
-   BOOLEAN        permanent_entry;
-   UINT32         arp_age;
-   UINT32         use_age;
-   UINT32         flush_tran_id;
-   UINT16         tick_count;
-   UINT16         packets_flooded;
-   } MAP_ESI_RECORD;
-
-#endif /* MAP_DATA_H */
diff -ur --new-file old/atm/led/svc_info.h new/atm/led/svc_info.h
--- old/atm/led/svc_info.h	Sun Jul  7 13:59:08 1996
+++ new/atm/led/svc_info.h	Thu Aug  8 20:50:30 1996
@@ -43,14 +43,8 @@
 *  JAD - John A. DeNisco
 *
 * Modification History:
-*  Date       Name  Description 
-*  26-Jan-95  JAD   Created.
-*  21-Feb-95  JAD   Use trillium definitions directly.
 *
 * Description:
-*  Generally the svc_info structures are used, to pass information to and
-*  from the connection manager and the svc interface. The svc interface is
-*  found in the modules svc_cm.h and cm_svc.h.
 *
 */
 #ifndef SVC_INFO_H
@@ -58,45 +52,10 @@
 
 #include <linux/atm.h>
 
-/* General constants */
-
-#define SVC_SIZE_STRING_MED              32    /* token string size - medium */
-#define SVC_ELEMENT_REPEAT_MAX            2    /* maximum repeated elements  */
-#define REL_LOC_USER                      0    /* ref: 5.4.5.15 UNI 3.0      */
-
 /* Cause Values */
 
-#define CAUSE_RESOURCE_UNAVAIL           47
 #define CAUSE_NORMAL                     31
 
-/* Event Values */
-
-#define EVENT_CALL_PROCEEDING             0
-#define EVENT_CONN_ACK                    2
-#define EVENT_UNKNOWN                     9
-
-/* The following definitions describe error conditions in the CM that result */
-/* in connection releases.  These values are used as input to                */
-/* "svc_release_info_make". These values can not conflict with the cause     */
-/* values in the UNI specification 5.4.5.15.                                 */
-
-#define RECORD_NOT_FOUND_ON_STATUS_IND    (0x01 | 0x8000)
-#define CONN_ID_MISSING                   (0x02 | 0x8000)
-#define RECORD_NOT_FOUND_ON_CONN_CFM      (0x03 | 0x8000)
-#define RECORD_NOT_FOUND_ON_REL_IND       (0x04 | 0x8000)
-#define REJECT_SAP_MISMATCH               (0x05 | 0x8000)
-#define CAUSE_QOS_CHECK_FAIL              (0x06 | 0x8000)
-#define CONN_RSP_CALL_FAILED              (0x07 | 0x8000)
-
-/* Type definitions */
-
-typedef unsigned char EVENT_TYPE;
-typedef long CALL_ID;
-typedef short RST_REASON;
-typedef long PORT_NUMBER;
-
-/* Redefine some trilllium definitions the svc module needs */
-
 /*++
  * CONN_INFO
  *
@@ -110,37 +69,6 @@
   struct atm_qos conqos;
 } CONN_INFO;
 
-
-/*++
- * CONN_STATUS
- *
- * This structure contains status related to a virtual connection.
- *
- --*/
-typedef struct {
-  int status;
-} CONN_STATUS;
-
-
-/*++
- * RELEASE_INFO
- *
- *  Information used to release a virtual connection.
- *
- --*/
-typedef int RELEASE_INFO;
-
-
-/*++
- * DROP_PTY_INFO
- *
- *  Information used for a drop party from a virtual connection.
- *
- --*/
-typedef int DROP_PTY_INFO;
-
-
-
 /*++
  * =====================
  * = svcinit_conn_info =
@@ -160,30 +88,13 @@
  * None
  *
  --*/
-
 void svcinit_conn_info (CONN_INFO *p_svc_conn_info);
 
-/*++
- * ==========================
- * = svc_release_info_make =
- * ==========================
- *
- * Overview:
- *  This function generates a RELEASE_INFO block appropriate to the indicated
- *  error condition.
- *
- * Arguments:
- *
- *  code           - Error Code.
- *  p_release_info - Pointer to the release information structure.
- *
- * Returns:
- *
- *  None
- *
- --*/
-
-void svc_release_info_make (int           code,
-                            RELEASE_INFO *p_release_info);
 
 #endif /* SVC_INFO_H */
+
+
+
+
+
+
diff -ur --new-file old/atm/led/timers.c new/atm/led/timers.c
--- old/atm/led/timers.c	Sun Jul  7 13:59:08 1996
+++ new/atm/led/timers.c	Tue Aug  6 16:33:07 1996
@@ -26,7 +26,7 @@
  * Timer creation, setting and allocation. Protypes defined in
  * utl_os.h
  *
- * $Id: timers.c,v 1.8 1996/07/07 11:51:47 carnil Exp carnil $
+ * $Id: timers.c,v 1.9 1996/08/06 14:14:11 carnil Exp carnil $
  *
  */
 
@@ -241,9 +241,25 @@
     to_call->callback(to_call->context);
 }
 
+void 
+timer_usage(void)
+{
+  Timer_t *tmp;
+
+  printf("Timer usage:\n");
+  for(tmp=timerlist;tmp;tmp=tmp->next)
+    printf("\tCallback %p Context:%p %d sec %d usec\n",
+	   tmp->callback, tmp->context, 
+	   tmp->alarm_time?tmp->alarm_time->tv_sec:0,
+	   tmp->alarm_time?tmp->alarm_time->tv_usec:0);
+}
+
 /*
  *
  * $Log: timers.c,v $
+ * Revision 1.9  1996/08/06 14:14:11  carnil
+ * Cleaning up
+ *
  * Revision 1.8  1996/07/07 11:51:47  carnil
  * Global_msgmask
  *
diff -ur --new-file old/atm/led/timers.h new/atm/led/timers.h
--- old/atm/led/timers.h	Sun Jul  7 13:59:08 1996
+++ new/atm/led/timers.h	Tue Aug  6 16:33:08 1996
@@ -24,7 +24,7 @@
 /*
  * Include file for timer funcs not used in DIGITAL's code
  *
- * $Id: timers.h,v 1.2 1996/04/25 19:42:13 carnil Exp carnil $
+ * $Id: timers.h,v 1.3 1996/08/06 14:14:11 carnil Exp carnil $
  *
  */
 /* Global includes */
@@ -36,10 +36,13 @@
 void timer_call_callback(HANDLE timer_handle);
 struct timeval* timer_get_expiration(HANDLE timer_handle);
 HANDLE timer_find_soonest(void);
-
+void timer_usage(void);
 /*
  *
  * $Log: timers.h,v $
+ * Revision 1.3  1996/08/06 14:14:11  carnil
+ * Cleaning up
+ *
  * Revision 1.2  1996/04/25 19:42:13  carnil
  * Copyright notice
  *
diff -ur --new-file old/atm/led/utils.c new/atm/led/utils.c
--- old/atm/led/utils.c	Sun Jul  7 13:59:08 1996
+++ new/atm/led/utils.c	Tue Aug 20 13:44:01 1996
@@ -26,7 +26,7 @@
  * Utility functions which are used, but not defined in DIGITAL's 
  * code are defined here.
  *
- * $Id: utils.c,v 1.6 1996/07/07 11:51:47 carnil Exp carnil $
+ * $Id: utils.c,v 1.7 1996/08/06 14:14:11 carnil Exp carnil $
  *
  */
 
@@ -37,7 +37,6 @@
 /* Digital includes */
 #include "utl.h"
 #include "utl_os.h"
-#include "line_up.h"
 #include "codes.h"
 #include "g_event.h"
 
@@ -55,41 +54,16 @@
 
 static MemList_t *memlist = NULL;
 
-void 
-utl_mem_zero (void *p_buf, int size)
-{
-  memset(p_buf,0,size);
-}
-
-void 
-utl_mem_copy (void *p_from, void *p_to, int size)
-{
-  memcpy(p_to, p_from, size);
-}
-
-void
-os_buff_hdr_copy (void *p_pkt, UINT32 pkt_len, void *p_dst,
-		  UINT32  dst_len, UINT32 *p_bytes_copied)
-{
-  memcpy(p_dst, p_pkt, pkt_len>dst_len?dst_len:pkt_len);
-  *p_bytes_copied = pkt_len>dst_len?dst_len:pkt_len;
-}
-
 void*
 os_mem_alloc(UINT32 size)
 {
-  void *memory;
-
-  memory = malloc(size);
-  if (memory)
-    memset(memory,0,size);
-  return memory;
+  return(mem_alloc("utils.c",size));
 }
 
 void 
 os_mem_dealloc(void *p_mem)
 {
-  (void)free(p_mem);
+  mem_free("utils.c", p_mem);
 }
 
 void*
@@ -105,8 +79,8 @@
   tmp->unit[strlen(unit)] = '\0';
   tmp->next = memlist;
   memlist = tmp;
-  EVENT(EM_DEBUG,("Unit %s allocates %ld bytes of memory from 0x%lx\n",
-		  unit, nbytes, (unsigned long)tmp->mem));
+  EVENT(EM_MEM,("Unit %s allocates %ld bytes of memory from 0x%lx\n",
+		unit, nbytes, (unsigned long)tmp->mem));
   return tmp->mem;
 
 }
@@ -116,7 +90,7 @@
 {
   MemList_t *tmp, *prev = NULL;
  
-  EVENT(EM_DEBUG, ("Unit %s frees ptr 0x%lx\n", unit, (unsigned long)mem));
+  EVENT(EM_MEM, ("Unit %s frees ptr 0x%lx\n", unit, (unsigned long)mem));
 
   for (tmp = memlist; tmp != NULL; prev = tmp, tmp = tmp->next) {
     if (tmp->mem == mem) {
@@ -126,7 +100,7 @@
   /* Found a match? */
   if (tmp) {
     if (strcmp(tmp->unit, unit) != 0) {
-      EVENT(EM_DEBUG,
+      EVENT(EM_MEM,
 	    ("Unit %s frees ptr 0x%lx size %d allocated by unit %s\n",
 	     unit, (unsigned long)tmp->mem, tmp->memsize, 
 	     tmp->unit));
@@ -137,25 +111,34 @@
     if (prev != NULL) {
       prev->next = tmp->next;
     }
+    free(tmp->unit);
     free(tmp->mem);
     free(tmp);
   }
   else {
-    EVENT(EM_DEBUG, ("could not find block 0x%lx for freeing\n", 
-		     (unsigned long)mem));
+    EVENT(EM_MEM, ("could not find block 0x%lx for freeing\n", 
+		   (unsigned long)mem));
   }
 }
 
-STATUS 
-line_up_uni_version_get (HANDLE  line_up_handle, UINT8  *p_uni_version)
+void
+mem_usage(void)
 {
-  *p_uni_version  = UNI_3_1;
-  return STATUS_K_SUCCESS;
-}
+  MemList_t *tmp;
 
+  tmp = memlist;
+  
+  printf("Memory usage:\n");
+  for(tmp=memlist;tmp;tmp=tmp->next) {
+    printf("\t%20s\t:%p %6d bytes\n",tmp->unit, tmp->mem, tmp->memsize);
+  }
+}
 /*
  *
  * $Log: utils.c,v $
+ * Revision 1.7  1996/08/06 14:14:11  carnil
+ * Malloc changed to mem_alloc
+ *
  * Revision 1.6  1996/07/07 11:51:47  carnil
  * Global_msgmask
  *
diff -ur --new-file old/atm/led/utl.h new/atm/led/utl.h
--- old/atm/led/utl.h	Sun Jul  7 13:59:08 1996
+++ new/atm/led/utl.h	Tue Aug 20 11:37:27 1996
@@ -490,56 +490,4 @@
       }                                         \
    }
 
-/*++
-* ================
-* = utl_mem_zero =
-* ================
-*
-* Overview:
-*   Clears all bytes of a virtually contiguous buffer to zero.
-*
-* Arguments:
-*   p_buf      - (IN)  Pointer to a memory buffer.
-*   size       - (IN)  Number of bytes in the buffer to be zeroed.
-* 
-* Returns:
-*   None
-*
-* Preconditions:
-*   There are at least 'size' bytes allocated to the buffer.
-*
-* Postconditions:
-*   The first 'size' bytes of the buffer are zero.
---*/
-void utl_mem_zero (void  *p_buf,
-                   int    size);
-
-
-/*++
-* ================
-* = utl_mem_copy =
-* ================
-*
-* Overview:
-*   Copies the indicated number of bytes from one buffer to another.
-*
-* Arguments:
-*   p_from     - (IN)  Pointer to the source memory buffer.
-*   p_to       - (IN)  Pointer to the destination memory buffer.
-*   size       - (IN)  Number of bytes in the buffer to be copied.
-* 
-* Returns:
-*   None
-*
-* Preconditions:
-*   There are at least 'size' bytes allocated to both buffers.
-*
-* Postconditions:
-*   The first 'size' bytes of the two buffers are identical to the input
-*   value of the source buffer.
---*/
-void utl_mem_copy (void  *p_from,
-                   void  *p_to,
-                   int    size);
-
 
diff -ur --new-file old/atm/led/utl_os.h new/atm/led/utl_os.h
--- old/atm/led/utl_os.h	Sun Jul  7 13:59:08 1996
+++ new/atm/led/utl_os.h	Tue Aug 20 13:43:53 1996
@@ -285,54 +285,7 @@
 
 void os_mem_dealloc (void   *p_mem);
 
-/*++
-* ====================
-* = os_buff_hdr_copy =
-* ====================
-*
-* Overview:
-*   Copies the specified packet (whose internal format is not known to the
-*   common code) to the specified buffer.  If the packet is larger than the 
-*   destination buffer, then only the part of the packet which fits is 
-*   copied.  The actual number of bytes copied is returned.  If the packet is
-*   corrupt, than the value returned for the number of bytes copied is 0.
-*
-*   The caller can determine that the entire 
-*
-* Arguments:
-*   p_pkt          - (IN) A pointer to the packet to copy.
-* 
-*   pkt_len        - (IN)  Number of bytes in the buffer pointed to by p_pkt.
-*                          This argument may be ignored for implementations
-*                          whose packet structure contains the packet length.
-*                          Note that callers must always provide this value.
-*
-*   p_dst          - (OUT) Pointer to the destination buffer.
-*
-*   dst_len        - (IN)  Number of bytes in the buffer pointed to by p_dst.
-*
-*   p_bytes_copied - (OUT) Number of bytes copied to p_dst.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   - p_bytes_copied has the number of bytes copied
-*   - p_bytes_copied is <= dst_len
-*   - p_bytes_copied == 0 if the pkt length is '0' or the packet is corrupt.
-*   - p_dst contains the bytes copied from the packet.
---*/
-
-void os_buff_hdr_copy (void   *p_pkt,
-                       UINT32  pkt_len,
-                       void   *p_dst,
-                       UINT32  dst_len,
-                       UINT32 *p_bytes_copied);
-
 void* mem_alloc(const char *unit, unsigned long nbytes);
 void mem_free(const char *unit, const void *mem);
-
+void mem_usage(void);
 #endif
diff -ur --new-file old/atm/mkdist new/atm/mkdist
--- old/atm/mkdist	Wed Jul 31 19:26:08 1996
+++ new/atm/mkdist	Thu Aug 29 16:20:32 1996
@@ -1,7 +1,7 @@
 #!/bin/sh
 [ -r ./VERSION ] || exit 1
 VERSION=`cat ./VERSION`
-SRCDIR=$HOME/k/200
+SRCDIR=$HOME/k/2014
 ARCHDIR=$HOME/l/arch
 (
     cd $SRCDIR
@@ -21,7 +21,8 @@
   atm/sigd/Makefile atm/sigd/atmsigd.c atm/sigd/cfg.l atm/sigd/cfg.y \
     atm/sigd/io.h atm/sigd/io.c atm/sigd/kernel.c atm/sigd/proto.h \
     atm/sigd/proto.c atm/sigd/q2931.c atm/sigd/timeout.c atm/sigd/timeout.h \
-    atm/sigd/sap.h atm/sigd/sap.c atm/sigd/mkmess.pl \
+    atm/sigd/sap.h atm/sigd/sap.c atm/sigd/trace.c atm/sigd/trace.h \
+    atm/sigd/mkmess.pl \
   atm/saal/Makefile atm/saal/saal.h atm/saal/saal.c atm/saal/sscf.h \
     atm/saal/sscf.c atm/saal/sscop.h atm/saal/sscop.c \
   atm/qgen/TODO atm/qgen/Makefile atm/qgen/common.h \
@@ -68,14 +69,26 @@
     atm/lib/timer.c atm/lib/arequipa.h atm/lib/arequipa.c \
   atm/led/USAGE atm/led/COPYRIGHT.DEC atm/led/COPYRIGHT.TUT \
     atm/led/lec.h atm/led/lec_arp.h atm/led/lec_ctrl.h atm/led/emask.h \
-    atm/led/lec_mgt.h atm/led/map.h atm/led/le_disp.h atm/led/g_event.h \
+    atm/led/le_disp.h atm/led/g_event.h \
     atm/led/addr_reg.h atm/led/af_lane.h atm/led/atm.h atm/led/cm.h \
     atm/led/cm_sap.h atm/led/codes.h atm/led/g_endian.h atm/led/g_types.h \
-    atm/led/line_up.h atm/led/map_data.h atm/led/svc_info.h atm/led/system.h \
+    atm/led/svc_info.h atm/led/system.h \
     atm/led/utl.h atm/led/utl_os.h atm/led/timers.h atm/led/kernel_itf.h \
-    atm/led/conn.h atm/led/lec_arp.c atm/led/lec_ctrl.c atm/led/map.c \
+    atm/led/conn.h atm/led/lec_arp.c atm/led/lec_ctrl.c \
     atm/led/le_disp.c atm/led/g_event.c atm/led/utils.c atm/led/timers.c \
     atm/led/address.c atm/led/conn.c atm/led/main.c atm/led/kernel_itf.c \
     atm/led/Makefile \
+  atm/lane/COPYRIGHT.TUT atm/lane/Makefile atm/lane/USAGE atm/lane/atm.c \
+    atm/lane/atm.h atm/lane/atm_lecs.c atm/lane/atm_lecs.h \
+    atm/lane/connect.c atm/lane/connect.h atm/lane/connect_bus.c \
+    atm/lane/db.c atm/lane/db.h atm/lane/dump.c atm/lane/dump.h \
+    atm/lane/events.c atm/lane/events.h atm/lane/lane.c atm/lane/lane.h \
+    atm/lane/ldb.c atm/lane/ldb.h atm/lane/lecs.c atm/lane/lecs.h \
+    atm/lane/lecs_db.h atm/lane/lecs_db.h atm/lane/lecs_db.l \
+    atm/lane/lecs_load.c atm/lane/lecs_load.h atm/lane/load.c atm/lane/load.h \
+    atm/lane/load_lex.h atm/lane/load_lex.l atm/lane/mem.c atm/lane/mem.h \
+    atm/lane/mem_lecs.c atm/lane/mem_lecs.h atm/lane/packet.c \
+    atm/lane/packet.h atm/lane/timers.h atm/lane/timers.c atm/lane/units.c \
+    atm/lane/units.h \
   atm/aqd/Makefile atm/aqd/arequipad.c atm/aqd/io.h atm/aqd/io.c \
   atm/atm.patch | gzip -9 >$ARCHDIR/atm-$VERSION.tar.gz
diff -ur --new-file old/atm/qgen/Makefile new/atm/qgen/Makefile
--- old/atm/qgen/Makefile	Fri Jul 26 12:14:25 1996
+++ new/atm/qgen/Makefile	Thu Aug 29 13:40:34 1996
@@ -1,7 +1,7 @@
 LIBS=-lfl # lex may want  -ll  here
 OBJS=common.o file.o first.o lex.yy.o qgen.o second.o third.o y.tab.o
 TRASH=q.out.h q.out.c qd.out.c qd.dump.c
-PGMS=qgen q.out.o #qtest
+PGMS=qgen q.out.o qd.dump.o #qtest
 
 include ../Rules.make
 
@@ -27,7 +27,11 @@
 				$(CC) $(CFLAGS) -o q.test $(STANDARDS) q.test.c
 
 q.dump:				qd.dump.c qd.out.c qlib.h qlib.c
-				$(CC) $(CFLAGS) -o q.dump $(STANDARDS) qd.dump.c
+				$(CC) $(CFLAGS) -DSTANDALONE -o q.dump \
+				  $(STANDARDS) qd.dump.c
+
+qd.dump.o:			qd.dump.c qd.out.c qlib.h qlib.c
+				$(CC) $(CFLAGS) -c $(STANDARDS) qd.dump.c
 
 qtest:				q.test
 				./q.test
diff -ur --new-file old/atm/qgen/qlib.c new/atm/qgen/qlib.c
--- old/atm/qgen/qlib.c	Tue Jul 30 23:05:04 1996
+++ new/atm/qgen/qlib.c	Thu Aug 29 13:42:45 1996
@@ -3,10 +3,14 @@
 /* Written 1995,1996 by Werner Almesberger, EPFL-LRC */
  
 
+#ifdef DUMP_MODE
+static int q_dump = 0;
+#else
 int q_dump = 0;
+#endif
 
 
-#ifdef DUMP_MODE
+#ifdef STANDALONE
 
 #include <stdarg.h>
 #include <stdio.h>
@@ -100,26 +104,6 @@
 }
 
 
-#if 0
-static void q_put(unsigned char *table,int pos,int size,unsigned long value)
-{
-    unsigned char *byte;
- 
-    byte = &table[pos >>3];
-    if (pos & 7) {
-	*byte++ |= value << (pos & 7);
-	value >>= 8-(pos & 7);
-	size -= 8-(pos & 7);
-    }
-    while (size > 0) {
-	size -= 8;
-	*byte++ |= value;
-	value >>= 8;
-    }
-}
-#endif
- 
-
 static void q_copy(unsigned char *src,int pos,unsigned char *dst,int size)
 {
     src += pos >> 3;
@@ -139,7 +123,7 @@
 }
 
 
-void q_start(void)
+void PREFIX(start)(void)
 {
     q_init_global();
 }
@@ -189,6 +173,8 @@
 }
 
 
+#ifndef DUMP_MODE
+
 static void use_group(Q_DSC *dsc,int group)
 {
     int *scan;
@@ -311,6 +297,8 @@
     return len;
 }
 
+#endif
+
 
 #define LENGTH_STACK 10
 
@@ -606,7 +594,7 @@
 }
 
 
-int q_open(Q_DSC *dsc,void *buf,int size)
+int PREFIX(open)(Q_DSC *dsc,void *buf,int size)
 {
     dsc->buffer = NULL;
     q_init(dsc);
@@ -614,6 +602,8 @@
 }
 
 
+#ifndef DUMP_MODE
+
 int q_create(Q_DSC *dsc,void *buf,int size)
 {
    dsc->buffer = buf;
@@ -622,8 +612,10 @@
    return 0;
 }
 
+#endif
+
 
-int q_close(Q_DSC *dsc)
+int PREFIX(close)(Q_DSC *dsc)
 {
     int size;
 
@@ -638,7 +630,7 @@
 }
 
 
-#ifdef DUMP_MODE
+#ifdef STANDALONE
 
 int main(int argc,const char **argv)
 {
@@ -649,7 +641,9 @@
     debug = argc != 1;
     len = 0;
     while (scanf("%x",&c) == 1) msg[len++] = c;
-    q_open(&dsc,msg,len);
+    qd_start();
+    qd_open(&dsc,msg,len);
+    qd_close(&dsc);
     return 0;
 }
 
diff -ur --new-file old/atm/qgen/qlib.h new/atm/qgen/qlib.h
--- old/atm/qgen/qlib.h	Wed Mar  6 18:39:00 1996
+++ new/atm/qgen/qlib.h	Thu Aug 29 13:31:05 1996
@@ -5,7 +5,13 @@
  
 #ifndef QLIB_H
 #define QLIB_H
- 
+
+#ifdef DUMP_MODE
+#define PREFIX(x) qd_##x
+#else
+#define PREFIX(x) q_##x
+#endif
+
 
 #include "q.out.h"
 
@@ -36,10 +42,10 @@
 } Q_DSC;
  
  
-void q_start(void);
-int q_open(Q_DSC *dsc,void *buf,int size);
+void PREFIX(start)(void);
+int PREFIX(open)(Q_DSC *dsc,void *buf,int size);
 int q_create(Q_DSC *dsc,void *buf,int size);
-int q_close(Q_DSC *dsc);
+int PREFIX(close)(Q_DSC *dsc);
 
 void q_assign(Q_DSC *dsc,int field,unsigned long value);
 void q_write(Q_DSC *dsc,int field,const void *buf,int size);
diff -ur --new-file old/atm/qgen/uni3x new/atm/qgen/uni3x
--- old/atm/qgen/uni3x	Tue Jun  4 19:23:35 1996
+++ new/atm/qgen/uni3x	Wed Jul 31 19:51:22 1996
@@ -125,7 +125,7 @@
     ITU_STD_HDR {
 	_ext <1@8,more> = 1
 	hli_type <7@1> = case {
-# Note: can't use ATM_HL_* here, because those values are incremented by one
+# Note: cannot use ATM_HL_* here, because those values are incremented by one
 	    0 { # ISO
 		iso_hli <-64>
 	    }
diff -ur --new-file old/atm/sigd/Makefile new/atm/sigd/Makefile
--- old/atm/sigd/Makefile	Wed Jul 31 14:40:52 1996
+++ new/atm/sigd/Makefile	Thu Aug 29 14:01:08 1996
@@ -1,9 +1,9 @@
 LIBS=-L../saal -lsaal -latmd -lfl # lex may want  -ll  here
 INCLUDES=-I../qgen -I../saal -I.
-OBJS=atmsigd.o io.o kernel.o mess.o proto.o q2931.o sap.o timeout.o q.out.o \
-  lex.yy.o y.tab.o
+OBJS=atmsigd.o io.o kernel.o mess.o proto.o q2931.o sap.o timeout.o trace.o \
+  q.out.o qd.dump.o lex.yy.o y.tab.o
 BOOTPGMS=atmsigd
-TRASH=q.out.h q.out.o mess.c
+TRASH=q.out.h q.out.o qd.dump.o mess.c
 MANS=
 
 include ../Rules.make
@@ -20,6 +20,9 @@
 
 q.out.o:
 			ln -s ../qgen/q.out.o
+
+qd.dump.o:
+			ln -s ../qgen/qd.dump.o
 
 depend:			fake_q.out.h
 
diff -ur --new-file old/atm/sigd/atmsigd.c new/atm/sigd/atmsigd.c
--- old/atm/sigd/atmsigd.c	Tue Jul 30 20:19:21 1996
+++ new/atm/sigd/atmsigd.c	Thu Aug 29 14:07:41 1996
@@ -19,6 +19,7 @@
 #include "io.h"
 #include "proto.h"
 #include "saal.h"
+#include "trace.h"
 
 
 #define COMPONENT "SIGD"
@@ -31,6 +32,7 @@
 int net = 0;
 int debug = 0;
 int pretty = A2T_PRETTY | A2T_NAME;
+int sig_pcr = -1;
 
 static SAAL_DSC saal;
 
@@ -38,7 +40,7 @@
 static void usage(const char *name)
 {
     fprintf(stderr,"usage: %s [ -b ] [ -c config_file ] [ -d ] [ -l logfile ] "
-      "[ -n ] [ -N ]\n",name);
+      "[ -n ] [ -N ] [ -P pcr ]\n",name);
     exit(1);
 }
 
@@ -71,12 +73,14 @@
 
 void to_signaling(void *msg,int size)
 {
+    trace_q2931("TO NETWORK",msg,size);
     saal_send(&saal,msg,size);
 }
 
 
 static void q_data_ind(void *user_data,void *data,int length)
 {
+    trace_q2931("FROM NETWORK",data,length);
     to_q2931(data,length);
 }
 
@@ -213,6 +217,7 @@
 int main(int argc,char **argv)
 {
     const char *config_file;
+    char *end;
     int c,background;
 
     set_application("atmsigd");
@@ -220,7 +225,7 @@
     background = 0;
     memset(&signaling_pvc,0,sizeof(signaling_pvc));
     signaling_pvc.sap_addr.vci = 5;
-    while ((c = getopt(argc,argv,"bc:dl:nN")) != EOF)
+    while ((c = getopt(argc,argv,"bc:dl:nNP:")) != EOF)
 	switch (c) {
 	    case 'b':
 		background = 1;
@@ -243,6 +248,10 @@
 		break;
 	    case 'N':
 		net = 1;
+		break;
+	    case 'P':
+		sig_pcr = strtol(optarg,&end,0);
+		if (*end) usage(argv[0]);
 		break;
 	    default:
 		usage(argv[0]);
diff -ur --new-file old/atm/sigd/io.c new/atm/sigd/io.c
--- old/atm/sigd/io.c	Wed Jul 31 15:40:56 1996
+++ new/atm/sigd/io.c	Thu Aug 29 14:33:41 1996
@@ -21,6 +21,7 @@
 
 #include "proto.h"
 #include "io.h"
+#include "trace.h"
 
 
 #define COMPONENT "IO"
@@ -73,6 +74,7 @@
     if (size == KERNEL_BUFFER_SIZE) /* gotcha ! */
 	diag(COMPONENT,DIAG_FATAL,"kernel message too big (>= %d)",
 	  KERNEL_BUFFER_SIZE);
+    trace_kernel("FROM KERNEL",(struct atmsvc_msg *) buffer,size);
     bllis = (size-KERNEL_BASE_LEN)/sizeof(struct atm_blli);
     if (size != KERNEL_BASE_LEN+bllis*sizeof(struct atm_blli))
 	diag(COMPONENT,DIAG_FATAL,
@@ -93,6 +95,7 @@
     diag("KERNEL",DIAG_DEBUG,"TO KERNEL: %s (%d) for 0x%lx/0x%lx <%d>",
       as_name[msg->type],msg->reply,msg->vcc,msg->listen_vcc,size);
 	/* should be "IO" ... */
+    trace_kernel("TO KERNEL",msg,size);
     wrote = write(kernel,msg,size);
     if (wrote == size) return;
     if (wrote < 0) {
@@ -123,7 +126,12 @@
 	return -1;
     }
     memset(&qos,0,sizeof(qos));
-    qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_UBR;
+    if (sig_pcr == -1)
+	qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_UBR;
+    else {
+	qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_CBR;
+	qos.rxtp.min_pcr = qos.txtp.min_pcr = sig_pcr;
+    }
     qos.rxtp.max_sdu = qos.txtp.max_sdu = MAX_Q_MSG;
     if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) {
 	perror("setsockopt SO_ATMQOS");
diff -ur --new-file old/atm/sigd/kernel.c new/atm/sigd/kernel.c
--- old/atm/sigd/kernel.c	Tue Jul 30 21:25:05 1996
+++ new/atm/sigd/kernel.c	Wed Aug  7 14:22:25 1996
@@ -154,7 +154,7 @@
 
 		for (walk = local_addr; walk->state != ls_unused; walk++)
 		    if (walk->state == ls_same && atm_equal(&walk->addr,
-		      &msg->svc,0,0)) break;
+		      &msg->svc,(ATM_ESA_LEN-1)*8,AXE_WILDCARD)) break;
 		if (walk->state == ls_unused)
 		    SEND_ERROR(msg->vcc,-EADDRNOTAVAIL);
 		else send_kernel(msg->vcc,0,as_okay,0,NULL,NULL,NULL,NULL);
diff -ur --new-file old/atm/sigd/proto.h new/atm/sigd/proto.h
--- old/atm/sigd/proto.h	Tue Jul 30 18:10:49 1996
+++ new/atm/sigd/proto.h	Tue Aug 20 17:21:19 1996
@@ -61,6 +61,7 @@
 
 extern int net;
 extern int pretty;
+extern int sig_pcr;
 
 
 #define msg2bllis(s) (((int) (s)-(int) sizeof(struct atmsvc_msg))/ \
diff -ur --new-file old/atm/sigd/q2931.c new/atm/sigd/q2931.c
--- old/atm/sigd/q2931.c	Tue Jul 30 18:14:56 1996
+++ new/atm/sigd/q2931.c	Thu Aug  8 13:37:35 1996
@@ -378,7 +378,8 @@
 	    {
 		unsigned char cause;
 
-		if (mid != QMSG_REL_COMP) cause = 0;
+		if (mid != QMSG_REL_COMP || !q_present(&in_dsc,QF_cause))
+		    cause = 0;
 		else {
 		    cause = q_fetch(&in_dsc,QF_cause);
 		    diag(COMPONENT,DIAG_DEBUG,"Cause %d (%s)",cause,
diff -ur --new-file old/atm/sigd/trace.c new/atm/sigd/trace.c
--- old/atm/sigd/trace.c	Thu Jan  1 01:00:00 1970
+++ new/atm/sigd/trace.c	Thu Aug 29 14:36:26 1996
@@ -0,0 +1,117 @@
+/* trace.c - Support functions for message tracing */
+ 
+/* Written 1996 by Werner Almesberger, EPFL-LRC */
+ 
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "atmd.h"
+
+#include "trace.h"
+
+
+typedef struct _entry {
+    struct timeval time;
+    void (*parse)(void *msg,int size);
+    const char *comment;
+    void *msg;
+    int size;
+    struct _entry *next;
+} ENTRY;
+
+
+int trace_size = 0;
+static int current = 0;
+ENTRY *first = NULL,*last = NULL;
+
+
+static void append(const char *fmt,...)
+{
+    /* append to a growing string */
+}
+
+
+static void parse_text(void *msg,int size)
+{
+    append("%s\n",msg);
+}
+
+
+static void parse_q2931(void *msg,int size)
+{
+    /* set q_report and let qd_open do the work */
+}
+
+
+static void parse_kernel(void *msg,int size)
+{
+    /* print the message */
+}
+
+
+static void store(void (*parse)(void *msg,int size),const char *comment,
+  void *msg,int size)
+{
+    ENTRY *entry;
+
+    if (!trace_size) return;
+    entry = alloc_t(ENTRY);
+    (void) gettimeofday(&entry->time,NULL);
+    entry->parse = parse;
+    entry->comment = comment;
+    entry->msg = msg;
+    entry->size = size;
+    entry->next = NULL;
+    if (current >= trace_size) { /* handle trace_size < 1 (actually < 0) too */
+	ENTRY *next;
+
+	next = first->next;
+	free(first->msg);
+	free(first);
+	if (first == last) last = NULL; /* someone set trace_size < 2 */
+	first = next;
+    }
+    if (last) last->next = entry;
+    else first = entry;
+    last = entry;
+}
+
+
+void trace_msg(const char *msg)
+{
+    char *buf;
+
+    buf = alloc(strlen(msg)+1);
+    strcpy(buf,msg);
+    store(&parse_text,"MESSAGE",buf,strlen(msg));
+}
+
+
+void trace_q2931(const char *comment,const void *msg,int size)
+{
+    void *buf;
+
+    buf = alloc(size);
+    memcpy(buf,msg,size);
+    store(&parse_q2931,comment,buf,size);
+}
+
+
+void trace_kernel(const char *comment,const struct atmsvc_msg *msg,int size)
+{
+    struct atmsvc_msg *buf;
+
+    buf = alloc(size);
+    memcpy(buf,msg,size); /* DON'T use *buf = *msg; */
+    store(&parse_kernel,comment,buf,size);
+}
+
+
+char *get_trace(void)
+{
+    static char msg[] = "Trace generation isn't implemented yet\n";
+
+    return msg;
+}
diff -ur --new-file old/atm/sigd/trace.h new/atm/sigd/trace.h
--- old/atm/sigd/trace.h	Thu Jan  1 01:00:00 1970
+++ new/atm/sigd/trace.h	Thu Aug 29 14:16:55 1996
@@ -0,0 +1,18 @@
+/* trace.h - Support functions for message tracing */
+ 
+/* Written 1996 by Werner Almesberger, EPFL-LRC */
+ 
+
+#ifndef TRACE_H
+#define TRACE_H
+
+#include <linux/atmsvc.h>
+
+extern int trace_size;
+
+void trace_msg(const char *msg);
+void trace_q2931(const char *comment,const void *msg,int size);
+void trace_kernel(const char *comment,const struct atmsvc_msg *msg,int size);
+char *get_trace(void);
+
+#endif