diff -ur --new-file old/atm/CHANGES new/atm/CHANGES
--- old/atm/CHANGES	Tue May 18 01:30:50 1999
+++ new/atm/CHANGES	Thu Jun  3 00:22:06 1999
@@ -1,3 +1,49 @@
+Version 0.57 to 0.58 (3-JUN-1999)
+====================
+
+Bug fixes
+---------
+
+ - ENI drivers sometimes directly dereferenced pointers instead of using readl/
+   writel (fixed by Mitchell Blank)
+ - nicstar driver no longer uses floating point (fixed by Rui Prior)
+ - nicstar driver may have refused CBR VC in some cases even with enough
+   bandwidth available (fixed by Rui Prior)
+ - usage.tex failed to build (fixed by Bill Brooks)
+ - zeppelin got byte order in BLLI wrong (reported by Chas Williams; fixed by
+   Mitchell Blank and Heikki Vatiainen)
+ - zeppelin did not work when the host had multiple ATM addresses (reported by
+   Benoit Steiner; fixed by Heikki Vatiainen)
+ - zeppelin incorrectly parsed -i command line option (reported by Benoit
+   Steiner; fixed by Heikki Vatiainen)
+ - atm_connect_vcc and /proc/atm/pvc report AAL0 now properly (reported by Zhu
+   Qun Ying and Uwe Dannowski)
+
+New features
+------------
+
+ - nicstar driver now support SONET diagnostics (by Rui Prior)
+ - nicstar driver now works on PowerPC (by Jay Talbott)
+ - LANE now also supports Token Ring (Heikki Vatiainen, with testing by
+   Holger Smolinski)
+
+Other changes
+-------------
+
+ - major non-i386 architecture and other cleanup in ENI driver (by Mitchell
+   Blank)
+ - number of lec devices is 40+8 (lec0-lec39 are Ethernet and lec40-lec47 are
+   Token Ring; Heikki Vatiainen)
+ - lec.c and mpc.c now use atm_force_charge (Heikki Vatiainen)
+ - net/802/tr.c limited interface names to 4 characters (fixed by Heikki
+   Vatiainen)
+ - zeppelin man page updated (Heikki Vatiainen)
+ - "zeppelin.new" is now "zeppelin", the old "zeppelin" is gone
+ - set "atm_connect" printk to KERN_DEBUG
+ - removed ATM_SAAL from include/linux/atm.h (there never was any support for
+   SAAL in the kernel)
+
+
 Version 0.56 to 0.57 (18-MAY-1999)
 ====================
 
diff -ur --new-file old/atm/Makefile new/atm/Makefile
--- old/atm/Makefile	Tue May 18 01:19:36 1999
+++ new/atm/Makefile	Wed Jun  2 23:37:20 1999
@@ -2,7 +2,7 @@
 # "lib" must appear before anything else
 # "maint" must appear after "qgen"
 
-DIRS=lib test debug qgen saal sigd maint arpd ilmid aqd man led led.new lane \
+DIRS=lib test debug qgen saal sigd maint arpd ilmid aqd man led lane \
   mpoad switch # extra
 
 all:
diff -ur --new-file old/atm/README new/atm/README
--- old/atm/README	Tue May 18 01:19:53 1999
+++ new/atm/README	Mon May 31 22:55:35 1999
@@ -1,4 +1,4 @@
-ATM on Linux, release 0.57 (alpha)        by Werner Almesberger, EPFL ICA
+ATM on Linux, release 0.58 (alpha)        by Werner Almesberger, EPFL ICA
 ============================================== Werner.Almesberger@epfl.ch
 
 This is experimental software. There are known major bugs and certainly
diff -ur --new-file old/atm/USAGE new/atm/USAGE
--- old/atm/USAGE	Tue May 18 01:30:05 1999
+++ new/atm/USAGE	Thu Jun  3 00:23:59 1999
@@ -1,6 +1,4 @@
-7
-
-%:Usage instructions  -  ATM on Linux, release 0.57
+%:Usage instructions  -  ATM on Linux, release 0.58
 %:-------------------------------------------------
 %:
 %:
@@ -22,7 +20,7 @@
 In order to install this package, you need 
 
   - the package itself  
-    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.57.tar.gz  
+    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.58.tar.gz  
   - the Linux kernel, version 2.2.1, e.g. from  
     ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.2.1.tar.gz  
   - Perl, version 4 or 5 
@@ -38,7 +36,7 @@
 all the files listed above there. Then extract the ATM on Linux 
 distribution:
 
-tar xfz atm-0.57.tar.gz
+tar xfz atm-0.58.tar.gz
 
 and the kernel source:
 
@@ -63,7 +61,6 @@
     ttcp_atm, window 
   atm/arpd/  ATMARP tools and demon: atmarp, atmarpd 
   atm/led/  LAN Emulation demon: zeppelin 
-  atm/led.new/  Experimental version: zeppelin.new 
   atm/lane/  LAN Emulation servers: bus, lecs, les 
   atm/mpoad/  Multi-Protocol Over ATM demon: mpcd 
   atm/aqd/  Arequipa demon: aqpvc, arequipad 
@@ -828,11 +825,11 @@
 parameters can be tailored with command line options which are defined in 
 zeppelin.8.
 
-The new zeppelin, zeppelin.new, will automatically join any ELANs which use 
-higher MTU than the default MTU of 1516 bytes. However, the MTU of the LANE 
-interface will not change before you use  ifconfig  to adjust it. This will 
-probably change later so that the interface MTU will adjust itself 
-according to the MTU of the current ELAN.
+zeppelin, will automatically join any ELANs which use higher MTU than the 
+default MTU of 1516 bytes. However, the MTU of the LANE interface will not 
+change before you use  ifconfig  to adjust it. This will probably change 
+later so that the interface MTU will adjust itself according to the MTU of 
+the current ELAN.
 
 The state of the LANE ARP cache entries can be monitored through 
 /proc/atm/lec. For each entry the MAC and ATM addresses and status is 
diff -ur --new-file old/atm/VERSION new/atm/VERSION
--- old/atm/VERSION	Tue May 18 00:39:42 1999
+++ new/atm/VERSION	Wed Jun  2 23:39:42 1999
@@ -1 +1 @@
-0.57
+0.58
diff -ur --new-file old/atm/atm.patch new/atm/atm.patch
--- old/atm/atm.patch	Tue May 18 01:29:48 1999
+++ new/atm/atm.patch	Thu Jun  3 00:31:13 1999
@@ -270,6 +270,18 @@
    fi
    endmenu
  fi
+--- ref/arch/sparc/config.in	Thu Jan 14 19:29:28 1999
++++ work/arch/sparc/config.in	Wed Jun  2 23:33:38 1999
+@@ -170,6 +170,9 @@
+ #		bool 'FDDI driver support' CONFIG_FDDI
+ #		if [ "$CONFIG_FDDI" = "y" ]; then
+ #		fi
++		if [ "$CONFIG_ATM" = "y" ]; then
++		  source drivers/atm/Config.in
++		fi
+ 	fi
+ 	endmenu
+ fi
 --- ref/drivers/Makefile	Fri Nov 20 17:59:01 1998
 +++ work/drivers/Makefile	Tue Feb  9 15:49:57 1999
 @@ -10,7 +10,7 @@
@@ -294,8 +306,8 @@
  
  ifeq ($(CONFIG_AP1000),y)
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/Config.in	Tue May 18 01:13:20 1999
-@@ -0,0 +1,42 @@
++++ work/drivers/atm/Config.in	Mon May 31 22:39:11 1999
+@@ -0,0 +1,45 @@
 +#
 +# ATM device configuration
 +#
@@ -329,6 +341,9 @@
 +#    bool '  Enable extended debugging' CONFIG_ATM_TNETA1570_DEBUG n
 +#  fi
 +  tristate 'IDT 77201 (NICStAR)' CONFIG_ATM_NICSTAR
++  if [ "$CONFIG_ATM_NICSTAR" != "n" ]; then
++    bool '  Use suni PHY driver' CONFIG_ATM_NICSTAR_USE_SUNI
++  fi
 +  tristate 'Madge Ambassador (Collage PCI 155 Server)' CONFIG_ATM_AMBASSADOR
 +  if [ "$CONFIG_ATM_AMBASSADOR" != "n" ]; then
 +    bool '  Enable debugging messages' CONFIG_ATM_AMBASSADOR_DEBUG
@@ -339,8 +354,8 @@
 +  fi
 +fi
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/Makefile	Tue May 18 01:13:20 1999
-@@ -0,0 +1,73 @@
++++ work/drivers/atm/Makefile	Mon May 31 22:39:11 1999
+@@ -0,0 +1,79 @@
 +# File: drivers/atm/Makefile
 +#
 +# Makefile for the Linux network (ATM) device drivers.
@@ -381,9 +396,15 @@
 +
 +ifeq ($(CONFIG_ATM_NICSTAR),y)
 +L_OBJS += nicstar.o
++  ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y)
++  LX_OBJS += suni.o
++  endif
 +else
 +  ifeq ($(CONFIG_ATM_NICSTAR),m)
 +  M_OBJS += nicstar.o
++    ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y)
++    MX_OBJS += suni.o
++    endif
 +  endif
 +endif
 +
@@ -6239,8 +6260,8 @@
 +#endif
 +    
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/eni.c	Wed Apr 21 17:36:48 1999
-@@ -0,0 +1,2259 @@
++++ work/drivers/atm/eni.c	Wed Jun  2 23:46:23 1999
+@@ -0,0 +1,2264 @@
 +/* drivers/atm/eni.c - Efficient Networks ENI155P device driver */
 + 
 +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
@@ -6273,6 +6294,11 @@
 +#include "suni.h"
 +#include "eni.h"
 +
++#ifndef __i386__
++#ifndef ioremap_nocache
++#define ioremap_nocache(X,Y) ioremap(X,Y)
++#endif 
++#endif
 +
 +/*
 + * TODO:
@@ -6334,7 +6360,8 @@
 + */
 +
 +#define NULLCHECK(x) \
-+  if ((unsigned long) (x) < 0x30) printk(KERN_CRIT #x "==0x%x\n", (int) (x))
++	if ((unsigned long) (x) < 0x30) \
++		printk(KERN_CRIT #x "==0x%lx\n",(unsigned long) (x))
 +
 +/*
 + * Very extensive activity logging. Greatly improves bug detection speed but
@@ -6395,6 +6422,10 @@
 +
 +static u32 *zeroes = NULL; /* aligned "magic" zeroes */
 +
++/* Read/write registers on card */
++#define eni_in(r)	readl(eni_dev->reg+(r)*4)
++#define eni_out(v,r)	writel((v),eni_dev->reg+(r)*4)
++
 +
 +/*-------------------------------- utilities --------------------------------*/
 +
@@ -6422,12 +6453,12 @@
 +	printk(KERN_NOTICE "TX buffers\n");
 +	for (i = 0; i < NR_CHAN; i++)
 +		if (eni_dev->tx[i].send)
-+			printk(KERN_NOTICE "  TX %d @ 0x%p: %ld\n",i,
++			printk(KERN_NOTICE "  TX %d @ 0x%lx: %ld\n",i,
 +			    eni_dev->tx[i].send,eni_dev->tx[i].words*4);
 +	printk(KERN_NOTICE "RX buffers\n");
 +	for (i = 0; i < 1024; i++)
 +		if (eni_dev->rx_map[i] && ENI_VCC(eni_dev->rx_map[i])->rx)
-+			printk(KERN_NOTICE "  RX %d @ 0x%p: %ld\n",i,
++			printk(KERN_NOTICE "  RX %d @ 0x%lx: %ld\n",i,
 +			    ENI_VCC(eni_dev->rx_map[i])->recv,
 +			    ENI_VCC(eni_dev->rx_map[i])->words*4);
 +	printk(KERN_NOTICE "----\n");
@@ -6498,8 +6529,7 @@
 +	*size = 1 << order;
 +	eni_put_free(eni_dev,start+*size,(1 << best_order)-*size);
 +	DPRINTK("%ld bytes (order %d) at 0x%lx\n",*size,order,start);
-+	for (i = (*size >> 2)-1; i >= 0; i--) /* never leak data */
-+		((unsigned long *) start)[i] = 0;
++	memset_io(start,0,*size);       /* never leak data */
 +	/*dump_mem(eni_dev);*/
 +	return start;
 +}
@@ -6548,12 +6578,14 @@
 +static void rx_ident_err(struct atm_vcc *vcc)
 +{
 +	struct atm_dev *dev;
++	struct eni_dev *eni_dev;
 +	struct eni_vcc *eni_vcc;
 +
 +	dev = vcc->dev;
++	eni_dev = ENI_DEV(dev);
 +	/* immediately halt adapter */
-+	writel(readl(ENI_DEV(dev)->reg+MID_MC_S) & ~(MID_DMA_ENABLE |
-+	    MID_TX_ENABLE | MID_RX_ENABLE),ENI_DEV(dev)->reg+MID_MC_S);
++	eni_out(eni_in(MID_MC_S) &
++	    ~(MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE),MID_MC_S);
 +	/* dump useful information */
 +	eni_vcc = ENI_VCC(vcc);
 +	printk(KERN_ALERT DEV_LABEL "(itf %d): driver error - RX ident "
@@ -6562,7 +6594,7 @@
 +	    eni_vcc->rxing,eni_vcc->words);
 +	printk(KERN_ALERT "  host descr 0x%lx, rx pos 0x%lx, descr value "
 +	    "0x%x\n",eni_vcc->descr,eni_vcc->rx_pos,
-+	    readl(eni_vcc->recv+eni_vcc->descr));
++	    (unsigned) readl(eni_vcc->recv+eni_vcc->descr*4));
 +	printk(KERN_ALERT "  last 0x%p, servicing %d\n",eni_vcc->last,
 +	    eni_vcc->servicing);
 +	EVENT("---dump ends here---\n",0,0);
@@ -6684,8 +6716,8 @@
 +	}
 +	dma[j-2] |= MID_DMA_END;
 +	j = j >> 1;
-+	dma_wr = readl(eni_dev->reg+MID_DMA_WR_RX);
-+	dma_rd = readl(eni_dev->reg+MID_DMA_RD_RX);
++	dma_wr = eni_in(MID_DMA_WR_RX);
++	dma_rd = eni_in(MID_DMA_RD_RX);
 +	/*
 +	 * Can I move the dma_wr pointer by 2j+1 positions without overwriting
 +	 * data that hasn't been read (position of dma_rd) yet ?
@@ -6697,8 +6729,8 @@
 +		return -1;
 +	}
 +        for (i = 0; i < j; i++) {
-+		writel(dma[i*2],eni_dev->rx_dma+dma_wr*2);
-+		writel(dma[i*2+1],eni_dev->rx_dma+dma_wr*2+1);
++		writel(dma[i*2],eni_dev->rx_dma+dma_wr*8);
++		writel(dma[i*2+1],eni_dev->rx_dma+dma_wr*8+4);
 +		dma_wr = (dma_wr+1) & (NR_DMA_RX-1);
 +        }
 +	if (skb) {
@@ -6708,7 +6740,7 @@
 +rx_enqueued++;
 +	}
 +	eni_vcc->descr = here;
-+	writel(dma_wr,eni_dev->reg+MID_DMA_WR_RX);
++	eni_out(dma_wr,MID_DMA_WR_RX);
 +	return 0;
 +}
 +
@@ -6740,7 +6772,7 @@
 +
 +	DPRINTK(">rx_aal0\n");
 +	eni_vcc = ENI_VCC(vcc);
-+	descr = readl(eni_vcc->recv+eni_vcc->descr);
++	descr = readl(eni_vcc->recv+eni_vcc->descr*4);
 +	if ((descr & MID_RED_IDEN) != (MID_RED_RX_ID << MID_RED_SHIFT)) {
 +		rx_ident_err(vcc);
 +		return 1;
@@ -6782,7 +6814,7 @@
 +	EVENT("rx_aal5\n",0,0);
 +	DPRINTK(">rx_aal5\n");
 +	eni_vcc = ENI_VCC(vcc);
-+	descr = readl(eni_vcc->recv+eni_vcc->descr);
++	descr = readl(eni_vcc->recv+eni_vcc->descr*4);
 +	if ((descr & MID_RED_IDEN) != (MID_RED_RX_ID << MID_RED_SHIFT)) {
 +		rx_ident_err(vcc);
 +		return 1;
@@ -6813,8 +6845,9 @@
 +	else {
 +		size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2);
 +		DPRINTK("size=%ld\n",size);
-+		length = readl(eni_vcc->recv+((eni_vcc->descr+size-1) &
-+		    (eni_vcc->words-1))) & 0xffff; /* -trailer(2)+header(1) */
++		length = readl(eni_vcc->recv+(((eni_vcc->descr+size-1) &
++		    (eni_vcc->words-1)))*4) & 0xffff;
++				/* -trailer(2)+header(1) */
 +		if (length && length <= (size << 2)-8 && length <=
 +		  ATM_MAX_AAL5_PDU) eff = (length+3) >> 2;
 +		else {				 /* ^ trailer length (8) */
@@ -6851,19 +6884,18 @@
 +
 +static inline int rx_vcc(struct atm_vcc *vcc)
 +{
-+	u32 *vci_dsc;
++	unsigned long vci_dsc,tmp;
 +	struct eni_vcc *eni_vcc;
-+	unsigned long tmp;
 +
 +	eni_vcc = ENI_VCC(vcc);
-+	vci_dsc = ENI_DEV(vcc->dev)->vci+vcc->vci*4;
++	vci_dsc = ENI_DEV(vcc->dev)->vci+vcc->vci*16;
 +	EVENT("rx_vcc(1)\n",0,0);
-+	while (eni_vcc->descr != (tmp = (readl(vci_dsc+1) & MID_VCI_DESCR) >>
++	while (eni_vcc->descr != (tmp = (readl(vci_dsc+4) & MID_VCI_DESCR) >>
 +	    MID_VCI_DESCR_SHIFT)) {
 +		EVENT("rx_vcc(2: host dsc=0x%lx, nic dsc=0x%lx)\n",
 +		    eni_vcc->descr,tmp);
 +		DPRINTK("CB_DESCR %ld REG_DESCR %d\n",ENI_VCC(vcc)->descr,
-+		    ((readl(vci_dsc+1) & MID_VCI_DESCR) >>
++		    (((unsigned) readl(vci_dsc+4) & MID_VCI_DESCR) >>
 +		    MID_VCI_DESCR_SHIFT));
 +		if (ENI_VCC(vcc)->rx(vcc)) return 1;
 +	}
@@ -6875,12 +6907,12 @@
 +	 * follows. So we have to loop again to be sure.
 +	 */
 +	EVENT("rx_vcc(3)\n",0,0);
-+	while (ENI_VCC(vcc)->descr != (tmp = (readl(vci_dsc+1) & MID_VCI_DESCR)
++	while (ENI_VCC(vcc)->descr != (tmp = (readl(vci_dsc+4) & MID_VCI_DESCR)
 +	    >> MID_VCI_DESCR_SHIFT)) {
 +		EVENT("rx_vcc(4: host dsc=0x%lx, nic dsc=0x%lx)\n",
 +		    eni_vcc->descr,tmp);
 +		DPRINTK("CB_DESCR %ld REG_DESCR %d\n",ENI_VCC(vcc)->descr,
-+		    ((readl(vci_dsc+1) & MID_VCI_DESCR) >>
++		    (((unsigned) readl(vci_dsc+4) & MID_VCI_DESCR) >>
 +		    MID_VCI_DESCR_SHIFT));
 +		if (ENI_VCC(vcc)->rx(vcc)) return 1;
 +	}
@@ -6919,8 +6951,8 @@
 +
 +	DPRINTK(">get_service\n");
 +	eni_dev = ENI_DEV(dev);
-+	while (readl(eni_dev->reg+MID_SERV_WRITE) != eni_dev->serv_read) {
-+		vci = readl(eni_dev->service+eni_dev->serv_read);
++	while (eni_in(MID_SERV_WRITE) != eni_dev->serv_read) {
++		vci = readl(eni_dev->service+eni_dev->serv_read*4);
 +		eni_dev->serv_read = (eni_dev->serv_read+1) & (NR_SERVICE-1);
 +		vcc = eni_dev->rx_map[vci & 1023];
 +		if (!vcc) {
@@ -6961,7 +6993,7 @@
 +	struct eni_vcc *eni_vcc;
 +	struct atm_vcc *vcc;
 +	struct sk_buff *skb;
-+	u32 *vci_dsc;
++	unsigned long vci_dsc;
 +	int first;
 +
 +	eni_dev = ENI_DEV(dev);
@@ -6982,9 +7014,9 @@
 +		vcc = ATM_SKB(skb)->vcc;
 +		eni_vcc = ENI_VCC(vcc);
 +		first = 0;
-+		vci_dsc = eni_dev->vci+(vcc->vci << 2);
++		vci_dsc = eni_dev->vci+vcc->vci*16;
 +		if (!EEPMOK(eni_vcc->rx_pos,ENI_PRV_SIZE(skb),
-+		    (readl(vci_dsc+1) & MID_VCI_READ) >> MID_VCI_READ_SHIFT,
++		    (readl(vci_dsc+4) & MID_VCI_READ) >> MID_VCI_READ_SHIFT,
 +		    eni_vcc->words)) {
 +			EVENT("requeuing\n",0,0);
 +			skb_queue_head(&eni_dev->rx_queue,skb);
@@ -7023,8 +7055,8 @@
 +	if (size > MID_MAX_BUF_SIZE && vcc->qos.rxtp.max_sdu <=
 +	    MID_MAX_BUF_SIZE)
 +		size = MID_MAX_BUF_SIZE;
-+	eni_vcc->recv = (u32 *) eni_alloc_mem(eni_dev,&size);
-+	DPRINTK("rx at 0x%p\n",eni_vcc->recv);
++	eni_vcc->recv = eni_alloc_mem(eni_dev,&size);
++	DPRINTK("rx at 0x%lx\n",eni_vcc->recv);
 +	eni_vcc->words = size >> 2;
 +	if (!eni_vcc->recv) return -ENOBUFS;
 +	eni_vcc->rx = vcc->qos.aal == ATM_AAL5 ? rx_aal5 : rx_aal0;
@@ -7039,7 +7071,7 @@
 +
 +static int open_rx_second(struct atm_vcc *vcc)
 +{
-+	u32 *here;
++	unsigned long here;
 +	struct eni_dev *eni_dev;
 +	struct eni_vcc *eni_vcc;
 +	unsigned long size;
@@ -7050,19 +7082,19 @@
 +	eni_vcc = ENI_VCC(vcc);
 +	if (!eni_vcc->rx) return 0;
 +	/* set up VCI descriptor */
-+	here = eni_dev->vci+(vcc->vci << 2);
-+	DPRINTK("loc 0x%x\n",eni_vcc->recv-eni_dev->ram);
++	here = eni_dev->vci+vcc->vci*16;
++	DPRINTK("loc 0x%x\n",(unsigned) (eni_vcc->recv-eni_dev->ram)/4);
 +	size = eni_vcc->words >> 8;
 +	for (order = -1; size; order++) size >>= 1;
-+	writel(0,here+1); /* descr, read = 0 */
-+	writel(0,here+2); /* write, state, count = 0 */
++	writel(0,here+4); /* descr, read = 0 */
++	writel(0,here+8); /* write, state, count = 0 */
 +	if (eni_dev->rx_map[vcc->vci])
 +		printk(KERN_CRIT DEV_LABEL "(itf %d): BUG - VCI %d already "
 +		    "in use\n",vcc->dev->number,vcc->vci);
 +	eni_dev->rx_map[vcc->vci] = vcc; /* now it counts */
 +	writel(((vcc->qos.aal != ATM_AAL5 ? MID_MODE_RAW : MID_MODE_AAL5) <<
 +	    MID_VCI_MODE_SHIFT) | MID_VCI_PTI_MODE |
-+	    (((eni_vcc->recv-eni_dev->ram) >> MID_LOC_SKIP) <<
++	    (((eni_vcc->recv-eni_dev->ram) >> (MID_LOC_SKIP+2)) <<
 +	    MID_VCI_LOCATION_SHIFT) | (order << MID_VCI_SIZE_SHIFT),here);
 +	return 0;
 +}
@@ -7070,17 +7102,16 @@
 +
 +static void close_rx(struct atm_vcc *vcc)
 +{
-+	u32 *here;
++	unsigned long here,flags;
 +	struct eni_dev *eni_dev;
 +	struct eni_vcc *eni_vcc;
-+	unsigned long flags;
 +	u32 tmp;
 +
 +	eni_vcc = ENI_VCC(vcc);
 +	if (!eni_vcc->rx) return;
 +	eni_dev = ENI_DEV(vcc->dev);
 +	if (vcc->vpi != ATM_VPI_UNSPEC && vcc->vci != ATM_VCI_UNSPEC) {
-+		here = eni_dev->vci+(vcc->vci << 2);
++		here = eni_dev->vci+vcc->vci*16;
 +		/* block receiver */
 +		writel((readl(here) & ~MID_VCI_MODE) | (MID_MODE_TRASH <<
 +		    MID_VCI_MODE_SHIFT),here);
@@ -7102,8 +7133,9 @@
 +			    eni_vcc->rxing);
 +			sleep_on(&eni_dev->rx_wait);
 +		}
-+		while (eni_vcc->rx_pos != (tmp = eni_dev->vci[vcc->vci*4+1] &
-+		    MID_VCI_READ) >> MID_VCI_READ_SHIFT) {
++		while (eni_vcc->rx_pos != (tmp =
++		     readl(eni_dev->vci+vcc->vci*16+4) & MID_VCI_READ)>>
++		     MID_VCI_READ_SHIFT) {
 +			EVENT("drain discard (host 0x%lx, nic 0x%lx)\n",
 +			    eni_vcc->rx_pos,tmp);
 +			printk(KERN_INFO "draining RX: host 0x%lx, nic 0x%x\n",
@@ -7112,8 +7144,7 @@
 +		}
 +		restore_flags(flags);
 +	}
-+	eni_free_mem(eni_dev,(unsigned long) eni_vcc->recv,
-+	    eni_vcc->words << 2);
++	eni_free_mem(eni_dev,eni_vcc->recv,eni_vcc->words << 2);
 +	eni_vcc->rx = NULL;
 +}
 +
@@ -7135,8 +7166,8 @@
 +	eni_dev->slow = eni_dev->last_slow = NULL;
 +	eni_dev->rx_wait = NULL;
 +	skb_queue_head_init(&eni_dev->rx_queue);
-+	eni_dev->serv_read = readl(eni_dev->reg+MID_SERV_WRITE);
-+	writel(0,eni_dev->reg+MID_DMA_WR_RX);
++	eni_dev->serv_read = eni_in(MID_SERV_WRITE);
++	eni_out(0,MID_DMA_WR_RX);
 +	return 0;
 +}
 +
@@ -7300,14 +7331,14 @@
 +	 * the manual calls "too close".
 +	 */
 +	if (!NEPMOK(tx->tx_pos,size+TX_GAP,
-+	    readl(eni_dev->reg+MID_TX_RDPTR(tx->index)),tx->words)) {
-+		DPRINTK(DEV_LABEL "(itf %d): TX full (size %ld)\n",
++	    eni_in(MID_TX_RDPTR(tx->index)),tx->words)) {
++		DPRINTK(DEV_LABEL "(itf %d): TX full (size %d)\n",
 +		    vcc->dev->number,size);
 +		return enq_next;
 +	}
 +	/* check DMA */
-+	dma_wr = readl(eni_dev->reg+MID_DMA_WR_TX);
-+	dma_rd = readl(eni_dev->reg+MID_DMA_RD_TX);
++	dma_wr = eni_in(MID_DMA_WR_TX);
++	dma_rd = eni_in(MID_DMA_RD_TX);
 +	dma_size = 3; /* JK for descriptor and final fill, plus final size
 +			 mis-alignment fix */
 +DPRINTK("iovcnt = %d\n",ATM_SKB(skb)->iovcnt);
@@ -7317,7 +7348,7 @@
 +		printk(KERN_CRIT DEV_LABEL "(itf %d): needs %d DMA entries "
 +		    "(got only %d)\n",vcc->dev->number,dma_size,TX_DMA_BUF);
 +	}
-+	DPRINTK("dma_wr is %ld, tx_pos is %ld\n",dma_wr,tx->tx_pos);
++	DPRINTK("dma_wr is %d, tx_pos is %ld\n",dma_wr,tx->tx_pos);
 +	if (dma_wr != dma_rd && ((dma_rd+NR_DMA_TX-dma_wr) & (NR_DMA_TX-1)) <
 +	     dma_size) {
 +		printk(KERN_WARNING DEV_LABEL "(itf %d): TX DMA full\n",
@@ -7353,30 +7384,31 @@
 +	j++;
 +	DPRINTK("DMA at end: %d\n",j);
 +	/* store frame */
-+	tx->send[tx->tx_pos] = (MID_SEG_TX_ID << MID_SEG_ID_SHIFT) |
++	writel((MID_SEG_TX_ID << MID_SEG_ID_SHIFT) |
 +	    (aal5 ? MID_SEG_AAL5 : 0) | (tx->prescaler << MID_SEG_PR_SHIFT) |
 +	    (tx->resolution << MID_SEG_RATE_SHIFT) |
-+	    (size/(ATM_CELL_PAYLOAD/4));
-+/*printk("dsc = 0x%08lx\n",tx->send[tx->tx_pos]);*/
-+	tx->send[(tx->tx_pos+1) & (tx->words-1)] = (vcc->vci <<
-+	    MID_SEG_VCI_SHIFT) | (aal5 ? 0 : (skb->data[3] & 0xf)) |
-+	    (ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? MID_SEG_CLP : 0);
-+	DPRINTK("size: %ld, len:%d\n",size,skb->len);
++	    (size/(ATM_CELL_PAYLOAD/4)),tx->send+tx->tx_pos*4);
++/*printk("dsc = 0x%08lx\n",(unsigned long) readl(tx->send+tx->tx_pos*4));*/
++	writel((vcc->vci << MID_SEG_VCI_SHIFT) |
++            (aal5 ? 0 : (skb->data[3] & 0xf)) |
++	    (ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? MID_SEG_CLP : 0),
++	    tx->send+((tx->tx_pos+1) & (tx->words-1))*4);
++	DPRINTK("size: %d, len:%d\n",size,skb->len);
 +	if (aal5)
-+		tx->send[(tx->tx_pos+size-AAL5_TRAILER) & (tx->words-1)] =
-+		    skb->len;
++		writel(skb->len,tx->send+
++                    ((tx->tx_pos+size-AAL5_TRAILER) & (tx->words-1))*4);
 +	j = j >> 1;
 +	for (i = 0; i < j; i++) {
-+		writel(eni_dev->dma[i*2],eni_dev->tx_dma+dma_wr*2);
-+		writel(eni_dev->dma[i*2+1],eni_dev->tx_dma+dma_wr*2+1);
++		writel(eni_dev->dma[i*2],eni_dev->tx_dma+dma_wr*8);
++		writel(eni_dev->dma[i*2+1],eni_dev->tx_dma+dma_wr*8+4);
 +		dma_wr = (dma_wr+1) & (NR_DMA_TX-1);
 +	}
 +	ENI_PRV_POS(skb) = tx->tx_pos;
 +	ENI_PRV_SIZE(skb) = size;
 +	ENI_VCC(vcc)->txing += size;
 +	tx->tx_pos = (tx->tx_pos+size) & (tx->words-1);
-+	DPRINTK("dma_wr set to %ld, tx_pos is now %ld\n",dma_wr,tx->tx_pos);
-+	writel(dma_wr,eni_dev->reg+MID_DMA_WR_TX);
++	DPRINTK("dma_wr set to %d, tx_pos is now %ld\n",dma_wr,tx->tx_pos);
++	eni_out(dma_wr,MID_DMA_WR_TX);
 +	skb_queue_tail(&eni_dev->tx_queue,skb);
 +queued++;
 +	return enq_ok;
@@ -7424,9 +7456,9 @@
 +		tx = ENI_VCC(vcc)->tx;
 +		NULLCHECK(ENI_VCC(vcc)->tx);
 +		DPRINTK("dequeue_tx: next 0x%lx curr 0x%x\n",ENI_PRV_POS(skb),
-+		    readl(eni_dev->reg+MID_TX_DESCRSTART(tx->index)));
++		    (unsigned) eni_in(MID_TX_DESCRSTART(tx->index)));
 +		if (ENI_VCC(vcc)->txing < tx->words && ENI_PRV_POS(skb) ==
-+		    readl(eni_dev->reg+MID_TX_DESCRSTART(tx->index))) {
++		    eni_in(MID_TX_DESCRSTART(tx->index))) {
 +			skb_queue_head(&eni_dev->tx_queue,skb);
 +			break;
 +		}
@@ -7529,14 +7561,14 @@
 +		}
 +		DPRINTK("got chan %d\n",tx->index);
 +		tx->reserved = tx->shaping = 0;
-+		tx->send = (u32 *) mem;
++		tx->send = mem;
 +		tx->words = size >> 2;
 +		skb_queue_head_init(&tx->backlog);
 +		for (order = 0; size > (1 << (order+10)); order++);
-+		writel((order << MID_SIZE_SHIFT) |
-+		    ((tx->send-eni_dev->ram) >> MID_LOC_SKIP),
-+		    eni_dev->reg+MID_TX_PLACE(tx->index));
-+		tx->tx_pos = readl(eni_dev->reg+MID_TX_DESCRSTART(tx->index)) &
++		eni_out((order << MID_SIZE_SHIFT) |
++		    ((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)),
++		    MID_TX_PLACE(tx->index));
++		tx->tx_pos = eni_in(MID_TX_DESCRSTART(tx->index)) &
 +		    MID_DESCR_START;
 +	}
 +	error = comp_tx(eni_dev,&rate,tx->reserved,&pre,&res,unlimited);
@@ -7551,7 +7583,7 @@
 +		error = -EINVAL;
 +	if (error) {
 +		if (new_tx) {
-+			tx->send = NULL;
++			tx->send = 0;
 +			eni_free_mem(eni_dev,mem,size);
 +		}
 +		return error;
@@ -7610,8 +7642,8 @@
 +	 * Looping a few times in here is probably far cheaper than keeping
 +	 * track of TX completions all the time, so let's poll a bit ...
 +	 */
-+	while (readl(eni_dev->reg+MID_TX_RDPTR(eni_vcc->tx->index)) !=
-+	    readl(eni_dev->reg+MID_TX_DESCRSTART(eni_vcc->tx->index)))
++	while (eni_in(MID_TX_RDPTR(eni_vcc->tx->index)) !=
++	    eni_in(MID_TX_DESCRSTART(eni_vcc->tx->index)))
 +		schedule();
 +	restore_flags(flags);
 +#if 0
@@ -7619,9 +7651,8 @@
 +		printk(KERN_CRIT DEV_LABEL "SKBs in BACKLOG !!!\n");
 +#endif
 +	if (eni_vcc->tx != eni_dev->ubr) {
-+		eni_free_mem(eni_dev,(unsigned long) eni_vcc->tx->send,
-+		    eni_vcc->tx->words << 2);
-+		eni_vcc->tx->send = NULL;
++		eni_free_mem(eni_dev,eni_vcc->tx->send,eni_vcc->tx->words << 2);
++		eni_vcc->tx->send = 0;
 +		eni_dev->tx_bw += eni_vcc->tx->reserved;
 +	}
 +	eni_vcc->tx = NULL;
@@ -7639,9 +7670,9 @@
 +	eni_dev->tx_wait = NULL;
 +	eni_dev->ubr = NULL;
 +	skb_queue_head_init(&eni_dev->tx_queue);
-+	writel(0,eni_dev->reg+MID_DMA_WR_TX);
++	eni_out(0,MID_DMA_WR_TX);
 +	for (i = 0; i < NR_CHAN; i++) {
-+		eni_dev->tx[i].send = NULL;
++		eni_dev->tx[i].send = 0;
 +		eni_dev->tx[i].index = i;
 +	}
 +	return 0;
@@ -7674,7 +7705,7 @@
 +	eni_dev = ENI_DEV(dev);
 +	if (reason & MID_STAT_OVFL) {
 +		EVENT("stat overflow\n",0,0);
-+		eni_dev->lost += readl(eni_dev->reg+MID_STAT) & MID_OVFL_TRASH;
++		eni_dev->lost += eni_in(MID_STAT) & MID_OVFL_TRASH;
 +	}
 +	if (reason & MID_SUNI_INT) {
 +		EVENT("SUNI int\n",0,0);
@@ -7716,7 +7747,7 @@
 +	DPRINTK(">eni_int\n");
 +	dev = dev_id;
 +	eni_dev = ENI_DEV(dev);
-+	while ((reason = readl(eni_dev->reg+MID_ISA))) {
++	while ((reason = eni_in(MID_ISA))) {
 +		DPRINTK(DEV_LABEL ": int 0x%lx\n",reason);
 +		if (reason & MID_RX_DMA_COMPLETE) {
 +			EVENT("INT: RX DMA complete, starting dequeue_rx\n",
@@ -7875,15 +7906,11 @@
 +
 +__initfunc(static int get_esi_fpga(struct atm_dev *dev,unsigned long base))
 +{
-+	struct eni_dev *eni_dev;
-+	struct midway_eprom *eprom;
++	unsigned long mac_base;
 +	int i;
 +
-+	eprom = (struct midway_eprom *) (base+EPROM_SIZE-sizeof(struct
-+	    midway_eprom));
-+	eni_dev = ENI_DEV(dev);
-+	for (i = 0; i < ESI_LEN; i++)
-+		dev->esi[i] = readl(&eprom->mac+((i & ~3) | (3-(i & 3))));
++	mac_base = base+EPROM_SIZE-sizeof(struct midway_eprom);
++	for (i = 0; i < ESI_LEN; i++) dev->esi[i] = readb(mac_base+(i^3));
 +	return 0;
 +}
 +
@@ -7934,17 +7961,16 @@
 +		if (readl(&eprom->magic) != ENI155_MAGIC) {
 +			printk("\n");
 +			printk(KERN_ERR KERN_ERR DEV_LABEL "(itf %d): bad "
-+			    "magic - expected 0x%X, got 0x%X\n",dev->number,
-+			    ENI155_MAGIC,readl(&eprom->magic));
++			    "magic - expected 0x%x, got 0x%x\n",dev->number,
++			    ENI155_MAGIC,(unsigned) readl(&eprom->magic));
 +			return -EINVAL;
 +		}
 +	}
-+	eni_dev->phy = (u32 *) (base+PHY_BASE);
-+	eni_dev->reg = (u32 *) (base+REG_BASE);
-+	eni_dev->ram = (u32 *) (base+RAM_BASE);
-+	last = (MAP_MAX_SIZE-RAM_BASE)/4;
-+	for (i = last-RAM_INCREMENT; i >= 0;
-+	    i -= RAM_INCREMENT) {
++	eni_dev->phy = base+PHY_BASE;
++	eni_dev->reg = base+REG_BASE;
++	eni_dev->ram = base+RAM_BASE;
++	last = MAP_MAX_SIZE-RAM_BASE;
++	for (i = last-RAM_INCREMENT; i >= 0; i -= RAM_INCREMENT) {
 +		writel(0x55555555,eni_dev->ram+i);
 +		if (readl(eni_dev->ram+i) != 0x55555555) last = i;
 +		else {
@@ -7955,15 +7981,15 @@
 +	}
 +	for (i = 0; i < last; i += RAM_INCREMENT)
 +		if (readl(eni_dev->ram+i) != i) break;
-+	eni_dev->mem = i << 2;
++	eni_dev->mem = i;
 +	memset_io(eni_dev->ram,0,eni_dev->mem);
 +	/* TODO: should shrink allocation now */
 +	printk("mem=%dkB (",eni_dev->mem >> 10);
 +	/* TODO: check for non-SUNI, check for TAXI ? */
-+	if (!(readl(eni_dev->reg+MID_RES_ID_MCON) & 0x200) != !eni_dev->asic) {
++	if (!(eni_in(MID_RES_ID_MCON) & 0x200) != !eni_dev->asic) {
 +		printk(")\n");
-+		printk(KERN_ERR DEV_LABEL "(itf %d): ERROR - wrong id 0x%0x\n",
-+		    dev->number,readl(eni_dev->reg+MID_RES_ID_MCON));
++		printk(KERN_ERR DEV_LABEL "(itf %d): ERROR - wrong id 0x%x\n",
++		    dev->number,(unsigned) eni_in(MID_RES_ID_MCON));
 +		return -EINVAL;
 +	}
 +	error = eni_dev->asic ? get_esi_asic(dev) : get_esi_fpga(dev,base);
@@ -7972,8 +7998,8 @@
 +		printk("%s%02X",i ? "-" : "",dev->esi[i]);
 +	printk(")\n");
 +	printk(KERN_NOTICE DEV_LABEL "(itf %d): %s,%s\n",dev->number,
-+	    readl(eni_dev->reg+MID_RES_ID_MCON) & 0x200 ? "ASIC" : "FPGA",
-+	    media_name[readl(eni_dev->reg+MID_RES_ID_MCON) & DAUGTHER_ID]);
++	    eni_in(MID_RES_ID_MCON) & 0x200 ? "ASIC" : "FPGA",
++	    media_name[eni_in(MID_RES_ID_MCON) & DAUGTHER_ID]);
 +	return suni_init(dev);
 +}
 +
@@ -7981,8 +8007,7 @@
 +__initfunc(static int eni_start(struct atm_dev *dev))
 +{
 +	struct eni_dev *eni_dev;
-+	u32 *buf;
-+	unsigned long buffer_mem;
++	unsigned long buf,buffer_mem;
 +	int error;
 +
 +	DPRINTK(">eni_start\n");
@@ -8008,16 +8033,15 @@
 +	}
 +	/* determine addresses of internal tables */
 +	eni_dev->vci = eni_dev->ram;
-+	eni_dev->rx_dma = eni_dev->ram+NR_VCI*4;
-+	eni_dev->tx_dma = eni_dev->rx_dma+NR_DMA_RX*2;
-+	eni_dev->service = eni_dev->tx_dma+NR_DMA_TX*2;
-+	buf = eni_dev->service+NR_SERVICE;
-+	DPRINTK("vci 0x%p,rx 0x%p, tx 0x%p,srv 0x%p,buf 0x%p\n",
-+	     eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma,eni_dev->service,
-+	     buf);
++	eni_dev->rx_dma = eni_dev->ram+NR_VCI*16;
++	eni_dev->tx_dma = eni_dev->rx_dma+NR_DMA_RX*8;
++	eni_dev->service = eni_dev->tx_dma+NR_DMA_TX*8;
++	buf = eni_dev->service+NR_SERVICE*4;
++	DPRINTK("vci 0x%lx,rx 0x%lx, tx 0x%lx,srv 0x%lx,buf 0x%lx\n",
++	     eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma,
++	     eni_dev->service,buf);
 +	/* initialize memory management */
-+	buffer_mem = eni_dev->mem-((unsigned long) buf-
-+	    (unsigned long) eni_dev->ram);
++	buffer_mem = eni_dev->mem-(buf-eni_dev->ram);
 +	eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
 +	eni_dev->free_list = (struct eni_free *) kmalloc(
 +	    sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL);
@@ -8027,7 +8051,7 @@
 +		return -ENOMEM;
 +	}
 +	eni_dev->free_len = 0;
-+	eni_put_free(eni_dev,(unsigned long) buf,buffer_mem);
++	eni_put_free(eni_dev,buf,buffer_mem);
 +	memset_io(eni_dev->vci,0,16*NR_VCI); /* clear VCI table */
 +	/*
 +	 * byte_addr  free (k)
@@ -8038,18 +8062,18 @@
 +	 * 0x00007000	  484  buffers
 +	 * 0x00080000	    0  end (512kB)
 +	 */
-+	writel(0xffffffff,eni_dev->reg+MID_IE);
++	eni_out(0xffffffff,MID_IE);
 +	error = start_tx(dev);
 +	if (error) return error;
 +	error = start_rx(dev);
 +	if (error) return error;
 +	error = dev->phy->start(dev);
 +	if (error) return error;
-+	writel(readl(eni_dev->reg+MID_MC_S) | (1 << MID_INT_SEL_SHIFT) |
++	eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) |
 +	    MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE,
-+	    eni_dev->reg+MID_MC_S);
++	    MID_MC_S);
 +	    /* Tonga uses SBus INTReq1 */
-+	(void) readl(eni_dev->reg+MID_ISA); /* clear Midway interrupts */
++	(void) eni_in(MID_ISA); /* clear Midway interrupts */
 +	return 0;
 +}
 +
@@ -8185,13 +8209,13 @@
 +	cli();
 +	for (skb = eni_dev->tx_queue.next; skb !=
 +	    (struct sk_buff *) &eni_dev->tx_queue; skb = skb->next) {
-+		u32 *dsc;
++		unsigned long dsc;
 +
 +		if (ATM_SKB(skb)->vcc != vcc) continue;
-+		dsc = tx->send+ENI_PRV_POS(skb);
-+		*dsc = (*dsc & ~(MID_SEG_RATE | MID_SEG_PR)) |
++		dsc = tx->send+ENI_PRV_POS(skb)*4;
++		writel((readl(dsc) & ~(MID_SEG_RATE | MID_SEG_PR)) |
 +		    (tx->prescaler << MID_SEG_PR_SHIFT) |
-+		    (tx->resolution << MID_SEG_RATE_SHIFT);
++		    (tx->resolution << MID_SEG_RATE_SHIFT), dsc);
 +	}
 +	restore_flags(flags);
 +	return 0;
@@ -8298,14 +8322,14 @@
 +static void eni_phy_put(struct atm_dev *dev,unsigned char value,
 +    unsigned long addr)
 +{
-+	writel(value,ENI_DEV(dev)->phy+addr);
++	writel(value,ENI_DEV(dev)->phy+addr*4);
 +}
 +
 +
 +
 +static unsigned char eni_phy_get(struct atm_dev *dev,unsigned long addr)
 +{
-+	return readl(ENI_DEV(dev)->phy+addr);
++	return readl(ENI_DEV(dev)->phy+addr*4);
 +}
 +
 +
@@ -8370,9 +8394,10 @@
 +
 +		if (!tx->send) continue;
 +		if (--left) continue;
-+		return sprintf(page,"tx[%d]:    0x%06x-0x%06lx (%6ld bytes), "
-+		    "rsv %d cps, shp %d cps%s\n",i,(tx->send-eni_dev->ram)*4,
-+		    (tx->send-eni_dev->ram+tx->words)*4-1,tx->words*4,
++		return sprintf(page,"tx[%d]:    0x%06lx-0x%06lx (%6ld bytes), "
++		    "rsv %d cps, shp %d cps%s\n",i,
++		    tx->send-eni_dev->ram,
++		    tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,
 +		    tx->reserved,tx->shaping,
 +		    tx == eni_dev->ubr ? " (UBR)" : "");
 +	}
@@ -8383,9 +8408,10 @@
 +		if (--left) continue;
 +		length = sprintf(page,"vcc %4d: ",vcc->vci);
 +		if (eni_vcc->rx) {
-+			length += sprintf(page+length,"0x%06x-0x%06lx "
-+			    "(%6ld bytes)",(eni_vcc->recv-eni_dev->ram)*4,
-+			    (eni_vcc->recv-eni_dev->ram+eni_vcc->words)*4-1,
++			length += sprintf(page+length,"0x%06lx-0x%06lx "
++			    "(%6ld bytes)",
++			    eni_vcc->recv-eni_dev->ram,
++			    eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1,
 +			    eni_vcc->words*4);
 +			if (eni_vcc->tx) length += sprintf(page+length,", ");
 +		}
@@ -8400,7 +8426,7 @@
 +		unsigned long offset;
 +
 +		if (--left) continue;
-+		offset = (unsigned long) eni_dev->ram+eni_dev->base_diff;
++		offset = eni_dev->ram+eni_dev->base_diff;
 +		return sprintf(page,"free      0x%06lx-0x%06lx (%6d bytes)\n",
 +		    fe->start-offset,fe->start-offset+(1 << fe->order)-1,
 +		    1 << fe->order);
@@ -8501,7 +8527,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/eni.h	Thu Apr 22 19:46:09 1999
++++ work/drivers/atm/eni.h	Thu Jun  3 00:26:42 1999
 @@ -0,0 +1,115 @@
 +/* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */
 + 
@@ -8536,7 +8562,7 @@
 +};
 +
 +struct eni_tx {
-+	u32 *send;			/* base, NULL if unused */
++	unsigned long send;		/* base, 0 if unused */
 +	int prescaler;			/* shaping prescaler */
 +	int resolution;			/* shaping divider */
 +	unsigned long tx_pos;		/* current TX write position */
@@ -8549,7 +8575,7 @@
 +
 +struct eni_vcc {
 +	int (*rx)(struct atm_vcc *vcc);	/* RX function, NULL if none */
-+	u32 *recv;			/* receive buffer */
++	unsigned long recv;		/* receive buffer */
 +	unsigned long words;		/* its size in words */
 +	unsigned long descr;		/* next descriptor (RX) */
 +	unsigned long rx_pos;		/* current RX descriptor pos */
@@ -8566,13 +8592,13 @@
 +struct eni_dev {
 +	/*-------------------------------- base pointers into Midway address
 +					   space */
-+	u32 *phy;			/* PHY interface chip registers */
-+	u32 *reg;			/* register base */
-+	u32 *ram;			/* RAM base */
-+	u32 *vci;			/* VCI table */
-+	u32 *rx_dma;			/* RX DMA queue */
-+	u32 *tx_dma;			/* TX DMA queue */
-+	u32 *service;			/* service list */
++	unsigned long phy;		/* PHY interface chip registers */
++	unsigned long reg;		/* register base */
++	unsigned long ram;		/* RAM base */
++	unsigned long vci;		/* VCI table */
++	unsigned long rx_dma;		/* RX DMA queue */
++	unsigned long tx_dma;		/* TX DMA queue */
++	unsigned long service;		/* service list */
 +	/*-------------------------------- TX part */
 +	struct eni_tx tx[NR_CHAN];	/* TX channels */
 +	struct eni_tx *ubr;		/* UBR channel */
@@ -12196,11 +12222,11 @@
 +
 +#endif /* DRIVER_ATM_HORIZON_H */
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/midway.h	Tue Feb  9 15:49:57 1999
++++ work/drivers/atm/midway.h	Mon May 31 22:30:32 1999
 @@ -0,0 +1,265 @@
 +/* drivers/atm/midway.h - Efficient Networks Midway (SAR) description */
 + 
-+/* Written 1995 by Werner Almesberger, EPFL LRC */
++/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 + 
 +
 +#ifndef DRIVERS_ATM_MIDWAY_H
@@ -12221,7 +12247,7 @@
 +#define PHY_BASE	0x00020000	/* offset of PHY register are */
 +#define REG_BASE	0x00040000	/* offset of Midway register area */
 +#define RAM_BASE	0x00200000	/* offset of RAM area */
-+#define RAM_INCREMENT	0x00008000	/* probe for RAM every 128kB (32 kw) */
++#define RAM_INCREMENT	0x00020000	/* probe for RAM every 128kB */
 +
 +#define MID_VCI_BASE	RAM_BASE
 +#define MID_DMA_RX_BASE	(MID_VCI_BASE+NR_VCI*16)
@@ -12361,8 +12387,8 @@
 +struct midway_eprom {
 +	unsigned char mac[MAC_LEN],inv_mac[MAC_LEN];
 +	unsigned char pad[36];
-+	unsigned long serial,inv_serial;
-+	unsigned long magic,inv_magic;
++	u32 serial,inv_serial;
++	u32 magic,inv_magic;
 +};
 +
 +
@@ -12464,15 +12490,16 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/nicstar.h	Wed Apr 21 18:37:17 1999
-@@ -0,0 +1,746 @@
++++ work/drivers/atm/nicstar.h	Mon May 31 22:39:11 1999
+@@ -0,0 +1,774 @@
 +/******************************************************************************
 + *
 + * nicstar.h
 + *
 + * Header file for the nicstar device driver.
 + *
-+ * Author: Rui Prior
++ * Author: Rui Prior (rprior@inescn.pt)
++ * PowerPC support by Jay Talbott (jay_talbott@mcg.mot.com) April 1999
 + *
 + * (C) INESC 1998
 + *
@@ -12603,8 +12630,10 @@
 +   u32 word_4;
 +} ns_rsqe;
 +
-+#define ns_rsqe_vpi(ns_rsqep) (((ns_rsqep)->word_1 & 0x00FF0000) >> 16)
-+#define ns_rsqe_vci(ns_rsqep) ((ns_rsqep)->word_1 & 0x0000FFFF)
++#define ns_rsqe_vpi(ns_rsqep) \
++        ((le32_to_cpu((ns_rsqep)->word_1) & 0x00FF0000) >> 16)
++#define ns_rsqe_vci(ns_rsqep) \
++        (le32_to_cpu((ns_rsqep)->word_1) & 0x0000FFFF)
 +
 +#define NS_RSQE_VALID      0x80000000
 +#define NS_RSQE_NZGFC      0x00004000
@@ -12617,16 +12646,25 @@
 +#define NS_RSQE_BUFSIZE_SM 0x00000000
 +#define NS_RSQE_BUFSIZE_LG 0x00001000
 +
-+#define ns_rsqe_valid(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_VALID)
-+#define ns_rsqe_nzgfc(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_NZGFC)
-+#define ns_rsqe_eopdu(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_EOPDU)
-+#define ns_rsqe_bufsize(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_BUFSIZE)
-+#define ns_rsqe_congestion(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_CONGESTION)
-+#define ns_rsqe_clp(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_CLP)
-+#define ns_rsqe_crcerr(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_CRCERR)
-+
-+#define ns_rsqe_cellcount(ns_rsqep) ((ns_rsqep)->word_4 & 0x000001FF)
-+#define ns_rsqe_init(ns_rsqep) ((ns_rsqep)->word_4 = 0x00000000)
++#define ns_rsqe_valid(ns_rsqep) \
++        (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_VALID)
++#define ns_rsqe_nzgfc(ns_rsqep) \
++        (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_NZGFC)
++#define ns_rsqe_eopdu(ns_rsqep) \
++        (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_EOPDU)
++#define ns_rsqe_bufsize(ns_rsqep) \
++        (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_BUFSIZE)
++#define ns_rsqe_congestion(ns_rsqep) \
++        (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CONGESTION)
++#define ns_rsqe_clp(ns_rsqep) \
++        (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CLP)
++#define ns_rsqe_crcerr(ns_rsqep) \
++        (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CRCERR)
++
++#define ns_rsqe_cellcount(ns_rsqep) \
++        (le32_to_cpu((ns_rsqep)->word_4) & 0x000001FF)
++#define ns_rsqe_init(ns_rsqep) \
++        ((ns_rsqep)->word_4 = cpu_to_le32(0x00000000)) 
 +
 +#define NS_RSQ_NUM_ENTRIES (NS_RSQSIZE / 16)
 +#define NS_RSQ_ALIGNMENT NS_RSQSIZE
@@ -12654,9 +12692,12 @@
 +
 +#define NS_RCQE_SIZE 64		/* bytes */
 +
-+#define ns_rcqe_islast(ns_rcqep) ((ns_rcqep)->word_2 != 0x00000000)
-+#define ns_rcqe_cellheader(ns_rcqep) ((ns_rcqep)->word_1)
-+#define ns_rcqe_nextbufhandle(ns_rcqep) ((ns_rcqep)->word_2)
++#define ns_rcqe_islast(ns_rcqep) \
++        (le32_to_cpu((ns_rcqep)->word_2) != 0x00000000)
++#define ns_rcqe_cellheader(ns_rcqep) \
++        (le32_to_cpu((ns_rcqep)->word_1))
++#define ns_rcqe_nextbufhandle(ns_rcqep) \
++        (le32_to_cpu((ns_rcqep)->word_2))
 +
 +
 +
@@ -12692,20 +12733,27 @@
 +#define NS_TBD_VPI_SHIFT 20
 +#define NS_TBD_VCI_SHIFT 4
 +
-+#define ns_tbd_mkword_1(flags, m, n, buflen) (flags | m << 23 | n << 16 | buflen)
-+#define ns_tbd_mkword_1_novbr(flags, buflen) (flags | buflen | 0x00810000)
-+#define ns_tbd_mkword_3(control, pdulen) (control << 16 | pdulen)
-+#define ns_tbd_mkword_4(gfc, vpi, vci, pt, clp) (gfc << 28 | vpi << 20 | vci << 4 | pt << 1 | clp))
++#define ns_tbd_mkword_1(flags, m, n, buflen) \
++        (cpu_to_le32(flags | m << 23 | n << 16 | buflen))
++#define ns_tbd_mkword_1_novbr(flags, buflen) \
++        (cpu_to_le32(flags | buflen | 0x00810000))
++#define ns_tbd_mkword_3(control, pdulen) \
++        (cpu_to_le32(control << 16 | pdulen))
++#define ns_tbd_mkword_4(gfc, vpi, vci, pt, clp) \
++        (cpu_to_le32(gfc << 28 | vpi << 20 | vci << 4 | pt << 1 | clp)))
 +
 +
 +#define NS_TSR_INTENABLE 0x20000000
 +
 +#define NS_TSR_SCDISVBR 0xFFFF		/* Use as scdi for VBR SCD */
 +
-+#define ns_tsr_mkword_1(flags) (NS_SCQE_TYPE_TSR | (flags))
-+#define ns_tsr_mkword_2(scdi, scqi) ((scdi) << 16 | 0x00008000 | (scqi))
++#define ns_tsr_mkword_1(flags) \
++        (cpu_to_le32(NS_SCQE_TYPE_TSR | (flags)))
++#define ns_tsr_mkword_2(scdi, scqi) \
++        (cpu_to_le32((scdi) << 16 | 0x00008000 | (scqi)))
 +
-+#define ns_scqe_is_tsr(ns_scqep) ((ns_scqep)->word_1 & NS_SCQE_TYPE_TSR)
++#define ns_scqe_is_tsr(ns_scqep) \
++        (le32_to_cpu((ns_scqep)->word_1) & NS_SCQE_TYPE_TSR)
 +
 +#define VBR_SCQ_NUM_ENTRIES 512
 +#define VBR_SCQSIZE 8192
@@ -12734,10 +12782,13 @@
 +#define NS_TSI_EMPTY          0x80000000
 +#define NS_TSI_TIMESTAMP_MASK 0x00FFFFFF
 +
-+#define ns_tsi_isempty(ns_tsip) ((ns_tsip)->word_2 & NS_TSI_EMPTY)
-+#define ns_tsi_gettimestamp(ns_tsip) ((ns_tsip)->word_2 & NS_TSI_TIMESTAMP_MASK)
++#define ns_tsi_isempty(ns_tsip) \
++        (le32_to_cpu((ns_tsip)->word_2) & NS_TSI_EMPTY)
++#define ns_tsi_gettimestamp(ns_tsip) \
++        (le32_to_cpu((ns_tsip)->word_2) & NS_TSI_TIMESTAMP_MASK)
 +
-+#define ns_tsi_init(ns_tsip) ((ns_tsip)->word_2 = NS_TSI_EMPTY)
++#define ns_tsi_init(ns_tsip) \
++        ((ns_tsip)->word_2 = cpu_to_le32(NS_TSI_EMPTY))
 +
 +
 +#define NS_TSQSIZE 8192
@@ -12747,9 +12798,12 @@
 +
 +#define NS_TSI_SCDISVBR NS_TSR_SCDISVBR
 +
-+#define ns_tsi_tmrof(ns_tsip) ((ns_tsip)->word_1 == 0x00000000)
-+#define ns_tsi_getscdindex(ns_tsip) (((ns_tsip)->word_1 & 0xFFFF0000) >> 16)
-+#define ns_tsi_getscqpos(ns_tsip) ((ns_tsip)->word_1 & 0x00007FFF)
++#define ns_tsi_tmrof(ns_tsip) \
++        (le32_to_cpu((ns_tsip)->word_1) == 0x00000000)
++#define ns_tsi_getscdindex(ns_tsip) \
++        ((le32_to_cpu((ns_tsip)->word_1) & 0xFFFF0000) >> 16)
++#define ns_tsi_getscqpos(ns_tsip) \
++        (le32_to_cpu((ns_tsip)->word_1) & 0x00007FFF)
 +
 +
 +
@@ -13213,13 +13267,13 @@
 +
 +#endif /* _LINUX_NICSTAR_H_ */
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/nicstar.c	Tue May 18 01:02:06 1999
-@@ -0,0 +1,2999 @@
++++ work/drivers/atm/nicstar.c	Mon May 31 22:39:11 1999
+@@ -0,0 +1,3054 @@
 +/******************************************************************************
 + *
 + * nicstar.c
 + *
-+ * Device driver supporting CBR for IDT 77211 "NICStAR" based cards.
++ * Device driver supporting CBR for IDT 77201/77211 "NICStAR" based cards.
 + *
 + * IMPORTANT: The included file nicstarmac.c was NOT WRITTEN BY ME.
 + *            It was taken from the frle-0.22 device driver.
@@ -13228,16 +13282,12 @@
 + *            frle-0.22 device driver.
 + *            Some code is based on the nicstar driver by M. Welsh.
 + *
-+ * Author: Rui Prior
++ * Author: Rui Prior (rprior@inescn.pt)
++ * PowerPC support by Jay Talbott (jay_talbott@mcg.mot.com) April 1999
 + *
-+ * URLs:
-+ *   NICStAR driver homepage
-+ *     http://jaguar.inescn.pt/~rprior/nicstar/nicstar.html
 + *
-+ *   IDT 77211 documentation
-+ *     http://www.idt.com/product_files/77211.html
++ * (C) INESC 1999
 + *
-+ * (C) INESC 1998
 + *
 + ******************************************************************************/
 +
@@ -13262,6 +13312,9 @@
 +#include <asm/uaccess.h>
 +#include "nicstar.h"
 +#include "nicstarmac.h"
++#ifdef CONFIG_ATM_NICSTAR_USE_SUNI
++#include "suni.h"
++#endif /* CONFIG_ATM_NICSTAR_USE_SUNI */
 +
 +
 +/* Additional code ************************************************************/
@@ -13370,6 +13423,10 @@
 +static void ns_poll(unsigned long arg);
 +static int ns_parse_mac(char *mac, unsigned char *esi);
 +static short ns_h2i(char c);
++static void ns_phy_put(struct atm_dev *dev, unsigned char value,
++                       unsigned long addr);
++static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr);
++
 +
 +
 +/* Global variables ***********************************************************/
@@ -13387,8 +13444,8 @@
 +   ns_send,		/* send */
 +   NULL,		/* sg_send */
 +   NULL,		/* send_oam */
-+   NULL,		/* phy_put */
-+   NULL,		/* phy_get */
++   ns_phy_put,		/* phy_put */
++   ns_phy_get,		/* phy_get */
 +   NULL,		/* feedback */
 +   NULL,		/* change_qos */
 +   NULL,		/* free_rx_skb */
@@ -13669,6 +13726,11 @@
 +   card->index = i;
 +   card->pcidev = pcidev;
 +   card->membase = (u32) (pcidev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
++#ifdef __powerpc__
++   /* Compensate for different memory map between host CPU and PCI bus.
++      Shouldn't we use a macro for this? */
++   card->membase += KERNELBASE;
++#endif /* __powerpc__ */
 +   card->membase = (u32) ioremap(card->membase, NS_IOREMAP_SIZE);
 +   if (card->membase == (u32) (NULL))
 +   {
@@ -13772,7 +13834,8 @@
 +         printk("nicstar%d: unknown PHY type (0x%08X).\n", i, data);
 +         error = 8;
 +         ns_init_card_error(card, error);
-+         return error; }
++         return error;
++   }
 +   writel(0x00000000, card->membase + GP);
 +
 +   /* Determine SRAM size */
@@ -13814,7 +13877,7 @@
 +
 +   if (request_irq(pcidev->irq, &ns_irq_handler, SA_INTERRUPT | SA_SHIRQ, "nicstar", card) != 0)
 +   {
-+      printk("nicstar%d: can't allocate IRQ.\n", i);
++      printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq);
 +      error = 9;
 +      ns_init_card_error(card, error);
 +      return error;
@@ -14065,7 +14128,8 @@
 +          NS_CFG_RSQAFIE |
 +          NS_CFG_TXEN |
 +          NS_CFG_TXIE |
-+          NS_CFG_TSQFIE_OPT,		/* Only enabled if ENABLE_TSQFIE */ 
++          NS_CFG_TSQFIE_OPT |		/* Only enabled if ENABLE_TSQFIE */ 
++          NS_CFG_PHYIE,
 +          card->membase + CFG);
 +
 +   /* Register device */
@@ -14091,6 +14155,18 @@
 +   card->atmdev->ci_range.vci_bits = card->vcibits;
 +   card->atmdev->link_rate = card->max_pcr;
 +
++#ifdef CONFIG_ATM_NICSTAR_USE_SUNI
++   if (card->max_pcr == ATM_OC3_PCR) {
++      suni_init(card->atmdev);
++#ifdef MODULE
++      MOD_INC_USE_COUNT;
++      /* Can't remove the nicstar driver or the suni driver would oops */
++#endif /* MODULE */
++   }
++#endif /* CONFIG_ATM_NICSTAR_USE_SUNI */
++   if (card->atmdev->phy && card->atmdev->phy->start)
++      card->atmdev->phy->start(card->atmdev);
++
 +   num_cards++;
 +
 +   return error;
@@ -14355,8 +14431,10 @@
 +{
 +   u32 stat_r;
 +   ns_dev *card;
++   struct atm_dev *dev;
 +
 +   card = (ns_dev *) dev_id;
++   dev = card->atmdev;
 +   card->intcnt++;
 +
 +   PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index);
@@ -14412,7 +14490,10 @@
 +   if (stat_r & NS_STAT_PHYI)
 +   {
 +      writel(NS_STAT_PHYI, card->membase + STAT);
-+      printk("nicstar%d: PHY interrupt.\n", card->index);
++      PRINTK("nicstar%d: PHY interrupt.\n", card->index);
++      if (dev->phy && dev->phy->interrupt) {
++         dev->phy->interrupt(dev);
++      }
 +   }
 +
 +   /* Small Buffer Queue is full */
@@ -14546,7 +14627,7 @@
 +   ns_dev *card;
 +   vc_map *vc;
 +   int error;
-+   double tmpd;
++   unsigned long tmpl, modl;
 +   int tcr, tcra;	/* target cell rate, and absolute value */
 +   int n = 0;		/* Number of entries in the TST. Initialized to remove
 +                           the compiler warning. */
@@ -14615,19 +14696,15 @@
 +         PRINTK("nicstar%d: target cell rate = %d.\n", card->index,
 +                vcc->qos.txtp.max_pcr);
 +
-+         tmpd = ((double) tcra) * ((double) NS_TST_NUM_ENTRIES) /
-+                ((double) card->max_pcr);      
++         tmpl = (unsigned long)tcra * (unsigned long)NS_TST_NUM_ENTRIES;
++         modl = tmpl % card->max_pcr;
 +
-+         n = (int) tmpd;
++         n = (int)(tmpl / card->max_pcr);
 +         if (tcr > 0)
 +         {
-+            if (tmpd > (double) n) n++;
++            if (modl > 0) n++;
 +         }
-+         else if (tcr < 0)
-+         {
-+            if (tmpd < (double) n) n--;
-+         }
-+         else /* tcr == 0 */
++         else if (tcr == 0)
 +         {
 +            if ((n = (card->tst_free_entries - NS_TST_RESERVED)) <= 0)
 +	    {
@@ -14644,17 +14721,6 @@
 +            return -EINVAL;
 +         }
 +
-+         if (vcc->qos.txtp.max_pcr > 0)
-+         {
-+            tmpd = (double) n * (double) card->max_pcr /
-+	           (double) NS_TST_NUM_ENTRIES;
-+            if (tmpd > PCR_TOLERANCE * (double) vcc->qos.txtp.max_pcr)
-+            {
-+               PRINTK("nicstar%d: target cell rate exceeded requested max_pcr.\n",
-+                      card->index);
-+            }
-+         }
-+
 +         if (n > (card->tst_free_entries - NS_TST_RESERVED))
 +         {
 +            PRINTK("nicstar%d: not enough free CBR bandwidth.\n", card->index);
@@ -14894,7 +14960,7 @@
 +static void fill_tst(ns_dev *card, int n, vc_map *vc)
 +{
 +   u32 new_tst;
-+   double c, q;
++   unsigned long cl;
 +   int e, r;
 +   u32 data;
 +      
@@ -14911,32 +14977,30 @@
 +      if (card->tste2vc[e] == NULL)
 +         break;
 +   }
-+   if (e == NS_TST_NUM_ENTRIES)
++   if (e == NS_TST_NUM_ENTRIES) {
 +      printk("nicstar%d: No free TST entries found. \n", card->index);
++      return;
++   }
 +
 +   r = n;
-+   c = 1.0;
-+   q = (double) n / (double) NS_TST_NUM_ENTRIES;
-+
++   cl = NS_TST_NUM_ENTRIES;
 +   data = ns_tste_make(NS_TST_OPCODE_FIXED, vc->cbr_scd);
 +      
-+   while (e < NS_TST_NUM_ENTRIES)
++   while (r > 0)
 +   {
-+      if (c >= 1.0 && card->tste2vc[e] == NULL)
++      if (cl >= NS_TST_NUM_ENTRIES && card->tste2vc[e] == NULL)
 +      {
 +         card->tste2vc[e] = vc;
 +         ns_write_sram(card, new_tst + e, &data, 1);
-+	 c -= 1.0;
-+	 if (--r == 0)
-+	    break;
++         cl -= NS_TST_NUM_ENTRIES;
++         r--;
 +      }
 +
-+      e++;
-+      c += q;
++      if (++e == NS_TST_NUM_ENTRIES) {
++         e = 0;
++      }
++      cl += n;
 +   }
-+   if (r != 0)
-+      printk("nicstar%d: Not enough free TST entries. CBR lower than requested.\n",
-+             card->index);
 +   
 +   /* End of fill procedure */
 +   
@@ -14997,24 +15061,25 @@
 +   {
 +      buflen = (skb->len + 47 + 8) / 48 * 48;	/* Multiple of 48 */
 +      flags = NS_TBD_AAL5;
-+      scqe.word_2 = (u32) virt_to_bus(skb->data);
-+      scqe.word_3 = (u32) skb->len;
-+      scqe.word_4 = ((u32) vcc->vpi) << NS_TBD_VPI_SHIFT |
-+                    ((u32) vcc->vci) << NS_TBD_VCI_SHIFT;
++      scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data));
++      scqe.word_3 = cpu_to_le32((u32) skb->len);
++      scqe.word_4 = cpu_to_le32(((u32) vcc->vpi) << NS_TBD_VPI_SHIFT |
++                                ((u32) vcc->vci) << NS_TBD_VCI_SHIFT);
 +      flags |= NS_TBD_EOPDU;
 +   }
 +   else /* (vcc->qos.aal == ATM_AAL0) */
 +   {
 +      buflen = ATM_CELL_PAYLOAD;	/* i.e., 48 bytes */
 +      flags = NS_TBD_AAL0;
-+      scqe.word_2 = (u32) virt_to_bus(skb->data) + NS_AAL0_HEADER;
-+      scqe.word_3 = 0x00000000;
++      scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data) + NS_AAL0_HEADER);
++      scqe.word_3 = cpu_to_le32(0x00000000);
 +      if (*skb->data & 0x02)	/* Payload type 1 - end of pdu */
 +         flags |= NS_TBD_EOPDU;
-+      scqe.word_4 = *((u32 *) skb->data) & ~NS_TBD_VC_MASK;
++      scqe.word_4 = cpu_to_le32(*((u32 *) skb->data) & ~NS_TBD_VC_MASK);
 +      /* Force the VPI/VCI to be the same as in VCC struct */
-+      scqe.word_4 |= (((u32) vcc->vpi) << NS_TBD_VPI_SHIFT |
-+                      ((u32) vcc->vci) << NS_TBD_VCI_SHIFT) & NS_TBD_VC_MASK;
++      scqe.word_4 |= cpu_to_le32((((u32) vcc->vpi) << NS_TBD_VPI_SHIFT |
++                                 ((u32) vcc->vci) << NS_TBD_VCI_SHIFT) &
++                                 NS_TBD_VC_MASK);
 +   }
 +
 +   if (vcc->qos.txtp.traffic_class == ATM_CBR)
@@ -15074,7 +15139,8 @@
 +   XPRINTK("nicstar%d: sending skb at 0x%x (pos %d).\n",
 +           card->index, (u32) skb, index);
 +   XPRINTK("nicstar%d: TBD written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n",
-+           card->index, tbd->word_1, tbd->word_2, tbd->word_3, tbd->word_4,
++           card->index, le32_to_cpu(tbd->word_1), le32_to_cpu(tbd->word_2),
++           le32_to_cpu(tbd->word_3), le32_to_cpu(tbd->word_4),
 +           (u32) scq->next);
 +   if (scq->next == scq->last)
 +      scq->next = scq->base;
@@ -15123,7 +15189,8 @@
 +         index = (int) scqi;
 +         scq->skb[index] = NULL;
 +         XPRINTK("nicstar%d: TSR written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n",
-+	         card->index, tsr.word_1, tsr.word_2, tsr.word_3, tsr.word_4,
++                 card->index, le32_to_cpu(tsr.word_1), le32_to_cpu(tsr.word_2),
++                 le32_to_cpu(tsr.word_3), le32_to_cpu(tsr.word_4),
 +		 (u32) scq->next);
 +         if (scq->next == scq->last)
 +            scq->next = scq->base;
@@ -15191,7 +15258,7 @@
 +               ns_tsi_init(card->tsq.next);
 +               return;
 +            }
-+	    scq = card->scd2vc[scdi]->scq;
++            scq = card->scd2vc[scdi]->scq;
 +         }
 +         drain_scq(card, scq, ns_tsi_getscqpos(card->tsq.next));
 +         scq->full = 0;
@@ -15301,7 +15368,7 @@
 +   card->sbfqc = ns_stat_sfbqc_get(stat);   
 +   card->lbfqc = ns_stat_lfbqc_get(stat);
 +
-+   skb = (struct sk_buff *) rsqe->buffer_handle;
++   skb = (struct sk_buff *) le32_to_cpu(rsqe->buffer_handle);
 +   vpi = ns_rsqe_vpi(rsqe);
 +   vci = ns_rsqe_vci(rsqe);
 +   if (vpi >= 1UL << card->vpibits || vci >= 1UL << card->vcibits)
@@ -15348,7 +15415,7 @@
 +            break;
 +         }
 +         /* Rebuild the header */
-+         *((u32 *) sb->data) = rsqe->word_1 << 4 |
++         *((u32 *) sb->data) = le32_to_cpu(rsqe->word_1) << 4 |
 +                               (ns_rsqe_clp(rsqe) ? 0x00000001 : 0x00000000);
 +         if (i == 1 && ns_rsqe_eopdu(rsqe))
 +            *((u32 *) sb->data) |= 0x00000002;
@@ -15448,10 +15515,10 @@
 +
 +   if (ns_rsqe_eopdu(rsqe))
 +   {
-+      aal5_len = *((unsigned short *) ((u32) skb->data + iov->iov_len - 6));
-+      /* Swap byte order. Is it just me or the nicstar manual sais this should
-+         already be in little endian format? */
-+      aal5_len = ((aal5_len & 0x00ff) << 8 | (aal5_len & 0xff00) >> 8);
++      /* This works correctly regardless of the endianness of the host */
++      unsigned char *L1L2 = (unsigned char *)((u32)skb->data +
++                                              iov->iov_len - 6);
++      aal5_len = L1L2[0] << 8 | L1L2[1];
 +      len = (aal5_len == 0x0000) ? 0x10000 : aal5_len;
 +      if (ns_rsqe_crcerr(rsqe) ||
 +          len + 8 > iovb->len || len + (47 + 8) < iovb->len)
@@ -16113,8 +16180,14 @@
 +         return 0;
 +
 +      default:
-+         if (dev->phy->ioctl == NULL) return -EINVAL;
-+	 return dev->phy->ioctl(dev, cmd, arg);
++         if (dev->phy && dev->phy->ioctl) {
++            return dev->phy->ioctl(dev, cmd, arg);
++         }
++         else {
++            printk("nicstar%d: %s == NULL \n", card->index,
++                   dev->phy ? "dev->phy->ioctl" : "dev->phy");
++            return -EINVAL;
++         }
 +   }
 +}
 +
@@ -16168,7 +16241,7 @@
 +      process_tsq(card);
 +      process_rsq(card);
 +
-+      writel(card->membase + STAT, stat_w);
++      writel(stat_w, card->membase + STAT);
 +      card->in_poll = 0;
 +      restore_flags(flags);
 +   }
@@ -16214,6 +16287,42 @@
 +      return (short) (c - 'a' + 10);
 +   return -1;
 +}
++
++
++
++static void ns_phy_put(struct atm_dev *dev, unsigned char value,
++                    unsigned long addr)
++{
++   ns_dev *card;
++   unsigned long flags;
++
++   card = dev->dev_data;
++   save_flags(flags); cli();
++   while(CMD_BUSY(card));
++   writel((unsigned long) value, card->membase + DR0);
++   writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF),
++          card->membase + CMD);
++   restore_flags(flags);
++}
++
++
++
++static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr)
++{
++   ns_dev *card;
++   unsigned long flags;
++   unsigned long data;
++
++   card = dev->dev_data;
++   save_flags(flags); cli();
++   while(CMD_BUSY(card));
++   writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF),
++          card->membase + CMD);
++   while(CMD_BUSY(card));
++   data = readl(card->membase + DR0) & 0x000000FF;
++   restore_flags(flags);
++   return (unsigned char) data;
++}
 --- /dev/null	Tue Jan  1 05:00:00 1980
 +++ work/drivers/atm/nicstar.c.old_skb	Tue Feb  9 15:49:57 1999
 @@ -0,0 +1,2883 @@
@@ -19760,7 +19869,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/suni.h	Thu Apr 22 19:46:07 1999
++++ work/drivers/atm/suni.h	Thu Jun  3 00:26:39 1999
 @@ -0,0 +1,210 @@
 +/* drivers/atm/suni.h - PMC SUNI (PHY) declarations */
 + 
@@ -22508,7 +22617,7 @@
 + 
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/zatm.h	Thu Apr 22 19:46:13 1999
++++ work/drivers/atm/zatm.h	Thu Jun  3 00:26:47 1999
 @@ -0,0 +1,137 @@
 +/* drivers/atm/zatm.h - ZeitNet ZN122x device driver declarations */
 +
@@ -22705,7 +22814,7 @@
  #ifdef CONFIG_VT
  	console_map_init();
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/include/linux/arequipa.h	Thu Apr 22 17:31:28 1999
++++ work/include/linux/arequipa.h	Thu Jun  3 00:27:20 1999
 @@ -0,0 +1,63 @@
 +/* arequipa.h - Arequipa interface definitions */
 + 
@@ -22771,11 +22880,11 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/include/linux/atm.h	Tue Feb  9 17:40:13 1999
-@@ -0,0 +1,245 @@
++++ work/include/linux/atm.h	Thu Jun  3 00:24:32 1999
+@@ -0,0 +1,244 @@
 +/* atm.h - general ATM declarations */
 + 
-+/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
++/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 + 
 +
 +/*
@@ -22821,7 +22930,6 @@
 +#define ATM_AAL2	2		/* AAL2 (VBR) */
 +#define ATM_AAL34	3		/* AAL3/4 (data) */
 +#define ATM_AAL5	5		/* AAL5 (data) */
-+#define ATM_SAAL	12		/* signaling AAL */
 +
 +/* socket option name coding functions */
 +
@@ -23293,7 +23401,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/include/linux/atmdev.h	Thu Apr 22 19:33:51 1999
++++ work/include/linux/atmdev.h	Thu Jun  3 00:26:39 1999
 @@ -0,0 +1,363 @@
 +/* atmdev.h - ATM device driver declarations and various related items */
 + 
@@ -23701,8 +23809,8 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/include/linux/atmlec.h	Tue Feb  9 18:09:24 1999
-@@ -0,0 +1,78 @@
++++ work/include/linux/atmlec.h	Thu Jun  3 00:27:20 1999
+@@ -0,0 +1,85 @@
 +/*
 + * 
 + * ATM Lan Emulation Daemon vs. driver interface
@@ -23723,7 +23831,13 @@
 +#define ATMLEC_MCAST _IO('a',ATMIOC_LANE+2)
 +
 +/* Maximum number of LEC interfaces (tweakable) */
-+#define MAX_LEC_ITF 16
++#define MAX_LEC_ITF 48
++
++/* From the total of MAX_LEC_ITF, last NUM_TR_DEVS are reserved for Token Ring.
++ * E.g. if MAX_LEC_ITF = 48 and NUM_TR_DEVS = 8, then lec0-lec39 are for
++ * Ethernet ELANs and lec40-lec47 are for Token Ring ELANS.
++ */
++#define NUM_TR_DEVS 8
 +
 +typedef enum { 
 +        l_set_mac_addr,   l_del_mac_addr, 
@@ -23733,6 +23847,7 @@
 +        l_narp_req, /* LANE2 mandates the use of this */
 +        l_config,         l_flush_tran_id, 
 +        l_set_lecid,      l_arp_xmt,
++        l_rdesc_arp_xmt,
 +        l_associate_req,
 +        l_should_bridge   /* should we bridge this MAC? */
 +} atmlec_msg_type;
@@ -23782,7 +23897,7 @@
 +};
 +#endif /* _ATMLEC_H_ */
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/include/linux/atmmpc.h	Tue May 18 00:41:41 1999
++++ work/include/linux/atmmpc.h	Thu Jun  3 00:27:20 1999
 @@ -0,0 +1,124 @@
 +#ifndef _ATMMPC_H_
 +#define _ATMMPC_H_
@@ -24073,7 +24188,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/include/linux/atmsvc.h	Mon Mar  1 15:01:23 1999
++++ work/include/linux/atmsvc.h	Thu Jun  3 00:27:20 1999
 @@ -0,0 +1,53 @@
 +/* atmsvc.h - ATM signaling kernel-demon interface definitions */
 + 
@@ -24271,7 +24386,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/include/net/atmclip.h	Thu Apr 22 19:46:35 1999
++++ work/include/net/atmclip.h	Thu Jun  3 00:27:13 1999
 @@ -0,0 +1,62 @@
 +/* net/atm/atmarp.h - RFC1577 ATM ARP */
 + 
@@ -25152,6 +25267,27 @@
 +	unregister_qdisc(&atm_qdisc_ops);
 +}
 +#endif
+--- ref/net/802/tr.c	Wed Dec 16 22:35:50 1998
++++ work/net/802/tr.c	Wed Jun  2 23:36:00 1999
+@@ -51,7 +51,7 @@
+  
+ struct rif_cache_s {	
+ 	unsigned char addr[TR_ALEN];
+-	unsigned char iface[5];
++	unsigned char iface[10];
+ 	__u16 rcf;
+ 	__u16 rseg[8];
+ 	rif_cache next;
+@@ -354,7 +354,8 @@
+ 		}
+ 
+ 		memcpy(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);
+-		memcpy(&(entry->iface[0]),dev->name,5);
++		strncpy(entry->iface,dev->name,sizeof(entry->iface));
++		entry->iface[sizeof(entry->iface)-1] = '\0';
+ 		entry->next=rif_table[hash];
+ 		entry->last_used=jiffies;
+ 		rif_table[hash]=entry;
 --- /dev/null	Tue Jan  1 05:00:00 1980
 +++ work/net/atm/Makefile	Thu May  6 10:50:28 1999
 @@ -0,0 +1,68 @@
@@ -25386,7 +25522,7 @@
 +	return total;
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/addr.h	Thu Apr 22 19:46:47 1999
++++ work/net/atm/addr.h	Thu Jun  3 00:27:20 1999
 @@ -0,0 +1,18 @@
 +/* net/atm/addr.h - Local ATM address registry */
 +
@@ -26098,8 +26234,8 @@
 +	return 0;
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/common.c	Thu Mar 25 16:29:11 1999
-@@ -0,0 +1,933 @@
++++ work/net/atm/common.c	Thu Jun  3 00:10:44 1999
+@@ -0,0 +1,936 @@
 +/* net/atm/common.c - ATM sockets (common part for PVC and SVC) */
 +
 +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
@@ -26377,11 +26513,14 @@
 +	if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC)
 +		vcc->flags &= ~ATM_VF_PARTIAL;
 +	else if (vcc->flags & ATM_VF_PARTIAL) return -EINVAL;
-+	printk("atm_connect (TX: cl %d,bw %d-%d,sdu %d; RX: cl %d,bw %d-%d,"
-+	    "sdu %d,AAL %d)\n",vcc->qos.txtp.traffic_class,
-+	    vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu,
++	printk(KERN_DEBUG "atm_connect (TX: cl %d,bw %d-%d,sdu %d; "
++	    "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n",
++	    vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr,
++	    vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu,
 +	    vcc->qos.rxtp.traffic_class,vcc->qos.rxtp.min_pcr,
-+	    vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu,vcc->qos.aal);
++	    vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu,
++	    vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" :
++	    " ??? code ",vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal);
 +	if (!(vcc->flags & ATM_VF_HASQOS)) return -EBADFD;
 +	if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS ||
 +	    vcc->qos.rxtp.traffic_class == ATM_ANYCLASS)
@@ -27138,7 +27277,7 @@
 +	skb_queue_head_init(from);
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/ipcommon.h	Thu Apr 22 19:48:26 1999
++++ work/net/atm/ipcommon.h	Thu Jun  3 00:27:26 1999
 @@ -0,0 +1,21 @@
 +/* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */
 +
@@ -27289,8 +27428,8 @@
 +EXPORT_SYMBOL(atm_find_ci);
 +EXPORT_SYMBOL(atm_pcr_goal);
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/lec.c	Tue May 18 00:41:41 1999
-@@ -0,0 +1,2092 @@
++++ work/net/atm/lec.c	Wed Jun  2 23:36:00 1999
+@@ -0,0 +1,2180 @@
 +/*
 + * lec.c: Lan Emulation driver 
 + * Marko Kiiskila carnil@cs.tut.fi
@@ -27312,6 +27451,11 @@
 +#include <net/dst.h>
 +#include <linux/proc_fs.h>
 +
++/* TokenRing if needed */
++#ifdef CONFIG_TR
++#include <linux/trdevice.h>
++#endif
++
 +/* And atm device */
 +#include <linux/atmdev.h>
 +#include <linux/atmlec.h>
@@ -27368,7 +27512,9 @@
 +};
 +
 +/* will be lec0, lec1, lec2 etc. */
-+static char myname[] = "lecx";
++static char myname[] = "lecxx";
++
++static unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
 +
 +/* Device structures */
 +static struct device *dev_lec[MAX_LEC_ITF];
@@ -27406,10 +27552,7 @@
 +                mesg->content.normal.flag = *(skb->nh.raw + BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) & TOPOLOGY_CHANGE;
 +
 +                priv = (struct lec_priv *)dev->priv;
-+                if (atm_charge(priv->lecd, skb2->truesize) == 0) {
-+                        kfree_skb(skb2);
-+                        return;
-+                }
++                atm_force_charge(priv->lecd, skb2->truesize);
 +                skb_queue_tail(&priv->lecd->recvq, skb2);
 +                wake_up(&priv->lecd->sleep);
 +        }
@@ -27419,6 +27562,49 @@
 +#endif /* CONFIG_BRIDGE */
 +
 +/*
++ * Modelled after tr_type_trans
++ * All multicast and ARE or STE frames go to BUS.
++ * Non source routed frames go by destination address.
++ * Last hop source routed frames go by destination address.
++ * Not last hop source routed frames go by _next_ route descriptor.
++ * Returns pointer to destination MAC address or fills in rdesc
++ * and returns NULL.
++ */
++#ifdef CONFIG_TR
++unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
++{
++        struct trh_hdr *trh;
++        int riflen, num_rdsc;
++        
++        trh = (struct trh_hdr *)packet;
++        if (trh->daddr[0] & (uint8_t)0x80)
++                return bus_mac; /* multicast */
++
++        if (trh->saddr[0] & TR_RII) {
++                riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
++                if ((ntohs(trh->rcf) >> 13) != 0)
++                        return bus_mac; /* ARE or STE */
++        }
++        else
++                return trh->daddr; /* not source routed */
++
++        if (riflen < 6)
++                return trh->daddr; /* last hop, source routed */
++                
++        /* riflen is 6 or more, packet has more than one route descriptor */
++        num_rdsc = (riflen/2) - 1;
++        memset(rdesc, 0, ETH_ALEN);
++        /* offset 4 comes from LAN destination field in LE control frames */
++        if (trh->rcf & htons((uint16_t)TR_RCF_DIR_BIT))
++                memcpy(&rdesc[4], &trh->rseg[num_rdsc-2], sizeof(uint16_t));
++        else
++                memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t));
++
++        return NULL;
++}
++#endif /* CONFIG_TR */
++
++/*
 + * Open/initialize the netdevice. This is called (in the current kernel)
 + * sometime after booting when the 'ifconfig' program is run.
 + *
@@ -27448,7 +27634,9 @@
 +        struct lecdatahdr_8023 *lec_h;
 +        struct atm_vcc *send_vcc;
 +	struct lec_arp_table *entry;
-+        unsigned char *nb;
++        unsigned char *nb, *dst;
++        unsigned char rdesc[ETH_ALEN]; /* Token Ring route descriptor */
++        int is_rdesc;
 +#if DUMP_PACKETS > 0
 +        char buf[300];
 +        int i=0;
@@ -27498,7 +27686,7 @@
 +                }
 +                skb_push(skb, 2);
 +
-+                /* Put le header to place */
++                /* Put le header to place, works for TokenRing too */
 +                lec_h = (struct lecdatahdr_8023*)skb->data;
 +                lec_h->le_header = htons(priv->lecid); 
 +
@@ -27540,8 +27728,19 @@
 +                }
 +
 +                /* Send to right vcc */
++                is_rdesc = 0;
++                dst = lec_h->h_dest;
++#ifdef CONFIG_TR
++                if (priv->is_trdev) {
++                        dst = get_tr_dst(skb->data+2, rdesc);
++                        if (dst == NULL) {
++                                dst = rdesc;
++                                is_rdesc = 1;
++                        }
++                }
++#endif
 +                entry = NULL;
-+                send_vcc = lec_arp_resolve(priv, lec_h->h_dest, &entry);
++                send_vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
 +                DPRINTK("%s:send_vcc:%p vcc_flags:%x, entry:%p\n", dev->name,
 +                        send_vcc, send_vcc?send_vcc->flags:0, entry);
 +                if (!send_vcc || !(send_vcc->flags & ATM_VF_READY)) {    
@@ -27723,10 +27922,7 @@
 +                        if (skb2 == NULL) break;
 +                        skb2->len = sizeof(struct atmlec_msg);
 +                        memcpy(skb2->data, mesg, sizeof(struct atmlec_msg));
-+                        if (atm_charge(priv->lecd, skb2->truesize) == 0) {
-+                                kfree_skb(skb2);
-+                                break;
-+                        }
++                        atm_force_charge(priv->lecd, skb2->truesize);
 +                        skb_queue_tail(&priv->lecd->recvq, skb2);
 +                        wake_up(&priv->lecd->sleep);
 +                }
@@ -27833,21 +28029,13 @@
 +	if (atm_addr)
 +		memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
 +
-+        if (atm_charge(priv->lecd, skb->truesize) == 0) {
-+                DPRINTK("lec: send_to_lecd, atm_charge()\n");
-+                kfree_skb(skb);
-+                return -1;
-+        }
++        atm_force_charge(priv->lecd, skb->truesize);
 +	skb_queue_tail(&priv->lecd->recvq, skb);
 +        wake_up(&priv->lecd->sleep);
 +
 +        if (data != NULL) {
 +                DPRINTK("lec: about to send %d bytes of data\n", data->len);
-+                if (atm_charge(priv->lecd, data->truesize) == 0) {
-+                        printk("lec: send_to_lecd, atm_charge\n");
-+                        kfree_skb(data);
-+                        return -1;
-+                }
++                atm_force_charge(priv->lecd, data->truesize);
 +                skb_queue_tail(&priv->lecd->recvq, data);
 +                wake_up(&priv->lecd->sleep);
 +        }
@@ -27867,13 +28055,14 @@
 +static int 
 +lec_init(struct device *dev)
 +{
-+        dev->priv = kmalloc(sizeof(struct lec_priv), GFP_KERNEL);
-+        if (!dev->priv)
-+                return -ENOMEM;
-+
-+        memset(dev->priv,0,sizeof(struct lec_priv));
++        struct lec_priv *priv;
 +
-+        ether_setup(dev);
++        priv = (struct lec_priv *)dev->priv;
++        if (priv->is_trdev) {
++#ifdef CONFIG_TR
++                init_trdev(dev, 0);
++#endif
++        } else ether_setup(dev);
 +        dev->change_mtu = lec_change_mtu;
 +        dev->open = lec_open;
 +        dev->stop = lec_close;
@@ -27948,6 +28137,10 @@
 +                }
 +                skb->dev = dev;
 +                skb->data += 2; /* skip lec_id */
++#ifdef CONFIG_TR
++                if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev);
++                else
++#endif
 +                skb->protocol = eth_type_trans(skb, dev);
 +                netif_rx(skb);
 +                priv->stats.rx_packets++;
@@ -27996,8 +28189,13 @@
 +                i = 0;
 +        else
 +                i = arg;
++#ifdef CONFIG_TR
 +        if (arg >= MAX_LEC_ITF)
 +                return -EINVAL;
++#else /* Reserve the top NUM_TR_DEVS for TR */
++        if (arg >= (MAX_LEC_ITF-NUM_TR_DEVS))
++                return -EINVAL;
++#endif
 +        if (!dev_lec[i]) {
 +                dev_lec[i] = (struct device*)kmalloc(sizeof(struct device)+
 +                                                     sizeof(myname)+1, 
@@ -28005,13 +28203,23 @@
 +                if (!dev_lec[i])
 +                        return -ENOMEM;
 +                memset(dev_lec[i],0, sizeof(struct device)+sizeof(myname)+1);
++
++                dev_lec[i]->priv = kmalloc(sizeof(struct lec_priv), GFP_KERNEL);
++                if (!dev_lec[i]->priv)
++                        return -ENOMEM;
++                memset(dev_lec[i]->priv,0,sizeof(struct lec_priv));
++                priv = (struct lec_priv *)dev_lec[i]->priv;
++
++                if (i >= (MAX_LEC_ITF - NUM_TR_DEVS))
++                        priv->is_trdev = 1;
++
 +                dev_lec[i]->name = (char*)(dev_lec[i]+1);
 +                sprintf(dev_lec[i]->name, "lec%d",i);
 +                dev_lec[i]->init = lec_init;
 +                if ((result = register_netdev(dev_lec[i])) !=0)
 +                        return result;
-+                priv = (struct lec_priv *)dev_lec[i]->priv;
-+	} else {
++                sprintf(dev_lec[i]->name, "lec%d", i); /* init_trdev globbers device name */
++        } else {
 +                priv = (struct lec_priv *)dev_lec[i]->priv;
 +                if (priv->lecd)
 +                        return -EADDRINUSE;
@@ -28070,6 +28278,7 @@
 +{
 +        int i;
 +        extern struct atm_lane_ops atm_lane_ops;
++        struct lec_priv *priv;
 +
 +        if (MOD_IN_USE) {
 +                printk(KERN_NOTICE "lec.c: module in use\n");
@@ -28083,7 +28292,13 @@
 +
 +        for (i = 0; i < MAX_LEC_ITF; i++) {
 +                if (dev_lec[i] != NULL) {
-+                        unregister_netdev(dev_lec[i]);
++                        priv = (struct lec_priv *)dev_lec[i]->priv;
++                        if (priv->is_trdev) {
++#ifdef CONFIG_TR
++                                unregister_trdev(dev_lec[i]);
++#endif
++                        } else
++                                unregister_netdev(dev_lec[i]);
 +                        kfree(dev_lec[i]->priv);
 +                        kfree(dev_lec[i]);
 +                        dev_lec[i] = NULL;
@@ -28704,8 +28919,10 @@
 +        DPRINTK("lec_arp_expire_arp\n");
 +        if (entry->status == ESI_ARP_PENDING) {
 +                if (entry->no_tries <= entry->priv->max_retry_count) {
-+                        send_to_lecd(entry->priv, l_arp_xmt, 
-+                                     entry->mac_addr, NULL, NULL);
++                        if (entry->is_rdesc)
++                                send_to_lecd(entry->priv, l_rdesc_arp_xmt, entry->mac_addr, NULL, NULL);
++                        else
++                                send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL);
 +                        entry->no_tries++;
 +                }
 +                entry->timer.expires = jiffies + (1*HZ);
@@ -28845,10 +29062,9 @@
 + * 
 + */
 +struct atm_vcc*
-+lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find,
++lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc,
 +                struct lec_arp_table **ret_entry)
 +{
-+        unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
 +        struct lec_arp_table *entry;
 +
 +        if (mac_to_find[0]&0x01) {
@@ -28904,7 +29120,11 @@
 +                entry->status = ESI_ARP_PENDING;
 +                entry->no_tries = 1;
 +                entry->last_used = entry->timestamp = jiffies;
-+                send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);
++                entry->is_rdesc = is_rdesc;
++                if (entry->is_rdesc)
++                        send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL, NULL);
++                else
++                        send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);
 +                entry->timer.expires = jiffies + (1*HZ);
 +                entry->timer.function = lec_arp_expire_arp;
 +                add_timer(&entry->timer);
@@ -29057,7 +29277,6 @@
 +{
 +        struct lec_arp_table *entry;
 +        int i, found_entry=0;
-+        unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff,0xff};
 +
 +        lec_arp_lock(priv);
 +        if (ioc_data->receive == 2) {
@@ -29335,20 +29554,28 @@
 +        struct lec_arp_table *entry, *prev;
 +        struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
 +        unsigned long flags;
-+  
++        unsigned char *src;
++#ifdef CONFIG_TR
++        struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
++
++        if (priv->is_trdev) src = tr_hdr->h_source;
++        else
++#endif
++        src = hdr->h_source;
++
 +        lec_arp_lock(priv);
 +        entry = priv->lec_arp_empty_ones;
 +        if (vcc == entry->vcc) {
 +                save_flags(flags);
 +                cli();
 +                del_timer(&entry->timer);
-+                memcpy(entry->mac_addr, hdr->h_source, ETH_ALEN);
++                memcpy(entry->mac_addr, src, ETH_ALEN);
 +                entry->status = ESI_FORWARD_DIRECT;
 +                entry->last_used = jiffies;
 +                priv->lec_arp_empty_ones = entry->next;
 +                restore_flags(flags);
 +                /* We might have got an entry */
-+                if ((prev=lec_arp_find(priv,hdr->h_source))) {
++                if ((prev=lec_arp_find(priv,src))) {
 +                        lec_arp_remove(priv->lec_arp_tables, prev);
 +                        kfree(prev);
 +                }
@@ -29370,12 +29597,12 @@
 +        save_flags(flags);
 +        cli();
 +        del_timer(&entry->timer);
-+        memcpy(entry->mac_addr, hdr->h_source, ETH_ALEN);
++        memcpy(entry->mac_addr, src, ETH_ALEN);
 +        entry->status = ESI_FORWARD_DIRECT;
 +        entry->last_used = jiffies;
 +        prev->next = entry->next;
 +        restore_flags(flags);
-+        if ((prev = lec_arp_find(priv, hdr->h_source))) {
++        if ((prev = lec_arp_find(priv, src))) {
 +                lec_arp_remove(priv->lec_arp_tables,prev);
 +                kfree(prev);
 +        }
@@ -29384,8 +29611,8 @@
 +}
 +
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/lec.h	Thu Apr 22 19:46:47 1999
-@@ -0,0 +1,149 @@
++++ work/net/atm/lec.h	Thu Jun  3 00:27:20 1999
+@@ -0,0 +1,150 @@
 +/*
 + *
 + * Lan Emulation client header file
@@ -29414,7 +29641,7 @@
 +  unsigned short le_header;
 +  unsigned char ac_pad;
 +  unsigned char fc;
-+  unsigned char h_dst[ETH_ALEN];
++  unsigned char h_dest[ETH_ALEN];
 +  unsigned char h_source[ETH_ALEN];
 +};
 +
@@ -29519,6 +29746,7 @@
 +	int itfnum;        /* e.g. 2 for lec2, 5 for lec5        */
 +        struct lane2_ops *lane2_ops; /* can be NULL for LANE v1  */
 +        int is_proxy;      /* bridge between ATM and Ethernet    */
++        int is_trdev;      /* Device type, 0 = Ethernet, 1 = TokenRing */
 +};
 +
 +int lecd_attach(struct atm_vcc *vcc, int arg);
@@ -29536,8 +29764,8 @@
 +#endif _LEC_H_
 +
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/lec_arpc.h	Thu Apr 22 19:46:47 1999
-@@ -0,0 +1,114 @@
++++ work/net/atm/lec_arpc.h	Thu Jun  3 00:27:20 1999
+@@ -0,0 +1,116 @@
 +/*
 + * Lec arp cache
 + * Marko Kiiskila carnil@cs.tut.fi
@@ -29554,6 +29782,7 @@
 +        struct lec_arp_table *next;          /* Linked entry list */
 +        unsigned char atm_addr[ATM_ESA_LEN]; /* Atm address */
 +        unsigned char mac_addr[ETH_ALEN];    /* Mac address */
++        int is_rdesc;                        /* Mac address is a route descriptor */
 +        struct atm_vcc *vcc;                 /* Vcc this entry is attached */
 +        struct atm_vcc *recv_vcc;            /* Vcc we receive data from */
 +        void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); 
@@ -29636,6 +29865,7 @@
 +
 +struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
 +                                unsigned char *mac_to_addr,
++                                int is_rdesc,
 +                                struct lec_arp_table **ret_entry);
 +void lec_vcc_added(struct lec_priv *dev,
 +                   struct atmlec_ioc *ioc_data, struct atm_vcc *vcc,
@@ -29653,8 +29883,8 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/mpc.c	Tue May 18 00:41:41 1999
-@@ -0,0 +1,1480 @@
++++ work/net/atm/mpc.c	Wed Jun  2 23:36:00 1999
+@@ -0,0 +1,1470 @@
 +#include <linux/kernel.h>
 +#include <linux/string.h>
 +#include <linux/timer.h>
@@ -30608,12 +30838,7 @@
 +                return -ENOMEM;
 +        skb_put(skb, sizeof(struct k_message));
 +        memcpy(skb->data, mesg, sizeof(struct k_message));
-+        if (atm_charge(mpc->mpoad_vcc, skb->truesize) == 0) {
-+                printk("mpoa: msg_to_mpoad: atm_charge failed\n");
-+                kfree_skb(skb);
-+                return -ENOMEM;
-+        }
-+
++        atm_force_charge(mpc->mpoad_vcc, skb->truesize);
 +        skb_queue_tail(&mpc->mpoad_vcc->recvq, skb);
 +        wake_up(&mpc->mpoad_vcc->sleep);
 +
@@ -30872,12 +31097,7 @@
 +        if (entry != NULL)
 +                purge_msg->content.eg_info = entry->ctrl_info;
 +
-+        if (atm_charge(vcc, skb->truesize) == 0) {
-+                printk("mpoa: purge_egress_shortcut: atm_charge failed\n");
-+                kfree_skb(skb);
-+                return;
-+        }
-+
++        atm_force_charge(vcc, skb->truesize);
 +        skb_queue_tail(&vcc->recvq, skb);
 +        wake_up(&vcc->sleep);
 +        dprintk("mpoa: purge_egress_shortcut: exiting:\n");
@@ -31136,7 +31356,7 @@
 +}
 +#endif /* MODULE */
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/mpc.h	Tue May 18 01:14:52 1999
++++ work/net/atm/mpc.h	Thu Jun  3 00:27:20 1999
 @@ -0,0 +1,65 @@
 +#ifndef _MPC_H_
 +#define _MPC_H_
@@ -31764,7 +31984,7 @@
 +        return;
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/mpoa_caches.h	Tue May 18 01:14:52 1999
++++ work/net/atm/mpoa_caches.h	Thu Jun  3 00:27:20 1999
 @@ -0,0 +1,90 @@
 +#ifndef MPOA_CACHES_H
 +#define MPOA_CACHES_H
@@ -32302,8 +32522,8 @@
 +}        
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/proc.c	Thu Feb 18 17:39:31 1999
-@@ -0,0 +1,615 @@
++++ work/net/atm/proc.c	Thu Jun  3 00:20:33 1999
+@@ -0,0 +1,617 @@
 +/* net/atm/proc.c - ATM /proc interface */
 +
 +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
@@ -32551,8 +32771,10 @@
 +{
 +	static const char *class_name[] = { "off","UBR","CBR","VBR","ABR" };
 +	static const char *aal_name[] = {
-+		"0",	"1",	"2",	"3/4",	/*  0- 3 */
-+		"???",	"5",	"???",	"???" };/*  4- 7 */
++		"---",	"1",	"2",	"3/4",	/*  0- 3 */
++		"???",	"5",	"???",	"???",	/*  4- 7 */
++		"???",	"???",	"???",	"???",	/*  8-11 */
++		"???",	"0",	"???",	"???"};	/* 12-15 */
 +	int off;
 +
 +	off = sprintf(buf,"%3d %3d %5d %-3s %7d %-5s %7d %-6s",
@@ -33388,7 +33610,7 @@
 +EXPORT_SYMBOL(shutdown_atm_dev);
 +EXPORT_SYMBOL(bind_vcc);
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/resources.h	Thu Apr 22 19:46:47 1999
++++ work/net/atm/resources.h	Thu Jun  3 00:27:20 1999
 @@ -0,0 +1,32 @@
 +/* net/atm/resources.h - ATM-related resources */
 +
@@ -33678,7 +33900,7 @@
 +	return 0;
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/signaling.h	Thu Apr 22 19:46:47 1999
++++ work/net/atm/signaling.h	Thu Jun  3 00:27:20 1999
 @@ -0,0 +1,25 @@
 +/* net/atm/signaling.h - ATM signaling */
 + 
diff -ur --new-file old/atm/doc/usage.tex new/atm/doc/usage.tex
--- old/atm/doc/usage.tex	Tue May 18 01:20:52 1999
+++ new/atm/doc/usage.tex	Wed Jun  2 23:55:42 1999
@@ -1,7 +1,7 @@
-7%def%:=
+%def%:=
 
 %:\begin{verbatim}
-%:Usage instructions  -  ATM on Linux, release 0.57
+%:Usage instructions  -  ATM on Linux, release 0.58
 %:-------------------------------------------------
 %:
 %:\end{verbatim}
@@ -38,14 +38,14 @@
 
 \title{ATM on Linux \\
   User's guide \\
-  Release 0.57 (alpha)}
+  Release 0.58 (alpha)}
 \author{Werner Almesberger \\
   {\tt Werner.Almesberger@epfl.ch} \\
   \\
   Institute for computer Communications and Applications (ICA) \\
   EPFL, CH-1015 Lausanne, Switzerland}
  
-\date{November 6, 1998}
+\date{June 3, 1999}
 
 \begin{document}
 \maketitle
@@ -82,7 +82,7 @@
 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.57.tar.gz}
+    \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.58.tar.gz}
   \item the Linux kernel, version 2.2.1, e.g. from
     \url{ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.2.1.tar.gz}
   \item Perl, version 4 or 5
@@ -99,7 +99,7 @@
 distribution:
 
 \begin{verbatim}
-tar xfz atm-0.57.tar.gz
+tar xfz atm-0.58.tar.gz
 \end{verbatim}
 
 and the kernel source:
@@ -133,7 +133,6 @@
     \name{ttcp\_atm}, \name{window}
   \item[\path{atm/arpd/}] ATMARP tools and demon: \name{atmarp}, \name{atmarpd}
   \item[\path{atm/led/}] LAN Emulation demon: \name{zeppelin}
-  \item[\path{atm/led.new/}] Experimental version: \name{zeppelin.new}
   \item[\path{atm/lane/}] LAN Emulation servers: \name{bus}, \name{lecs},
     \name{les}
   \item[\path{atm/mpoad/}] Multi-Protocol Over ATM demon: \name{mpcd}
@@ -1000,7 +999,7 @@
 an proxy LEC. These parameters can be tailored with command line
 options which are defined in \name{zeppelin.8}.
 
-The new zeppelin, \name{zeppelin.new}, will automatically join any
+\name{zeppelin}, will automatically join any
 ELANs which use higher MTU than the default MTU of 1516
 bytes. However, the MTU of the LANE interface will not change before
 you use \raw{ifconfig} to adjust it. This will probably change later
diff -ur --new-file old/atm/doc/usage.txt new/atm/doc/usage.txt
--- old/atm/doc/usage.txt	Tue May 18 01:30:05 1999
+++ new/atm/doc/usage.txt	Thu Jun  3 00:23:59 1999
@@ -1,6 +1,4 @@
-7
-
-%:Usage instructions  -  ATM on Linux, release 0.57
+%:Usage instructions  -  ATM on Linux, release 0.58
 %:-------------------------------------------------
 %:
 %:
@@ -22,7 +20,7 @@
 In order to install this package, you need 
 
   - the package itself  
-    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.57.tar.gz  
+    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.58.tar.gz  
   - the Linux kernel, version 2.2.1, e.g. from  
     ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.2.1.tar.gz  
   - Perl, version 4 or 5 
@@ -38,7 +36,7 @@
 all the files listed above there. Then extract the ATM on Linux 
 distribution:
 
-tar xfz atm-0.57.tar.gz
+tar xfz atm-0.58.tar.gz
 
 and the kernel source:
 
@@ -63,7 +61,6 @@
     ttcp_atm, window 
   atm/arpd/  ATMARP tools and demon: atmarp, atmarpd 
   atm/led/  LAN Emulation demon: zeppelin 
-  atm/led.new/  Experimental version: zeppelin.new 
   atm/lane/  LAN Emulation servers: bus, lecs, les 
   atm/mpoad/  Multi-Protocol Over ATM demon: mpcd 
   atm/aqd/  Arequipa demon: aqpvc, arequipad 
@@ -828,11 +825,11 @@
 parameters can be tailored with command line options which are defined in 
 zeppelin.8.
 
-The new zeppelin, zeppelin.new, will automatically join any ELANs which use 
-higher MTU than the default MTU of 1516 bytes. However, the MTU of the LANE 
-interface will not change before you use  ifconfig  to adjust it. This will 
-probably change later so that the interface MTU will adjust itself 
-according to the MTU of the current ELAN.
+zeppelin, will automatically join any ELANs which use higher MTU than the 
+default MTU of 1516 bytes. However, the MTU of the LANE interface will not 
+change before you use  ifconfig  to adjust it. This will probably change 
+later so that the interface MTU will adjust itself according to the MTU of 
+the current ELAN.
 
 The state of the LANE ARP cache entries can be monitored through 
 /proc/atm/lec. For each entry the MAC and ATM addresses and status is 
diff -ur --new-file old/atm/led/COPYRIGHT.DEC new/atm/led/COPYRIGHT.DEC
--- old/atm/led/COPYRIGHT.DEC	Wed Nov 19 12:59:15 1997
+++ new/atm/led/COPYRIGHT.DEC	Thu Jan  1 01:00:00 1970
@@ -1,11 +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.  
- *************************************************************************/
diff -ur --new-file old/atm/led/Makefile new/atm/led/Makefile
--- old/atm/led/Makefile	Wed Nov 19 12:59:16 1997
+++ new/atm/led/Makefile	Wed Jun  2 23:37:34 1999
@@ -1,11 +1,10 @@
-LIBS=-latm
-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
+LIBS=-latm -latmd
+OBJS=join.o conn.o main.o address.o frames.o display.o kernel.o
 BOOTPGMS=zeppelin
-MAN8= zeppelin.8
-CFLAGS_PRIVATE=-ansi -pedantic
+MAN8=zeppelin.8
+CFLAGS_PRIVATE=
 
 include ../Rules.make
 
-zeppelin:		$(OBJS)
-			$(CC) $(LDFLAGS) -o zeppelin $(OBJS) $(LIBD) $(LDLIBS)
+zeppelin:$(OBJS)
+	$(CC) $(LDFLAGS) -o $(BOOTPGMS) $(OBJS) $(LIBD) $(LDLIBS) $(LIBS)
diff -ur --new-file old/atm/led/addr_reg.h new/atm/led/addr_reg.h
--- old/atm/led/addr_reg.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/addr_reg.h	Thu Jan  1 01:00:00 1970
@@ -1,265 +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:
-*   addr_reg.h
-*
-* Abstract:
-*   This file is the interface to the ATM address registration.
-*
-* Authors:
-*   DMW - Douglas M. Washabaugh
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description
-*   06-Oct-94  DMW   Created.
-*   07-Nov-94  DMW   Updated with review comments, reversed order of routines.
-*   29-Mar-95  TLR   Changed callback typedef to a pointer.
-*   16-May-95  TLR   Added support for event reporting.
-*   06-Sep-95  TLR   Added special address allocation call.
-*
-* Description:   
-*
-*   MANAGEMENT INTEFACE:
-*   
-*   The management interface does not perform any work, but enables applications
-*   to have some visibility into this module.  Currently the management
-*   interface exports functions to determine the state of address registration
-*   and to get a list of the ATM addresses that have been registered.  Generally
-*   these routines can be called at any time.
-*
-* Call Sequence:
-*   addr_reg_create              - Creates an instance, inits the MAC addresses.
-*   addr_reg_client_register     - Client registers
-*   addr_reg_atm_addr_alloc      - Gets and registers an ATM address.
-*   addr_reg_atm_addr_dealloc    - Deregister an ATM address.
-*   addr_reg_destroy             - Returns any allocated resources.
-*
-* Issues:
-*   - Do the clients need to be able to deregister themselves?  Currently this
-*     interface assumes that they do not.
-*
-*   - Does the management interface require the state of each client?  Does
-*     it require a list of clients?
---*/
-
-/* Define the types of events for address status change callbacks. */
-
-typedef enum
-   {
-   ADDR_REG_EVENT_ATM_ADDR_ALLOCATED,   /* An ATM address was registered.   */
-   ADDR_REG_EVENT_ATM_ADDR_INVALIDATED  /* Registered addr was invalidated. */
-   } ADDR_REG_ADDR_EVENT;
-
-/* Define values for the addr_reg_special_alloc call. */
-
-#define ADDR_REG_ESI_NEW  0x8001
-#define ADDR_REG_ESI_ANY  0x8002
-#define ADDR_REG_SEL_ANY  0x8003
-
-/*++
-* ---------------------
-* - ADDR_REG_CALLBACK -
-* ---------------------
-*
-* Overview:
-*   This is the callback made whenever an address is invalidated or registered.
-*   In the event an address is invalidated, the selector of the address is not
-*   significant.  All addresses with the provided prefix and ESI are to be
-*   considered invalidated by this single callback.
-*
-* Arguments:
-*   context    - (IN)  The caller context (handle) that was specified when
-*                      the address was registered.
-*
-*   p_atm_addr - (IN)  Pointer to the ATM address that was registered.  This
-*                      pointer is only valid in the callback routine.  It 
-*                      may not be saved away.  Instead, the ATM address must
-*                      be copied.
-*
-*   event      - (IN)  The event associated with the ATM address.  The event 
-*                      is one of: ADDR_REG_ADDR_EVENT_REGISTERED, 
-*                      ADDR_REG_ADDR_EVENT_INVALIDATED.
-*
-* Returns:
-*   none
-*
-* Preconditions:
-*   The registration of an address was started and or completed. 
-*
-* Postconditions:
-*   none
-*
-* Issues:
-*   none
---*/                                              
-
-typedef void (*ADDR_REG_CALLBACK) (HANDLE               context,
-                                   ADDR_ATM            *p_atm_addr,
-                                   ADDR_REG_ADDR_EVENT  event);   
-
-/*++
-* ============================
-* = addr_reg_client_register =
-* ============================
-*
-* Overview:
-*   Registers a client.  After a client is registered, it may register and 
-*   deregister ATM addresses.  A client must
-*   register so that it can be told about changes in ATM addresses.
-*
-* Arguments:
-*   addr_reg_handle - (IN)  The handle that was returned from addr_reg_create.
-*
-*   p_callback      - (IN)  A pointer to a routine to call when an ATM address
-*                           registration or deregistration has completed.
-* 
-*   callback_handle - (IN)  A value that is passed on a callback to the client.
-*
-*   p_text          - (IN)  A text string to describe this client.
-*
-*   p_client_handle - (OUT) Handle that may be required for subsequent calls
-*                           to this module.
-* Returns:
-*   STATUS_K_SUCCESS   - Client is registered.
-*   STATUS_K_RESOURCES - Client is NOT registered.
-*
-* Preconditions:
-*   addr_reg_create returned a valid handle.
-*
-* Postconditions:
-*   On success, the client handle is valid.
-*
-* Issues:
-*   none
---*/                                              
-
-STATUS addr_reg_client_register (HANDLE             addr_reg_handle,
-                                 ADDR_REG_CALLBACK  callback,
-                                 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);
-
-/*++
-* ===========================
-* = addr_reg_atm_addr_alloc =
-* ===========================
-*
-* Overview:
-*   Directs this module to start the process of registering an ATM address
-*   with the switch.  When the registration completes, the client is called
-*   back.
-*  
-*   This routine can be anytime after the client has registered.  Note the 
-*   client can only have one outstanding registration request at a time.
-*
-* Arguments:
-*   client_handle - (IN) The handle that was returned from
-*                        addr_reg_client_register.
-*
-* Returns:
-*   STATUS_K_PENDING - Operation successfully queued.
-*   STATUS_K_BUSY    - Client already has a pending operation.
-*
-* Preconditions:
-*   - The routine addr_reg_create was called. 
-*   - The routine addr_reg_client_register was called.
-*
-* Postconditions:
-*   The registration of the address will start at the next opportunity.  An
-*   opportunity occurs when there is not another pending address registration
-*   and there is at least one network prefix with an available MAC address.
-*
-* Issues:
-*   none
---*/                                              
-
-STATUS addr_reg_atm_addr_alloc (HANDLE client_handle);
- 
-/*++
-* =============================
-* = addr_reg_atm_addr_dealloc =
-* =============================
-*
-* Overview:
-*   The specified ATM address is deallocated and can be reused.  After this
-*   call completes, no more packets destined to the ATM address should be sent.
-*
-* Arguments:
-*   client_handle - (IN) The handle that was returned from
-*                        addr_reg_client_register.
-*
-*   p_atm_addr    - (IN) Pointer to the ATM address to deregister.
-*
-* Returns:
-*   STATUS_K_SUCCESS  - The the operation was successfully queued.
-*   STATUS_K_ARG2_BAD - The MAC address is not registered.
-*
-* Preconditions:
-*   - The routine addr_reg_create was called. 
-*   - The routine addr_reg_client_register was called.
-*
-* Postconditions:
-*   The specified ATM address available for reuse.
-*
-* Issues:
-*   none
---*/                                              
-
-STATUS addr_reg_atm_addr_dealloc (HANDLE    client_handle,
-                                  ADDR_ATM *p_atm_addr); 
-
-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	Tue Aug 11 16:53:56 1998
+++ new/atm/led/address.c	Wed Jun  2 23:36:52 1999
@@ -1,3 +1,5 @@
+/* address.c - functions to query ESI and local ATM address from kernel */
+
 /*
  * Marko Kiiskila carnil@cs.tut.fi 
  * 
@@ -22,432 +24,70 @@
  * 
  */
 
-/*
- *
- * Client registration/query funcs used in Digital's code
- *
- * $Id: address.c,v 1.13 1996/08/06 14:14:11 carnil Exp carnil $
- *
- */
-
+/*  Copyright (C) 1999  Heikki Vatiainen hessu@cs.tut.fi */
 
-/* Global prototypes */
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <sys/socket.h>
+#include <sys/ioctl.h>
 #include <unistd.h>
+#include <errno.h>
 
-/* Atm includes */
 #include <atm.h>
 #include <linux/atmdev.h>
-#include <sys/ioctl.h>
-#include <atm.h>
-
-/* Digital prototypes */
-#include "g_types.h"
-#include "lane_atm.h"
-#include "af_lane.h"
-#include "addr_reg.h"
-#include "codes.h"
-#include "g_event.h"
-#include "utl_os.h"
-#include "le_disp.h"
-
-#define EMOD MOD_ADDR_REG
-#define EINST "address.c"
-
-#include "emask.h"
-
-#define ADDR_TIMER_FREQ 5000
-
-/* One-way list. There won't be that many clients registered.. */
-typedef struct _client_t_ {
-  ADDR_REG_CALLBACK callback; /* Callback func */
-  HANDLE callback_handle; /* Handle to give in callback */
-  char *name; /* Describing text string */
-  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;
-
-void addr_reg_timer_callback(HANDLE context);
-
-STATUS 
-addr_reg_client_register (HANDLE addr_reg_handle, ADDR_REG_CALLBACK callback,
-			  HANDLE callback_handle, const char *p_text,
-			  HANDLE *p_client_handle)
-{
-  Client_t *to_register;
-
-  EVENT(EM_DEBUG,("Addr_reg_client_register\n"));
-  assert(callback);
-  to_register = (Client_t*)mem_alloc(EINST,sizeof(Client_t));
-  if (!to_register)
-    return STATUS_K_RESOURCES;
-  to_register->callback = callback;
-  to_register->callback_handle = callback_handle;
-  if (p_text) {
-    to_register->name = (char*)mem_alloc(EINST,
-					 sizeof(char)*(strlen(p_text)+1));
-    if (!to_register->name) {
-      mem_free(EINST,to_register);
-      return STATUS_K_RESOURCES;
-    }
-    memcpy(to_register->name, p_text, strlen(p_text));
-    to_register->name[strlen(p_text)] = '\0';
-  } else {
-    /* No name. Still allocate some room, to avoid suprises in
-       memory references to name :) */
-    to_register->name = (char*)mem_alloc(EINST,sizeof(char));
-    if (!to_register->name) {
-      mem_free(EINST,to_register);
-      return STATUS_K_RESOURCES;
-    }
-    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;
-  Clientlist = to_register;
-  return os_timer_alloc(addr_reg_timer_callback, to_register, 
-			&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)
-{
-  Client_t *client;
-
-  EVENT(EM_DEBUG,("Addr_reg_atm_addr_alloc\n"));
-
-  client = (Client_t *)client_handle;
-
-  if (ATM_EQUAL_NULL(client->addr)) {
-    client->notify=1;
-    addr_reg_timer_callback((HANDLE)client);
-  } else {
-    client->notify=0;
-    client->callback(client->callback_handle,&client->addr, 
-		     ADDR_REG_EVENT_ATM_ADDR_ALLOCATED);
-    addr_reg_timer_callback((HANDLE)client);
-  }
-  return STATUS_K_SUCCESS;
-}
-
-STATUS 
-addr_reg_atm_addr_dealloc (HANDLE client_handle, ADDR_ATM *p_atm_addr)
-{
-  Client_t *client;
-
-  EVENT(EM_DEBUG,("Addr_reg_atm_addr_dealloc\n"));
-
-  client = (Client_t *)client_handle;
-
-  /* Dealloc atm address, if allocated */
-  ATM_COPY_NULL(client->addr);
-  /* Call callback */
-  return STATUS_K_SUCCESS;
-}
-
-void
-addr_set_atm_addr(ADDR_ATM *set_to)
-{
-  Client_t *client = Clientlist;
-
-  ATM_COPY(*set_to, client->addr);
-  EVENT(EM_DEBUG,("Addr_set_atm_addr %s\n",disp_atm_text(client->addr)));
-}
-
-int
-address_convert(char* parsestring, ADDR_ATM *atm_addr)
-{
-  struct sockaddr_atmsvc tmp;
+#include <atmd.h>
 
-  if (text2atm(parsestring, (struct sockaddr*)&tmp, sizeof(tmp),
-	       T2A_NAME) <0) {
-    return -1;
-  }
-  atm_addr->prefix[0] = tmp.sas_addr.prv[0];
-  atm_addr->prefix[1] = tmp.sas_addr.prv[1];
-  atm_addr->prefix[2] = tmp.sas_addr.prv[2];
-  atm_addr->prefix[3] = tmp.sas_addr.prv[3];
-  atm_addr->prefix[4] = tmp.sas_addr.prv[4];
-  atm_addr->prefix[5] = tmp.sas_addr.prv[5];
-  atm_addr->prefix[6] = tmp.sas_addr.prv[6];
-  atm_addr->prefix[7] = tmp.sas_addr.prv[7];
-  atm_addr->prefix[8] = tmp.sas_addr.prv[8];
-  atm_addr->prefix[9] = tmp.sas_addr.prv[9];
-  atm_addr->prefix[10] = tmp.sas_addr.prv[10];
-  atm_addr->prefix[11] = tmp.sas_addr.prv[11];
-  atm_addr->prefix[12] = tmp.sas_addr.prv[12];
-  atm_addr->esi[0] = tmp.sas_addr.prv[13];
-  atm_addr->esi[1] = tmp.sas_addr.prv[14];
-  atm_addr->esi[2] = tmp.sas_addr.prv[15];
-  atm_addr->esi[3] = tmp.sas_addr.prv[16];
-  atm_addr->esi[4] = tmp.sas_addr.prv[17];
-  atm_addr->esi[5] = tmp.sas_addr.prv[18];
-  atm_addr->sel = tmp.sas_addr.prv[19];
-  return 0;
-}
+#include "address.h"
 
-void 
-addr_reg_timer_callback(HANDLE context)
-{
-  Client_t *client = (Client_t *)context;
-  unsigned char *buffer;
-  struct sockaddr_atmsvc *ouraddr;
-  struct atmif_sioc req;
-  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 = buffer;
-  req.length = 5*sizeof(*ouraddr);
-
-  /* Reset (or set) timer */
-  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 */
-      mem_free(EINST, buffer);
-      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 (!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]) {
-	/*...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->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);
-}
+#define COMPONENT "address.c"
 
-int 
-addr_getesi(unsigned char *mac_addr)
+/* Gets End System Identifier (MAC address) from kernel
+ * Returns < 0 for error
+ */
+int addr_getesi(unsigned char *mac_addr)
 {
-  int fd;
-  struct atmif_sioc req;
+        int fd, retval;
+        struct atmif_sioc req;
+        
+        fd = socket(PF_ATMSVC, SOCK_DGRAM, 0);
+        if (fd < 0) {
+                diag(COMPONENT, DIAG_ERROR, "addr_getesi: socket: %s\n",
+                     strerror(errno));
+                return -1;
+        }
+        req.number = 0;
+        req.arg = mac_addr;
+        req.length = ESI_LEN;
+        retval = ioctl(fd, ATM_GETESI, &req);
+        if (retval < 0) diag(COMPONENT, DIAG_ERROR, "ioctl ATM_GETESI: %s\n",
+                             strerror(errno));
+        close(fd);
 
-  fd=socket(PF_ATMSVC, SOCK_DGRAM, 0);
-  if (!fd) {
-    EVENT(EM_DEBUG,("Failed to create ATM socket:%s\n",strerror(errno)));
-    return -1;
-  }
-  req.number=0;
-  req.arg=mac_addr;
-  req.length=ESI_LEN;
-  if (ioctl(fd, ATM_GETESI, &req)<0) {
-    EVENT(EM_DEBUG,("ioctl failed:%s\n",strerror(errno)));
-    return -1;
-  }
-  close(fd);
-  return 0;
+        return retval;
 }
 
-int
-addr_getouratmaddr(struct sockaddr_atmsvc *addr)
+/* Gets one of our ATM addresses from kernel. Useful for binding listen sockets.
+ * Returns < 0 for error
+ */
+#define MAX_LOCAL_ADDRS 32
+int get_listenaddr(unsigned char *atm_addr)
 {
-  Client_t *client;
+        int fd, retval;
+        struct atmif_sioc req;
+        struct sockaddr_atmsvc listen_addr[MAX_LOCAL_ADDRS];
+        
+        fd = socket(PF_ATMSVC, SOCK_DGRAM, 0);
+        if (fd < 0) {
+                diag(COMPONENT, DIAG_ERROR, "get_listenaddr: socket: %s\n",
+                     strerror(errno));
+                return -1;
+        }
+        req.number = 0;
+        req.arg = listen_addr;
+        req.length = sizeof(listen_addr);
+        retval = ioctl(fd, ATM_GETADDR, &req);
+        if (retval < 0) diag(COMPONENT, DIAG_ERROR, "ioctl ATM_GETADDR: %s\n",
+                             strerror(errno));
+        close(fd);
 
-  client = Clientlist;
+        memcpy(atm_addr, listen_addr[0].sas_addr.prv, ATM_ESA_LEN);
 
-  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;
+        return retval;
 }
-
-
-/*
- *
- * $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
- *
- * Revision 1.11  1996/04/25 19:42:13  carnil
- * Copyright notice
- *
- * Revision 1.10  1996/04/19 06:37:49  carnil
- * addr_getesi
- *
- * Revision 1.9  1996/04/11 09:16:14  carnil
- * address copy bug fix
- *
- * Revision 1.8  1996/03/17 21:23:41  carnil
- * *** empty log message ***
- *
- * Revision 1.7  1996/02/29 11:24:12  carnil
- * address allocation with ioctl
- *
- * Revision 1.6  1996/02/19 16:32:01  carnil
- * Address ioctl
- *
- * Revision 1.5  1996/02/16 06:16:20  carnil
- * oshandle,cmhandle removed
- *
- * Revision 1.4  1996/01/29  09:30:43  carnil
- * mem_alloc, mem_free
- *
- * Revision 1.3  1996/01/23  10:02:12  carnil
- * Debug info added
- * addr_reg_atm_addr_dealloc
- *
- * Revision 1.2  1996/01/22  12:59:50  carnil
- * Proto diff fixed
- *
- * Revision 1.1  1996/01/19  13:24:31  carnil
- * Initial revision
- *
- *
- */
diff -ur --new-file old/atm/led/address.h new/atm/led/address.h
--- old/atm/led/address.h	Thu Jan  1 01:00:00 1970
+++ new/atm/led/address.h	Sat Feb  6 15:06:08 1999
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ * 
+ */
+
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
+#ifndef ADDRESS_H
+#define ADDRESS_H
+
+int addr_getesi(unsigned char *mac_addr);
+int get_listenaddr(unsigned char *atm_addr);
+
+#endif /* ADDRESS_H */
diff -ur --new-file old/atm/led/af_lane.h new/atm/led/af_lane.h
--- old/atm/led/af_lane.h	Mon Oct  5 12:07:00 1998
+++ new/atm/led/af_lane.h	Thu Jan  1 01:00:00 1970
@@ -1,314 +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:
-*   af_lane.h
-*   
-* Overview:
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   13-Dec-94  TLR   Created.
-*
-* Dependencies:
-*
-* Description:
-*
-*/
-
-#ifndef _AF_LANE_H_
-#define _AF_LANE_H_
-
-#include "lane_atm.h"
-
-#define  LE_CTRL_MARKER          0xff00
-#define  LE_CTRL_PROTOCOL        1
-#define  LE_CTRL_VERSION         1
-
-/*
- * Control Frame Flag Definitions
- */
-#define  LE_FLAG_REMOTE_ADDR     0x0001
-#define  LE_FLAG_PROXY           0x0080
-#define  LE_FLAG_TOPOLOGY_CHANGE 0x0100
-#define  LE_FLAG_V2_CAPABLE      0x0002        /* LANE2 */
-#define  LE_FLAG_SELECTIVE_MCAST 0x0004        /* LANE2 */
-#define  LE_FLAG_V2_REQUIRED     0x0008        /* LANE2 */
-#define  LE_FLAG_TOKEN_RING_EE   0x0200        /* LANE2 */
-
-/*
- * Control Frame Status Definitions
- */
-#define  LE_STATUS_SUCCESS                0
-#define  LE_STATUS_VERSION_NOT_SUPPORTED  1
-#define  LE_STATUS_INVALID_PARAMS         2
-#define  LE_STATUS_DUP_LAN_DST            4
-#define  LE_STATUS_DUP_ATM_ADDR           5
-#define  LE_STATUS_RESOURCES              6
-#define  LE_STATUS_ACCESS_DENIED          7
-#define  LE_STATUS_INVALID_REQ_ID         8
-#define  LE_STATUS_INVALID_LAN_DEST       9
-#define  LE_STATUS_INVALID_ATM_ADDR      10
-#define  LE_STATUS_NO_CONFIG             20
-#define  LE_STATUS_LE_CONFIG_ERROR       21
-#define  LE_STATUS_INSUFFICIENT_INFO     22
-#define  LE_STATUS_TLV_NOT_FOUND         24    /* LANE2 */
-
-/*
- * Control Frame Op-Codes
- */
-#define  LE_CONFIG_REQ     0x0001
-#define  LE_CONFIG_RSP     0x0101
-#define  LE_JOIN_REQ       0x0002
-#define  LE_JOIN_RSP       0x0102
-#define  READY_QUERY       0x0003
-#define  READY_IND         0x0103
-#define  LE_REGISTER_REQ   0x0004
-#define  LE_REGISTER_RSP   0x0104
-#define  LE_UNREGISTER_REQ 0x0005
-#define  LE_UNREGISTER_RSP 0x0105
-#define  LE_ARP_REQ        0x0006
-#define  LE_ARP_RSP        0x0106
-#define  LE_FLUSH_REQ      0x0007
-#define  LE_FLUSH_RSP      0x0107
-#define  LE_NARP_REQ       0x0008
-#define  LE_TOPOLOGY_REQ   0x0009
-#define  LE_VERIFY_REQ     0x000a    /* LANE2 */
-#define  LE_VERIFY_RSP     0x010a    /* LANE2 */
-
-/*
- * TLV Types
- */
-#define  TLV_CTRL_TIMEOUT              0x00a03e01
-#define  TLV_MAX_UNKNOWN_COUNT         0x00a03e02
-#define  TLV_MAX_UNKNOWN_TIME          0x00a03e03
-#define  TLV_VCC_TIMEOUT               0x00a03e04
-#define  TLV_MAX_RETRY                 0x00a03e05
-#define  TLV_AGING_TIME                0x00a03e06
-#define  TLV_FORW_DELAY_TIME           0x00a03e07
-#define  TLV_ARP_RSP_TIME              0x00a03e08
-#define  TLV_FLUSH_TIMEOUT             0x00a03e09
-#define  TLV_PATH_SWITCH_DELAY         0x00a03e0a
-#define  TLV_LOCAL_SEG_ID              0x00a03e0b
-#define  TLV_MCAST_VCC_TYPE            0x00a03e0c
-#define  TLV_MCAST_VCC_AVG_RATE        0x00a03e0d
-#define  TLV_MCAST_VCC_PEAK_RATE       0x00a03e0e
-#define  TLV_CONNECT_COMPLETION_TIMER  0x00a03e0f
-#define  TLV_X5_ADJUSTEMENT            0x00a03e2c /* LANE2 TLVs from here */
-#define  TLV_L3_ADDRESS                0x00a03e11
-#define  TLV_ELAN_ID                   0x00a03e12
-#define  TLV_PREFERRED_LES             0x00a03e2d
-#define  TLV_SERVICE_CATEGORY          0x00a03e13
-#define  TLV_LLC_MUXED_ATM_ADDRESS     0x00a03e2b
-#define  TLV_CONFIG_FRAG_INFO          0x00a03e10
-
-/* Definitions for BLLI codepoint values in signaled VCCs. */
-
-#define BLLI_CONTROL       1
-#define BLLI_DIRECT_802_3  2
-#define BLLI_DIRECT_802_5  3
-#define BLLI_BUS_802_3     4
-#define BLLI_BUS_802_5     5
-
-
-typedef enum
-   {
-   LEC_DIRECT,
-   LEC_MCAST,
-   LEC_CTRL
-   } LEC_CONN_TYPE;
-
-/* LEC_CONN_CONTEXT
- */
-typedef struct
-   {
-   HANDLE         ld_elan_handle;
-   HANDLE         lc_elan_handle;
-   LEC_CONN_TYPE  conn_type;
-   } LEC_CONN_CONTEXT;
-
-
-typedef struct
-   {
-   UINT16   le_hdr;
-   ADDR_48  dst_addr;
-   ADDR_48  src_addr;
-   } HDR_802_3;
-
-typedef struct
-   {
-   UINT16   le_hdr;
-   UINT8    ac_pad;
-   UINT8    fc;
-   ADDR_48  dst_addr;
-   ADDR_48  src_addr;
-   } HDR_802_5;
-
-/*
- * Packet Formats
- */
-typedef struct
-   {
-   UINT16   marker;
-   UINT8    protocol;
-   UINT8    version;
-   UINT16   op_code;
-   UINT16   status;
-   UINT32   tran_id;
-   UINT16   req_lec_id;
-   UINT16   flags;
-   } LE_CTRL_HDR;
-
-#define TAG_NOT_PRESENT    0
-#define TAG_MAC_ADDR       1
-#define TAG_ROUTE_DESC     2
-
-typedef struct
-   {
-   UINT16   tag;
-/*
-   union
-      {
-*/
-      ESI  mac_addr;
-/*
-      struct
-         {
-         UINT32   reserved;
-         UINT16   route_descr;
-         };
-      };
-*/
-   } LE_LAN_DST;
-
-typedef struct
-   {
-   LE_CTRL_HDR    hdr;
-   LE_LAN_DST     src_lan_dst;
-   LE_LAN_DST     target_lan_dst;
-   ADDR_ATM       src_atm_addr;
-   UINT8          lan_type;
-   UINT8          max_frame_size;
-   UINT8          tlv_count;
-   UINT8          elan_name_size;
-   ADDR_ATM       target_atm_addr;
-   char           elan_name[32];
-   } LE_CONFIG_FRAME;
-
-typedef struct
-   {
-   LE_CTRL_HDR    hdr;
-   LE_LAN_DST     src_lan_dst;
-   LE_LAN_DST     target_lan_dst;
-   ADDR_ATM       src_atm_addr;
-   UINT8          lan_type;
-   UINT8          max_frame_size;
-   UINT8          tlv_count;
-   UINT8          elan_name_size;
-   ADDR_ATM       target_atm_addr;
-   char           elan_name[32];
-   } LE_JOIN_FRAME;
-
-typedef struct
-   {
-   LE_CTRL_HDR    hdr;
-   LE_LAN_DST     src_lan_dst;
-   LE_LAN_DST     target_lan_dst;
-   ADDR_ATM       src_atm_addr;
-   UINT8          reserved1[2];  /* LANE2 */
-   UINT8          tlv_count;     /* LANE2 */
-   UINT8          reserved2[53]; /* LANE2 */
-   } LE_REG_FRAME;
-
-typedef struct
-   {
-   LE_CTRL_HDR    hdr;
-   LE_LAN_DST     src_lan_dst;
-   LE_LAN_DST     target_lan_dst;
-   ADDR_ATM       src_atm_addr;
-     /*   UINT32         reserved1; */ /* lane 1 version */
-   UINT16         reserved1;
-   UINT8          tlv_count; /* LANE2: tlv_count added */
-   UINT8          reserved3;
-   ADDR_ATM       target_atm_addr;
-   UINT32         reserved2[8];
-   } LE_ARP_FRAME;
-
-typedef struct /* this is the LANE2 version */
-   {
-   LE_CTRL_HDR    hdr;
-   LE_LAN_DST     src_lan_dst;
-   LE_LAN_DST     target_lan_dst;
-   ADDR_ATM       src_atm_addr;
-   UINT16         reserved;
-   UINT8          tlv_count;
-   UINT8          reserved2;
-   ADDR_ATM       target_atm_addr;
-   UINT32         reserved3[8];
-   } LE_NARP_FRAME;
-
-typedef struct
-   {
-   LE_CTRL_HDR    hdr;
-   UINT32         reserved[23];
-   } LE_TOPOLOGY_FRAME;
-
-typedef struct
-   {
-   UINT16   marker;
-   UINT8    protocol;
-   UINT8    version;
-   UINT16   op_code;
-   } LE_READY_HDR;
-
-typedef struct
-   {
-   LE_READY_HDR   hdr;
-   } LE_READY_FRAME;
-
-typedef struct
-   {
-   LE_CTRL_HDR    hdr;
-   LE_LAN_DST     src_lan_dst;
-   LE_LAN_DST     target_lan_dst;
-   ADDR_ATM       src_atm_addr;
-   UINT32         reserved1;
-   ADDR_ATM       target_atm_addr;
-   UINT32         reserved2[8];
-   } LE_FLUSH_FRAME;
-
-#endif
diff -ur --new-file old/atm/led/cm.h new/atm/led/cm.h
--- old/atm/led/cm.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/cm.h	Thu Jan  1 01:00:00 1970
@@ -1,52 +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:
-*   cm.h
-*   
-* Overview:
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   17-Oct-94  TLR   Created.
-*   19-Jan-94  TLR   Added LAN Emulation map list hook.
-*
-*/
-
-typedef void (*LINK_CALLBACK) (HANDLE link_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	Wed Nov 19 12:59:15 1997
+++ new/atm/led/cm_sap.h	Thu Jan  1 01:00:00 1970
@@ -1,589 +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:
-*   cm_sap.h
-*   
-* Overview:
-*   This describes the Service Access Point (SAP) interface to the
-*   Connection Manager.
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   28-Sep-94  TLR   Created.
-*   10-Oct-94  TLR   Updated based on Team Review.
-*   12-Oct-94  TLR   Added the user_data field to the XMT and RCV calls.
-*   17-Oct-94  TLR   Added Support for Multi-CM Instances.
-*   24-Oct-94  TLR   Small updates while writing implementation.
-*    4-Nov-94  TLR   Added Link Status Indication
-*    9-Nov-94  TLR   Removed Binding and SAP_ID Concept
-*   16-Dec-94  TLR   Added conn_context and conn_handle, point-to-multipoint
-*                    support, transmit done callback, and miscellaneous
-*                    clean-up.
-*   19-Jan-95  TLR   Added length parameters to the transmit and receive calls.
-*   15-Feb-95  TLR   Updated SVC Information Block Types.  Added AAL Data.
-*
-* Dependencies:
-*   types.h    - Generally used type definitions.
-*   codes.h    - Completion codes.
-*   lane_atm.h - ATM specific definitions and types.
-*   svc_info.h - SVC Information Block Definitions.
-*
-* Description:
-*
-*   The Connection Manager (CM) exports this interface to software entities
-*   called Service Access Points (SAPs) which communicate over an ATM
-*   network.  The SAP is a registration interface to which at any time an
-*   arbitrary number of SAP entities may register.
-*
-*   A SAP may open and communicate on any number of VCs.  A SAP may also use a
-*   mix of Permanent Virtual Channels (PVCs) and Switched Virtual Channels
-*   (SVCs).
-*
-*   The SAP interface provides the following basic services:
-*
-*       - Setup and Teardown of PVCs,
-*       - Setup and Teardown of SVCs,
-*       - Packet Transmission based on Connection or ATM Address,
-*       - Demultiplexing of Received Packets to SAPs.
-*
-*   This module assumes that any synchronization issues are handled externally.
-*   It is assumed that there is at most one process thread running in each
-*   instance of the module at any time.
-*
-*   The CM handles transmit and receive packets.  It is not concerned with the
-*   format of the packets and does not look into the contents of packets.  The
-*   CM simply treats each packet as a pointer to void.  The CM's neighboring
-*   components must agree on the format of data packets
-*
-* Concepts:
-*
-*   Connection Handle:
-*
-*     Connection handles are used to uniquely identify individual PVCs and
-*     SVCs.  Connection handles are more abstract than VCIs because the VCI
-*     is not always known during the life of an SVC.  At circuit setup time,
-*     the Connection Manager provides a connection handle that the SAP must
-*     subsequently use.
-*
-*   Connection Context:
-*
-*     Connection contexts are defined by SAP clients and are opaque to the
-*     Connection Manager.  These contexts are provided by the SAP client during
-*     VC setup and are stored by the Connection Manager with the other VC
-*     information.  The connection context is passed back to the SAP in each
-*     callback that is specific to a particular VC.  For example, each packet
-*     received is passed to the SAP along with the connection context for the
-*     VC on which that packet was received.
-*
-*   User Data:
-*
-*
-*   AAL Data:
-*
-*     The connection manager is not specific to any particular ATM Adaptation
-*     Layer (AAL).  An AAL_Data field is passed along with each transmit and
-*     receive packet.  Refer to the definition of AAL_DATA in the "lane_atm.h"
-*     header file.
-*
-*/
-#ifndef CM_SAP_H
-#define CM_SAP_H
-#include "lane_atm.h"
-#include "svc_info.h"
-#include "system.h"
-/*************************************************************************
- * Types that are specific to this interface.                            *
- *************************************************************************/
-
-/* NOTIFY_EVENT
- *
- *   This type enumerates the possible events that may be reported to a
- *   registered SAP client by the Connection Manager.
- *
- *   CONN_VC_READY......This event marks the completion of a VC setup.
- *                      The PVC or SVC is now ready for use.
- *
- *   CONN_RELEASE.......This event occurs when an existing SVC is released.
- *                      This may happen because the remote station released
- *                      the connection, or because a local event caused the
- *                      circuit to be released (i.e. loss of link).
- *
- *   CONN_PARTY_ADD.....An endpoint was successfully added to a point-to-
- *                      multipoint SVC.
- *
- *   CONN_PARTY_DROP....An endpoint was dropped from a point-to-multipoint
- *                      SVC.  This is also used to inform the SAP client that
- *                      a requested add party operation failed.
- *
- *   CONN_STALL.........This event occurs when a VC is stalled for any reason.
- *                      VCs become stalled as a result of flow-control credit
- *                      resynchronization or by network management action.
- *                      The stalled event will not occur as a result of
- *                      congestion experienced on the network, rather only
- *                      when some local entity explicitly stalls a VC.
- *
- *   CONN_UNSTALL.......This event marks the end of stalled status of a VC.
- */
-
-typedef enum
-   {
-   CONN_VC_READY,
-   CONN_RELEASE,
-   CONN_PARTY_ADD,
-   CONN_PARTY_DROP,
-   CONN_STALL,
-   CONN_UNSTALL
-   } NOTIFY_EVENT;
-
-/*************************************************************************
- * SAP Interface Callbacks                                               *
- *************************************************************************/
-
-/*++
-* ======================
-* = (SAP_RCV_CALLBACK) =
-* ======================
-*
-* Overview:
-*   Callback for received packets.  A pointer to this routine is supplied
-*   at registration time by the SAP.
-*
-* Arguments:
-*   conn_context - (IN) Connection Context for the incoming VC.
-*   conn_handle  - (IN) Handle of Connection on which the packet was received.
-*   length       - (IN) Length of the packet payload in bytes.
-*   user_data    - (IN) User data that was transferred from the layers below
-*                       the CM to the SAP.
-*   p_aal_data   - (IN) Data specific to the AAL being used is passed in this
-*                       structure.
-*   pp_packet    - (IO) Pointer to a pointer to a packet.  On input, the packet
-*                       is the received packet.  On output, the pointer is a
-*                       reference to a buffer that is ready to be reused.  If
-*                       this function does not copy the packet, it must either
-*                       return a pointer to a buffer that is free or return
-*                       a NULL pointer.
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The packet referred to by *pp_packet may be safely overwritten or
-*   destroyed.
---*/
-typedef void (*SAP_RCV_CALLBACK) (HANDLE     conn_context,
-                                  HANDLE     conn_handle,
-                                  UINT32     length,
-                                  UINT32     user_data,
-                                  AAL_DATA  *p_aal_data,
-                                  void     **pp_packet);
-
-/*++
-* ===========================
-* = (SAP_XMT_DONE_CALLBACK) =
-* ===========================
-*
-* Overview:
-*   Callback for transmit-done indications.  This callback notifies the
-*   SAP that the transmitted buffer has been DMA'd out of memory and may
-*   be freed.
-*
-* Arguments:
-*   conn_context - (IN  Connection Context of Transmit VC.
-*   p_packet     - (IN) Pointer to the data packet.
-*   user_data    - (IN) User data that was provided by this SAP in the
-*                       transmit request.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-typedef void (*SAP_XMT_DONE_CALLBACK) (HANDLE  conn_context,
-                                       void   *p_packet,
-                                       UINT32  user_data);
-
-
-/*++
-* ============================
-* = (SAP_VC_NOTIFY_CALLBACK) =
-* ============================
-*
-* Overview:
-*   Callback to notify the SAP of the results of a VC setup or to indicate
-*   that an SVC was closed by the remote party.
-*
-* Arguments:
-*   conn_context  - (IN) Connection Context for this VC.
-*   conn_handle   - (IN) Connection Handle which identifies the VC.
-*   event         - (IN) Type of event the SAP is being notified of.
-*   reason        - (IN) Reason value for release and drop party events.
-*   endpoint_ref  - (IN) Endpoint reference for party adds and drops.
-*   calling_party - (IN) Boolean flag:  Set iff this SAP is the calling party
-*                        of the new connection.
-*   
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-typedef void (*SAP_VC_NOTIFY_CALLBACK) (HANDLE         conn_context,
-                                        HANDLE         conn_handle,
-                                        NOTIFY_EVENT   event,
-                                        UINT16         reason,
-                                        UINT32         endpoint_ref,
-                                        BOOLEAN        calling_party);
-
-
-/*++
-* ==========================
-* = (SAP_CONNECT_CALLBACK) =
-* ==========================
-*
-* Overview:
-*   This is the callback that the CM invokes when it wishes to offer a new
-*   connection to a SAP.  The SAP must decide whether or not it wants the
-*   connection and return a boolean value indicating its decision.
-*
-* Arguments:
-*   sap_context      - (IN)  SAP context supplied at registration time.
-*   p_conn_info      - (IN)  Connection information block for the connection.
-*   conn_handle      - (IN)  Handle which identifies the VC.
-*   p_conn_context   - (OUT) Connection context if accepted.
-*   p_age_limit      - (OUT) The age limit for this SVC in seconds.  If this
-*                            SVC is idle (no traffic) for longer than the
-*                            age limit, it will be torn down.  If the age limit
-*                            is specified as zero, the SVC will never be
-*                            aged out.
-*   p_reject_reason  - (OUT) The reason this connection was rejected if the
-*                            return value is FALSE.  If this connection is
-*                            being rejected because the SAP is not interested
-*                            in it (i.e. the called party address or BLLI
-*                            does not match), this value MUST be
-*                            REJECT_SAP_MISMATCH.
-*              
-* Returns:
-*   TRUE  - Connection Accepted.
-*   FALSE - Connection Rejected.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-typedef BOOLEAN (*SAP_CONNECT_CALLBACK) (HANDLE       sap_context,
-                                         CONN_INFO   *p_conn_info,
-                                         HANDLE       conn_handle,
-                                         HANDLE      *p_conn_context,
-                                         UINT32      *p_age_limit,
-                                         UINT32      *p_reject_reason);
-
-/*++
-* ==============================
-* = (SAP_LINK_STATUS_CALLBACK) =
-* ==============================
-*
-* Overview:
-*   The Connection Manager invokes this callback when the link status changes.
-*   This serves to notify the SAP client when the link becomes available or
-*   unavailable.
-*
-*   When the link becomes unavailable, all open SVCs are automatically closed.
-*   Therefore once a SAP receives an indication that the link is unavailable,
-*   it will subsequently receive individual release notifications for each of
-*   its open SVCs.
-*
-* Arguments:
-*   sap_context    - (IN) Context of registered SAP.
-*   link_status    - (IN) New value of link status.
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-typedef void (*SAP_LINK_STATUS_CALLBACK) (HANDLE           sap_context,
-                                          ATM_LINK_STATE   link_state);
-
-
-/*************************************************************************
- * SAP Interface Function Prototypes                                     *
- *************************************************************************/
-  
-
-/*++
-* ===================
-* = cm_sap_register =
-* ===================
-*
-* Overview:
-*   Registers a new SAP with the Connection Manager.
-*
-* Arguments:
-*   cm_handle               - (IN)  Handle returned by cm_create.
-*
-*   sap_context             - (IN)  Context handle for this SAP client.  This
-*                                   handle is provided by the client and is
-*                                   passed back to the client during connect
-*                                   callbacks.
-*
-*   p_rcv_callback          - (IN)  Pointer to the receive callback.
-*
-*   p_vc_notify_callback    - (IN)  Pointer to the notify callback.
-*
-*   p_svc_connect_callback  - (IN)  Pointer to the connect callback.  If this
-*                                   pointer is NULL, the Connection Manager
-*                                   shall not offer any incoming connections
-*                                   to this SAP.
-*
-*   p_link_status_callback  - (IN)  Pointer to the link status callback.
-*
-*   p_xmt_done_callback     - (IN)  Pointer to the transmit done callback.
-*
-*   p_sap_text              - (IN)  Pointer to a descriptive string.
-*
-*   p_sap_handle            - (OUT) Handle to be used in subsequent cm_sap_*
-*                                   calls.
-*              
-* Returns:
-*   STATUS_K_SUCCESS    - Success: See Postconditions.
-*   STATUS_K_RESOURCES  - Insufficient resources to complete registration.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The handle is valid.
---*/
-STATUS cm_sap_register (
-                        HANDLE                     sap_context,
-                        SAP_RCV_CALLBACK           rcv_callback,
-                        SAP_VC_NOTIFY_CALLBACK     vc_notify_callback,
-                        SAP_CONNECT_CALLBACK       svc_connect_callback,
-                        SAP_XMT_DONE_CALLBACK      xmt_done_callback,
-			int itf_num,
-                        const char                *p_sap_text,
-                        HANDLE                    *p_sap_handle);
-
-
-/*++
-* =====================
-* = cm_sap_unregister =
-* =====================
-*
-* Overview:
-*   Cancel the registration of a SAP. The handle is unusable immediately upon
-*   the completion of this call but if there were opened VCs, it will be some
-*   time before those VC_IDs are again available for use.
-*
-* Arguments:
-*   sap_handle    - (IN) Handle of the SAP to be unregistered
-*              
-* Returns:
-*   None
-*   
-* Preconditions:
-*   The handle is valid.
-*
-* Postconditions:
-*   The handle is invalid.
---*/
-void cm_sap_unregister (HANDLE sap_handle);
-
-
-/*++
-* ====================
-* = cm_sap_svc_setup =
-* ====================
-*
-* Overview:
-*   Requests the setup of an SVC.  This is an asynchronous call.  The SVC
-*   will not be available for use for some time after this call completes.
-*   The (sap_vc_notify) callback is used to notify the caller that the
-*   SVC has been set up and is ready for use.
-*
-* Arguments:
-*   sap_handle       - (IN)  SAP Handle returned by cm_sap_register
-*   conn_context     - (IN)  Connection Context for this VC.
-*   p_conn_info      - (IN)  Requested VC signaling parameters.
-*   p_age_limit      - (OUT) The age limit for this SVC in seconds.  If this
-*                            SVC is idle (no traffic) for longer than the
-*                            age limit, it will be torn down.  If the age limit
-*                            is specified as zero, the SVC will never be
-*                            aged out.
-*   p_conn_handle    - (OUT) Connection handle that identifies pending VC.
-*              
-* Returns:
-*   STATUS_K_PENDING           - Success: Async operation has begun.
-*   STATUS_K_RESOURCES         - Insufficient internal resources to complete
-*                                the setup.
-*   STATUS_K_INSUFFICIENT_DATA - The connection information block doesn't have
-*                                enough detail to complete the operation.
-*   STATUS_K_ATM_RESOURCES     - Insufficient ATM resources available to meet
-*                                requested parameters.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-STATUS cm_sap_svc_setup (HANDLE     sap_handle,
-                         HANDLE     conn_context,
-                         CONN_INFO *p_conn_info,
-                         UINT32     age_limit,
-                         HANDLE    *p_conn_handle);
-
-
-/*++
-* =======================
-* = cm_sap_svc_teardown =
-* =======================
-*
-* Overview:
-*   Disconnect and Close an SVC.  This function begins the process of
-*   closing the VC.  The VC_ID may not be available for reuse for some time
-*   after this call completes.
-*
-*   When the connection is closed, the SAP will be notified via the 
-*   sap_vc_notify callback.
-*
-* Arguments:
-*   conn_handle     - (IN)  Connection handle of the SVC to be removed.
-*              
-* Returns:
-*   STATUS_K_PENDING        - Success: Async operation has begun
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-STATUS cm_sap_svc_teardown (HANDLE        conn_handle);
-
-/*++
-* =================
-* = cm_sap_xmt_vc =
-* =================
-*
-* Overview:
-*   Transmit a packet directly via a VC.  No lookup is necessary to perform
-*   this transmit operation.  It will execute very quickly.
-*
-* Arguments:
-*   conn_handle   - (IN)  Connection handle of outgoing channel.
-*
-*   p_data        - (IN)  Pointer to the data packet.
-*
-*   length        - (IN)  Length of the data packet in bytes. If this parameter
-*                         is set to zero, the length is considered unspecified.
-*                         In this case, the lower layers must be able to find
-*                         the length by some other means.  For protocol-
-*                         generated packets, the p_data pointer will point to
-*                         some structure that contains the length and location
-*                         of the packet's payload data.  In this case, an
-*                         unspecified length value is appropriate.
-*
-*   user_data     - (IN)  User data to be transferred from the SAP to the
-*                         layers below the CM.
-*   p_aal_data    - (IN)  Data specific to the AAL being used is passed in this
-*                         structure.
-*              
-* Returns:
-*   STATUS_K_SUCCESS    - Packet was transmitted, buffer may be freed.
-*   STATUS_K_PENDING    - Packet was queued, buffer may not be freed.
-*   STATUS_K_CONGESTED  - Transmit queue full.  The packet was not transmitted
-*                         and has not been deallocated.  The SAP may either
-*                         queue or discard the packet.
-*
-* Preconditions:
-*   It is assumed that the requested vc_id is bound to this SAP.
-*
-*   It is assumed that the VC is opened and ready for use.
-*
-* Postconditions:
-*   None
---*/
-STATUS cm_sap_xmt_vc (HANDLE    conn_handle,
-                      void     *p_data,
-                      UINT32    length,
-                      UINT32    user_data,
-                      AAL_DATA *p_aal_data);
-
-
-/*++
-* ==========================
-* = cm_sap_link_status_get =
-* ==========================
-*
-* Overview:
-*   Returns the current link status of the driver attached to the CM.
-*
-* Arguments:
-*   sap_handle    - (IN)  Handle returned by cm_sap_register.
-*   p_link_status - (OUT) Current Link Status.
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-void cm_sap_link_status_get (HANDLE           sap_handle,
-                             ATM_LINK_STATE  *p_link_state);
-#endif /* CM_SAP_H */
-
diff -ur --new-file old/atm/led/codes.h new/atm/led/codes.h
--- old/atm/led/codes.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/codes.h	Thu Jan  1 01:00:00 1970
@@ -1,105 +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:
-*   codes.h
-*   
-* Abstract:
-*   This module defines return and error codes.
-*
-* Authors:
-*   DMW - Douglas M. Washabaugh
-*
-* Modification History:
-*   Date       Name  Description 
-*   08-Aug-94  DMW   Created.
-*   28-Sep-94  TLR   Added _ATM_RESOURCES and _NO_PRIVILEGE
-*   24-Oct-94  TLR   Added _PENDING
-*   15-Dec-94  TLR   Added _CONGESTED
-*   20-Feb-95  TLR   Added _NOT_IMPLEMENTED
-*   21-Feb-95  TLR   Added _INSUFFICIENT_DATA and _SIGNALING_ERROR
-*   07-Mar-95  DMW   Added _NOT_READY and _BUFFER_TOO_SMALL
-*
-* Description:
-*   A collection of common return codes.
---*/
-
-/* Define argument errors first, so that value matches argument number. */
-
-#define STATUS_K_SUCCESS             0
-#define STATUS_K_ARG_1_BAD           1
-#define STATUS_K_ARG_2_BAD           2
-#define STATUS_K_ARG_3_BAD           3
-#define STATUS_K_ARG_4_BAD           4
-#define STATUS_K_ARG_5_BAD           5
-#define STATUS_K_ARG_6_BAD           6
-#define STATUS_K_ARG_7_BAD           7
-#define STATUS_K_ARG_8_BAD           8
-#define STATUS_K_ARG_9_BAD           9
-#define STATUS_K_ARG_10_BAD          10
-#define STATUS_K_ARG_11_BAD          11
-#define STATUS_K_ARG_12_BAD          12
-#define STATUS_K_ARG_13_BAD          13
-#define STATUS_K_ARG_14_BAD          14
-#define STATUS_K_ARG_15_BAD          15
-
-/* Leave undefined values for future expansion. Start at a round hex value. */
-
-#define STATUS_K_FAILURE             32
-#define STATUS_K_NOT_OPEN            33
-#define STATUS_K_ALREADY_OPEN        34
-#define STATUS_K_NOT_CLOSED          35
-#define STATUS_K_ALREADY_CLOSED      36
-#define STATUS_K_BUSY                37
-#define STATUS_K_RESOURCES           38
-#define STATUS_K_ATM_RESOURCES       39
-#define STATUS_K_TIMEOUT             40
-#define STATUS_K_ARGS_INCONSISTENT   41
-#define STATUS_K_SW_FAULT            42
-#define STATUS_K_HW_FAULT            43
-#define STATUS_K_CONFIG_BAD          44
-#define STATUS_K_NOT_FOUND           45
-#define STATUS_K_NO_WORK_TO_DO       46
-#define STATUS_K_NO_PRIVILEGE        47
-#define STATUS_K_PENDING             48
-#define STATUS_K_CONGESTED           49
-#define STATUS_K_NOT_IMPLEMENTED     50
-#define STATUS_K_INSUFFICIENT_DATA   51
-#define STATUS_K_SIGNALING_ERROR     52
-#define STATUS_K_NOT_READY           53
-#define STATUS_K_BUFFER_TOO_SMALL    54
-#define STATUS_K_MISMATCH            55
-#define STATUS_K_REJECT              56
-
-
diff -ur --new-file old/atm/led/conn.c new/atm/led/conn.c
--- old/atm/led/conn.c	Tue Feb  9 17:12:00 1999
+++ new/atm/led/conn.c	Wed Jun  2 23:36:53 1999
@@ -1,3 +1,5 @@
+/* conn.c - functions for handling SVCs, create, accept, send, etc. */
+
 /*
  * Marko Kiiskila carnil@cs.tut.fi 
  * 
@@ -21,72 +23,34 @@
  * SOFTWARE.
  * 
  */
-/*
- *
- * Connection forming/teardown & packet send/receive
- *
- * $Id: conn.c,v 1.26 1996/08/06 14:14:11 carnil Exp carnil $
- *
- */
 
-/* Global includes */
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <assert.h>
-#include <sys/socket.h>
+#include <stdlib.h>
 #include <unistd.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <assert.h>
-#include <netinet/in.h>
 #include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
 
-/* Atm includes */
-
-#include <atm.h>
-#include <linux/atmdev.h>
 #include <atm.h>
+#include <atmsap.h>
+#include <linux/atmlec.h>
 
-#include "lane2.h"
+#include <atmd.h>
 
-/* Digital includes */
-#include "codes.h"
-#include "g_types.h"
-#include "cm_sap.h"
-#include "lec.h"
-#include "lane_atm.h"
-#include "atmsap.h"
-#include "cm.h"
-#include "g_event.h"
 #include "conn.h"
-#include "utl_os.h"
-#include "af_lane.h"
-#include "le_disp.h"
-#include "kernel_itf.h"
-#include "lec_ctrl.h"
-#include "addr_reg.h"
-#include "lec_arp.h"
-
-#define EMOD MOD_CM
-#define EINST "conn.c"
-#include "emask.h"
-
-#define BUFSIZE 4096      /* Buffer size. LANE Control packets aren't
-			     supposed to be big... */
-#define QLEN 5            /* Max length of listen queue */
+#include "display.h"
+#include "lec.h"
+#include "frames.h"
+#include "kernel.h"
 
+#define COMPONENT "conn.c"
 
 /* status */
-#define CONNECTED 1245    /* Connection made, not notified */
-#define NOTIFIED 1246     /* 
-			     Connection made, notified
-			     Packet transmitted, notified
-			   */
-#define TRANSMITTED 1247  /* Packet transmitted, not notified */
-#define RELEASED 1248     /* Connection released */
-#define CONNECTING 1249   /* Non blocking socket, connecting */
+#define CONNECTED  42    /* Operational socket */
+#define CONNECTING 43    /* Non-blocking socket, not yet connected */
 
 /* type */
 #define WEMADE 7
@@ -94,978 +58,827 @@
 #define LISTENING 9
 #define KERNEL_SOCK 10
 
-typedef struct _conn_t_ {
-  int fd;                  /* Socket connected to this connection */
-  unsigned long age_limit; /* In seconds. If this SVC is idle (no traffic) 
-			      for longer than the age limit, it will be 
-			      torn down.  If the age limit is specified 
-			      as zero, the SVC will never be aged out. */
-  HANDLE sap_handle;       /* Connection is linked to some sap */
-  HANDLE conn_context;     /* Connection context for this VC */
-  int status;              /* Connection status */
-  int type;                /* We made, they made, listen socket */
-  void *p_packet;          /* Save packets address, needed in callback */
-  CONN_INFO *conn_info;    /* Listen socket conn_info */
-  unsigned char atm_address[ATM_ESA_LEN]; 
-                           /* Destination address, not in listen or kernel
-                             sockets */
-  struct _conn_t_ *next;
-  struct _conn_t_ *previous;
-} Conn_t;
-
-typedef struct _Sap_client_t_ {
-  HANDLE sap_context;
-  SAP_RCV_CALLBACK rcv_callback;
-  SAP_VC_NOTIFY_CALLBACK vc_notify_callback;
-  SAP_CONNECT_CALLBACK svc_connect_callback;
-  SAP_XMT_DONE_CALLBACK xmt_done_callback;
-  char *p_sap_text;
-  unsigned long xmt_packet_count;
-  unsigned long rcv_packet_count;
-  unsigned long accept_packet_count;
-  unsigned long reject_packet_count;
-  int itf_num;
-  struct _Sap_client_t_ *next;
-} Sap_client_t;
+static Conn_t *connlist = NULL;
+
+/* Local protos */
+static void list_remove_conn(Conn_t *conn);
+static Conn_t *list_add_conn(unsigned char *dest_atm_addr);
+static Conn_t *conn_already_exists(unsigned char *atm_addr, Conn_t *current);
+static const char *get_type_string(int type);
+static int maxmtu2maxsdu(uint8_t mtu);
+static uint16_t conn_type2codepoint(int conn_type);
 
-Sap_client_t *clientlist = NULL;
+static void delete_addr(unsigned char *atm_addr)
+{
+        struct atmlec_msg msg;
 
-Conn_t *connlist = NULL;
+        msg.type = l_addr_delete;
+        memcpy(msg.content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
+        msg_to_kernel(&msg, sizeof(struct atmlec_msg));
 
-/* Local protos */
-static void list_remove_conn(HANDLE conn_handle);
-static int list_add_conn(HANDLE sap_handle, HANDLE conn_context, 
-			 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, 
-		SAP_VC_NOTIFY_CALLBACK vc_notify_callback,
-		SAP_CONNECT_CALLBACK svc_connect_callback,
-		SAP_XMT_DONE_CALLBACK xmt_done_callback,
-		int itf_num,
-		const char *p_sap_text, HANDLE *p_sap_handle)
-{
-  Sap_client_t *client;
-
-  EVENT(EM_DEBUG,("Cm_sap_register\n"));
-
-  client = (Sap_client_t *)mem_alloc(EINST,sizeof(Sap_client_t));
-  if (!client)
-    return STATUS_K_RESOURCES;
-
-  /* Callback func copying */
-  client->sap_context = sap_context;
-  client->rcv_callback = rcv_callback;
-  client->vc_notify_callback = vc_notify_callback;
-  client->svc_connect_callback = svc_connect_callback;
-  client->xmt_done_callback = xmt_done_callback;
-
-  /* Allocate space etc for text string */
-  if (p_sap_text) {
-    client->p_sap_text = (char *)mem_alloc(EINST,strlen(p_sap_text)+1);
-    if (!client->p_sap_text) {
-      mem_free(EINST,client);
-      return STATUS_K_RESOURCES;
-    }
-    memcpy(client->p_sap_text, p_sap_text, strlen(p_sap_text));
-    client->p_sap_text[strlen(p_sap_text)] = '\0';
-  } else {
-    client->p_sap_text = (char *)mem_alloc(EINST,1);
-    if (!client->p_sap_text) {
-      mem_free(EINST,client);
-      return STATUS_K_RESOURCES;
-    }
-    client->p_sap_text[0] = '\0';
-  }
+        return;
+}
 
-  /* Statistic variables */
-  client->xmt_packet_count = client->rcv_packet_count = 
-    client->accept_packet_count = client->reject_packet_count = 0;
+/* Checks if connection to atm_addr already exists. Does not
+ * check against current though.
+ * Returns NULL for no connection, or Conn_t of existing connection.
+ */
+static Conn_t *conn_already_exists(unsigned char *atm_addr, Conn_t *current)
+{
+        Conn_t *conn;
 
-  client->itf_num = itf_num;
-  
-  /* Link to place */
-  client->next = clientlist;
-  clientlist = client;
-
-  /* Returning handle */
-  *p_sap_handle = client;
-  return STATUS_K_SUCCESS;
-}
-
-void
-cm_sap_unregister(HANDLE sap_handle)
-{
-  Sap_client_t *sap, *curr;
-  Sap_client_t *prev = NULL;
-  Conn_t *conn, *next;
-
-  sap = (Sap_client_t *)sap_handle;
-
-  curr = clientlist;
-  while(curr && curr != sap) {
-    prev = curr;
-    curr = curr->next;
-  }
-
-  if (!curr) {
-    EVENT(EM_NERR,("Aaargh! Unregistering client. Not found\n"));
-    return;
-  }
-
-  /* Found */
-  if (!prev) { /* Removing first */
-    clientlist = curr->next;
-  } else { /* Removing from middle */
-    prev->next = curr->next;    
-  }
-  /* Remove vcc's */
-  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;conn=next) {
-    next=conn->next;
-    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);
-}
-
-/* Don't check parameter current for atm address match */
-static Conn_t*
-conn_already_exists(unsigned char *atm_addr, Conn_t *current)
-{
-  Conn_t *conn;
-  int len;
-
-  conn = connlist;
-  len = sizeof(struct sockaddr_atmsvc);
-
-  while (conn) {
-    if (conn != current && conn->type != LISTENING && 
-	conn->type != KERNEL_SOCK && conn->status != RELEASED) {
-      if (memcmp(conn->atm_address, atm_addr, ATM_ESA_LEN) == 0)
-       return conn;
-    }
-    conn= conn->next;
-  }
-  return NULL;
+        conn = connlist;
+        while (conn) {
+                if (conn != current &&
+                    conn->type != LISTENING && 
+                    conn->type != KERNEL_SOCK) {
+                        if (memcmp(conn->atm_address, atm_addr, ATM_ESA_LEN) == 0)
+                                return conn;
+                }
+                conn = conn->next;
+        }
+        
+        return NULL;
 }
 
-static int
-is_data_direct(CONN_INFO *p_conn_info)
+/* Initializes and fills in *sap and *qos according to Blli
+ * code point value specified in conn_type.
+ */
+void init_conn_params(struct atm_sap *sap, struct atm_qos *qos,
+                      uint16_t conn_type)
 {
-  return (p_conn_info->blli.l3.tr9577.snap[4] == 0x02 ||
-	  p_conn_info->blli.l3.tr9577.snap[4] == 0x03);
+
+        unsigned int bllicode;
+        int i, sdu;
+        char qos_text[MAX_ATM_QOS_LEN + 1];
+
+        diag(COMPONENT, DIAG_DEBUG, "init_conn_params, conn_type %x\n", conn_type);
+
+        memset(qos, 0, sizeof(struct atm_qos));
+        memset(sap, 0, sizeof(struct atm_sap));
+        qos->aal = ATM_AAL5;
+  
+        /* Set the forward and backward Max CPCS-SDU Size */
+        switch(conn_type) {
+        case CONTROL_CONN:
+                qos->rxtp.max_sdu = 1516;
+                qos->txtp.max_sdu = 1516;
+                break;
+        case DATA_DIRECT_CONN:
+        case MCAST_CONN:
+                sdu = maxmtu2maxsdu(lec_params.c3_max_frame_size);
+                qos->rxtp.max_sdu = sdu;
+                qos->txtp.max_sdu = sdu;
+                break;
+        default:
+                diag(COMPONENT, DIAG_ERROR, "unknown conn_type %x\n", conn_type);
+                break;
+        }
+        
+        /* ATM User Cell Rate/ATM Traffic Descriptor. */
+        qos->txtp.traffic_class = ATM_UBR;
+        qos->rxtp.traffic_class = ATM_UBR;
+   
+        if (get_verbosity(COMPONENT) >= DIAG_DEBUG) {
+                if (qos2text(qos_text, sizeof(qos_text), qos, 0) < 0)
+                        sprintf(qos_text, "<bad qos>");
+                diag(COMPONENT, DIAG_DEBUG, "init_conn_params, QoS '%s'\n", qos_text);
+        }
+
+        /* No Broadband High Layer Information in LANE. */
+        sap->bhli.hl_type = ATM_HL_NONE;
+
+        /* Broadband Lower Layer Information. */
+        sap->blli[0].l3_proto = ATM_L3_TR9577;
+        sap->blli[0].l3.tr9577.ipi = NLPID_IEEE802_1_SNAP;
+        sap->blli[0].l3.tr9577.snap[0] = 0x00;
+        sap->blli[0].l3.tr9577.snap[1] = 0xa0;
+        sap->blli[0].l3.tr9577.snap[2] = 0x3e;
+        bllicode = conn_type2codepoint(conn_type);
+        sap->blli[0].l3.tr9577.snap[3] = (unsigned char)(0xff&(bllicode>>8));
+        sap->blli[0].l3.tr9577.snap[4] = (unsigned char)(0xff&bllicode);
+
+        if (get_verbosity(COMPONENT) == DIAG_DEBUG) {
+                for(i=0; i < 5; i++) {
+                        diag(COMPONENT, DIAG_DEBUG, "snap[%d] = 0x%2.2x",
+                             i, sap->blli[0].l3.tr9577.snap[i]);
+                }
+        }
+
+        return;
 }
 
-STATUS 
-cm_sap_svc_setup (HANDLE sap_handle, HANDLE conn_context,
-		  CONN_INFO *p_conn_info, UINT32 age_limit,
-		  HANDLE *p_conn_handle)
+/* Returns != 0 if blli indicates Data Direct
+ * connection
+ */
+static int is_data_direct(struct atm_blli *blli)
 {
-  Conn_t *conn;
-  Sap_client_t *sap = (Sap_client_t *)sap_handle;
-  int s;
-  int ret;
-  struct sockaddr_atmsvc us;
-  struct atm_blli blli;
-  struct atm_sap atmsap;
+        return (blli->l3.tr9577.snap[4] == DATA_DIRECT_8023 ||
+                blli->l3.tr9577.snap[4] == DATA_DIRECT_8025);
+}
 
-  EVENT(EM_EVENT,("Outgoing call setup\n"));
-  
-  /* We don't create connection to entity where we already have
-     a connection. */
-  if (conn_already_exists(p_conn_info->addr.sas_addr.prv, NULL) &&
-      is_data_direct(p_conn_info))
-    return STATUS_K_ALREADY_OPEN;
-
-  switch(p_conn_info->blli.l3.tr9577.snap[4]) { /* Kludge.  Eh? */
-  case 0x01:
-    EVENT(EM_DEBUG,("LE Control SVC setup\n"));
-    break;
-  case 0x02:
-    EVENT(EM_DEBUG,("Data direct 802.3\n"));
-    break;
-  case 0x03:
-    EVENT(EM_DEBUG,("Data direct 802.5\n"));
-    break;
-  case 0x04:
-    EVENT(EM_DEBUG,("Multicast 802.3\n"));
-    break;
-  case 0x05:
-    EVENT(EM_DEBUG,("Multicast 802.5\n"));
-    break;
-  default:
-    EVENT(EM_ASSERT,("Unknown codepoint in svc setup\n"));
-  }
-  
-  /* Create socket */
-  s = socket(PF_ATMSVC, SOCK_DGRAM, 0);
-  if (s<0) {
-    EVENT(EM_NERR,("socket creation failure:%s\n",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);
-    }
-    *p_conn_handle = NULL;
-    return STATUS_K_RESOURCES;
-  }
-  /* Initialize address structs */
-  memset(&us,0,sizeof(us));
-  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);
-    }
+/* Creates a socket with the specified parameters.
+ * If listen_addr is non NULL binds to it.
+ * Returns < 0 for error or new socket descriptor.
+ */
+static int get_socket(struct sockaddr_atmsvc *listen_addr,
+                      struct atm_sap *sap, struct atm_qos *qos)
+{
+        int s, ret;
 
-    close(s);
-    *p_conn_handle = NULL;
-    return STATUS_K_ATM_RESOURCES;
-  }
-  
-  /* Copy blli information */
-  memcpy(&blli, &(p_conn_info->blli), sizeof(struct atm_blli));
-  /* Set traffic parameters */
-  if (setsockopt(s,SOL_ATM,SO_ATMQOS, &(p_conn_info->conqos), 
-		 sizeof(p_conn_info->conqos)) < 0) {
-    EVENT(EM_NERR,("setsockopt SO_ATMQOS: %s\n",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;
-  }
-  
-  us.sas_family = p_conn_info->addr.sas_family;
+        s = socket(PF_ATMSVC, SOCK_DGRAM, 0);
+        if (s < 0) {
+                diag(COMPONENT, DIAG_ERROR, "socket creation failure: %s\n",
+                     strerror(errno));
+                return -1;
+        }
+        diag(COMPONENT, DIAG_DEBUG, "get_socket: got fd %d\n", s);
+        
+        if (setsockopt(s, SOL_ATM, SO_ATMQOS, qos, sizeof(struct atm_qos)) < 0) {
+                diag(COMPONENT, DIAG_ERROR, "get_socket: setsockopt SO_ATMQOS: %s\n", strerror(errno));
+                close(s);
+                return -1;
+        }
+        if (setsockopt(s, SOL_ATM, SO_ATMSAP, sap, sizeof(struct atm_sap)) < 0) {
+                diag(COMPONENT, DIAG_ERROR, "setup_svc setsockop(SO_ATMSAP)\n");
+                close(s);
+                return -1;
+        }
+        
+        /* Bind the socket to our local address */
+        if (listen_addr == NULL)
+                return s;
+        ret = bind(s, (struct sockaddr *)listen_addr, sizeof(struct sockaddr_atmsvc));
+        if (ret < 0) {
+                diag(COMPONENT, DIAG_ERROR, "bind error: %s\n", strerror(errno));
+                close(s);
+                return -1;
+        }
+        
+        return s;
+}
 
-  if (EMASK & EM_DEBUG)
-    disp_sockaddr(p_conn_info);
 
-  /* new since 0.33-pre-x, SO_ATMSAP */
-  memset(&atmsap, 0, sizeof(struct atm_sap));
-  atmsap.blli[0] = blli;
-  if (setsockopt(s,SOL_ATM,SO_ATMSAP,&atmsap,sizeof(atmsap)) < 0) {
-    EVENT(EM_NERR,("conn.c::cm_sap_svc_setup setsockop(SO_ATMSAP)\n"));
-    (void) close(s);
-    return -1;
-  }
-
-  ret = bind(s, (struct sockaddr *)&us, sizeof(us));
-  if (ret<0) {
-    EVENT(EM_NERR,("bind error:%s\n",strerror(errno)));
-    if (is_data_direct(p_conn_info)) {
-      /* Try to remove possible entry in kernel */
-    }
+/*
+ * You need to check this if setup_svc() returns NULL
+ */
+#if 0
+        if (is_data_direct(&sap->blli[0])) {
+                /* Try to remove possible entry in kernel */
+                delete_addr(conn->atm_address);
+        }
+#endif
+/* Does an active open to dst_addr using pre-filled
+ * parameters in sap and qos.
+ * If listen_addr is non NULL, binds to it.
+ * Data direct SVCs are non-blocking, others block
+ * Returns NULL for error or new connections.
+ */
+Conn_t *setup_svc(struct sockaddr_atmsvc *dst_addr,
+                  struct sockaddr_atmsvc *listen_addr,
+                  struct atm_sap *sap, struct atm_qos *qos)
+{
+        Conn_t *conn;
+        int s, ret;
+        char buff[MAX_ATM_ADDR_LEN+1];
+
+        diag(COMPONENT, DIAG_DEBUG, "Outgoing call setup\n");
+        
+        /* The code below is commented out due to the following scenario:
+           We have made a connection to another LEC and our address was
+           numerically lower than theirs (LANEv2 8.1.13).
+           The other end has also connected us, but we must not use that
+           VCC.
+           However, if the connection we made gets closed, we can not open
+           it again since a connection to the destination LEC already exists.
+        */
+#if 0
+        /* We don't create connection to an entity where we already have
+           a connection. */
+        if (conn_already_exists(dst_addr->sas_addr.prv, NULL) &&
+            is_data_direct(&sap->blli[0]))
+                return NULL;
+#endif
+
+        dst_addr->sas_family = AF_ATMSVC;
+        listen_addr->sas_family = AF_ATMSVC;
+        
+        switch(sap->blli[0].l3.tr9577.snap[4]) { /* Kludge.  Eh? */
+        case CONTROL_CONN:
+                diag(COMPONENT, DIAG_DEBUG, "LE Control SVC setup\n");
+                break;
+        case DATA_DIRECT_8023:
+                diag(COMPONENT, DIAG_DEBUG, "Data direct 802.3\n");
+                break;
+        case DATA_DIRECT_8025:
+                diag(COMPONENT, DIAG_DEBUG, "Data direct 802.5\n");
+                break;
+        case MCAST_CONN_8023:
+                diag(COMPONENT, DIAG_DEBUG, "Multicast 802.3\n");
+                break;
+        case MCAST_CONN_8025:
+                diag(COMPONENT, DIAG_DEBUG, "Multicast 802.5\n");
+                break;
+        default:
+                diag(COMPONENT, DIAG_ERROR, "Unknown codepoint in svc setup\n");
+        }
+ 
+        s = get_socket(listen_addr, sap, qos);
+        if (s < 0) return NULL;
+        if (atm2text(buff, sizeof(buff), (struct sockaddr *)dst_addr, A2T_PRETTY | A2T_NAME | A2T_LOCAL) < 0)
+                sprintf(buff, "<Unknown ATM address>");
+        diag(COMPONENT, DIAG_DEBUG, "Call to %s", buff);
+
+        /* Make data direct SVCs non-blocking */
+        if (is_data_direct(&sap->blli[0])) {
+                ret = fcntl(s, F_GETFL);
+                if (ret < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "fcntl(s, F_GETFL)\n");
+                        close(s);
+                } else if (fcntl(s, F_SETFL, ret|O_NONBLOCK) < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "fcntl(s, F_SETFL, x|O_NONBLOCK)\n");
+                        close(s);
+                        return NULL;
+                }
+        }
+
+        ret = connect(s, (struct sockaddr *)dst_addr, sizeof(struct sockaddr_atmsvc));
+        if (ret < 0 && errno != EINPROGRESS) {
+                diag(COMPONENT, DIAG_ERROR, "connect error: %s\n", strerror(errno));
+                close(s);
+                return NULL;
+        }
+
+        conn = list_add_conn(dst_addr->sas_addr.prv);
+        diag(COMPONENT, DIAG_DEBUG, "Conn:%p\n", conn);
+        if (conn == NULL) {
+                close(s);
+                return NULL;
+        }
+        conn->fd = s;
+        conn->type = WEMADE;
+        conn->codepoint = sap->blli[0].l3.tr9577.snap[4];
+
+        if (is_data_direct(&sap->blli[0]))
+                conn->status = CONNECTING;
+        else
+                conn->status = CONNECTED;
+        
+        return conn;
+}
+
+/* Creates listen socket for incoming data direct connections.
+ * Only for data direct, not for Control or Multicast listen sockets.
+ * Returns < 0 for error
+ */
+int create_data_listen(void)
+{
+        struct atm_sap sap;
+        struct atm_qos qos;
+        struct sockaddr_atmsvc addr;
 
-    close(s);
-    *p_conn_handle = NULL;
-    return STATUS_K_ATM_RESOURCES;
-  }
-
-  if (EMASK & EM_DEBUG)
-    disp_sockaddr(p_conn_info);
-
-  EVENT(EM_EVENT,("Call to %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",
-		  p_conn_info->addr.sas_addr.prv[0]&0xff,
-		  p_conn_info->addr.sas_addr.prv[1]&0xff,
-		  p_conn_info->addr.sas_addr.prv[2]&0xff,
-		  p_conn_info->addr.sas_addr.prv[3]&0xff,
-		  p_conn_info->addr.sas_addr.prv[4]&0xff,
-		  p_conn_info->addr.sas_addr.prv[5]&0xff,
-		  p_conn_info->addr.sas_addr.prv[6]&0xff,
-		  p_conn_info->addr.sas_addr.prv[7]&0xff,
-		  p_conn_info->addr.sas_addr.prv[8]&0xff,
-		  p_conn_info->addr.sas_addr.prv[9]&0xff,
-		  p_conn_info->addr.sas_addr.prv[10]&0xff,
-		  p_conn_info->addr.sas_addr.prv[11]&0xff,
-		  p_conn_info->addr.sas_addr.prv[12]&0xff,
-		  p_conn_info->addr.sas_addr.prv[13]&0xff,
-		  p_conn_info->addr.sas_addr.prv[14]&0xff,
-		  p_conn_info->addr.sas_addr.prv[15]&0xff,
-		  p_conn_info->addr.sas_addr.prv[16]&0xff,
-		  p_conn_info->addr.sas_addr.prv[17]&0xff,
-		  p_conn_info->addr.sas_addr.prv[18]&0xff,
-		  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 && 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;
-  }
-
-  /* Notify lower layer. */
-  switch (p_conn_info->blli.l3.tr9577.snap[4]) { /* AAAAAARRRGGHHH! */
-  case 0x02:
-  case 0x03:
-    break;
-  case 0x04:
-  case 0x05:
-    if (ioctl(s, ATMLEC_MCAST, sap->itf_num)<0) {
-      EVENT(EM_SERR,("Can't change socket into LE mcast socket:%s\n",
-		     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;
-    }
-    break;
-  default:
-    break;
-  }
-
-  /* Ok. Connect made. Add to list */
-  ret = list_add_conn(sap_handle, conn_context,
-		      age_limit, p_conn_info, &conn);
-  EVENT(EM_DEBUG,("Conn:%lx\tcontext:%lx\n",(long)conn, (long)conn_context));
-  if (ret <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_RESOURCES;
-  }
-  conn->fd = s;
-  conn->type = WEMADE;
+        memset(&addr, 0, sizeof(struct sockaddr_atmsvc));
+        memcpy(addr.sas_addr.prv, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+        addr.sas_family = AF_ATMSVC;
+        init_conn_params(&sap, &qos, DATA_DIRECT_CONN);
 
-  /* Connection was made. Must notify upper level later. */
-  if (is_data_direct(p_conn_info))
-    conn->status = CONNECTING;
-  else
-    conn->status = CONNECTED;
+        lec_params.data_listen = create_listensocket(&addr, &sap, &qos);
+        if (lec_params.data_listen == NULL) {
+                diag(COMPONENT, DIAG_FATAL, "Could not create listen socket for incoming Data Direct VCCs\n");
+                return -1;
+        }
 
-  EVENT(EM_DEBUG,("Conn_handle %lx,fd:%d\n",(long)conn, s));
-  *p_conn_handle = conn;
-  return STATUS_K_SUCCESS;
+        return 0;
 }
 
-STATUS 
-cm_sap_svc_teardown(HANDLE conn_handle)
+/* Opens a Multicast or non-blocking Data Direct VCC to atm_addr.
+ * Not for Control connections.
+ * Returns < 0 for error
+ */
+int create_data_svc(unsigned char *atm_addr, int codepoint)
 {
-  Conn_t *conn;
+        struct atm_sap sap;
+        struct atm_qos qos;
+        struct sockaddr_atmsvc my_addr, dst_addr;
+        Conn_t *conn;
+
+        memset(&my_addr, 0, sizeof(struct sockaddr_atmsvc));
+        memcpy(my_addr.sas_addr.prv, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+        memset(&dst_addr, 0, sizeof(struct sockaddr_atmsvc));
+        memcpy(dst_addr.sas_addr.prv, atm_addr, ATM_ESA_LEN);
+        my_addr.sas_family = dst_addr.sas_family = AF_ATMSVC;
+        init_conn_params(&sap, &qos, codepoint);
+
+        conn = setup_svc(&dst_addr, &my_addr, &sap, &qos);
+        if (conn == NULL) {
+                diag(COMPONENT, DIAG_ERROR, "Could not create Data Direct VCC\n");
+                delete_addr(dst_addr.sas_addr.prv);
+                return -1;
+        }
+
+        return 0;
+}
+
+/* Creates a listen socket with parameters specified with
+ * arguments.
+ * Returns NULL for error or Conn_t for new listen socket.
+ */
+Conn_t *create_listensocket(struct sockaddr_atmsvc *listen_addr,
+                            struct atm_sap *sap, struct atm_qos *qos)
+{
+        int fd, ret;
+        Conn_t *conn;
 
-  EVENT(EM_DEBUG,("Cm_sap_svc_teardown %lx\n",(long)conn_handle));
-  conn = (Conn_t *)conn_handle;
+        diag(COMPONENT, DIAG_DEBUG, "conn_create_listensocket\n");
+        
+        fd = get_socket(listen_addr, sap, qos);
+        if (fd < 0) return NULL;
+        
+        ret = listen(fd, 5);
+        if (ret != 0) {
+                diag(COMPONENT, DIAG_DEBUG, "Listen failed: %s\n", strerror(errno));
+                close(fd);
+                return NULL;
+        }
+        
+        conn = list_add_conn(NULL);
+        if (conn == NULL) {
+                diag(COMPONENT, DIAG_ERROR, "List_add_conn failed\n");
+                close(fd);    
+                return NULL;
+        }
+
+        conn->type = LISTENING;
+        conn->fd = fd;
+        diag(COMPONENT, DIAG_DEBUG, "Listen socket created blli:%2.2x %2.2x fd: %d\n",
+             sap->blli[0].l3.tr9577.snap[3],
+             sap->blli[0].l3.tr9577.snap[4],
+             conn->fd);
+        
+        return conn;
+}
 
-  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);
+/* Accepts a new connection from listen socket in conn.
+ * Returns NULL for error
+ */
+Conn_t *accept_conn(Conn_t *conn)
+{
+        Conn_t *new;
+        struct sockaddr_atmsvc addr;
+        size_t len;
+        int fd;
+        char buff[MAX_ATM_ADDR_LEN+1];
+
+        diag(COMPONENT, DIAG_DEBUG, "Accepting connection on fd %d\n", conn->fd);
+        len = sizeof(addr);
+        fd = accept(conn->fd, (struct sockaddr *)&addr, &len);
+        diag(COMPONENT, DIAG_DEBUG, "accept returned %d\n", fd);
+        if (fd < 0) {
+                diag(COMPONENT, DIAG_ERROR, "accept: %s\n", strerror(errno));
+                return NULL;
+        }
+        if (atm2text(buff, sizeof(buff), (struct sockaddr *)&addr, A2T_PRETTY | A2T_NAME | A2T_LOCAL) < 0)
+                sprintf(buff, "<Unknown ATM address>");
+        diag(COMPONENT, DIAG_DEBUG, "Call from %s", buff);
+
+        new = list_add_conn(addr.sas_addr.prv);
+        if (new == NULL) return NULL;
+        new->fd = fd;
+        new->status = CONNECTED;
+        new->type = THEYMADE;
+        if (conn == lec_params.ctrl_listen) new->codepoint  = CONTROL_CONN;
+        if (conn == lec_params.mcast_listen) new->codepoint = MCAST_CONN;
+        if (conn == lec_params.data_listen) new->codepoint  = DATA_DIRECT_CONN;
 
-  return STATUS_K_SUCCESS;
+        return new;
 }
 
-STATUS
-cm_sap_xmt_vc (HANDLE conn_handle, void *p_data,
-	       UINT32 length, UINT32 user_data,
-	       AAL_DATA *p_aal_data)
+/* Close all connections, important or not.
+ */
+void close_connections(void)
 {
-  Conn_t *conn;
-  Sap_client_t *sap;
-  int ret;
+        Conn_t *conn, *next;
 
-  /* 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);
+        for(conn = connlist; conn; conn = next) {
+                diag(COMPONENT, DIAG_DEBUG, "Destroying:%p fd:%d type:%d\n",
+                     conn, conn->fd, conn->type);
+                next = conn->next;
+                close(conn->fd);
+                list_remove_conn(conn);
+                free(conn);
+        }
+
+        return;
+}
+
+/* Closes a connection and checks its importance.
+ * Important connections are kernel socket, LES connections,
+ * BUS Default Multicast Send VCC, last Multicast Forward VCC from Bus
+ * and any of the listen sockets.
+ * Returns < 0 for important connection.
+ */
+int close_connection(Conn_t *conn)
+{
+        int bad = 0;
+        Conn_t *mcast;
 
-  /* Tried to transmit packet */
-  sap->xmt_packet_count++;
-  conn->p_packet = p_data;
+        diag(COMPONENT, DIAG_DEBUG, "close_connection %p\n", conn);
 
-  /* Failure */
-  if (ret<0) {
-    EVENT(EM_NERR,("Write failed: %s\n",strerror(errno)));
-    conn->status = RELEASED;
-    return STATUS_K_CONGESTED; /* Asdf */
-  } 
-  if (EMASK & EM_XCTRL)
-    le_frame_display(p_data, length, "Xmitted");
-  return STATUS_K_SUCCESS;
+        if (conn == lec_params.kernel ||
+            conn == lec_params.ctrl_direct  ||
+            conn == lec_params.ctrl_dist    ||
+            conn == lec_params.mcast_send   ||
+            conn == lec_params.mcast_listen ||
+            conn == lec_params.data_listen)
+                bad = -1;
+        else {
+                bad = -1;
+                for (mcast = connlist; mcast; mcast = mcast->next)
+                        if (mcast != conn &&
+                            mcast->type == THEYMADE &&
+                            mcast->codepoint == MCAST_CONN)
+                                bad = 0;
+        }
+
+        close(conn->fd);
+        list_remove_conn(conn);
+        free(conn);
+        
+        return bad;
+}
+
+/* Accepts a new incoming Data Direct or Multicast Forward connection.
+ * Control connections (LECS/LES) are accepted during configuration/join.
+ * Returns < 0 for serious error such as broken listen socket.
+ */
+static int handle_accept(Conn_t *conn)
+{
+        Conn_t *new;
+        struct atmlec_ioc ioc;
+        
+        new = accept_conn(conn);
+        if (new == NULL) return -1;
+
+        if (conn == lec_params.mcast_listen) {
+                diag(COMPONENT, DIAG_DEBUG, "Multicast Forward VCC accepted\n");
+                ioc.receive = 2;
+        } else {
+                diag(COMPONENT, DIAG_DEBUG, "Data Direct VCC accepted\n");
+                ioc.receive = 0;
+                if (conn_already_exists(new->atm_address, new) &&
+                    memcmp(lec_params.c1n_my_atm_addr, new->atm_address,  ATM_ESA_LEN) < 0) {
+                        diag(COMPONENT, DIAG_DEBUG, "Using it only to receive, spec 8.1.1\n");
+                        ioc.receive = 1;
+                }
+        }
+        memcpy(ioc.atm_addr, new->atm_address, ATM_ESA_LEN);
+        ioc.dev_num = lec_params.itf_num;
+        diag(COMPONENT, DIAG_DEBUG, "Attaching a new VCC, fd %d\n", new->fd);
+        if (ioctl(new->fd, ATMLEC_DATA, &ioc) < 0) {
+                diag(COMPONENT, DIAG_ERROR, "VCC attach failed: ioctl: %s\n", strerror(errno));
+                return -1;
+        }
+
+        return 0;
+}
+
+/* Reads a LE control frame from conn, usually Data Direct or
+ * Multicast Forward connection. Calls the incoming packet
+ * handler function.
+ * Returns < 0 for serious error such as broken LES connection
+ */
+static int handle_data(Conn_t *conn)
+{
+        char buff[MAX_CTRL_FRAME];
+        int retval;
+
+        retval = recv_frame(conn, buff, sizeof(buff));
+        if (retval < 0) {
+                diag(COMPONENT, DIAG_ERROR, "handle_data: read: %s\n", strerror(errno));
+                return (close_connection(conn));
+        }
+        if (retval == 0) {
+                diag(COMPONENT, DIAG_DEBUG, "fd %d, Data or Multicast VCC closed\n", conn->fd);
+                return (close_connection(conn));
+        }
+
+        return handle_frame(conn, buff, retval);
+}
+
+/* Checks connections in *fds. The only allowed sockets
+ * in *fds are listen sockets, data direct and control
+ * sockets.
+ * Returns < 0 for serious error such as broken LES connection
+ */
+int check_connections(fd_set *fds)
+{
+        Conn_t *conn, *next;
+
+        conn = connlist;
+        while (conn != NULL) {
+                next = conn->next;
+                if (!FD_ISSET(conn->fd, fds)) {
+                        conn = next;
+                        continue;
+                }
+
+                switch (conn->type) {
+                case LISTENING:
+                        if (handle_accept(conn) < 0)
+                                return -1;
+                        break;
+                case WEMADE:
+                case THEYMADE:
+                        if (handle_data(conn) < 0)
+                                return -1;
+                        break;
+                default:
+                        diag(COMPONENT, DIAG_ERROR, "check_connections: bad_type '%s'\n",
+                             get_type_string(conn->type));
+                        break;
+                }
+                
+                conn = next;
+        }
+        
+        return 0;
 }
 
-void
-cm_sap_link_status_get(HANDLE sap_handle, ATM_LINK_STATE *p_link_state)
+/* Completes a non-blocking connect.
+ * Returns < 0 for serious error
+ */
+static int handle_connect(Conn_t *conn)
 {
-  int s;
+        int retval;
+        struct sockaddr_atmsvc dummy;
+        struct atmlec_msg msg;
+        struct atmlec_ioc ioc;
+
+        diag(COMPONENT, DIAG_DEBUG, "handle_connect: completing fd %d\n", conn->fd);
+        /* this seems to be common method in Linux-ATM
+         * making sure that nonblocking connect was
+         * completed successfully
+         */
+        conn->status = CONNECTED;
+        retval = connect(conn->fd, (struct sockaddr *)&dummy, sizeof(struct sockaddr_atmsvc));
+        if (retval < 0) {
+                diag(COMPONENT, DIAG_DEBUG, "handle_connect: connect: %s\n", strerror(errno));
+                delete_addr(conn->atm_address);
+                close_connection(conn);
+                return 0;
+        }
+
+        send_ready_ind(conn);
+
+        memcpy(ioc.atm_addr, conn->atm_address, ATM_ESA_LEN);
+        ioc.dev_num = lec_params.itf_num;
+        ioc.receive = 0;
+        diag(COMPONENT, DIAG_DEBUG, "Attaching a new active VCC, fd %d\n", conn->fd);
+        if (ioctl(conn->fd, ATMLEC_DATA, &ioc) < 0) {
+                diag(COMPONENT, DIAG_ERROR, "VCC attach failed: ioctl: %s\n", strerror(errno));
+                return -1;
+        }
+
+        memset(&msg, 0, sizeof(struct atmlec_msg));
+        msg.type = l_flush_tran_id;
+        memcpy(msg.content.normal.atm_addr, conn->atm_address, ATM_ESA_LEN);
+        msg.content.normal.flag = send_flush_req(conn);
+        
+        msg_to_kernel(&msg, sizeof(struct atmlec_msg));
 
-  EVENT(EM_DEBUG,("Cm_sap_link_status_get\n"));
-  assert(sap_handle);
 
-  if ((s=socket(AF_ATMSVC, SOCK_DGRAM, 0))<0) {
-    /* Socket creation failure -> not capable of running LE */
-    EVENT(EM_SERR,("Not capable of creating ATM socket."));
-    *p_link_state = LINK_DOWN;
-    exit(-1);
-  }
-  close(s);
-  *p_link_state = LINK_SIG_UP;
+        return 0;
 }
 
-void
-svcinit_conn_info(CONN_INFO *p_svc_conn_info)
+/* Complete non-blocking connections in *fds.
+ * Returns < 0 for serious error (problems with kernel). 
+ */
+int complete_connections(fd_set *fds)
 {
-  memset(p_svc_conn_info,0,sizeof(CONN_INFO));
+        Conn_t *conn, *next;
+        int retval;
+
+        conn = connlist;
+        while (conn) {
+                next = conn->next;
+                if (FD_ISSET(conn->fd, fds)) {
+                        retval = handle_connect(conn);
+                        if (retval < 0) return -1;
+                }
+                conn = next;
+        }
+                
+        return 0;
 }
 
-/* Callbacks for connections */
-void
-conn_call_callbacks(void)
+/* Send a LE control frame using *conn.
+ * Returns < 0 for serious error
+ */
+int send_frame(Conn_t *conn, void *frame, int length)
 {
-  Conn_t *conn;
-  Sap_client_t *sap;
-  
-  conn = connlist;
-  EVENT(EM_DEBUG,("Conn_call_callbacks %p\n",connlist));
-  while(conn) {
-    if (conn->status == CONNECTED) {
-      /* Connection made, not notified yet */
-      conn->status = NOTIFIED;
-      sap = (Sap_client_t *)conn->sap_handle;
-      sap->vc_notify_callback(conn->conn_context,
-			      conn,
-			      CONN_VC_READY,
-			      0,
-			      0,
-			      TRUE);
-      conn = conn->next;
-    } else if (conn->status == TRANSMITTED) {
-      conn->status = NOTIFIED;
-      conn->p_packet = NULL;
-      sap = (Sap_client_t *)conn->sap_handle;
-      sap->xmt_done_callback(conn->conn_context,
-			     conn->p_packet,
-			     0);
-      conn = conn->next;
-    } else if (conn->status == RELEASED) {
-      EVENT(EM_DEBUG,("Conn_call_callbacks, released conn %p\n",conn));
-      conn->status = NOTIFIED;
-      sap = (Sap_client_t *)conn->sap_handle;
-      sap->vc_notify_callback(conn->conn_context,
-			      conn,
-			      CONN_RELEASE,
-			      CAUSE_NORMAL,
-			      0,
-			      (conn->type==WEMADE)?TRUE:FALSE);
-      conn=connlist;
-    } else {
-      conn = conn->next;
-    }
-  }
+        struct frame_hdr *hdr;
+        int ret;
+
+        diag(COMPONENT, DIAG_DEBUG, "send_frame: fd:%d len:%ld\n", conn->fd, length);
+        hdr = (struct frame_hdr *)frame;
+        if (hdr->opcode == htons(READY_QUERY) ||
+            hdr->opcode == htons(READY_IND))
+                diag(COMPONENT, DIAG_DEBUG, "%s\n", opcode2text(hdr->opcode));
+        else 
+                display_frame(frame);
+
+        ret = write(conn->fd, frame, length);
+        if (ret < 0) {
+                diag(COMPONENT, DIAG_ERROR, "send_frame: write: %s\n", strerror(errno));
+                return -1;
+        } 
+
+        return ret;
 }
 
-static const char*
-conn_get_type_string(int type) {
-  switch(type) {
-  case WEMADE:
-    return "WEMADE";
-  case THEYMADE:
-    return "THEYMADE";
-  case LISTENING:
-    return "LISTENING";
-  case KERNEL_SOCK:
-    return "KERNEL_SOCK";
-  default:
-    return "UNKNOWN";
-  }
-}
-
-/* 
- * Get connections fds for main's select(),
- * Quite ugly way BTW.
- */
-void
-conn_get_fds(fd_set *fds)
-{
-  Conn_t *conn;
-  char *buff = NULL, *ch = NULL;  /* once again, silence gcc 2.7.2.1 */
-
-  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_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 = NULL, *ch = NULL;  /* once again, silence gcc 2.7.2.1 */
-
-  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);
+/* Receive a LE control frame from *conn.
+ * Returns < 0 for serious error.
+ */
+int recv_frame(Conn_t *conn, void *buff, int length)
+{
+        int ret;
+
+        diag(COMPONENT, DIAG_DEBUG, "recv_frame: fd:%d\n", conn->fd);
+        ret = read(conn->fd, buff, length);
+        if (ret < 0) {
+                diag(COMPONENT, DIAG_ERROR, "Read failed: %s\n", strerror(errno));
+                return -1;
+        } 
+
+#if 0
+        diag(COMPONENT, DIAG_DEBUG, "recv_frame: read %d bytes\n", ret);
+        if (get_verbosity(COMPONENT) >= DIAG_DEBUG) {
+                int i;
+                for (i = 0; i < 11; i++)
+                        diag(COMPONENT, DIAG_DEBUG, "0x%2x", ((unsigned char *)buff)[i]);
+        }
+#endif
+
+        return ret;
 }
-  
-int
-conn_check_incoming(fd_set *fds)
+
+
+/*
+ * LANE2: 5.2.1.4 and others, sleep random time before trying to reconnect
+ */
+void random_delay(void)
 {
-  Conn_t *conn, *tmpconn;
-  Sap_client_t *sap;
-  unsigned char buffer[BUFSIZE];
-  unsigned char *tmp;
-  long nbytes;
-  int fd, len;
-  unsigned long reject_reason;
-  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) && 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) {
-	  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,
-				  CONN_RELEASE,
-				  CAUSE_NORMAL,
-				  0,
-				  FALSE);
-	} else {
-	  to_add->fd = fd;
-	  to_add->status = NOTIFIED;
-	  to_add->type = THEYMADE;
-	  if (conn->conn_info->blli.l3.tr9577.snap[4] !=1) { 
-	    /*Others are data*/
-	    len = sizeof(struct sockaddr_atmsvc);
-	    memset(&addr, 0, len);
-	    if (getpeername(fd, (struct sockaddr *)&addr, &len)<0) {
-	      EVENT(EM_SERR,("Can't get socket address:%s\n",strerror(errno)));
-	      list_remove_conn(to_add);
-	      sap->vc_notify_callback(to_add->conn_context,
-				      to_add,
-				      CONN_RELEASE,
-				      CAUSE_NORMAL,
-				      0,
-				      FALSE);
-	    } else {
-	      EVENT(EM_EVENT,("Call from %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",
-			      addr.sas_addr.prv[0]&0xff,
-			      addr.sas_addr.prv[1]&0xff,
-			      addr.sas_addr.prv[2]&0xff,
-			      addr.sas_addr.prv[3]&0xff,
-			      addr.sas_addr.prv[4]&0xff,
-			      addr.sas_addr.prv[5]&0xff,
-			      addr.sas_addr.prv[6]&0xff,
-			      addr.sas_addr.prv[7]&0xff,
-			      addr.sas_addr.prv[8]&0xff,
-			      addr.sas_addr.prv[9]&0xff,
-			      addr.sas_addr.prv[10]&0xff,
-			      addr.sas_addr.prv[11]&0xff,
-			      addr.sas_addr.prv[12]&0xff,
-			      addr.sas_addr.prv[13]&0xff,
-			      addr.sas_addr.prv[14]&0xff,
-			      addr.sas_addr.prv[15]&0xff,
-			      addr.sas_addr.prv[16]&0xff,
-			      addr.sas_addr.prv[17]&0xff,
-			      addr.sas_addr.prv[18]&0xff,
-			      addr.sas_addr.prv[19]&0xff));
-	      /* LE spec 8.1.11. Accept all calls. If there already
-		 exists a connection to this calling entity, and our
-		 atm address is numerically lower than theirs, then
-		 don't make it default interface to use in kernel. */
-	      memcpy(ioc_data.atm_addr, addr.sas_addr.prv, ATM_ESA_LEN);
-	      if (conn->conn_info->blli.l3.tr9577.snap[4] == 2 ||
-		  conn->conn_info->blli.l3.tr9577.snap[4] == 3) {
-		tmpconn = conn_already_exists(addr.sas_addr.prv, to_add);
-		if (tmpconn) {
-		  addr_getouratmaddr(&addr);
-		  if (memcmp(addr.sas_addr.prv, ioc_data.atm_addr, ATM_ESA_LEN)
-		      <0)
-		    ioc_data.receive = 1;
-		  else
-		    ioc_data.receive = 0;
-		} else
-		  ioc_data.receive = 0; /* Data direct */
-	      } else
-		ioc_data.receive = 2; /* Multicast distribute */
-	      ioc_data.dev_num = sap->itf_num;
-	      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) {
-    tmpconn = conn->next;
-    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)) &&
-	  errno != EINPROGRESS) {
-	  */
-	if (connect(conn->fd, (struct sockaddr*)&addr, sizeof(addr))<0) {
-	  EVENT(EM_SERR,("Nonblocking connect() :%s\n",strerror(errno)));
-	  lc_addr_delete(conn->conn_context, conn->atm_address);
-	  conn->status = RELEASED;
-	} else {
-	  EVENT(EM_DEBUG,("Call connected\n"));
-	  conn->status = CONNECTED;
-	  memcpy(ioc_data.atm_addr, conn->atm_address, ATM_ESA_LEN);
-	  sap = conn->sap_handle;
-	  ioc_data.dev_num = sap->itf_num;
-	  ioc_data.receive = 0;
-	  EVENT(EM_DEBUG,("About to ioctl(s, ATMLEC_DATA, &ioc_data)\n"));
-	  if (ioctl(conn->fd, ATMLEC_DATA, &ioc_data)<0) {
-	    EVENT(EM_SERR,("Can't change socket into LE data socket:%s\n",
-			   strerror(errno)));
-	    conn->status = RELEASED;
-	    lc_addr_delete(conn->conn_context, conn->atm_address);
-	  } else {
-	    EVENT(EM_DEBUG,("ioctl done\n"));
-	    kernel_flush_xmt(conn->atm_address);
-	  }
-	}
-      } 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 || 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 {
-	  sap = (Sap_client_t *)conn->sap_handle;
-	  sap->rcv_packet_count++;
-	  if ((EMASK & EM_RCTRL) && (((LE_CTRL_HDR*)buffer)->op_code != ntohs(LE_TOPOLOGY_REQ)))
-	    le_frame_display(buffer, nbytes, "Received");
-	  tmp=buffer;
-	  sap->rcv_callback(conn->conn_context,
-			    conn,
-			    nbytes,
-			    0,
-			    NULL,
-			    (void*)&tmp);
-	  fflush(stdout);
-	}
-      }
-    }
-    conn = tmpconn;
-  }
-  return reset;
-}
-
-int
-conn_create_listensocket(HANDLE sap_handle, HANDLE conn_context,
-			 unsigned short blli_codepoint, const char *qos_spec,
-			 LAN_MTU mtu)
-{
-  int fd, ret, len, sdu;
-  Conn_t *conn;
-  CONN_INFO *conn_info;
-  struct atm_sap atmsap;
-
-  conn_info = (CONN_INFO *)mem_alloc(EINST, sizeof(CONN_INFO));
-
-  EVENT(EM_DEBUG,("conn_create_listensocket\n"));
-  fd = socket(PF_ATMSVC, SOCK_DGRAM, 0);
-  if (fd < 0) {
-    EVENT(EM_NERR,("Socket failed: %s\n",strerror(errno)));
-    return -1;
-  }
- 
-  memset(conn_info , 0, sizeof(CONN_INFO));
+        struct timeval tv;
+        int millis, interval;
+        
+        srand(time(NULL));
+        interval = lec_params.c38_max_reconfig_delay - lec_params.c37_min_reconfig_delay;
+        millis = (rand() % interval) + lec_params.c37_min_reconfig_delay;
+        tv.tv_sec  = (millis - (millis % 1000)) / 1000;
+        tv.tv_usec = (millis % 1000) * 1000;
+        
+        diag(COMPONENT, DIAG_DEBUG, "random_delay: sleeping %d.%d seconds\n", tv.tv_sec, tv.tv_usec);
+        (void)select(0, NULL, NULL, NULL, &tv);
+        
+        return;
+}
 
-  conn_info->conqos.aal = ATM_AAL5;
-  conn_info->conqos.txtp.traffic_class = ATM_UBR;
-  conn_info->conqos.rxtp.traffic_class = ATM_UBR;
-
-  switch (blli_codepoint) {
-  case BLLI_CONTROL:
-    conn_info->conqos.rxtp.max_sdu = 1516;
-    conn_info->conqos.txtp.max_sdu = 1516;
-    break;
-  case BLLI_DIRECT_802_3:
-  case BLLI_BUS_802_3:
-    sdu = maxframe2maxsdu(mtu);
-    conn_info->conqos.rxtp.max_sdu = sdu;
-    conn_info->conqos.txtp.max_sdu = sdu;
-    break;
-  case BLLI_DIRECT_802_5:
-  case BLLI_BUS_802_5:
-    conn_info->conqos.rxtp.max_sdu = 4544;
-    conn_info->conqos.txtp.max_sdu = 4544;
-    break;
-  default:
-    EVENT(EM_ASSERT,("Unknown BLLI codepoint:%x\n",blli_codepoint));
-  }
-
-  if (qos_spec)
-    if (text2qos(qos_spec,&conn_info->conqos,T2Q_DEFAULTS) < 0)
-      EVENT(EM_ASSERT,("text2qos failed in conn_create_listensocket\n"));
-
-  /* Set traffic parameters */
-  if (setsockopt(fd,SOL_ATM,SO_ATMQOS, &(conn_info->conqos), 
-		 sizeof(conn_info->conqos)) < 0) {
-    EVENT(EM_NERR,("setsockopt SO_ATMQOS: %s\n",strerror(errno)));
-    close(fd);
-    return -1;
-  }
-  
-  if (addr_getouratmaddr(&conn_info->addr)<0) {
-    close(fd);
-    return -1;
-  }
-  conn_info->blli.l3_proto = ATM_L3_TR9577;
-  conn_info->blli.l3.tr9577.ipi = NLPID_IEEE802_1_SNAP;
-  conn_info->blli.l3.tr9577.snap[0] = 0x00;
-  conn_info->blli.l3.tr9577.snap[1] = 0xa0;
-  conn_info->blli.l3.tr9577.snap[2] = 0x3e;
-  conn_info->blli.l3.tr9577.snap[3] = 
-    (unsigned char)(0xff&(blli_codepoint>>8));
-  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);
-
-  memset(&atmsap, 0, sizeof(struct atm_sap));
-  atmsap.blli[0] = conn_info->blli;
-  if (setsockopt(fd,SOL_ATM,SO_ATMSAP,&atmsap,sizeof(atmsap)) < 0) {
-    EVENT(EM_NERR,("conn.c::conn_create_listensocket setsockop(SO_ATMSAP)\n"));
-    (void) close(fd);
-    return -1;
-  }
-
-  ret = bind(fd, (struct sockaddr *)&conn_info->addr, len);
-  if (ret != 0) {
-    EVENT(EM_NERR,("Bind failed: %s\n",strerror(errno)));
-    close(fd);
-    return -1;
-  }
-
-  ret = listen(fd, QLEN);
-  if (ret != 0) {
-    EVENT(EM_NERR,("Listen failed: %s\n",strerror(errno)));
-    close(fd);
-    return -1;
-  }
-
-  if (list_add_conn(sap_handle, conn_context, 0, NULL, &conn)<0) {
-    EVENT(EM_NERR,("List_add_conn failed\n"));
-    close(fd);    
-    return -1;
-  }
-  conn->type = LISTENING;
-  conn->status = NOTIFIED;
-  conn->conn_info = conn_info;
-  conn->fd = fd;
-  EVENT(EM_EVENT,("Listen socket created blli:%2.2x %2.2x\n",
-		  conn_info->blli.l3.tr9577.snap[3],
-		  conn_info->blli.l3.tr9577.snap[4]));
-  return fd;
-}
-
-static int
-list_add_conn(HANDLE sap_handle, HANDLE conn_context, long age_limit, 
-	      CONN_INFO *info, Conn_t **p_conn)
-{
-  Conn_t *conn;
-
-  conn = (Conn_t *)mem_alloc(EINST,sizeof(Conn_t));
-  *p_conn = conn;
-  if (!conn)
-    return -1;
-  
-  conn->sap_handle = sap_handle;
-  conn->conn_context = conn_context;
-  conn->age_limit = age_limit;
-  if (info)
-    memcpy(conn->atm_address, info->addr.sas_addr.prv, ATM_ESA_LEN);
-  else
-    memset(conn->atm_address, 0, ATM_ESA_LEN);
-
-  conn->next = connlist;
-  conn->previous = NULL;
-  if (connlist)
-    connlist->previous = conn;
-  connlist = conn;
-  EVENT(EM_DEBUG,("Added conn:%p\n",conn));
-  
-  return 0;
+/* Collect already connected sockets in *fds
+ */
+void conn_get_fds(fd_set *fds)
+{
+        Conn_t *conn;
+
+        diag(COMPONENT, DIAG_DEBUG, "collecting ready fds ");
+        conn = connlist;
+        while (conn) {
+                if (conn->status != CONNECTING) {
+                        FD_SET(conn->fd, fds);
+                        diag(COMPONENT, DIAG_DEBUG, "%d type %s", conn->fd, get_type_string(conn->type));
+                }
+                conn = conn->next;
+        }
+        
+        return;
 }
 
-static void
-list_remove_conn(HANDLE conn_handle)
+/* Collect non-blocking connecting sockets in *fds
+ */
+void conn_get_connecting_fds(fd_set *fds)
 {
-  Conn_t *conn;
+        Conn_t *conn;
 
-  conn = (Conn_t *)conn_handle;
-
-  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, 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, 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;
-  } else /* First in line */
-    connlist = conn->next;
-  if (conn->next)
-    conn->next->previous = conn->previous;  
-  EVENT(EM_DEBUG,("Connlist:%lx\n",(long)connlist));
-  conn->next=conn->previous= NULL;
+        diag(COMPONENT, DIAG_DEBUG, "collecting connecting fds ");
+        conn = connlist;
+        while (conn) {
+                if (conn->status == CONNECTING) {
+                        FD_SET(conn->fd, fds);
+                        diag(COMPONENT, DIAG_DEBUG, "%d", conn->fd);
+                }
+                conn = conn->next;
+        }
+        
 }
 
-int 
-conn_set_kernel_socket(int fd)
+/* Creates Conn_t for fd and marks it as kernel socket
+ * Returns < 0 for error
+ */
+int conn_set_kernel_socket(int fd)
 {
-  Conn_t *conn;
-  
-  if (list_add_conn(NULL, NULL, 0, NULL, &conn)<0) {
-    EVENT(EM_NERR,("List_add_conn failed\n"));
-    return -1;
-  }
-  conn->type = KERNEL_SOCK;
-  conn->status = NOTIFIED;
-  conn->fd = fd;
-  return fd;
+        Conn_t *conn;
+
+        conn = list_add_conn(NULL);
+        if (conn == NULL) {
+                diag(COMPONENT, DIAG_ERROR, "conn_set_kernel_socket: list_add_conn failed\n");
+                return -1;
+        }
+        conn->type = KERNEL_SOCK;
+        conn->status = CONNECTED;
+        conn->fd = fd;
+        lec_params.kernel = conn;
+
+        return fd;
+}
+
+/* Creates new Conn_t object and allocates memory for it.
+ * atm_addr should be the ATM address of the other end
+ * or NULL if not applicable
+ */
+static Conn_t *list_add_conn(unsigned char *atm_addr)
+{
+        Conn_t *conn;
+
+        conn = (Conn_t *)malloc(sizeof(Conn_t));
+        if (!conn)
+                return NULL;
+
+        memset(conn, 0, sizeof(Conn_t));
+        if (atm_addr)
+                memcpy(conn->atm_address, atm_addr, ATM_ESA_LEN);
+
+        conn->next = connlist;
+        conn->previous = NULL;
+        if (connlist)
+                connlist->previous = conn;
+        connlist = conn;
+        diag(COMPONENT, DIAG_DEBUG, "Added conn:%p\n", conn);
+
+        return conn;
 }
 
-int
-maxframe2maxsdu(LAN_MTU mtu)
+/* Helper for close_connection and close_connections
+ */
+static void list_remove_conn(Conn_t *conn)
+{
+
+        if (conn->next == NULL && conn->previous == NULL
+            && connlist != conn) return;
+        diag(COMPONENT, DIAG_DEBUG, "Removing conn:%p fd:%d previous:%p next:%p ",
+             conn, conn->fd, conn->previous, conn->next);
+
+        if (conn->previous) 
+                diag(COMPONENT, DIAG_DEBUG, "Previous:%p, fd:%d, next:%p, previous:%p ",
+                     conn->previous, conn->previous->fd,
+                     conn->previous->next, conn->previous->previous);
+        if (conn->next)
+                diag(COMPONENT, DIAG_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;
+        } else /* First in line */
+                connlist = conn->next;
+        if (conn->next)
+                conn->next->previous = conn->previous;  
+        diag(COMPONENT, DIAG_DEBUG, "Connlist: %p\n", connlist);
+        conn->next=conn->previous= NULL;
+        
+        return;
+}
+
+static const char *get_type_string(int type)
+{
+        switch(type) {
+        case WEMADE:
+                return "WEMADE";
+                break;
+        case THEYMADE:
+                return "THEYMADE";
+                break;
+        case LISTENING:
+                return "LISTENING";
+                break;
+        case KERNEL_SOCK:
+                return "KERNEL_SOCK";
+                break;
+        default:
+                break;
+        }
+        
+        return "UNKNOWN";
+}
+
+static int maxmtu2maxsdu(uint8_t mtu)
 {
 
     int sdu;
@@ -1093,91 +906,32 @@
 
     return sdu;
 }
-/*
- *
- * $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
- *
- * Revision 1.24  1996/06/10 04:27:28  carnil
- * traffic parameter via setsockopt
- * compiler warning fix
- * Bug fixes
- *
- * Revision 1.22  1996/05/29 08:22:39  carnil
- * bug fix
- *
- * Revision 1.21  1996/05/23 11:50:54  carnil
- * *** empty log message ***
- *
- * Revision 1.20  1996/05/13 08:53:27  carnil
- * *** empty log message ***
- *
- * Revision 1.19  1996/04/25 19:42:13  carnil
- * Copyright notice
- *
- * Revision 1.18  1996/04/20 16:24:47  carnil
- * *** empty log message ***
- *
- * Revision 1.17  1996/04/19 06:37:49  carnil
- * *** empty log message ***
- *
- * Revision 1.16  1996/04/11 09:16:14  carnil
- * conn direction, data direct
- *
- * Revision 1.15  1996/03/30 15:14:23  carnil
- * DATA ioctl
- *
- * Revision 1.14  1996/03/22 11:26:23  carnil
- * *** empty log message ***
- *
- * Revision 1.13  1996/03/18 18:15:25  carnil
- * ATMLECD_DATA ioctl arg change
- *
- * Revision 1.12  1996/03/18 16:43:50  carnil
- * *** empty log message ***
- *
- * Revision 1.11  1996/03/17 21:23:41  carnil
- * kernel_init()
- *
- * Revision 1.10  1996/03/15 07:08:09  carnil
- * Kernel fd added to list
- *
- * Revision 1.9  1996/03/04 08:55:39  carnil
- * listen socket creation works
- * Communication to servers works
- *
- * Revision 1.8  1996/02/29 11:24:12  carnil
- * Atm connection making works
- *
- * Revision 1.7  1996/02/19 16:32:01  carnil
- * *** empty log message ***
- *
- * Revision 1.6  1996/02/16 06:16:20  carnil
- * listen socket creation, separate funcs for conn list handling
- * tcp code to atmsocket code
- * connection accepting
- *
- * Revision 1.5  1996/02/06  11:23:41  carnil
- * fds for select
- * xmt,rcv, tcp implementation
- *
- * Revision 1.4  1996/01/30  15:20:49  carnil
- * Clients to list, cm_sap_xmt, receiving of packets
- * svc creation using tcp sockets
- *
- * Revision 1.3  1996/01/29  09:30:43  carnil
- * mem_alloc, mem_free
- *
- * Revision 1.2  1996/01/23  10:02:12  carnil
- * Debug info
- *
- * Revision 1.1  1996/01/22  12:59:50  carnil
- * Initial revision
- *
- *
+
+/* Convert a type of connection (CONTROL_CONN, DATA_DIRECT and MCAST_CONN)
+ * to a BLLI codepoint which depends on C2 LAN Type.
  */
+static uint16_t conn_type2codepoint(int conn_type)
+{
+        if (conn_type == CONTROL_CONN) return CONTROL_CONN;
+
+        if (conn_type == DATA_DIRECT_CONN) {
+                if (lec_params.c2_lan_type == LAN_TYPE_8023 || lec_params.c2_lan_type == LAN_TYPE_UNSPEC)
+                        return DATA_DIRECT_8023;
+                else if (lec_params.c2_lan_type == LAN_TYPE_8025)
+                        return DATA_DIRECT_8025;
+                diag(COMPONENT, DIAG_ERROR, "conn_type2codepoint, bad lan_type %d", lec_params.c2_lan_type);
+                return DATA_DIRECT_8023;
+        }
+        else if (conn_type == MCAST_CONN) {
+                if (lec_params.c2_lan_type == LAN_TYPE_8023 || lec_params.c2_lan_type == LAN_TYPE_UNSPEC)
+                        return MCAST_CONN_8023;
+                else if (lec_params.c2_lan_type == LAN_TYPE_8025)
+                        return MCAST_CONN_8025;
+                diag(COMPONENT, DIAG_ERROR, "conn_type2codepoint, bad lan_type %d", lec_params.c2_lan_type);
+                return MCAST_CONN_8023;
+        }
+
+        diag(COMPONENT, DIAG_ERROR, "conn_type2codepoint, unknown type %d", conn_type);
+
+        return DATA_DIRECT_8023;
+}
diff -ur --new-file old/atm/led/conn.h new/atm/led/conn.h
--- old/atm/led/conn.h	Sat Dec  5 01:35:57 1998
+++ new/atm/led/conn.h	Wed Jun  2 23:36:53 1999
@@ -1,44 +1,88 @@
 /*
- *
- * Some conn funcs prototypes
- *
- *
+ * Marko Kiiskila carnil@cs.tut.fi 
+ * 
+ * Copyright (c) 1996
+ * Tampere University of Technology - Telecommunications Laboratory
+ * All rights reserved.
+ *
+ * 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.
+ * 
  */
+
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
 #ifndef CONN_H
 #define CONN_H
 
-#include <unistd.h>
-#include <atm.h>
-#include <sys/types.h>
-#include <sys/time.h>
+typedef struct _conn_t_ {
+        int fd;                  /* Socket connected to this connection */
+        int status;              /* Connection status */
+        int type;                /* We made, they made, listen socket */
+        int codepoint;           /* One of the below, MCAST_CONN etc. */
+        unsigned char atm_address[ATM_ESA_LEN]; 
+                                 /* Destination address, not in listen or
+                                    kernel sockets */
+        struct _conn_t_ *next;
+        struct _conn_t_ *previous;
+} Conn_t;
 
-#include "af_lane.h"
-#include "lec.h"     /* for LAN_MTU */
+void close_connections(void);
+void init_conn_params(struct atm_sap *sap, struct atm_qos *qos,
+                      uint16_t blli_codepoint);
+int create_data_svc(unsigned char *atm_addr, int codepoint);
+Conn_t *setup_svc(struct sockaddr_atmsvc *dst_addr,
+                  struct sockaddr_atmsvc *listen_addr,
+                  struct atm_sap *sap, struct atm_qos *qos);
+int create_data_listen(void);
+Conn_t *create_listensocket(struct sockaddr_atmsvc *listen_addr,
+                            struct atm_sap *sap, struct atm_qos *qos);
+Conn_t *accept_conn(Conn_t *conn);
+int close_connection(Conn_t *conn);
+int check_connections(fd_set *fds);
+int complete_connections(fd_set *fds);
+
+int send_frame(Conn_t *conn, void *frame, int length);
+int recv_frame(Conn_t *conn, void *buff, int length);
 
-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,
-			     const char *qos_spec,
-			     LAN_MTU mtu);
+
 int conn_set_kernel_socket(int fd);
-int maxframe2maxsdu(LAN_MTU mtu);
+void random_delay(void);
 
 /*
-void conn_convert_to_data_vcc(HANDLE conn_handle);
-*/
-#endif /* CONN_H */
+ * Connection types for BLLI codepoints.
+ */
+#define CONTROL_CONN      1
+#define DATA_DIRECT_CONN  2
+#define MCAST_CONN        4
+
+#define DATA_DIRECT_8023  2
+#define DATA_DIRECT_8025  3
+#define MCAST_CONN_8023   4
+#define MCAST_CONN_8025   5
+
 /*
- *
- * $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
- *
- *
+ * MTU sizes
  */
+#define MTU_UNSPEC 0
+#define MTU_1516   1
+#define MTU_1580   5   /* LANEv2 */
+#define MTU_4544   2
+#define MTU_9234   3
+#define MTU_18190  4
+
+#endif /* CONN_H */
diff -ur --new-file old/atm/led/display.c new/atm/led/display.c
--- old/atm/led/display.c	Thu Jan  1 01:00:00 1970
+++ new/atm/led/display.c	Sat Feb  6 21:54:37 1999
@@ -0,0 +1,307 @@
+/* display.c - display frames, addresses, opcodes, etc. */
+
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
+#include <atm.h>
+#include <atmd.h>
+
+#include "display.h"
+#include "frame_defs.h"
+
+#define COMPONENT "display.c"
+
+#define MAX_TEXT 1024  /* Buffer size for displaying LE control frames */
+
+static int my_atm2text(unsigned char *atm_addr, char *dest);
+static const char *lan_dst2text(struct lan_dst *dst);
+static void display_ready(void *buff);
+
+/* Prints out more or less human readable summary of
+ * LE Control Frame pointed by frame.
+ */
+void display_frame(void *frame)
+{
+        struct frame_hdr *hdr;
+        struct ctrl_frame *f;
+        char text[MAX_TEXT];
+        char *p;
+
+        hdr = (struct frame_hdr *)frame;
+        if (hdr->opcode == htons(READY_QUERY) ||
+            hdr->opcode == htons(READY_IND))
+                display_ready(frame);
+       
+        p = text;
+        p += sprintf(p, "\n");
+        p += sprintf(p, "Marker         0x%x\n", ntohs(hdr->marker));
+        p += sprintf(p, "Protocol       0x%x\n", hdr->protocol);
+        p += sprintf(p, "Version        0x%x\n", hdr->version);
+        p += sprintf(p, "Op-Code        0x%x (%s)\n", ntohs(hdr->opcode), opcode2text(hdr->opcode));
+        p += sprintf(p, "Status           %d (%s)\n", hdr->status, status2text(hdr->status));
+        p += sprintf(p, "Trans-ID         %d\n", ntohl(hdr->tran_id));
+        p += sprintf(p, "Req Lec-ID       %d\n", ntohs(hdr->lec_id));
+        p += sprintf(p, "Flags          0x%x", ntohs(hdr->flags));
+        if (hdr->flags & htons(REMOTE_ADDRESS)) p+= sprintf(p, " 'Remote Address'");
+        if (hdr->flags & htons(V2_CAPABLE))     p+= sprintf(p, " 'V2 Capable'");
+        if (hdr->flags & htons(V2_REQUIRED))    p+= sprintf(p, " 'V2 Required'");
+        if (hdr->flags & htons(PROXY_FLAG))     p+= sprintf(p, " 'Proxy Flag'");
+        if (hdr->flags & htons(TOPO_CHANGE))    p+= sprintf(p, " 'Topology Change'");
+        p += sprintf(p, "\n");
+        
+        f = (struct ctrl_frame *)frame;
+        p += sprintf(p, "Source Lan     0x%x (%s)\n", ntohs(f->src_lan_dst.tag), lan_dst2text(&f->src_lan_dst));
+        p += sprintf(p, "Target Lan     0x%x (%s)\n", ntohs(f->target_lan_dst.tag), lan_dst2text(&f->target_lan_dst));
+        p += sprintf(p, "Source ATM     "); p += my_atm2text(f->src_atm_addr, p); p += sprintf(p, "\n");
+        p += sprintf(p, "Lan type       0x%x\n", f->lan_type);
+        p += sprintf(p, "Lan MTU        0x%x\n", f->max_frame_size);
+        p += sprintf(p, "# of TLVs      0x%x\n", f->num_tlvs);
+        p += sprintf(p, "Elan Name size 0x%x\n", f->elan_name_size);
+        p += sprintf(p, "Target ATM     "); p += my_atm2text(f->target_atm_addr, p); p += sprintf(p, "\n");
+        p += sprintf(p, "Elan Name          (");
+        memcpy(p, f->elan_name, f->elan_name_size); p += f->elan_name_size;
+        p += sprintf(p, ")\n");
+
+
+        *p = '\0';
+        diag(COMPONENT, DIAG_DEBUG, "%s\n", text);
+
+        return;
+}
+
+static void display_ready(void *ready_frame)
+{
+        diag(COMPONENT, DIAG_DEBUG, "ready frame\n");
+
+        return;
+}
+
+/* Poor man's atm2text */
+static int my_atm2text(unsigned char *atm_addr, char *dest)
+{
+        int i, len;
+        
+        len = 0;
+        for (i = 0; i < ATM_ESA_LEN; i++)
+                len += sprintf(dest + len, "%2.2x ", *(atm_addr + i));
+        
+        return len;
+}
+
+static const char *lan_dst2text(struct lan_dst *dst)
+{
+        static char text[42]; /* big enough for text + MAC */
+        char *p = text;
+
+        switch(ntohs(dst->tag)) {
+        case LAN_DST_NOT_PRESENT:
+                sprintf(text, "Not present");
+                break;
+        case LAN_DST_MAC_ADDR:
+                p += sprintf(p, "MAC address");
+                p += sprintf(p, " ");
+                mac2text(p, dst->mac);
+                break;
+        case LAN_DST_ROUTE_DESC:
+                p += sprintf(p, "Route Descriptor");
+                p += sprintf(p, " ");
+                mac2text(p, dst->mac);
+                break;
+        default:
+                sprintf(text, "<Unknown Lan destination>");
+                break;
+        }
+
+        return text;
+}
+
+void mac2text(char *buff, unsigned char *mac_addr)
+{
+        sprintf(buff, "%02x-%02x-%02x-%02x-%02x-%02x",
+                mac_addr[0], mac_addr[1], mac_addr[2], 
+                mac_addr[3], mac_addr[4], mac_addr[5]);
+        
+        return;
+}
+
+const char *opcode2text(uint16_t opcode) {
+        switch (ntohs(opcode)) {
+        case LE_CONFIG_REQ:
+                return "LE_CONFIG_REQUEST";
+                break;
+        case LE_CONFIG_RSP:
+                return "LE_CONFIG_RESPONSE";
+                break;
+        case LE_JOIN_REQ:
+                return "LE_JOIN_REQUEST";
+                break;
+        case LE_JOIN_RSP:
+                return "LE_JOIN_RESPONSE";
+                break;
+        case LE_REG_REQ:
+                return "LE_REGISTER_REQUEST";
+                break;
+        case LE_REG_RSP:
+                return "LE_REGISTER_RESPONSE";
+                break;
+        case LE_ARP_REQ:
+                return "LE_ARP_REQUEST";
+                break;
+        case LE_ARP_RSP:
+                return "LE_ARP_RESPONSE";
+                break;
+        case LE_FLUSH_REQ:
+                return "LE_FLUSH_REQUEST";
+                break;
+        case LE_FLUSH_RSP:
+                return "LE_FLUSH_RESPONSE";
+                break;
+        case READY_QUERY:
+                return "READY_QUERY";
+                break;
+        case READY_IND:
+                return "READY_INDICATION";
+                break;
+        case LE_TOPO_REQ:
+                return "LE_TOPOLOGY_REQUEST";
+                break;
+        case LE_NARP_REQ:
+                return "LE_NARP_REQUEST";
+                break;
+        default:
+                break;
+        }
+
+        return "<Unknown OP-CODE>";
+}
+
+const char *tlv2text(uint32_t type)
+{
+        switch (type) {
+        case MAX_CUM_CTRL_TIMEOUT:
+                return "Max-Cumulative-Control-Time-out";
+                break;
+        case MAX_UNKNOWN_FRAME_CNT:
+                return "Max-Unknown-Frame-Count";
+                break;
+        case MAX_UNKNOWN_FRAME_TIME:
+                return "Max-Unknown-Frame-Time";
+                break;
+        case VCC_TIMEOUT_PERIOD:
+                return "VCC-Timeout-Period";
+                break;
+        case MAX_RETRY_COUNT:
+                return "Max-Retry-Count";
+                break;
+        case AGING_TIME:
+                return "Aging-Time";
+                break;
+        case FORWARD_DELAY_TIME:
+                return "Forward-Delay-Time";
+                break;
+        case EXPECTED_LE_ARP_TIME:
+                return "Expected-LE_ARP-Response-Time";
+                break;
+        case FLUSH_TIMEOUT:
+                return "Flush-Time-out";
+                break;
+        case PATH_SWITCHING_DELAY:
+                return "Path-Switching-Delay";
+                break;
+        case LOCAL_SEGMENT_ID:
+                return "Local-Segment-ID";
+                break;
+        case DEF_MCAST_SND_VCC_TYPE:
+                return "Default-Mcast-Send-VCC-Type";
+                break;
+        case DEF_MCAST_SND_VCC_AVG:
+                return "Default-Mcast-Send-VCC-AvgRate";
+                break;
+        case DEF_MCAST_SEND_PEAK_RT:
+                return "Default-Mcast-Send-VCC-PeakRate";
+                break;
+        case CONN_COMPLETION_TIMER:
+                return "Connection-Completion-Timer";
+                break;
+        case CONFIG_FRAG_INFO:
+                return "Config-Frag-Info";
+                break;
+        case LAYER3_ADDRESS:
+                return "Layer-3-Address";
+                break;
+        case ELAN_ID:
+                return "ELAN-ID";
+                break;
+        case SERVICE_CATEGORY:
+                return "Service-Category";
+                break;
+        case LLC_MUXED_ATM_ADDR:
+                return "LLC-Muxed-ATM-Address";
+                break;
+        case X5_ADJUSTMENT:
+                return "X5-Adjustment";
+                break;
+        case PREFERRED_LES:
+                return "Preferred-LES";
+                break;
+        case FORE_NAME:
+                return "Fore's LANE client name";
+                break;
+        default:
+                break;
+        }
+
+        return "<Unknown TLV type>";
+}
+
+const char *status2text(uint16_t status)
+{
+
+        switch (ntohs(status)) {
+        case 0:
+                return "Success";
+                break;
+        case 1:
+                return "Version Not Supported";
+                break;
+        case 2:
+                return "Invalid request parameters";
+                break;
+        case 4:
+                return "Duplicate LAN Destination registration";
+                break;
+        case 5:
+                return "Dupliate ATM address";
+                break;
+        case 6:
+                return "Insufficient resources to grant request";
+                break;
+        case 7:
+                return "Access denied";
+                break;
+        case 8:
+                return "Invalid REQUESTOR-ID";
+                break;
+        case 9:
+                return "Invalid LAN Destination";
+                break;
+        case 10:
+                return "Invalid ATM Address";
+                break;
+        case 20:
+                return "No Configuration";
+                break;
+        case 21:
+                return "LE_CONFIGURE Error";
+                break;
+        case 22:
+                return "Insufficient Information";
+                break;
+        case 24:
+                return "TLV Not Found";
+                break;
+        default:
+                break;
+        }
+
+        return "<Something not supported in LANEv2>";
+}
diff -ur --new-file old/atm/led/display.h new/atm/led/display.h
--- old/atm/led/display.h	Thu Jan  1 01:00:00 1970
+++ new/atm/led/display.h	Sat Feb  6 14:44:23 1999
@@ -0,0 +1,13 @@
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
+#ifndef DISPLAY_H
+#define DISPLAY_H
+
+void display_frame(void *frame);
+
+void mac2text(char *buff, unsigned char *mac_addr);
+const char *opcode2text(uint16_t opcode);
+const char *tlv2text(uint32_t type);
+const char *status2text(uint16_t status);
+
+#endif /* DISPLAY_H */
diff -ur --new-file old/atm/led/emask.h new/atm/led/emask.h
--- old/atm/led/emask.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/emask.h	Thu Jan  1 01:00:00 1970
@@ -1,31 +0,0 @@
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-
-/*
- * Global mask for messages from LE daemon. Location of variable is in main.c.
- * 
- * $Id: emask.h,v 1.1 1996/07/07 11:51:47 carnil Exp carnil $ 
- *
- */
-extern UINT32 EMASK;
diff -ur --new-file old/atm/led/frame_defs.h new/atm/led/frame_defs.h
--- old/atm/led/frame_defs.h	Thu Jan  1 01:00:00 1970
+++ new/atm/led/frame_defs.h	Sun Feb  7 12:05:21 1999
@@ -0,0 +1,125 @@
+/* frame_defs.h - definitions for LANE control frames, TLVs etc. */
+
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
+#ifndef FRAMES_DEFS_H
+#define FRAMES_DEFS_H
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+/* Try to squeeze out all the padding from the structs so that we
+ * can use them as templates for filling in and examining frames.
+ * From the gcc documentation:
+ *    This attribute, attached to an `enum', `struct', or `union' type
+ *    definition, specified that the minimum required memory be used to
+ *    represent the type.
+ */
+#ifndef PACKED
+#define PACKED __attribute__((packed))
+#endif
+
+/* READY_QUERY and READY_IND frame format
+ */
+struct ready_frame {
+        uint16_t marker;
+        uint8_t  protocol;
+        uint8_t  version;
+        uint16_t opcode;
+};
+
+/* Fields common to all control frames,
+ * not including READY_*
+ */
+struct frame_hdr {
+        uint16_t marker;
+        uint8_t  protocol;
+        uint8_t  version;
+        uint16_t opcode;
+        uint16_t status;
+        uint32_t tran_id;
+        uint16_t lec_id;
+        uint16_t flags;
+} PACKED;
+
+/* values for lan_dst.tag
+ */
+#define LAN_DST_NOT_PRESENT 0x0000
+#define LAN_DST_MAC_ADDR    0x0001
+#define LAN_DST_ROUTE_DESC  0x0002
+
+struct lan_dst { /* Token Ring route descriptors omitted */
+        uint16_t tag;
+        uint8_t  mac[ETH_ALEN];
+} PACKED;
+
+/* All frames except STATUS_INQ and STATUS_REPLY look like this
+ */
+struct ctrl_frame {
+        struct frame_hdr header;
+        struct lan_dst src_lan_dst;
+        struct lan_dst target_lan_dst;
+        uint8_t src_atm_addr[ATM_ESA_LEN];
+        uint8_t lan_type;
+        uint8_t max_frame_size;
+        uint8_t num_tlvs;
+        uint8_t elan_name_size;
+        uint8_t target_atm_addr[ATM_ESA_LEN];
+        uint8_t elan_name[32];
+        /* TLVs if any follow elan_name */
+} PACKED;
+
+/* Frame types
+ */
+#define LE_CONFIG_REQ 0x0001
+#define LE_CONFIG_RSP 0x0101
+#define LE_JOIN_REQ   0x0002
+#define LE_JOIN_RSP   0x0102
+#define LE_REG_REQ    0x0004
+#define LE_REG_RSP    0x0104
+#define LE_ARP_REQ    0x0006
+#define LE_ARP_RSP    0x0106
+#define LE_FLUSH_REQ  0x0007
+#define LE_FLUSH_RSP  0x0107
+#define LE_NARP_REQ   0x0008
+#define LE_TOPO_REQ   0x0009
+#define READY_QUERY   0x0003 /* READY_* are not in ctrl_frame format */
+#define READY_IND     0x0103
+
+/* Flags for LE Control Frames
+ */
+#define REMOTE_ADDRESS  0x0001
+#define V2_CAPABLE      0x0002
+#define V2_REQUIRED     0x0008
+#define PROXY_FLAG      0x0080
+#define TOPO_CHANGE     0x0100
+
+/* TLV types defined in LANEv1 and v2 + one Fore specific TLV
+ */
+#define MAX_CUM_CTRL_TIMEOUT   0x00A03E01
+#define MAX_UNKNOWN_FRAME_CNT  0x00A03E02
+#define MAX_UNKNOWN_FRAME_TIME 0x00A03E03
+#define VCC_TIMEOUT_PERIOD     0x00A03E04
+#define MAX_RETRY_COUNT        0x00A03E05
+#define AGING_TIME             0x00A03E06
+#define FORWARD_DELAY_TIME     0x00A03E07
+#define EXPECTED_LE_ARP_TIME   0x00A03E08
+#define FLUSH_TIMEOUT          0x00A03E09
+#define PATH_SWITCHING_DELAY   0x00A03E0A
+#define LOCAL_SEGMENT_ID       0x00A03E0B
+#define DEF_MCAST_SND_VCC_TYPE 0x00A03E0C
+#define DEF_MCAST_SND_VCC_AVG  0x00A03E0D
+#define DEF_MCAST_SEND_PEAK_RT 0x00A03E0E
+#define CONN_COMPLETION_TIMER  0x00A03E0F
+#define CONFIG_FRAG_INFO       0x00A03E10 /* This and the rest are LANEv2 only */
+#define LAYER3_ADDRESS         0x00A03E11
+#define ELAN_ID                0x00A03E12
+#define SERVICE_CATEGORY       0x00A03E13
+#define LLC_MUXED_ATM_ADDR     0x00A03E2B
+#define X5_ADJUSTMENT          0x00A03E2C /* length 0 */
+#define PREFERRED_LES          0x00A03E2D
+
+#define FORE_NAME              0x00204808 /* check zeppelin(8), -f option */
+
+#endif /* FRAMES_DEFS_H */
diff -ur --new-file old/atm/led/frames.c new/atm/led/frames.c
--- old/atm/led/frames.c	Thu Jan  1 01:00:00 1970
+++ new/atm/led/frames.c	Sat Feb  6 21:45:03 1999
@@ -0,0 +1,582 @@
+/* frames.c - handle incoming frames, prefill outgoing frames, parse TLVs etc. */
+
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
+/* Functions for handling LANE control frames used when joining an
+ * ELAN are in lec.c
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <atm.h>
+#include <linux/atmlec.h>
+#include <atmd.h>
+
+#include "conn.h"
+#include "lec.h"
+#include "frames.h"
+#include "display.h"
+#include "kernel.h"
+
+#define COMPONENT "frames.c"
+
+static uint32_t transaction_id = 0;
+static void extract_tlv_value(uint16_t opcode, uint32_t type, unsigned char *tlvp, int len);
+static void handle_x5(uint16_t opcode);
+
+/* Initializes LANE Control frame of type 'type'
+ */
+void prefill_frame(void *buff, uint16_t type)
+{
+        struct frame_hdr *header;
+        
+        memset(buff, 0, sizeof(struct ctrl_frame));
+        header = (struct frame_hdr *)buff;
+        header->marker   = htons(0xff00);
+        header->protocol = 0x01;
+        header->version  = 0x01;
+        header->opcode   = htons(type);
+        header->status   = htons(0x0000);
+        header->tran_id  = htonl(transaction_id);
+        header->lec_id   = htons(lec_params.c14_lec_id);
+        header->flags    = htons(0x0000);
+        
+        transaction_id++;
+        
+        return;
+}
+
+/* Validates incoming Control frames except READY_IND and
+ * READY_QUERY which do not start with the common header.
+ * Also calls display_frame() to print out conforming frames.
+ * Returns < 0 for error
+ */
+int validate_frame(unsigned char *buff, int size)
+{
+        struct ready_frame *hdr; /* Ready is the shortest possible */
+
+        if (size < sizeof(struct ready_frame)) {
+                diag(COMPONENT, DIAG_DEBUG, "short frame, size %d\n", size);
+                return -1;
+        }
+
+        hdr = (struct ready_frame *)buff;
+        if (hdr->marker   != htons(0xff00) ||
+            hdr->protocol != 0x01 ||
+            hdr->version  != 0x01)
+                return -1;
+
+        /* READY_* frames are shorter than others */
+        if (hdr->opcode == htons(READY_QUERY) ||
+            hdr->opcode == htons(READY_IND)) {
+                diag(COMPONENT, DIAG_DEBUG, "Received a %s\n", opcode2text(hdr->opcode));
+                return 0;
+        }
+
+        if (size < sizeof(struct ctrl_frame)) {
+                diag(COMPONENT, DIAG_DEBUG, "short frame, size %d\n", size);
+                return -1;
+        }
+
+        display_frame(buff);
+
+        return 0;
+}
+
+/* Handle incoming LE_FLUSH_REQUEST frames.
+ */
+static void handle_flush_req(struct ctrl_frame *f)
+{
+        if (memcmp(lec_params.c1n_my_atm_addr, f->target_atm_addr, ATM_ESA_LEN) != 0)
+                return;
+        f->header.opcode = htons(LE_FLUSH_RSP);
+        if (send_frame(lec_params.ctrl_direct, f, sizeof(struct ctrl_frame)) < 0)
+                diag(COMPONENT, DIAG_DEBUG, "could not send LE_FLUSH_RESPONSE\n");
+
+        return;
+}
+
+/* Handle incoming LE_FLUSH_RESPONSE frames.
+ */
+static void handle_flush_rsp(struct ctrl_frame *f)
+{
+        struct atmlec_msg msg;
+
+        if (f->header.lec_id != htons(lec_params.c14_lec_id)) {
+                diag(COMPONENT, DIAG_DEBUG, "Wrong lec_id, ignoring\n");
+                return;
+        }
+
+        memset(&msg, 0, sizeof(struct atmlec_msg));
+        msg.type = l_flush_complete;
+        msg.content.normal.flag = ntohl(f->header.tran_id);
+        msg_to_kernel(&msg, sizeof(struct atmlec_msg));
+        
+        return;
+}
+
+/* Handle incoming READY_QUERY frames.
+ */
+static void handle_ready_query(Conn_t *conn, struct ready_frame *f)
+{
+        f->opcode = htons(READY_IND);
+        send_frame(conn, f, sizeof(struct ready_frame));
+
+        return;
+}
+
+/* Helper for handle_le_arp_req.
+ * If the target_lan_dst was not our MAC address, try to
+ * see if the bridging table in the kernel knows about it.
+ * Returns < 0 for serious error
+ */
+static int check_bridge(struct ctrl_frame *frame, int size)
+{
+        struct atmlec_msg msg;
+
+        if (lec_params.c4_proxy_flag == 0)
+                return 0;
+
+        memset(&msg, 0, sizeof(struct atmlec_msg));
+        msg.type = l_should_bridge;
+        memcpy(msg.content.proxy.mac_addr, frame->target_lan_dst.mac, ETH_ALEN);
+        memcpy(msg.content.proxy.atm_addr, frame->src_atm_addr, ATM_ESA_LEN);
+        msg.content.proxy.tran_id = frame->header.tran_id;
+        msg.content.proxy.lec_id = frame->header.lec_id;
+
+        return msg_to_kernel(&msg, sizeof(struct atmlec_msg));
+}
+
+/* Handles incoming LE_ARP_REQ and targetless LE_ARP_REQ.
+ * See LANEv2, 7.1.5 and 7.1.30
+ * Returns < 0 for serious error
+ */
+static int handle_le_arp_req(struct ctrl_frame *frame, int size)
+{
+        int sizeoftlvs, sizeofrsp, retval;
+        struct ctrl_frame *rsp;
+        struct atmlec_msg *msg;
+
+        if (frame->header.lec_id == htons(lec_params.c14_lec_id)) {
+                diag(COMPONENT, DIAG_DEBUG, "Ignoring own LE_ARP_REQUEST\n");
+                return 0;
+        }
+
+        retval = 0;
+        if (frame->target_lan_dst.tag == htons(LAN_DST_MAC_ADDR)) {
+                if (memcmp(frame->target_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN) != 0)
+                        return (check_bridge(frame, size)); /* target was not us */
+                sizeofrsp = sizeof(struct ctrl_frame) + lec_params.sizeoftlvs;
+                rsp = (struct ctrl_frame *)malloc(sizeofrsp);
+                if (rsp == NULL) return 0;
+                memcpy(rsp, frame, sizeof(struct ctrl_frame));
+                rsp->header.opcode = htons(LE_ARP_RSP);
+                memcpy(rsp->target_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+                rsp->num_tlvs = lec_params.num_tlvs;
+                if (lec_params.num_tlvs > 0)
+                        memcpy(rsp + 1, lec_params.tlvs, lec_params.sizeoftlvs);
+
+                retval = send_frame(lec_params.ctrl_direct, rsp, sizeofrsp);
+                free(rsp);
+        } else if (frame->target_lan_dst.tag == htons(LAN_DST_NOT_PRESENT) &&
+                   lec_params.c29_v2_capable) {
+                sizeoftlvs = size - sizeof(struct ctrl_frame);
+                msg = (struct atmlec_msg *)malloc(sizeof(struct atmlec_msg) + sizeoftlvs);
+                if (msg == NULL) return -1;
+                memset(msg, 0, sizeof(struct atmlec_msg));
+                msg->type = l_arp_update;
+                memcpy(msg->content.normal.mac_addr, frame->src_lan_dst.mac, ETH_ALEN);
+                memcpy(msg->content.normal.atm_addr, frame->src_atm_addr, ATM_ESA_LEN);
+                msg->content.normal.flag = (frame->header.flags & REMOTE_ADDRESS) ? 1 : 0;
+                msg->content.normal.targetless_le_arp = 1;
+                msg->sizeoftlvs = sizeoftlvs;
+                if (sizeoftlvs > 0) memcpy(msg + 1, frame + 1, sizeoftlvs);
+
+                retval = msg_to_kernel(msg, sizeof(struct atmlec_msg) + sizeoftlvs);
+                free(msg);
+        }
+        
+        return retval;
+}
+
+/* Handles incoming LE_NARP_REQUESTS frames.
+ * Mandatory only in LANEv2. If we are LANEv1, we'll just ignore these.
+ * See LANEv2, 7.1.31-35 LE_NARP_REQUEST/RESPONSE.
+ * For no-source, i.e. no source ATM address, we remove the LE_ARP cache entry.
+ * If the source is non-zero, we first remove the entry
+ * and then add the new entry in the LE_ARP cache.
+ * Returns < 0 for serious error.
+ */
+static int handle_narp_req(struct ctrl_frame *frame, int size)
+{
+        int sizeoftlvs, no_source = 0, retval;
+        struct atmlec_msg *msg;
+        unsigned char empty[ATM_ESA_LEN];
+
+        if (frame->header.lec_id == htons(lec_params.c14_lec_id) ||
+            lec_params.c29_v2_capable == 0) {
+                diag(COMPONENT, DIAG_DEBUG, "Ignoring LE_NARP_REQUEST\n");
+                return 0;
+        }
+
+        memset(empty, 0, ATM_ESA_LEN);
+        if (memcmp(empty, frame->src_atm_addr, ATM_ESA_LEN) == 0)
+                no_source = 1;
+
+        sizeoftlvs = size - sizeof(struct ctrl_frame);
+        msg = (struct atmlec_msg *)malloc(sizeof(struct atmlec_msg) + sizeoftlvs);
+        if (msg == NULL) return -1;
+        memset(msg, 0, sizeof(struct atmlec_msg));
+        msg->type = l_narp_req;
+        memcpy(msg->content.normal.mac_addr, frame->src_lan_dst.mac, ETH_ALEN);
+        memcpy(msg->content.normal.atm_addr, frame->src_atm_addr, ATM_ESA_LEN);
+        msg->content.normal.flag = (frame->header.flags & REMOTE_ADDRESS) ? 1 : 0;
+        msg->content.normal.no_source_le_narp = no_source;
+        msg->sizeoftlvs = sizeoftlvs;
+        if (sizeoftlvs > 0) memcpy(msg + 1, frame + 1, sizeoftlvs);
+        retval = msg_to_kernel(msg, sizeof(struct atmlec_msg) + sizeoftlvs);
+        
+        free(msg);
+        
+        return retval;
+}
+
+/* Handles incoming LE_ARP_RESPONSE frames.
+ * Returns < 0 for serious error
+ */
+static int handle_arp_rsp(struct ctrl_frame *frame, int size)
+{
+        int sizeoftlvs, msglen, retval;
+        char buff[MAX_CTRL_FRAME];
+        struct atmlec_msg *msg;
+        
+        if (frame->header.lec_id != htons(lec_params.c14_lec_id)) {
+                diag(COMPONENT, DIAG_DEBUG, "Wrong lec_id, ignoring\n");
+                return 0;
+        }
+
+        sizeoftlvs = size - sizeof(struct ctrl_frame);
+        msglen = sizeof(struct atmlec_msg) + sizeoftlvs;
+        msg = (struct atmlec_msg *)buff;
+        memset(msg, 0, msglen);
+        
+        msg->type = l_arp_update;
+        memcpy(msg->content.normal.mac_addr, frame->target_lan_dst.mac, ETH_ALEN);
+        memcpy(msg->content.normal.atm_addr, frame->target_atm_addr, ATM_ESA_LEN);
+        msg->content.normal.flag = (frame->header.flags & REMOTE_ADDRESS) ? 1 : 0;
+        msg->sizeoftlvs = sizeoftlvs;
+        if (sizeoftlvs > 0) memcpy(msg + 1, frame + 1, sizeoftlvs);
+
+        retval = msg_to_kernel(msg, msglen);
+
+        return retval;
+}
+
+/* Handles incoming LE_TOPOLOGY_REQUEST frames.
+ * Returns < 0 for serious error
+ */
+static int handle_topo_req(struct ctrl_frame *frame)
+{
+        struct atmlec_msg msg;
+
+        memset(&msg, 0, sizeof(struct atmlec_msg));
+        msg.type = l_topology_change;
+        if (frame->header.flags & htons(TOPO_CHANGE))
+                msg.content.normal.flag = 1;
+
+        return(msg_to_kernel(&msg, sizeof(struct atmlec_msg)));
+}
+
+/* Processes and validates incoming frames. Calls frame
+ * dependant handler functions.
+ * Returns < 0 for serious error
+ */
+int handle_frame(Conn_t *conn, char *buff, int size)
+{
+        struct ctrl_frame *frame;
+
+        if (validate_frame(buff, size) < 0)
+                return 0;
+
+        frame = (struct ctrl_frame *)buff;
+
+        switch (ntohs(frame->header.opcode)) {
+        case LE_FLUSH_REQ:
+                handle_flush_req(frame);
+                break;
+        case LE_FLUSH_RSP:
+                handle_flush_rsp(frame);
+                break;
+        case READY_QUERY:
+                handle_ready_query(conn, (struct ready_frame *)frame);
+                break;
+        case READY_IND:
+                /* We can ignore these */
+                break;
+        case LE_ARP_REQ:
+                if (handle_le_arp_req(frame, size) < 0)
+                        return -1;
+                break;
+        case LE_ARP_RSP:
+                if (handle_arp_rsp(frame, size) < 0)
+                        return -1;
+                break;
+        case LE_TOPO_REQ:
+                if (handle_topo_req(frame) < 0)
+                        return -1;
+                break;
+        case LE_REG_RSP:
+                /* FIXME: Should we do something? */
+                break;
+        case LE_NARP_REQ:
+                if (handle_narp_req(frame, size) < 0)
+                        return -1;
+                break;
+        default:
+                diag(COMPONENT, DIAG_ERROR,
+                     "Unknown frame, opcode 0x%x %s\n", ntohs(frame->header.opcode),
+                     opcode2text(frame->header.opcode));
+                break;
+        }
+
+        return 0;
+}
+
+/* Sends a READY_INDICATION when a non-blocking connect completes.
+ */
+void send_ready_ind(Conn_t *conn)
+{
+        struct ready_frame frame;
+        int retval;
+
+        frame.marker   = htons(0xff00);
+        frame.protocol = 0x01;
+        frame.version  = 0x01;
+        frame.opcode   = htons(READY_IND);
+
+        retval = send_frame(conn, &frame, sizeof(struct ready_frame));
+        if (retval < 0)
+                diag(COMPONENT, DIAG_DEBUG, "Could not send READY_IND, fd %d\n", conn->fd);
+
+        return;
+}
+
+/* Sends a LE_FLUSH_REQUEST
+ * Returns the transaction used with this flush REQ/RSP pair.
+ */
+uint32_t send_flush_req(Conn_t *conn)
+{
+        struct ctrl_frame frame;
+
+        prefill_frame(&frame, LE_FLUSH_REQ);
+        memcpy(frame.src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+        memcpy(frame.target_atm_addr, conn->atm_address, ATM_ESA_LEN);
+
+        send_frame(lec_params.mcast_send, &frame, sizeof(struct ctrl_frame));
+
+        return ntohl(frame.header.tran_id);
+}
+
+/* Registers our MAC address and associated TLVs with LES.
+ * See LANEv2, 6. Registaration Protocol
+ */
+void send_register_req(void)
+{
+        char buff[MAX_CTRL_FRAME];
+        struct ctrl_frame *frame;
+
+        frame = (struct ctrl_frame *)buff;
+        prefill_frame(frame, LE_REG_REQ);
+        frame->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
+        memcpy(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN);
+        memcpy(frame->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+        frame->num_tlvs = lec_params.num_tlvs;
+        if (lec_params.sizeoftlvs > 0)
+                memcpy((frame + 1), lec_params.tlvs, lec_params.sizeoftlvs);
+
+        send_frame(lec_params.ctrl_direct, frame, sizeof(struct ctrl_frame) + lec_params.sizeoftlvs);
+        
+        return;
+}
+
+/* Goes through the TLVs trailing a frame while passing them
+ * one by one to the TLV handler.
+ */
+void parse_tlvs(uint16_t opcode, unsigned char *tlvp, int numtlvs, int sizeoftlvs)
+{
+        uint32_t type;
+        uint8_t len;
+        unsigned char *end_of_tlvs;
+
+        end_of_tlvs = tlvp + sizeoftlvs;
+        while (numtlvs-- > 0 && end_of_tlvs - tlvp >= 5) {
+                type = *(uint32_t *)tlvp;
+                type = ntohl(type);
+                len  = tlvp[4];
+                tlvp += 5;
+                diag(COMPONENT, DIAG_DEBUG, "parse_tlvs: type %s len %d\n",
+                     tlv2text(type), len);
+                if (tlvp + len > end_of_tlvs)
+                        return; /* value too long */
+                
+                extract_tlv_value(opcode, type, tlvp, len);
+                tlvp += len;
+        }
+
+        return;
+}
+
+/* Does something depending on the frame type this TLV arrived with,
+ * TLV type, and contents of TLV.
+ */
+static void extract_tlv_value(uint16_t opcode, uint32_t type, unsigned char *tlvp, int len)
+{
+
+        uint16_t value16;
+        uint32_t value32;
+
+        /* LE_JOIN_RESPONSE does not support all the TLVs */
+        if (opcode == htons(LE_JOIN_RSP) && type != htonl(ELAN_ID))
+                return;
+
+        switch(len) {
+        case 0:
+                switch (type) {
+                case X5_ADJUSTMENT:
+                        handle_x5(opcode);
+                        break;
+                default:
+                        goto whine;
+                        break;
+                }
+                break;
+        case 2:
+                value16 = *(uint16_t *)tlvp;
+                value16 = ntohs(value16);
+                diag(COMPONENT, DIAG_DEBUG, "value of TLV %d\n", value16);
+                switch (type) {
+                case MAX_CUM_CTRL_TIMEOUT:
+                        lec_params.c7_ctrl_timeout = value16;
+                        break;
+                case MAX_UNKNOWN_FRAME_CNT:
+                        lec_params.c10_max_unknown_frames = value16;
+                        break;
+                case MAX_UNKNOWN_FRAME_TIME:
+                        lec_params.c11_max_unknown_frame_time = value16;
+                        break;
+                case MAX_RETRY_COUNT:
+                        lec_params.c13_max_retry_count = value16;
+                        break;
+                case FORWARD_DELAY_TIME:
+                        lec_params.c18_forward_delay_time = value16;
+                        break;
+                case EXPECTED_LE_ARP_TIME:
+                        lec_params.c20_le_arp_response_time = value16;
+                        break;
+                case FLUSH_TIMEOUT:
+                        lec_params.c21_flush_timeout = value16;
+                        break;
+                case PATH_SWITCHING_DELAY:
+                        lec_params.c22_path_switching_delay = value16;
+                        break;
+                case LOCAL_SEGMENT_ID:
+                case DEF_MCAST_SND_VCC_TYPE:
+                case CONN_COMPLETION_TIMER:
+                case SERVICE_CATEGORY:
+                        /* do nothing */
+                        break;
+                default:
+                        goto whine;
+                        break;
+                }
+                break;
+        case 4:
+                value32 = *(uint32_t *)tlvp;
+                value32 = ntohl(value32);
+                diag(COMPONENT, DIAG_DEBUG, "value of TLV %d\n", value32);
+                switch (type) {
+                case VCC_TIMEOUT_PERIOD:
+                        lec_params.c12_vcc_timeout = value32;
+                        break;
+                case AGING_TIME:
+                        lec_params.c17_aging_time = value32;
+                        break;
+                case ELAN_ID:
+                        lec_params.c31_elan_id = value32;
+                        break;
+                case DEF_MCAST_SND_VCC_AVG:
+                case DEF_MCAST_SEND_PEAK_RT:
+                        /* do nothing */
+                        break;
+                default:
+                        goto whine;
+                        break;
+                }
+                break;
+        case 20:
+                switch(type) {
+                case PREFERRED_LES:
+                        memcpy(lec_params.c35_preferred_les, tlvp, ATM_ESA_LEN);
+                        lec_params.c35_contains_address = 1;
+                        break;
+                case LLC_MUXED_ATM_ADDR:
+                        /* do nothing */
+                        break;
+                default:
+                        goto whine;
+                        break;
+                }
+                break;
+        default:
+                /* handle variable length TLVs */
+                switch(type) {
+                case CONFIG_FRAG_INFO:
+                        diag(COMPONENT, DIAG_INFO, "Got Config-Frag-Info TLV\n");
+                        break;
+                case LAYER3_ADDRESS:
+                        /* do nothing */
+                        break;
+                default:
+                        goto whine;
+                        break;
+                }
+                break;
+        }
+
+        return;
+
+ whine:
+        diag(COMPONENT, DIAG_DEBUG, "Unknown TLV, type 0x%x, len %d\n", type, len);
+
+        return;
+}
+
+/* Figures out what to do when we get a X5-Adjustment TLV
+ */
+static void handle_x5(uint16_t opcode)
+{
+        if (!lec_params.c29_v2_capable)
+                return;
+        if (opcode != ntohs(LE_CONFIG_RSP)) {
+                diag(COMPONENT, DIAG_WARN, "X5-Adjustment TLV received but not with LE_CONFIG_RSP\n");
+                return;
+        }
+
+        switch(lec_params.c3_max_frame_size) {
+        case 1:
+                lec_params.c3_max_frame_size = 5; /* 1580 */
+                return;
+                break;
+        case 2:
+                lec_params.c3_max_frame_size = 5; /* 1580 */
+                return;
+                break;
+        default:
+                /* rest of the values are not affected by X5 */
+                break;
+        }
+
+        return;
+}
diff -ur --new-file old/atm/led/frames.h new/atm/led/frames.h
--- old/atm/led/frames.h	Thu Jan  1 01:00:00 1970
+++ new/atm/led/frames.h	Sat Feb  6 21:54:23 1999
@@ -0,0 +1,21 @@
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
+#ifndef FRAMES_H
+#define FRAMES_H
+
+#include "frame_defs.h"
+
+#define MAX_CTRL_FRAME 512
+
+void prefill_frame(void *ctrl_frame, uint16_t type);
+int validate_frame(unsigned char *buff, int size);
+
+void send_ready_ind(Conn_t *conn);
+void send_register_req(void);
+
+int handle_frame(Conn_t *conn, char *buff, int size);
+uint32_t send_flush_req(Conn_t *conn);
+
+void parse_tlvs(uint16_t opcode, unsigned char *tlvp, int numtlvs, int sizeoftlvs);
+
+#endif /* FRAMES_H */
diff -ur --new-file old/atm/led/g_endian.h new/atm/led/g_endian.h
--- old/atm/led/g_endian.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/g_endian.h	Thu Jan  1 01:00:00 1970
@@ -1,51 +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.
- * 
- */
-
-/* g_endian.h
- */
-
-#define hton16(x) ((UINT16) (((((UINT16) (x)) & 0xff00) >> 8) | \
-                             ((((UINT16) (x)) & 0x00ff) << 8)))
-
-#define ntoh16(x) ((UINT16) (((((UINT16) (x)) & 0xff00) >> 8) | \
-                             ((((UINT16) (x)) & 0x00ff) << 8)))
-
-#define hton32(x) ((UINT32) (((((UINT32) (x)) & 0xff000000) >> 24) | \
-                             ((((UINT32) (x)) & 0x00ff0000) >> 8)  | \
-                             ((((UINT32) (x)) & 0x0000ff00) << 8)  | \
-                             ((((UINT32) (x)) & 0x000000ff) << 24)))
-
-#define ntoh32(x) ((UINT32) (((((UINT32) (x)) & 0xff000000) >> 24) | \
-                             ((((UINT32) (x)) & 0x00ff0000) >> 8)  | \
-                             ((((UINT32) (x)) & 0x0000ff00) << 8)  | \
-                             ((((UINT32) (x)) & 0x000000ff) << 24)))
diff -ur --new-file old/atm/led/g_event.c new/atm/led/g_event.c
--- old/atm/led/g_event.c	Wed Nov 19 12:59:16 1997
+++ new/atm/led/g_event.c	Thu Jan  1 01:00:00 1970
@@ -1,106 +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:
-*   g_event.c
-*   
-* Abstract:
-*   This file contains routines that support event reporting.
-*                                                                             
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   15-May-95  TLR   - Created.
-*
-* Description:
-*/
-
-
-/* Include general headers. */
-#include "g_types.h"
-#include "codes.h"
-#include "g_event.h"
-
-const char *emodtext  (UINT16 mod)
-   {
-   switch (mod)
-      {
-      case MOD_CM        : return "CM    ";
-      case MOD_SIG       : return "SIGNAL";
-      case MOD_LEC_DATA  : return "LECDAT";
-      case MOD_LEC_CTRL  : return "LECCTL";
-      case MOD_LEC_ARP   : return "LECARP";
-      case MOD_UP_DRV    : return "UP_DRV";
-      case MOD_LO_DRV    : return "LO_DRV";
-      case MOD_ILMI_IO   : return "ILMIIO";
-      case MOD_ADDR_REG  : return "ADRREG";
-      case MOD_LINE_UP   : return "LINEUP";
-      case MOD_SNMP      : return "SNMPAG";
-      case MOD_MIB_II    : return "MIB_II";
-      case MOD_ILMI_MIB  : return "IL_MIB";
-      case MOD_DEC_MIB   : return "DECMIB";
-      case MOD_UTL_OS    : return "UTL_OS";
-      case MOD_DIAG      : return "DIAGS ";
-      case MOD_FLOW      : return "FLOW  ";
-      case MOD_OAM       : return "OAM   ";
-      case MOD_ATMIP     : return "ATMIP ";
-      case MOD_ATMARP    : return "ATMARP";
-		case MOD_INIT      : return "INIT  ";
-		case MOD_CLIP      : return "CLIP  ";
-		default            : return "??????";
-      }
-   }
-
-const char *emasktext (UINT32 mask)
-{
-  if (mask & EM_SERR)     return "SERR";
-  if (mask & EM_NERR)     return "NERR";
-  if (mask & EM_WARN)     return "WARN";
-  if (mask & EM_ASSERT)   return "ASRT";
-  if (mask & EM_TRAN)     return "TRAN";
-  if (mask & EM_EVENT)    return "EVNT";
-  if (mask & EM_RCTRL)    return "RCTL";
-  if (mask & EM_XCTRL)    return "XCTL";
-  if (mask & EM_RDATA)    return "RDAT";
-  if (mask & EM_XDATA)    return "XDAT";
-  if (mask & EM_TRACE)    return "TRCE";
-  if (mask & EM_TIMER)    return "TIMR";
-  if (mask & EM_MEM)      return "MEM ";
-  if (mask & EM_MSG)      return "MSG ";
-  if (mask & EM_DEBUG)    return "DBUG";
-  return "????";
-}
-
diff -ur --new-file old/atm/led/g_event.h new/atm/led/g_event.h
--- old/atm/led/g_event.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/g_event.h	Thu Jan  1 01:00:00 1970
@@ -1,126 +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:
-*   g_event.h
-*   
-* Abstract:
-*   
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   10-May-95  TLR   Created.
-*   16-May-95  DMW   Added OPPO module.
-*
-* Description:
-* 
-*/
-
-#ifndef G_EVENT_H
-#define G_EVENT_H
-/* Module ID Values */
-
-#include <stdio.h>
-
-#include "g_types.h"
-
-#define MOD_CM          101
-#define MOD_SIG         102
-#define MOD_LEC_DATA    103
-#define MOD_LEC_CTRL    104
-#define MOD_LEC_ARP     105
-#define MOD_UP_DRV      106
-#define MOD_LO_DRV      107
-#define MOD_INIT        108
-#define MOD_ILMI_IO     109
-#define MOD_ADDR_REG    110
-#define MOD_LINE_UP     111
-#define MOD_SNMP        112
-#define MOD_MIB_II      113
-#define MOD_ILMI_MIB    114
-#define MOD_DEC_MIB     115
-#define MOD_UTL_OS      116
-#define MOD_DIAG        117
-#define MOD_FLOW        118
-#define MOD_OAM         119
-#define MOD_ATMIP       120
-#define MOD_ATMARP      121
-#define MOD_OPPO        122
-#define MOD_CLIP        123
-#define MOD_TASK        124
-
-/* Event Type Mask Values */
-
-#define EM_SERR      0x00000001  /* Severe Error               */
-#define EM_NERR      0x00000002  /* Normal Error               */
-#define EM_WARN      0x00000004  /* Warning                    */
-#define EM_ASSERT    0x00000008  /* Assertion Failure          */
-#define EM_TRAN      0x00000010  /* State Transition           */
-#define EM_EVENT     0x00000020  /* Normal Event               */
-#define EM_RCTRL     0x00000040  /* Received Control Frame     */
-#define EM_XCTRL     0x00000080  /* Transmitted Control Frame  */
-#define EM_RDATA     0x00000100  /* Received Data Frame        */
-#define EM_XDATA     0x00000200  /* Transmitted Data Frame     */
-#define EM_TRACE     0x00000400  /* Code path trace            */
-#define EM_TIMER     0x00000800  /* Timer Events               */
-#define EM_MEM       0x00001000  /* Memory Management Events   */
-#define EM_MSG       0x00002000  /* Message Events             */
-#define EM_DEBUG     0x00004000  /* Debugging messages         */
-
-#define EM_DEFAULT    (EM_SERR | EM_NERR | EM_ASSERT)
-
-#define EVENT(mask, text)                                                \
-   if (EMASK & mask)                                                     \
-      {                                                                  \
-      printf ("%s %s '%s': ", emodtext (EMOD), emasktext (mask), EINST); \
-      printf text;                                                       \
-      fflush (stdout);    }
-
-/* 
- *
- * example event:
- *
- *    event (type_mask, ("Event Text %d %s", var1, str1))
- */
-
-/* The following are function prototypes for value-to-text conversion
- * routines that are used to display events.
- */
-const char *emodtext  (UINT16 mod);
-const char *emasktext (UINT32 mask);
-
-#endif /* G_EVENT_H */
diff -ur --new-file old/atm/led/g_types.h new/atm/led/g_types.h
--- old/atm/led/g_types.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/g_types.h	Thu Jan  1 01:00:00 1970
@@ -1,155 +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:
-*   g_types.h
-*   
-* Abstract:
-*   This module defines basic types that can be shared amongst modules.
-*
-* Authors:
-*   DMW - Douglas M. Washabaugh
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   08-Aug-94  DMW   Created.
-*   06-Oct-94  DMW   Added UINT8.
-*   12-Oct-94  DMW   Fixed UINT8, removed BYTE, ULONG, LONG.
-*                    Changed BOOLEAN to be unsigned char.
-*   05-Dec-94  DMW   Added change to avoid collision with NT and HANDLE.
-*   05-Jan-95  DMW   Changed boolean to be 32 bits for NOVELL.
-*   09-May-95  TLR   Renamed file and added alpha conditionals.
-*
-* Description:
-*   The types in this module are defined only if previously undefined.  This
-*   allows a specific implemenation to override a definition if needed.
-*
-* Conditional Compilation:
-*   - NOVELL
---*/
-#ifndef G_TYPES_H
-#define G_TYPES_H
-
-/* Define the unsigned data types. */
-#ifndef VW_DEFS
-#ifndef UINT32 
-#ifdef __alpha
-typedef unsigned int UINT32;
-#else
-typedef unsigned long int UINT32;
-#endif
-#endif
-
-#ifndef UINT16
-typedef unsigned short int UINT16;
-#endif
-
-#ifndef UINT8
-typedef unsigned char UINT8;
-#endif
-
-/* Define the signed data types. */
-
-#ifndef INT32
-#ifdef __alpha
-typedef signed int INT32;
-#else
-typedef signed long int INT32;
-#endif
-#endif
-
-#ifndef INT16
-typedef signed short int INT16;
-#endif
-
-#ifndef INT8
-typedef signed char INT8;
-#endif
-#endif
-/* Define some miscellaneous data types. */
-
-#ifndef BOOLEAN
-#ifdef NOVELL
-typedef unsigned long BOOLEAN;
-#else
-typedef unsigned char BOOLEAN;
-#endif
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-
-#if !defined HANDLE
-typedef void *HANDLE;
-#endif
-
-#ifndef VW_DEFS
-#ifndef STATUS
-typedef unsigned int STATUS;
-#endif
-#endif
-
-/* Define STATIC so that it does nothing for DEBUG builds. */
-
-#ifndef STATIC
-#ifdef DEBUG
-#define STATIC
-#else
-#define STATIC static
-#endif
-#endif
-
-/* Define the values that should be used with BOOLEAN types. */
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif 
-
-/* The default value is defined to be the largest value for any size field. */
-
-#define DEFAULT -1
-
-/* This macro is used to specify arguments that are not used in functions.  */
-
-#define ARG_NOT_USED(x) (x=x)
-
-#endif
-/* G_TYPES_H */
diff -ur --new-file old/atm/led/join.c new/atm/led/join.c
--- old/atm/led/join.c	Thu Jan  1 01:00:00 1970
+++ new/atm/led/join.c	Wed Jun  2 23:36:54 1999
@@ -0,0 +1,766 @@
+/* join.c - functions which are only needed when joining an ELAN */
+
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h> /* for rand() */
+#include <sys/ioctl.h>
+#include <atm.h>
+
+#include <linux/atmlec.h>
+
+#include <atmd.h>
+
+#include "conn.h"
+#include "lec.h"
+#include "join.h"
+#include "frames.h"
+#include "display.h"
+
+#define COMPONENT "lec.c"
+
+struct lec_params lec_params;
+
+static unsigned char bus_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+static unsigned char well_known_lecs[ATM_ESA_LEN] = {0x47,0x00,0x79,0x00,0x00,
+                                                     0x00,0x00,0x00,0x00,0x00,
+                                                     0x00,0x00,0x00,0x00,0xA0,
+                                                     0x3E,0x00,0x00,0x01,0x00};
+static int do_lec_configure(Conn_t *conn);
+static int send_config_req(Conn_t *conn);
+static int read_config_rsp(Conn_t *conn, char *buff, int buffsize);
+static int parse_config_rsp(unsigned char *buff, int size);
+
+static int send_join_req(Conn_t *conn);
+static int read_join_rsp(char *buff, int buffsize);
+static int parse_join_rsp(unsigned char *buff, int size);
+
+static int get_bus_addr(struct sockaddr_atmsvc *addr);
+static int read_bus_arp(Conn_t *conn, struct sockaddr_atmsvc *addr, char *buff, int buffsize);
+
+/*
+ * 5.1, Initial state
+ */
+void init_lec_params(unsigned char *mac_addr, char *elan_name,
+                     unsigned char *listen_addr, int itf, char *foreId,
+                     int max_frame_size, int proxy_flag, int lane_version)
+{
+        memcpy(lec_params.c6_mac_addr, mac_addr, ETH_ALEN);
+        strcpy(lec_params.c5_elan_name, elan_name);
+        memcpy(lec_params.c1n_my_atm_addr, listen_addr, ATM_ESA_LEN);
+        lec_params.itf_num = itf;
+        strcpy(lec_params.foreId, foreId);
+        lec_params.c3_max_frame_size = max_frame_size;
+        lec_params.c4_proxy_flag = proxy_flag;
+
+        if (lane_version > 1 ) lec_params.c29_v2_capable = 1;
+        else lec_params.c29_v2_capable = 0;
+        
+        /* then come the defaults */
+        lec_params.c2_lan_type = LAN_TYPE_UNSPEC; /* Unspecified, implies Ethernet */
+        if (lec_params.c29_v2_capable) {
+                lec_params.c7_ctrl_timeout = 30;
+                lec_params.c10_max_unknown_frames = 10;
+        }
+        else {
+                lec_params.c7_ctrl_timeout = 10;
+                lec_params.c10_max_unknown_frames = 1;
+        }
+        lec_params.c7i_initial_ctrl_timeout = 5;
+        lec_params.c7x_timeout_multiplier = 2;
+        lec_params.c7c_current_timeout = lec_params.c7i_initial_ctrl_timeout;
+        lec_params.c11_max_unknown_frame_time = 1;
+        lec_params.c12_vcc_timeout            = 1200;
+        lec_params.c13_max_retry_count        = 2;
+        lec_params.c14_lec_id                 = 0;
+        lec_params.c17_aging_time             = 300;
+        lec_params.c18_forward_delay_time     = 15;
+        lec_params.c19_topology_change        = 0;
+        lec_params.c20_le_arp_response_time   = 1;
+        lec_params.c21_flush_timeout          = 4;
+        lec_params.c22_path_switching_delay   = 6;
+        /* LANE2 added the following, only the ones used are listed */
+        memset(lec_params.c35_preferred_les, 0, ATM_ESA_LEN);
+        lec_params.c35_contains_address       = 0;
+        lec_params.c37_min_reconfig_delay     = 1;    /* milliseconds */
+        lec_params.c38_max_reconfig_delay     = 5000; /* milliseconds */
+
+        if (lec_params.tlvs != NULL) free (lec_params.tlvs);
+        lec_params.tlvs       = NULL;
+        lec_params.sizeoftlvs = 0;
+        lec_params.num_tlvs   = 0;
+
+        return;
+}
+
+/* ------------- Configure phase specific stuff starts ------------- */
+
+/*
+ * 5.2 LECS connect phase
+ * Returns < 0 for error
+ */
+int lec_configure(int lecs_method, struct sockaddr_atmsvc *manual_atm_addr,
+                  struct sockaddr_atmsvc *listen_addr)
+{
+        int retval;
+        struct sockaddr_atmsvc addr_c5, addr_47;
+        struct atm_sap sap;
+        struct atm_qos qos;
+        Conn_t *conn;
+        
+        diag(COMPONENT, DIAG_DEBUG, "entering lec_configure\n");
+        
+        /* initialize well known LECS addresses */
+        memset(&addr_c5, 0, sizeof(struct sockaddr_atmsvc));
+        memset(&addr_47, 0, sizeof(struct sockaddr_atmsvc));
+        addr_c5.sas_family = addr_47.sas_family = AF_ATMSVC;
+        memcpy(addr_c5.sas_addr.prv, well_known_lecs, ATM_ESA_LEN);
+        memcpy(addr_47.sas_addr.prv, well_known_lecs, ATM_ESA_LEN);
+        addr_c5.sas_addr.prv[0] = 0xC5;
+
+        /* see if the user wants to skip LECS */
+        if (lecs_method == LECS_NONE)
+                return 0;
+        
+        init_conn_params(&sap, &qos, CONTROL_CONN);
+
+        while(1) {
+                if (lecs_method == LECS_MANUAL) {
+                        diag(COMPONENT, DIAG_DEBUG, "trying manual LECS address\n");
+                        conn = setup_svc(manual_atm_addr, listen_addr, &sap, &qos);
+                        if (conn) {
+                                retval = do_lec_configure(conn);
+                                close_connection(conn);
+                                return retval;
+                        }
+                        else random_delay();
+                }
+                diag(COMPONENT, DIAG_DEBUG, "trying well-known anycast LECS address\n");
+                conn = setup_svc(&addr_c5, listen_addr, &sap, &qos);
+                if (conn) {
+                        retval = do_lec_configure(conn);
+                        close_connection(conn);
+                        return retval;
+                }
+                else random_delay();
+                diag(COMPONENT, DIAG_DEBUG, "trying well-known LECS address\n");
+                conn = setup_svc(&addr_47, listen_addr, &sap, &qos);
+                if (conn) {
+                        retval = do_lec_configure(conn);
+                        close_connection(conn);
+                        return retval;
+                }
+                else random_delay();
+        }
+        
+        return -1; /* not reached */
+}
+
+/*
+ * 5.3 Configuration phase, get configuration from LECS
+ * Returns < 0 for error
+ */
+static int do_lec_configure(Conn_t *conn)
+{
+        int frame_size = 0;
+        char buff[MAX_CTRL_FRAME];
+
+        lec_params.c7c_current_timeout = lec_params.c7i_initial_ctrl_timeout; /* reset it */
+        while (lec_params.c7c_current_timeout <= lec_params.c7_ctrl_timeout) {
+                if (send_config_req(conn) < 0) return -1;
+                frame_size = read_config_rsp(conn, buff, sizeof(buff));
+                if (frame_size < 0) return -1;
+                if (frame_size == 0) /* timeout */
+                        lec_params.c7c_current_timeout *= lec_params.c7x_timeout_multiplier;
+                else
+                        break; /* frame in */
+        }
+        lec_params.c7c_current_timeout = lec_params.c7i_initial_ctrl_timeout; /* reset it */
+        if (frame_size == 0) {
+                diag(COMPONENT, DIAG_INFO, "Timed out while waiting for LE_CONFIGURE_RESPONSE\n");
+                return -1; /* timeout */
+        }
+
+        if (parse_config_rsp(buff, frame_size) < 0) {
+                diag(COMPONENT, DIAG_ERROR, "Parsing LE_CONFIG_RESPONSE indicates failure\n");
+                return -1;
+        }
+
+        return 0;
+}
+
+/*
+ * Compose a LE Config request frame and send it to LECS
+ * Returns < 0 for error
+ */
+static int send_config_req(Conn_t *conn)
+{
+        int frame_size;
+        struct ctrl_frame *config_req;
+        char buff[MAX_CTRL_FRAME];
+
+        diag(COMPONENT, DIAG_DEBUG, "Sending LE_CONFIGURE_REQUEST\n");
+
+        /* TLVs make config frame variable length */
+        frame_size = sizeof(struct ctrl_frame);
+        if (lec_params.c3_max_frame_size == MTU_1580) frame_size += 5;
+        config_req = (struct ctrl_frame *)buff;
+        memset(config_req, 0, frame_size);
+
+        prefill_frame(config_req, LE_CONFIG_REQ);
+        if (lec_params.c29_v2_capable)
+                config_req->header.flags = htons(V2_CAPABLE);
+        config_req->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
+        memcpy(config_req->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN);
+        memcpy(config_req->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+        config_req->lan_type = lec_params.c2_lan_type;
+        config_req->max_frame_size = lec_params.c3_max_frame_size;
+        config_req->elan_name_size = strlen(lec_params.c5_elan_name);
+        if (strlen(lec_params.c5_elan_name) > 0)
+                strcpy(config_req->elan_name, lec_params.c5_elan_name);
+        if (lec_params.c3_max_frame_size == MTU_1580) {
+                lec_params.c3_max_frame_size = MTU_1516;
+                *(uint32_t *)(config_req + 1) = htonl(X5_ADJUSTMENT);
+                config_req->num_tlvs++;
+        }
+
+        if (send_frame(conn, buff, frame_size) != frame_size)
+                return -1;
+
+        return 0;
+}
+
+/*
+ * Reads in Config frame or timeouts
+ * Returns Config frame length, < 0 for error, 0 for timeout
+ */
+static int read_config_rsp(Conn_t *conn, char *buff, int buffsize)
+{
+        int frame_size, retval;
+        struct timeval tv;
+        fd_set rfds;
+
+        tv.tv_sec = lec_params.c7c_current_timeout;
+        tv.tv_usec = 0;
+        FD_ZERO(&rfds);
+        FD_SET(conn->fd, &rfds);
+
+        retval = select(conn->fd + 1, &rfds, NULL, NULL, &tv);
+        if (retval < 0) {
+                diag(COMPONENT, DIAG_ERROR, "read_ctrl_rsp: select: %s\n",
+                     strerror(errno));
+                return retval;
+        }
+        if (retval == 0) return 0; /* timeout */
+        
+        frame_size = recv_frame(conn, buff, buffsize);
+        if (frame_size < 0) {
+                diag(COMPONENT, DIAG_ERROR, "read_ctrl_rsp: recv_frame: %s\n",
+                     strerror(errno));
+                return frame_size;
+        }
+        if (frame_size == 0) {
+                diag(COMPONENT, DIAG_ERROR, "read_ctrl_rsp: conn closed: %s\n",
+                     strerror(errno));
+                return -1;
+        }
+
+        return frame_size;
+}
+
+/* Validates and parses a LE_CONFIGURE_RESPONSE.
+ * See LANEv2, 5.3.x
+ * Returns < 0 for error
+ */
+static int parse_config_rsp(unsigned char *buff, int size)
+{
+        struct ctrl_frame *frame;
+
+        diag(COMPONENT, DIAG_DEBUG, "Parsing LE_CONFIG_RESPONSE\n");
+        if (validate_frame(buff, size) < 0) {
+                diag(COMPONENT, DIAG_ERROR, "parse_config_rsp: bad frame\n");
+                return -1;
+        }
+
+        frame = (struct ctrl_frame *)buff;
+        if (frame->header.opcode != htons(LE_CONFIG_RSP)) {
+                diag(COMPONENT, DIAG_ERROR, "parse_config_rsp: not a LE_CONFIG_RESPONSE\n");
+                return -1;
+        }
+        
+        if (frame->header.status != 0) {
+                diag(COMPONENT, DIAG_ERROR, "LECS said: %s\n",
+                     status2text(frame->header.status));
+                return -1;
+        }
+        if (frame->elan_name_size > 32) return -1;
+
+        /* looks good, now extract the information */
+        lec_params.c2_lan_type = frame->lan_type;
+        lec_params.c3_max_frame_size = frame->max_frame_size;
+        if (frame->elan_name_size != 0)
+                strncpy(lec_params.c5_elan_name, frame->elan_name, frame->elan_name_size);
+        lec_params.c5_elan_name[frame->elan_name_size] = '\0';
+        memcpy(lec_params.c9_les_atm_addr, frame->target_atm_addr, ATM_ESA_LEN);
+
+        parse_tlvs(frame->header.opcode, buff + sizeof(struct ctrl_frame),
+                   frame->num_tlvs, size - sizeof(struct ctrl_frame));
+
+        return 0;
+}
+
+/* ------------- Configure phase specific stuff ends ------------- */
+
+
+/* -------------- Join phase specific stuff starts --------------- */
+
+/*
+ * 5.4 Join phase
+ * Create control direct VCC and accept possible control distribute VCC
+ * Returns < 0 for error
+ */
+int les_connect(int lecs_method, struct sockaddr_atmsvc *manual_atm_addr,
+                  struct sockaddr_atmsvc *listen_addr)
+{
+        struct sockaddr_atmsvc les_addr;
+        struct atm_sap sap;
+        struct atm_qos qos;
+        char buff[MAX_CTRL_FRAME];
+        int frame_size = 0; /* shut up, GCC */
+
+        diag(COMPONENT, DIAG_DEBUG, "Entering Join phase\n");
+
+        if (lecs_method == LECS_NONE) {
+                diag(COMPONENT, DIAG_DEBUG, "Skipping LECS, connecting straight to LES\n");
+                memcpy(les_addr.sas_addr.prv, manual_atm_addr->sas_addr.prv, ATM_ESA_LEN);
+        } else memcpy(les_addr.sas_addr.prv, lec_params.c9_les_atm_addr, ATM_ESA_LEN);
+
+        init_conn_params(&sap, &qos, CONTROL_CONN);
+        lec_params.ctrl_direct = setup_svc(&les_addr, listen_addr, &sap, &qos);
+        if (lec_params.ctrl_direct == NULL) {
+                diag(COMPONENT, DIAG_ERROR, "Control direct SVC failed\n");
+                random_delay();
+                return -1;
+        }
+        lec_params.ctrl_listen = create_listensocket(listen_addr, &sap, &qos);
+        if (lec_params.ctrl_listen == NULL) {
+                diag(COMPONENT, DIAG_ERROR, "Control distribute listen socket failed\n");
+                random_delay();
+                return -1;
+        }
+
+        lec_params.c7c_current_timeout = lec_params.c7i_initial_ctrl_timeout; /* reset it */
+        while (lec_params.c7c_current_timeout <= lec_params.c7_ctrl_timeout) {
+                if (send_join_req(lec_params.ctrl_direct) < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "Sending LE_JOIN_REQUEST failed\n");
+                        random_delay();
+                        return -1;
+                }
+                frame_size = read_join_rsp(buff, sizeof(buff));
+                if (frame_size < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "Receiving LE_JOIN_RESPONSE failed\n");
+                        random_delay();
+                        return -1;
+                } else if (frame_size == 0) /* timeout */
+                        lec_params.c7c_current_timeout *= lec_params.c7x_timeout_multiplier;
+                else
+                        break; /* frame in */
+        }
+        lec_params.c7c_current_timeout = lec_params.c7i_initial_ctrl_timeout; /* reset it */
+        if (frame_size == 0) {
+                diag(COMPONENT, DIAG_ERROR, "LE_JOIN_RESPONSE timed out\n");
+                return -1;
+        }
+        
+        if (parse_join_rsp(buff, frame_size) < 0) {
+                diag(COMPONENT, DIAG_ERROR, "Parsing LE_JOIN_RESPONSE failed\n");
+                return -1;
+        }
+
+        return 0;
+}
+
+/* 5.4.1.2 Transmitting LE_JOIN_REQUEST
+ * Note that the TLVs should be the same as in LE_CONFIG_REQUEST
+ * excluding X5-Adjustment and Preferred-LES
+ */
+static int send_join_req(Conn_t *conn)
+{
+        char buff[MAX_CTRL_FRAME], *tlvp;
+        struct ctrl_frame *frame;
+        int frame_size;
+
+        frame_size = sizeof(struct ctrl_frame);
+        if (lec_params.c3_max_frame_size == 5) frame_size += 5;
+        if (lec_params.c35_contains_address) frame_size += (5 + ATM_ESA_LEN);
+        if (strlen(lec_params.foreId) > 0) frame_size += (5 + strlen(lec_params.foreId));
+
+        frame = (struct ctrl_frame *)buff;
+        tlvp = (char *)(frame + 1);
+        prefill_frame(frame, LE_JOIN_REQ);
+        frame->lan_type = lec_params.c2_lan_type;
+        if (lec_params.c4_proxy_flag) frame->header.flags |= htons(PROXY_FLAG);
+        frame->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
+        strcpy(frame->elan_name, lec_params.c5_elan_name);
+        frame->elan_name_size = strlen(lec_params.c5_elan_name);
+        if (lec_params.c29_v2_capable) frame->header.flags |= htons(V2_CAPABLE);
+        memcpy(frame->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+        memcpy(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN);
+        frame->max_frame_size = lec_params.c3_max_frame_size;
+        if (lec_params.c3_max_frame_size == 5) {
+                frame->max_frame_size = 1;
+                *(uint32_t *)tlvp = htonl(X5_ADJUSTMENT);
+                tlvp += 4; *tlvp = 0; tlvp++;
+                frame->num_tlvs++;
+        }
+        if (lec_params.c35_contains_address) {
+                *(uint32_t *)tlvp = htonl(PREFERRED_LES);
+                tlvp +=4; *tlvp = (uint8_t)ATM_ESA_LEN; tlvp++;
+                memcpy(tlvp, lec_params.c35_preferred_les, ATM_ESA_LEN);
+                tlvp += 20;
+                frame->num_tlvs++;
+        }
+        if (strlen(lec_params.foreId) > 0) {
+                *(uint32_t *)tlvp = htonl(FORE_NAME);
+                tlvp +=4; *tlvp = (uint8_t)strlen(lec_params.foreId); tlvp++;
+                memcpy(tlvp, lec_params.foreId, strlen(lec_params.foreId));
+                tlvp += strlen(lec_params.foreId);
+                frame->num_tlvs++;
+        }
+
+        if (send_frame(conn, frame, frame_size) != frame_size)
+                return -1;
+
+        return 0;
+}
+
+/* LE_JOIN_RESPONSE can either come over ctrl_direct or ctrl_dist.
+ * However, if LES uses Control Direct VCC, we can ignore connections
+ * to ctrl_listen and if it connects to ctrl_listen we can wait
+ * the reponse to arrive that route. Simple :)
+ * 
+ * Returns < 0 for error, 0 for timeout, > 0 for frame size
+ */
+static int read_join_rsp(char *buff, int buffsize)
+{
+        Conn_t *dist;
+        int n, retval, frame_size = 0;
+        struct timeval tv;
+        fd_set rfds;
+
+        /* Idea here is always to listen for two sockets. One of the
+           sockets is always Control Direct and the other is either
+           listen socket for Control Distribute or the Control
+           Distribute itself. We can do it like this, since listen
+           socket gets closed as soon as it creates a new connection
+        */
+
+        dist = (lec_params.ctrl_listen != NULL) ? lec_params.ctrl_listen : lec_params.ctrl_dist;
+        n = (lec_params.ctrl_direct->fd > dist->fd) ? lec_params.ctrl_direct->fd : dist->fd;
+        n++;
+
+        tv.tv_sec = lec_params.c7c_current_timeout;
+        tv.tv_usec = 0;
+        FD_ZERO(&rfds);
+        FD_SET(lec_params.ctrl_direct->fd, &rfds);
+        FD_SET(dist->fd, &rfds);
+        
+        retval = select(n, &rfds, NULL, NULL, &tv);
+        if (retval < 0) {
+                diag(COMPONENT, DIAG_ERROR, "get_join_rsp: select: %s\n",
+                     strerror(errno));
+                return -1;
+        }
+        if (retval == 0) return 0; /* timeout */
+
+        /* Be careful here. The both sockets might be readable
+         * and the response can come from either one
+         */
+        if (FD_ISSET(lec_params.ctrl_direct->fd, &rfds)) {
+                /* Control Direct was changed */
+                frame_size = recv_frame(lec_params.ctrl_direct, buff, buffsize);
+                if (frame_size < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "get_join_rsp: recv_frame: %s\n",
+                             strerror(errno));
+                        return -1;
+                }
+                if (frame_size == 0) {
+                        diag(COMPONENT, DIAG_ERROR, "get_join_rsp: Control direct VCC closed\n");
+                        return -1;
+                }
+                diag(COMPONENT, DIAG_DEBUG, "LE_JOIN_RESPONSE over Control direct VCC\n");
+        }
+        if (FD_ISSET(dist->fd, &rfds)) {
+                /* Event in listen socket or Control Distribute */
+                if (dist == lec_params.ctrl_listen) {
+                        /* Connection to control listen */
+                        lec_params.ctrl_dist = accept_conn(lec_params.ctrl_listen);
+                        if (lec_params.ctrl_dist == NULL) {
+                                diag(COMPONENT, DIAG_ERROR, "accept of Ctrl distribute failed\n");
+                                return -1;
+                        }
+                        diag(COMPONENT, DIAG_DEBUG, "Closing listen socket for Ctrl distribute VCC\n");
+                        close_connection(lec_params.ctrl_listen);
+                        lec_params.ctrl_listen = NULL;
+
+                        /* let's see if this new socket has something for us */
+                        return (read_join_rsp(buff, buffsize));
+                }
+                /* Event in Control distribute */
+                frame_size = recv_frame(lec_params.ctrl_dist, buff, buffsize);
+                if (frame_size < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "get_join_rsp: recv_frame: %s\n",
+                             strerror(errno));
+                        return -1;
+                }
+                if (frame_size == 0) {
+                        diag(COMPONENT, DIAG_ERROR, "Control distribute VCC closed\n");
+                        return -1;
+                }
+                diag(COMPONENT, DIAG_DEBUG, "LE_JOIN_RESPONSE over Control distribute VCC\n");
+        }
+
+        return frame_size;
+}
+
+/* Validates and parses a LE_JOIN_RESPONSE.
+ * See LANEv2 5.4.x
+ * Returns < 0 for error
+ */
+static int parse_join_rsp(unsigned char *buff, int size)
+{
+        struct ctrl_frame *frame;
+
+        diag(COMPONENT, DIAG_DEBUG, "Parsing LE_JOIN_RESPONSE\n");
+        if (validate_frame(buff, size) < 0)
+                return -1;
+
+        frame = (struct ctrl_frame *)buff;
+        if (frame->header.opcode != htons(LE_JOIN_RSP))
+                return -1;
+        
+        if (frame->header.status != 0) {
+                diag(COMPONENT, DIAG_ERROR, "LES said: %s\n",
+                     status2text(frame->header.status));
+                return -1;
+        }
+        if (frame->elan_name_size > 32) return -1;
+
+        /* looks good, now extract the information */
+        lec_params.c2_lan_type = frame->lan_type;
+        lec_params.c3_max_frame_size = frame->max_frame_size;
+        if (frame->elan_name_size != 0)
+                strncpy(lec_params.c5_elan_name, frame->elan_name, frame->elan_name_size);
+        lec_params.c5_elan_name[frame->elan_name_size] = '\0';
+        lec_params.c14_lec_id = ntohs(frame->header.lec_id);
+
+        if (!(frame->header.flags & htons(V2_REQUIRED)) && lec_params.c29_v2_capable) {
+                diag(COMPONENT, DIAG_INFO, "LES did not return V2 Required Flag, acting as V1 client\n");
+                lec_params.c29_v2_capable = 0;
+        }
+        if (!(frame->header.flags & htons(V2_REQUIRED)) &&
+            (lec_params.c3_max_frame_size == MTU_1580)) {
+                /* Against spec, but we'll accept the MTU and clear the flag */
+                diag(COMPONENT, DIAG_ERROR, "LES not LANEv2 but uses MTU of 1580 bytes\n");
+                lec_params.c29_v2_capable = 0;
+        }
+        parse_tlvs(frame->header.opcode, buff + sizeof(struct ctrl_frame),
+                   frame->num_tlvs, size - sizeof(struct ctrl_frame));
+
+        return 0;
+}
+
+/* --------------- Join phase specific stuff ends ---------------- */
+
+
+/* -------------- Bus connect specific stuff starts --------------- */
+
+int bus_connect(void)
+{
+        struct ctrl_frame *frame;
+        char buff[MAX_CTRL_FRAME];
+        struct sockaddr_atmsvc bus_addr, listen_addr;
+        int retval, tries, n;
+        struct atm_sap sap;
+        struct atm_qos qos;
+        struct timeval tv;
+        fd_set rfds;
+        Conn_t *mcast_fwd;
+        struct atmlec_ioc ioc_data;
+
+        frame = (struct ctrl_frame *)buff;
+        memset(&bus_addr, 0, sizeof(struct sockaddr_atmsvc));
+        memset(&listen_addr, 0, sizeof(struct sockaddr_atmsvc));
+        
+        /* try to arp BUS two times */
+        tries = 2;
+        while (tries > 0) {
+                prefill_frame(frame, LE_ARP_REQ);
+                frame->header.lec_id = htons(lec_params.c14_lec_id);
+                frame->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
+                memcpy(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN);
+                memcpy(frame->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+                frame->target_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
+                memcpy(frame->target_lan_dst.mac, bus_mac, ETH_ALEN);
+                retval = send_frame(lec_params.ctrl_direct, frame, sizeof(struct ctrl_frame));
+                if (retval < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "LE_ARP_REQUEST for BUS failed\n");
+                        return -1;
+                }
+                retval = get_bus_addr(&bus_addr);
+                if (retval < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "LE_ARP_RESPONSE for BUS failed\n");
+                        return -1;
+                } else if (retval > 0)
+                        break; /* got it */
+                tries--;
+        }
+        if (tries == 0) {
+                diag(COMPONENT, DIAG_ERROR, "LE_ARP_RESPONSE for BUS timed out\n");
+                return -1;
+        }
+
+        /* We got address for BUS. Make the listen socket for Multicast
+         * Forward first and then contact BUS.
+         */
+        memcpy(listen_addr.sas_addr.prv, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+        listen_addr.sas_family = bus_addr.sas_family = AF_ATMSVC;
+        init_conn_params(&sap, &qos, MCAST_CONN);
+        lec_params.mcast_listen = create_listensocket(&listen_addr, &sap, &qos);
+        if (lec_params.mcast_listen == NULL) {
+                diag(COMPONENT, DIAG_ERROR, "Listen socket for BUS failed\n");
+                return -1;
+        }
+
+        lec_params.mcast_send = setup_svc(&bus_addr, &listen_addr, &sap, &qos);
+        if (lec_params.mcast_send == NULL) {
+                diag(COMPONENT, DIAG_ERROR, "Connect to BUS failed\n");
+                return -1;
+        }
+        /* Default Multicast send VCC to BUS ready, notify kernel */
+        if (ioctl(lec_params.mcast_send->fd, ATMLEC_MCAST, lec_params.itf_num) < 0) {
+                diag(COMPONENT, DIAG_FATAL, "Can't change socket into LE mcast socket: %s\n", strerror(errno));
+                return -1;
+        }
+
+        diag(COMPONENT, DIAG_DEBUG, "About to wait for BUS to connect\n");
+        tv.tv_sec = lec_params.c7_ctrl_timeout;
+        tv.tv_usec = 0;
+        FD_ZERO(&rfds);
+        FD_SET(lec_params.mcast_listen->fd, &rfds);
+        n = lec_params.mcast_listen->fd + 1;
+        retval = select(n, &rfds, NULL, NULL, &tv);
+        if (retval == 0) {
+                diag(COMPONENT, DIAG_ERROR, "BUS connect to Multicast Forward listen socket timed out\n");
+                return -1;
+        }
+        if (retval < 0) {
+                diag(COMPONENT, DIAG_ERROR, "while waiting for Multicast Forward VCC: select: %s\n",
+                     strerror(errno));
+                return -1;
+        }
+        mcast_fwd = accept_conn(lec_params.mcast_listen);
+        if (mcast_fwd == NULL) {
+                diag(COMPONENT, DIAG_ERROR, "BUS connect to Multicast Forward listen socket failed\n");
+                return -1;
+        }
+        
+        memcpy(ioc_data.atm_addr, mcast_fwd->atm_address, ATM_ESA_LEN);
+        ioc_data.dev_num = lec_params.itf_num;
+        ioc_data.receive = 2; /* Multicast distribute */
+        diag(COMPONENT, DIAG_DEBUG, "About to notify kernel about Multicast Forward VCC\n");
+        if (ioctl(mcast_fwd->fd, ATMLEC_DATA, &ioc_data) < 0) {
+                diag(COMPONENT, DIAG_DEBUG, "Could not notify kernel: %s\n", strerror(errno));
+                return -1;
+        }
+
+        /* All done. We're in! */
+        return 0;
+}
+
+/*
+ * Waits for LE_ARP_RESPONSE for BUS' ATM address to arrive.
+ * Returns < 0 for error, 0 for timeout > 0 for success
+ * BUS ATM address will be stored in *addr */
+static int get_bus_addr(struct sockaddr_atmsvc *addr)
+{
+
+        fd_set rfds;
+        struct timeval tv;
+        int n = 0, retval, timeout;
+        char buff[MAX_CTRL_FRAME];
+
+        timeout = 4; /* wait response for 4 seconds */
+        lec_params.c7c_current_timeout = 1;
+        while (lec_params.c7c_current_timeout <= timeout) {
+                tv.tv_sec = lec_params.c7c_current_timeout; /* actually not specified exactly */
+                tv.tv_usec = 0;
+                FD_ZERO(&rfds);
+                FD_SET(lec_params.ctrl_direct->fd, &rfds);
+                if (lec_params.ctrl_dist != NULL) {
+                        FD_SET(lec_params.ctrl_dist->fd, &rfds);
+                        n = lec_params.ctrl_dist->fd;
+                }
+                n = (lec_params.ctrl_direct->fd > n) ? lec_params.ctrl_direct->fd : n;
+                n++;
+                
+                retval = select(n, &rfds, NULL, NULL, &tv);
+                if (retval == 0) {
+                        lec_params.c7c_current_timeout++;
+                        continue; /* back to waiting */
+                }
+                if (retval < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "get_bus_addr: select: %s\n", strerror(errno));
+                        return -1;
+                }
+                if (FD_ISSET(lec_params.ctrl_direct->fd, &rfds)) {
+                        diag(COMPONENT, DIAG_DEBUG, "get_bus_addr: ctrl.direct changed:\n");
+                        retval = read_bus_arp(lec_params.ctrl_direct, addr, buff, sizeof(buff));
+                        if (retval < 0) return -1;
+                        if (retval > 0) return retval;
+                }
+                if (lec_params.ctrl_dist != NULL && FD_ISSET(lec_params.ctrl_dist->fd, &rfds)) {
+                        diag(COMPONENT, DIAG_DEBUG, "get_bus_addr: ctrl.dist changed:\n");
+                        retval = read_bus_arp(lec_params.ctrl_dist, addr, buff, sizeof(buff));
+                        if (retval < 0) return -1;
+                        if (retval > 0) return retval;
+                }
+                diag(COMPONENT, DIAG_DEBUG, "get_bus_addr: consumed a packet\n");
+        }
+
+        diag(COMPONENT, DIAG_ERROR, "Timeout while waiting for BUS LE_ARP response\n");
+        return 0;
+}
+/*
+ * Tries to read BUS ATM address in *addr
+ * returns < 0 for error, 0 for not found > 0 for success
+ */
+static int read_bus_arp(Conn_t *conn, struct sockaddr_atmsvc *addr, char *buff, int buffsize)
+{
+        int frame_size;
+        struct ctrl_frame *frame;
+
+        frame_size = recv_frame(conn, buff, buffsize);
+        if (frame_size == 0) {
+                diag(COMPONENT, DIAG_ERROR, "LES Control connection closed\n");
+                return -1;
+        }
+        if (frame_size < 0) {
+                diag(COMPONENT, DIAG_ERROR, "get_bus_arp: recv_frame: %s\n", strerror(errno));
+                return -1;
+        }
+        frame = (struct ctrl_frame *)buff;
+        if (validate_frame(buff, frame_size) >= 0 &&
+            frame->header.opcode == htons(LE_ARP_RSP) &&
+            memcmp(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN) == 0) {
+                memcpy(addr->sas_addr.prv, frame->target_atm_addr, ATM_ESA_LEN);
+                return frame_size;
+        }
+
+        return 0; /* not found */
+}
+
+/* --------------- Bus connect specific stuff ends --------------- */
diff -ur --new-file old/atm/led/join.h new/atm/led/join.h
--- old/atm/led/join.h	Thu Jan  1 01:00:00 1970
+++ new/atm/led/join.h	Sat Feb  6 21:20:44 1999
@@ -0,0 +1,20 @@
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
+#ifndef JOIN_H
+#define JOIN_H
+
+void init_lec_params(unsigned char *mac_addr, char *elan_name,
+                     unsigned char *listen_addr, int itf, char *foreId,
+                     int max_frame_size, int proxy_flag, int lane_version);
+int lec_configure(int lecs_method, struct sockaddr_atmsvc *manual_atm_addr,
+                  struct sockaddr_atmsvc *listen_addr);
+int les_connect(int lecs_method, struct sockaddr_atmsvc *manual_atm_addr,
+                struct sockaddr_atmsvc *listen_addr);
+int bus_connect(void);
+
+/* Different ways to contact LECS */
+#define LECS_NONE      0
+#define LECS_WELLKNOWN 1
+#define LECS_MANUAL    2
+
+#endif /* JOIN_H */
diff -ur --new-file old/atm/led/kernel.c new/atm/led/kernel.c
--- old/atm/led/kernel.c	Thu Jan  1 01:00:00 1970
+++ new/atm/led/kernel.c	Wed Jun  2 23:36:54 1999
@@ -0,0 +1,336 @@
+/* kernel.c - send and receive messages from kernel and act accordingly */
+
+/*
+ * Marko Kiiskila carnil@cs.tut.fi 
+ * 
+ * Copyright (c) 1996
+ * Tampere University of Technology - Telecommunications Laboratory
+ * All rights reserved.
+ *
+ * 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.
+ * 
+ */
+
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
+/* System includes */
+#include <errno.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* Atm includes */
+#include <atm.h>
+#include <linux/atmdev.h>
+#include <linux/atmlec.h>
+
+#include <atmd.h>
+
+/* Local includes */
+#include "kernel.h"
+#include "lec.h"
+#include "frames.h"
+
+#define COMPONENT "kernel.c"
+
+/* Local vars */
+static int lec_socket;
+
+static const char* get_mesg_type_str(atmlec_msg_type type);
+static void send_le_arp_req(unsigned char *mac_addr, int is_rdesc, int sizeoftlvs);
+static void send_proxy_arp_rsp(unsigned char *target_mac, uint32_t tran_id,
+                               uint16_t lec_id, unsigned char *src_atm_addr);
+static void send_topology_req(int flag);
+static void associate_tlvs(int sizeoftlvs);
+
+/* Notify kernel that zeppelin is present and tell
+ * kernel what MAC address this LEC uses
+ */
+int kernel_init(unsigned char *mac_addr, int itf)
+{
+        int rvalue;
+        struct atmlec_msg msg;
+
+        lec_socket = socket(PF_ATMSVC, SOCK_DGRAM, 0);
+        if (lec_socket < 0) {
+                diag(COMPONENT, DIAG_FATAL, "Kernel socket creation failed: %s\n",
+                     strerror(errno));
+                return -1;
+        }
+        itf = ioctl(lec_socket, ATMLEC_CTRL, itf);
+        if (itf < 0) {
+                diag(COMPONENT, DIAG_FATAL, "Socket ioctl to lecd_ctrl failed:%s\n",
+                     strerror(errno));
+                close(lec_socket);
+                return -1;
+        }
+        msg.type = l_set_mac_addr;
+        memcpy(msg.content.normal.mac_addr, mac_addr, ETH_ALEN);
+        
+        rvalue = write(lec_socket, &msg, sizeof(msg));
+        if (rvalue < 0) {
+                diag(COMPONENT, DIAG_FATAL, "Can't write mac address to LEC:%s\n",
+                     strerror(errno));
+                close(lec_socket);
+                return -1;
+        }
+        diag(COMPONENT, DIAG_DEBUG, "Kernel interface initialized\n");
+        
+        if (conn_set_kernel_socket(lec_socket) < 0) {
+                close(lec_socket);
+                return -1;
+        }
+        
+        return itf;
+}
+
+/* Send a message to kernel
+ * Returns < 0 for error
+ */
+int msg_to_kernel(struct atmlec_msg *msg, int msg_size)
+{
+        int retval;
+
+        diag(COMPONENT, DIAG_DEBUG, "msg_to_kernel, type %s\n", get_mesg_type_str(msg->type));
+        retval = write(lec_params.kernel->fd, msg, msg_size);
+        if (retval < 0) {
+                diag(COMPONENT, DIAG_ERROR, "msg_to_kernel: write: %s\n", strerror(errno));
+                return -1;
+        }
+        if (retval != msg_size) {
+                diag(COMPONENT, DIAG_ERROR, "msg_to_kernel: partial write\n");
+                return -1;
+        }
+
+        return retval;
+}
+
+/* Read and process message from kernel
+ * Returns < 0 for error
+ */
+int msg_from_kernel(void)
+{
+        int retval;
+        struct atmlec_msg msg;
+        int codepoint, is_rdesc = 0;
+        uint8_t bcast;
+
+        retval = read(lec_params.kernel->fd, &msg, sizeof(struct atmlec_msg));
+        if (retval < 0) {
+                diag(COMPONENT, DIAG_FATAL, "msg_from_kernel: read: %s\n", strerror(errno));
+                return -1;
+        }
+        if (retval != sizeof(struct atmlec_msg)) {
+                diag(COMPONENT, DIAG_ERROR, "msg_from_kernel: msg size != sizeof(atmlec_msg)\n");
+                return 0;
+        }
+
+        diag(COMPONENT, DIAG_DEBUG, "msg_from_kernel: type %s\n", get_mesg_type_str(msg.type));
+        switch (msg.type) {
+        case l_rdesc_arp_xmt:
+                is_rdesc = 1;
+                /* fall through */
+        case l_arp_xmt:
+                if (msg.content.normal.targetless_le_arp)
+                        send_le_arp_req(NULL, 0, msg.sizeoftlvs);
+                else
+                        send_le_arp_req(msg.content.normal.mac_addr, is_rdesc, msg.sizeoftlvs);
+                break;
+        case l_svc_setup:
+                bcast = (lec_params.c2_lan_type == LAN_TYPE_8025) ? 0x80 : 0x01; /* TR is MSB */
+                codepoint = (msg.content.normal.mac_addr[0] & bcast) ? MCAST_CONN : DATA_DIRECT_CONN;
+                if (create_data_svc(msg.content.normal.atm_addr, codepoint) < 0)
+                        diag(COMPONENT, DIAG_ERROR, "Data direct VCC failed\n");
+                break;
+        case l_associate_req:
+                associate_tlvs(msg.sizeoftlvs);
+                break;
+        case l_should_bridge:
+                send_proxy_arp_rsp(msg.content.proxy.mac_addr, msg.content.proxy.tran_id,
+                                   msg.content.proxy.lec_id, msg.content.proxy.atm_addr);
+                break;
+        case l_topology_change:
+                send_topology_req(msg.content.normal.flag);
+                break;
+        default:
+                diag(COMPONENT, DIAG_ERROR, "no handler for kernel msg %s\n", get_mesg_type_str(msg.type));
+                break;
+        }
+
+        return 0;
+}
+
+/* Send LE_ARP_REQUEST. If mac_addr is NULL, sends a targetless LE_ARP.
+ * If sizeoftlvs != 0, reads TLVs waiting in the kernel socket and
+ * adds them to the frame. If sizeoftlvs == 0 then the TLVs (if any)
+ * associated with this LEC are used.
+ * FIXME: add TLV count in kernel messages
+ */
+static void send_le_arp_req(unsigned char *mac_addr, int is_rdesc, int sizeoftlvs)
+{
+        struct ctrl_frame *frame;
+        int frame_size;
+        char buff[MAX_CTRL_FRAME];
+
+        diag(COMPONENT, DIAG_DEBUG, "Sending LE_ARP_REQUEST\n");
+
+        if (sizeoftlvs == 0) frame_size = sizeof(struct ctrl_frame) + lec_params.sizeoftlvs;
+        else frame_size = sizeof(struct ctrl_frame) + sizeoftlvs;
+        frame = (struct ctrl_frame *)buff;
+        memset(frame, 0, frame_size);
+
+        prefill_frame(frame, LE_ARP_REQ);
+        frame->header.lec_id = htons(lec_params.c14_lec_id);
+        frame->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
+        memcpy(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN);
+        memcpy(frame->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+        if (mac_addr != NULL) {
+                memcpy(frame->target_lan_dst.mac, mac_addr, ETH_ALEN);
+                if (is_rdesc)
+                        frame->target_lan_dst.tag = htons(LAN_DST_ROUTE_DESC);
+                else
+                        frame->target_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
+        } else diag(COMPONENT, DIAG_DEBUG, "Sending targetless LE_ARP\n");
+
+        if (sizeoftlvs != 0) {
+                if (read(lec_params.kernel->fd, (frame + 1), sizeoftlvs) < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "reading TLVs from kernel failed: %s\n", strerror(errno));
+                        return;
+                }
+                frame->num_tlvs++;
+        } else if (lec_params.sizeoftlvs != 0) {
+                memcpy((frame + 1), lec_params.tlvs, lec_params.sizeoftlvs);
+                frame->num_tlvs += lec_params.num_tlvs;
+        }
+
+        send_frame(lec_params.ctrl_direct, frame, frame_size);
+
+        return;
+}
+
+/* Associate the set of TLVs available in kernel socket
+ * with this LEC. The old TLVs, if any, are removed.
+ * Also, send a LE_REGISTER_REQUEST to register the TLVs
+ * we just got.
+ */
+static void associate_tlvs(int sizeoftlvs)
+{
+
+        if (lec_params.tlvs != NULL) free (lec_params.tlvs);
+        lec_params.sizeoftlvs = 0;
+        lec_params.num_tlvs = 0;
+        lec_params.tlvs = malloc(sizeoftlvs);
+        if (lec_params.tlvs == NULL) {
+                diag(COMPONENT, DIAG_ERROR, "Could not associate TLVs, out of memory\n");
+                lec_params.sizeoftlvs = 0;
+                lec_params.num_tlvs = 0;
+                return;
+        }
+        if (read(lec_params.kernel->fd, lec_params.tlvs, sizeoftlvs) < 0) {
+                diag(COMPONENT, DIAG_ERROR, "reading TLVs from kernel failed: %s\n", strerror(errno));
+                return;
+        }
+
+        lec_params.sizeoftlvs = sizeoftlvs;
+        lec_params.num_tlvs = 1; /* FIXME, add TLV count in messages */
+
+        send_register_req();
+
+        return;
+}
+
+/* Send a LE_ARP_RESPONSE for a LAN destination (MAC address) when
+ * the LAN destination is present in kernel bridging table and we
+ * are acting as a proxy lane client
+ */
+static void send_proxy_arp_rsp(unsigned char *target_mac, uint32_t tran_id,
+                               uint16_t lec_id, unsigned char *src_atm_addr)
+{
+        struct ctrl_frame *frame;
+        int frame_size;
+
+        frame_size = sizeof(struct ctrl_frame) + lec_params.sizeoftlvs;
+        frame = malloc(frame_size);
+        if (frame == NULL) return;
+        memset(frame, 0, frame_size);
+        prefill_frame(frame, LE_ARP_RSP);
+        frame->header.tran_id = tran_id;
+        frame->header.lec_id = lec_id;
+        frame->header.flags = htons(REMOTE_ADDRESS);
+        memcpy(frame->target_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
+        frame->target_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
+        memcpy(frame->target_lan_dst.mac, target_mac, ETH_ALEN);
+        memcpy(frame->src_atm_addr, src_atm_addr, ATM_ESA_LEN);
+        frame->num_tlvs = lec_params.num_tlvs;
+        if (lec_params.num_tlvs > 0)
+                memcpy(frame + 1, lec_params.tlvs, lec_params.sizeoftlvs);
+
+        if (send_frame(lec_params.ctrl_direct, frame, frame_size) < 0)
+                diag(COMPONENT, DIAG_ERROR, "send_proxy_arp_rsp: send_frame() failed");
+	free(frame);
+
+        return;
+}
+
+/* 7.1.25 Send a LE_TOPOLOGY_REQUEST */
+static void send_topology_req(int flag)
+{
+        struct ctrl_frame frame;
+
+        prefill_frame(&frame, LE_TOPO_REQ);
+        if (flag) frame.header.flags = htons(TOPO_CHANGE);
+
+        send_frame(lec_params.ctrl_direct, &frame, sizeof(struct ctrl_frame));
+
+        return;
+}
+
+static const char *get_mesg_type_str(atmlec_msg_type type)
+{
+        switch(type) {
+        case l_set_mac_addr:
+                return "SET_MAC_ADDR";
+        case l_del_mac_addr:
+                return "DEL_MAC_ADDR";
+        case l_svc_setup:
+                return "SVC_SETUP";
+        case l_arp_xmt:
+                return "ARP_XMT";
+        case l_addr_delete:
+                return "ADDR_DELETE";
+        case l_topology_change:
+                return "TOPOLOGY_CHANGE";
+        case l_flush_tran_id:
+                return "FLUSH_TRANSACTION_ID";
+        case l_flush_complete:
+                return "FLUSH_COMPLETE";
+        case l_arp_update:
+                return "ARP_UPDATE";
+        case l_config:
+                return "CONFIG";
+        case l_associate_req:
+                return "LANE2_ASSOCIATE_REQ";
+        case l_set_lecid:
+                return "SET_LEC_ID";
+        case l_narp_req:
+                return "LE_NARP_REQUEST";
+        case l_should_bridge:
+                return "SHOULD_BRIDGE";
+        default:
+                return "<Unknown message type>";
+        }
+}
diff -ur --new-file old/atm/led/kernel.h new/atm/led/kernel.h
--- old/atm/led/kernel.h	Thu Jan  1 01:00:00 1970
+++ new/atm/led/kernel.h	Sat Feb  6 14:45:20 1999
@@ -0,0 +1,36 @@
+/*
+ * Marko Kiiskila carnil@cs.tut.fi 
+ * 
+ * Copyright (c) 1996
+ * Tampere University of Technology - Telecommunications Laboratory
+ * All rights reserved.
+ *
+ * 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.
+ * 
+ */
+
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
+
+#ifndef KERNEL_H
+#define KERNEL_H
+#include <linux/atmlec.h>
+
+int kernel_init(unsigned char *mac_addr, int itf);
+int msg_to_kernel(struct atmlec_msg *msg, int msg_size);
+int msg_from_kernel(void);
+int read_from_kernel (char *buff, int size);
+
+#endif /* KERNEL_H */
diff -ur --new-file old/atm/led/kernel_itf.c new/atm/led/kernel_itf.c
--- old/atm/led/kernel_itf.c	Tue Feb  9 17:12:01 1999
+++ new/atm/led/kernel_itf.c	Thu Jan  1 01:00:00 1970
@@ -1,248 +0,0 @@
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-/*
- * Kernel interface
- *
- * $Id: kernel_itf.c,v 1.9 1996/07/07 11:51:47 carnil Exp carnil $
- *
- */
-/* System includes */
-#include <errno.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <linux/if_ether.h>
-#include <string.h>
-#include <stdlib.h>  /* for malloc() and free() */
-/* Atm includes */
-#include <atm.h>
-#include <linux/atmdev.h>
-#include <linux/atmlec.h>
-
-/* Local includes */
-#include "kernel_itf.h"
-#include "g_event.h"
-#include "conn.h"
-
-#define EMOD MOD_UP_DRV
-#define EINST "kernel_itf.c"
-#include "emask.h"
-
-/* Local vars */
-static int lec_socket;
-/* Callback func array */
-static kernel_callback callback_funcs[ATMLEC_MSG_TYPE_MAX];
-
-int 
-kernel_init(unsigned char *mac_addr, int itf_num)
-{
-  int rvalue;
-  struct atmlec_msg msg;
-
-  lec_socket = socket(PF_ATMSVC, SOCK_DGRAM, 0);
-  if (lec_socket <0) {
-    EVENT(EM_SERR,("Socket creation failure:%s\n",strerror(errno)));
-    return -1;
-  }
-  itf_num = ioctl(lec_socket, ATMLEC_CTRL, itf_num);
-  if (itf_num <0) {
-    EVENT(EM_SERR,("Socket ioctl to lecd_ctrl failed:%s\n", strerror(errno)));
-    close(lec_socket);
-    return -1;
-  }
-  memcpy(&msg.content.normal.mac_addr, mac_addr, ETH_ALEN);
-
-  msg.type = l_set_mac_addr;
-  
-  rvalue = write(lec_socket, &msg, sizeof(msg));
-  if (rvalue<0) {
-    EVENT(EM_SERR,("Can't write mac address to LEC:%s\n",strerror(errno)));
-    close(lec_socket);
-    return -1;
-  }
-  EVENT(EM_DEBUG,("Kernel interface initialized\n"));
-  memset(callback_funcs, 0, sizeof(kernel_callback)*ATMLEC_MSG_TYPE_MAX);
-  
-  if (conn_set_kernel_socket(lec_socket)<0) {
-    close(lec_socket);
-    return -1;
-  }
-  /* Add fd to select */
-  return itf_num;
-}
-
-/*
- * LANE2: The messages to/from kernel can be variable size.
- * We now have to be prepared to malloc() the right size msg
- *
- */
-int 
-kernel_sendmsg(atmlec_msg_type type, unsigned char *mac_addr, 
-	       unsigned char *atm_addr, struct atmlec_config_msg *config,
-	       unsigned long flag, char *data, int datalen,
-               int targetless_le_arp, int no_source_le_narp)
-{
-  struct atmlec_msg *mesg;
-
-  mesg = (struct atmlec_msg *)malloc(sizeof(struct atmlec_msg) + datalen);
-
-  memset(mesg, 0, sizeof(struct atmlec_msg) + datalen);
-  mesg->type = type;
-
-  if (type == l_config)
-    memcpy(&mesg->content.config, config, sizeof(struct atmlec_config_msg));
-  else if (type == l_should_bridge) {
-      memcpy(mesg->content.proxy.mac_addr, mac_addr, ETH_ALEN);
-      mesg->content.proxy.tran_id = flag;
-      mesg->content.proxy.lec_id = no_source_le_narp; /* cheat with arguments */
-  }
-  else {
-    if (mac_addr)
-      memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN);
-    if (atm_addr)
-      memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
-    mesg->content.normal.flag = flag;
-    mesg->content.normal.targetless_le_arp = targetless_le_arp; /* LANE2 */
-    mesg->content.normal.no_source_le_narp = no_source_le_narp;
-  }
-
-  mesg->sizeoftlvs = datalen;
-  if (datalen > 0)
-    memcpy(mesg + 1, data, datalen);   /* Add the TLVs */
-
-  if (write(lec_socket, mesg, sizeof(struct atmlec_msg) + datalen)<0) {
-    EVENT(EM_SERR,("Write to kernel failed!\n"));
-    free(mesg);
-    return -1;
-  }
-  free(mesg);
-  return 0;  
-}
-
-int 
-kernel_register_callback(atmlec_msg_type type, kernel_callback callback)
-{
-  if (callback_funcs[type])
-    return -1;
-  callback_funcs[type] = callback;
-
-  return 0;
-}
-
-static const char*
-get_mesg_type_str(atmlec_msg_type type)
-{
-  switch(type) {
-  case l_set_mac_addr:
-    return "SET_MAC_ADDR";
-  case l_del_mac_addr:
-    return "DEL_MAC_ADDR";
-  case l_svc_setup:
-    return "SVC_SETUP";
-  case l_arp_xmt:
-    return "ARP_XMT";
-  case l_addr_delete:
-    return "ADDR_DELETE";
-  case l_topology_change:
-    return "TOPOLOGY_CHANGE";
-  case l_flush_complete:
-    return "FLUSH_COMPLETE";
-  case l_arp_update:
-    return "ARP_UPDATE";
-  case l_config:
-    return "CONFIG";
-  case l_associate_req:
-    return "LANE2_ASSOCIATE_REQ";
-  case l_should_bridge:
-    return "SHOULD_BRIDGE";
-  default:
-    return "UNKNOWN MSG TYPE";
-  }
-}
-
-void
-kernel_dispatch_handlers(void)
-{
-  struct atmlec_msg mesg;
-
-  if (read(lec_socket, &mesg, sizeof(mesg))<0) {
-    EVENT(EM_SERR,("Read from kernel socket failed:%s\n",strerror(errno)));
-    return;
-  }
-  EVENT(EM_DEBUG,("Received message %d from kernel: %s, sizeoftlvs=%d\n",
-                  mesg.type, get_mesg_type_str(mesg.type),
-                  mesg.sizeoftlvs));
-  if (callback_funcs[mesg.type]) {
-    callback_funcs[mesg.type](&mesg);
-  } else
-    EVENT(EM_NERR,("No handler for message type:%s\n",
-		   get_mesg_type_str(mesg.type)));  
-}
-
-/*
- * LANE2: LE_ARP frames can now have TLVs with them. Use this after
- * l_arp_xmt message from kernel to read the TLVs that follow.
- */
-int read_from_kernel (char *buff, int size)
-{
-        int retval;
-        
-        retval = read(lec_socket, buff, size);
-        if (retval < 0)
-                EVENT(EM_SERR,("Read for extra data from kernel socket failed:%s\n",strerror(errno)));
-        return retval;
-}
-
-/*
- *
- * $Log: kernel_itf.c,v $
- * Revision 1.9  1996/07/07 11:51:47  carnil
- * Global msg_mask
- *
- * Revision 1.8  1996/06/10 04:27:28  carnil
- * compiler warning fix
- *
- * Revision 1.7  1996/05/29 08:22:39  carnil
- * *** empty log message ***
- *
- * Revision 1.6  1996/05/23 11:50:54  carnil
- * *** empty log message ***
- *
- * Revision 1.5  1996/04/25 19:42:13  carnil
- * Copyright notice
- *
- * Revision 1.4  1996/04/19 06:37:49  carnil
- * l_set_lecid
- *
- * Revision 1.3  1996/03/18 16:43:50  carnil
- * Bug fixes
- *
- * Revision 1.2  1996/03/17 21:23:41  carnil
- * kernel_sendmsg change
- *
- * Revision 1.1  1996/03/15 07:08:09  carnil
- * Initial revision
- *
- *
- */
diff -ur --new-file old/atm/led/kernel_itf.h new/atm/led/kernel_itf.h
--- old/atm/led/kernel_itf.h	Tue Aug 11 16:53:57 1998
+++ new/atm/led/kernel_itf.h	Thu Jan  1 01:00:00 1970
@@ -1,59 +0,0 @@
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-/*
- * Include file for kernel interface
- *
- * $Id: kernel_itf.h,v 1.3 1996/04/25 19:42:13 carnil Exp carnil $
- *
- */
-#ifndef KERNEL_ITF_H
-#define KERNEL_ITF_H
-#include <linux/atmlec.h>
-
-typedef void (*kernel_callback)(struct atmlec_msg *mesg);
-
-int kernel_init(unsigned char *mac_addr, int itf_num);
-int kernel_sendmsg(atmlec_msg_type type, unsigned char *mac_addr,
-		   unsigned char *atm_addr, struct atmlec_config_msg *config,
-		   unsigned long flag, char *data, int datalen,
-                   int targetless_le_arp, int no_source_le_arp);
-int kernel_register_callback(atmlec_msg_type type, kernel_callback callback);
-void kernel_dispatch_handlers(void);
-int read_from_kernel (char *buff, int size);
-
-#endif /* KERNEL_ITF_H */
-/*
- *
- * $Log: kernel_itf.h,v $
- * Revision 1.3  1996/04/25 19:42:13  carnil
- * Copyright notice
- *
- * Revision 1.2  1996/03/17 21:23:41  carnil
- * kernel_sendmsg changed
- *
- * Revision 1.1  1996/03/15 07:08:09  carnil
- * Initial revision
- *
- *
- */
diff -ur --new-file old/atm/led/lane2.h new/atm/led/lane2.h
--- old/atm/led/lane2.h	Tue Aug 11 16:53:57 1998
+++ new/atm/led/lane2.h	Thu Jan  1 01:00:00 1970
@@ -1,8 +0,0 @@
-#ifndef LANE2_H
-#define LANE2_H
-
-extern int lane_version(void); /* returns 1 for LANE v1, 2 for LANE v2 etc */
-#define ADDR_L3 UINT32
-
-#endif /* LANE2_H */
-
diff -ur --new-file old/atm/led/lane_atm.h new/atm/led/lane_atm.h
--- old/atm/led/lane_atm.h	Wed Nov 19 12:59:16 1997
+++ new/atm/led/lane_atm.h	Thu Jan  1 01:00:00 1970
@@ -1,191 +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:
-*   lane_atm.h
-*   
-* Abstract:
-*   This module defines ATM specific types and constants.
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   16-Sep-94  TLR   Created.
-*   31-Oct-94  DMW   Use INT8 instead of UCHAR, add definition for PREFIX.
-*                    Change definition for ADDR_ATM to use basic types and 
-*                    to not have selector be an array.   
-*   10-Jan-95  TLR   Added address copy and compare methods.
-*   08-Sep-95  TLR   Updated QOS definitions and removed buggy atm_is_greater.
-*   17-Oct-97  hessu Changed the filename from atm.h to lane_atm.h
-*
-* Description:
-*   Only ATM specific types should be defined here.
---*/
-#ifndef LANE_ATM_H
-#define LANE_ATM_H
-
-/* General address related definitions. */
-
-typedef UINT8 ADDR_48[6];  /* MAC Address.          */
-typedef UINT8 ESI[6];      /* End System Identifier */
-typedef UINT8 PREFIX[13];  /* Network Prefix.       */
-
-/* Type for ATM Address. */
-
-typedef struct
-   {
-   PREFIX   prefix;  /* Network Prefix set by the switch. */
-   ESI      esi;     /* ESI or MAC Addr                   */
-   UINT8    sel;     /* Selector                          */
-   } ADDR_ATM;
-
-typedef union
-   {
-   struct
-      {
-      UINT8    cpcs_uu;
-      UINT8    clp;
-      } aal5_data;
-   } AAL_DATA;
-
-#define ESI_COPY(from, to) \
-   {                       \
-   (to)[0] = (from)[0];    \
-   (to)[1] = (from)[1];    \
-   (to)[2] = (from)[2];    \
-   (to)[3] = (from)[3];    \
-   (to)[4] = (from)[4];    \
-   (to)[5] = (from)[5];    \
-   }
-
-#define ESI_IS_BCAST(esi)  (((esi)[0] == 0xff) && \
-                            ((esi)[1] == 0xff) && \
-                            ((esi)[2] == 0xff) && \
-                            ((esi)[3] == 0xff) && \
-                            ((esi)[4] == 0xff) && \
-                            ((esi)[5] == 0xff))
-
-#define ATM_COPY(from, to)               \
-	{                                     \
-	(to).prefix[0]  = (from).prefix[0];   \
-	(to).prefix[1]  = (from).prefix[1];   \
-	(to).prefix[2]  = (from).prefix[2];   \
-	(to).prefix[3]  = (from).prefix[3];   \
-	(to).prefix[4]  = (from).prefix[4];   \
-	(to).prefix[5]  = (from).prefix[5];   \
-	(to).prefix[6]  = (from).prefix[6];   \
-	(to).prefix[7]  = (from).prefix[7];   \
-	(to).prefix[8]  = (from).prefix[8];   \
-	(to).prefix[9]  = (from).prefix[9];   \
-	(to).prefix[10] = (from).prefix[10];  \
-	(to).prefix[11] = (from).prefix[11];  \
-	(to).prefix[12] = (from).prefix[12];  \
-	(to).esi[0]     = (from).esi[0];      \
-	(to).esi[1]     = (from).esi[1];      \
-	(to).esi[2]     = (from).esi[2];      \
-	(to).esi[3]     = (from).esi[3];      \
-	(to).esi[4]     = (from).esi[4];      \
-	(to).esi[5]     = (from).esi[5];      \
-	(to).sel        = (from).sel;         \
-	}
-
-#define ATM_COPY_NULL(to)                \
-	{                                     \
-	(to).prefix[0]  = 0;                  \
-	(to).prefix[1]  = 0;                  \
-	(to).prefix[2]  = 0;                  \
-	(to).prefix[3]  = 0;                  \
-	(to).prefix[4]  = 0;                  \
-	(to).prefix[5]  = 0;                  \
-	(to).prefix[6]  = 0;                  \
-	(to).prefix[7]  = 0;                  \
-	(to).prefix[8]  = 0;                  \
-	(to).prefix[9]  = 0;                  \
-	(to).prefix[10] = 0;                  \
-	(to).prefix[11] = 0;                  \
-	(to).prefix[12] = 0;                  \
-	(to).esi[0]     = 0;                  \
-	(to).esi[1]     = 0;                  \
-	(to).esi[2]     = 0;                  \
-	(to).esi[3]     = 0;                  \
-	(to).esi[4]     = 0;                  \
-	(to).esi[5]     = 0;                  \
-	(to).sel        = 0;                  \
-	}
-
-#define ATM_EQUAL(a1, a2) (((a1).sel        == (a2).sel) &&         \
-                           ((a1).esi[5]     == (a2).esi[5]) &&      \
-                           ((a1).esi[4]     == (a2).esi[4]) &&      \
-                           ((a1).esi[3]     == (a2).esi[3]) &&      \
-                           ((a1).esi[2]     == (a2).esi[2]) &&      \
-                           ((a1).esi[1]     == (a2).esi[1]) &&      \
-                           ((a1).esi[0]     == (a2).esi[0]) &&      \
-                           ((a1).prefix[12] == (a2).prefix[12]) &&  \
-                           ((a1).prefix[11] == (a2).prefix[11]) &&  \
-                           ((a1).prefix[10] == (a2).prefix[10]) &&  \
-                           ((a1).prefix[9]  == (a2).prefix[9]) &&   \
-                           ((a1).prefix[8]  == (a2).prefix[8]) &&   \
-                           ((a1).prefix[7]  == (a2).prefix[7]) &&   \
-                           ((a1).prefix[6]  == (a2).prefix[6]) &&   \
-                           ((a1).prefix[5]  == (a2).prefix[5]) &&   \
-                           ((a1).prefix[4]  == (a2).prefix[4]) &&   \
-                           ((a1).prefix[3]  == (a2).prefix[3]) &&   \
-                           ((a1).prefix[2]  == (a2).prefix[2]) &&   \
-                           ((a1).prefix[1]  == (a2).prefix[1]) &&   \
-                           ((a1).prefix[0]  == (a2).prefix[0]))
-
-#define ATM_EQUAL_NULL(a1) (((a1).sel       == 0) &&  \
-									((a1).esi[5]     == 0) &&  \
-									((a1).esi[4]     == 0) &&  \
-									((a1).esi[3]     == 0) &&  \
-									((a1).esi[2]     == 0) &&  \
-									((a1).esi[1]     == 0) &&  \
-									((a1).esi[0]     == 0) &&  \
-									((a1).prefix[12] == 0) &&  \
-									((a1).prefix[11] == 0) &&  \
-									((a1).prefix[10] == 0) &&  \
-									((a1).prefix[9]  == 0) &&  \
-									((a1).prefix[8]  == 0) &&  \
-									((a1).prefix[7]  == 0) &&  \
-									((a1).prefix[6]  == 0) &&  \
-									((a1).prefix[5]  == 0) &&  \
-									((a1).prefix[4]  == 0) &&  \
-									((a1).prefix[3]  == 0) &&  \
-									((a1).prefix[2]  == 0) &&  \
-									((a1).prefix[1]  == 0) &&  \
-									((a1).prefix[0]  == 0))
-
-#endif /* LANE_ATM_H */
diff -ur --new-file old/atm/led/le_disp.c new/atm/led/le_disp.c
--- old/atm/led/le_disp.c	Tue Aug 11 16:53:57 1998
+++ new/atm/led/le_disp.c	Thu Jan  1 01:00:00 1970
@@ -1,307 +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.
- * 
- */
-
-/* le_disp.c
- *
- * LE Frame Parser and Displayer
- *
- */
-#include <stdio.h>
-#include "codes.h"
-#include "g_types.h"
-#include "lane_atm.h"
-#include "system.h"
-#include "g_endian.h"
-#include "af_lane.h"
-#include "le_disp.h"
-#include "svc_info.h"    /* for CONN_INFO */
-
-const char *disp_status_text (UINT16 status)
-   {
-   switch (status)
-      {
-      case 0 :  return "Success";
-      case 1 :  return "Version_Not_Supported";
-      case 2 :  return "Invalid_Parameters";
-      case 4 :  return "Duplicate_LAN_Destination";
-      case 5 :  return "Duplicate_ATM_Address";
-      case 6 :  return "Insufficient_Resources";
-      case 7 :  return "Access_Denied";
-      case 8 :  return "Invalid_Request_ID";
-      case 9 :  return "Invalid_LAN_Destination";
-      case 10 : return "Invalid_ATM_Address";
-      case 20 : return "No_Configuration";
-      case 21 : return "LE_Configuration_Error";
-      case 22 : return "Insufficient_Information";
-      default : return "<Unknown Error Code>";
-      }
-   }
-
-static const char *opcode_text (UINT16 opcode)
-   {
-   switch (opcode)
-      {
-      case 0x0001 : return "LE_CONFIG_REQUEST";
-      case 0x0101 : return "LE_CONFIG_RESPONSE";
-      case 0x0002 : return "LE_JOIN_REQUEST";
-      case 0x0102 : return "LE_JOIN_RESPONSE";
-      case 0x0003 : return "READY_QUERY";
-      case 0x0103 : return "READY_INDICATION";
-      case 0x0004 : return "LE_REGISTER_REQUEST";
-      case 0x0104 : return "LE_REGISTER_RESPONSE";
-      case 0x0005 : return "LE_UNREGISTER_REQUEST";
-      case 0x0105 : return "LE_UNREGISTER_RESPONSE";
-      case 0x0006 : return "LE_ARP_REQUEST";
-      case 0x0106 : return "LE_ARP_RESPONSE";
-      case 0x0007 : return "LE_FLUSH_REQUEST";
-      case 0x0107 : return "LE_FLUSH_RESPONSE";
-      case 0x0008 : return "LE_NARP_REQUEST";
-      case 0x0009 : return "LE_TOPOLOGY_REQUEST";
-      default :     return "<Unknown Opcode>";
-      }
-   }
-
-char *disp_atm_text (ADDR_ATM atm)
-   {
-   static char buffer[100];
-   int         i;
-
-   for (i = 0; i < 100; i++)  buffer[i] = (char) 0;
-
-   sprintf(buffer, "pre:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
-                   " esi:%02x-%02x-%02x-%02x-%02x-%02x sel:%02x",
-           atm.prefix[0],
-           atm.prefix[1],
-           atm.prefix[2],
-           atm.prefix[3],
-           atm.prefix[4],
-           atm.prefix[5],
-           atm.prefix[6],
-           atm.prefix[7],
-           atm.prefix[8],
-           atm.prefix[9],
-           atm.prefix[10],
-           atm.prefix[11],
-           atm.prefix[12],
-           atm.esi[0],
-           atm.esi[1],
-           atm.esi[2],
-           atm.esi[3],
-           atm.esi[4],
-           atm.esi[5],
-           atm.sel);
-
-   return buffer;
-   }
-
-char *disp_esi_text (ESI esi)
-   {
-   static char buffer[100];
-   int         i;
-
-   for (i = 0; i < 100; i++)  buffer[i] = (char) 0;
-
-   sprintf(buffer, "%02x-%02x-%02x-%02x-%02x-%02x",
-           esi[0],
-           esi[1],
-           esi[2],
-           esi[3],
-           esi[4],
-           esi[5]);
-
-   return buffer;
-   }
-
-static void disp_lan_dst (LE_LAN_DST *p_dst)
-   {
-   switch (ntoh16 (p_dst->tag))
-      {
-      case TAG_NOT_PRESENT :
-
-         printf ("<Not Present>\n");
-         break;
-      case TAG_MAC_ADDR :
-
-         printf ("MAC : %s\n", disp_esi_text (p_dst->mac_addr));
-         break;
-      case TAG_ROUTE_DESC :
-
-         printf ("Route Desc: \n");
-         break;
-
-      default:
-         printf ("<Unknown Tag>  Tag=%d\n", ntoh16 (p_dst->tag));
-      }
-   }
-
-static void disp_arp (void *frame, UINT32 length)
-   {
-   LE_ARP_FRAME   *p_arp;
-
-   p_arp = (LE_ARP_FRAME *) frame;
-
-   printf ("    Source LAN Destination : ");
-   disp_lan_dst (&p_arp->src_lan_dst);
-   printf ("    Target LAN Destination : ");
-   disp_lan_dst (&p_arp->target_lan_dst);
-
-   printf ("    Source ATM : %s\n", disp_atm_text (p_arp->src_atm_addr));
-   printf ("    Target ATM : %s\n", disp_atm_text (p_arp->target_atm_addr));
-   }
-
-static void disp_join (void *frame, unsigned long length)
-{
-  LE_JOIN_FRAME *p_frame;
-  
-  p_frame = (LE_JOIN_FRAME *) frame;
-
-  printf ("    Source LAN Destination : ");
-  disp_lan_dst(&p_frame->src_lan_dst);
-  printf ("    Source ATM : %s\n", disp_atm_text (p_frame->src_atm_addr));
-}
-
-static void
-disp_flush(void *frame, unsigned long length)
-{
-  LE_FLUSH_FRAME *p_frame;
-
-  p_frame = (LE_FLUSH_FRAME *)frame;
-  printf ("    Source ATM : %s\n", disp_atm_text (p_frame->src_atm_addr));
-  printf ("    Target ATM : %s\n", disp_atm_text (p_frame->target_atm_addr));
-  
-}
-
-static void 
-disp_control (void *frame, UINT32 length)
-{
-   LE_CTRL_HDR *p_hdr;
-
-   p_hdr = (LE_CTRL_HDR *) frame;
-
-   printf ("          %02x - Protocol\n", p_hdr->protocol);
-   printf ("          %02x - Version\n",  p_hdr->version);
-   printf ("        %04x - OpCode (%s)\n",
-           ntoh16 (p_hdr->op_code),
-           opcode_text (ntoh16 (p_hdr->op_code)));
-   
-   if ((ntoh16 (p_hdr->op_code) & 0x00ff) != READY_QUERY)
-      {
-      printf ("        %04x - Status (%s)\n",
-              ntoh16 (p_hdr->status),
-              disp_status_text (ntoh16 (p_hdr->status)));
-      printf ("    %08lx - Transaction ID\n", ntoh32 (p_hdr->tran_id));
-      printf ("        %04x - Requestor LEC_ID\n", ntoh16 (p_hdr->req_lec_id));
-      printf ("        %04x - Flags\n", ntoh16 (p_hdr->flags));
-      }
-
-   switch (ntoh16 (p_hdr->op_code))
-      {
-      case LE_ARP_RSP :
-      case LE_ARP_REQ :    disp_arp(frame, length);  break;
-      case LE_JOIN_REQ:
-      case LE_JOIN_RSP:
-	disp_join(frame, length);
-	break;
-      case LE_FLUSH_REQ:
-      case LE_FLUSH_RSP:
-	disp_flush(frame, length);
-	break;
-      }
-   }
-
-static void 
-disp_data (void *frame, UINT32 length)
-   {
-   UINT8 *p_data;
-
-   p_data = (UINT8*) frame;
-
-   printf("        %02X-%02X-%02X-%02X-%02X-%02X - Destination Address\n",
-          p_data[2],p_data[3],p_data[4],
-          p_data[5],p_data[6],p_data[7]);
-   printf("        %02X-%02X-%02X-%02X-%02X-%02X - Source Address\n",
-          p_data[8], p_data[9], p_data[10],
-          p_data[11],p_data[12],p_data[13]);
-   }
-
-
-void le_frame_display (void   *frame,
-                       UINT32  length,
-                       const char   *text)
-   {
-   UINT16   *p_hdr;
-
-   p_hdr = (UINT16 *) frame;
-
-   printf ("\nLAN Emulation Frame %s: (%ld bytes)\n\n",
-           text,
-           length);
-   printf ("        %04X - ", ntoh16 (*p_hdr));
-
-   if (ntoh16 (*p_hdr) == LE_CTRL_MARKER)
-      {
-      printf ("Control Frame Marker\n");
-      disp_control (frame, length);
-      return;
-      }
-
-   if (ntoh16 (*p_hdr) < LE_CTRL_MARKER)
-      {
-      printf ("Data Frame\n");
-      disp_data (frame, length);
-      return;
-      }
-
-   printf ("Illegal Frame\n");
-   }
-
-void disp_sockaddr(CONN_INFO *p_conn_info)
-{
-  int i;
-
-  printf("Sas_family:%d\n\tAddress:", p_conn_info->addr.sas_family);
-  for(i=0;i<20;i++) {
-    printf("%2.2x ",p_conn_info->addr.sas_addr.prv[i]);
-  }
-  printf("\nBlli:\n\t");
-  printf("l2_proto:%d\n\t",p_conn_info->blli.l2_proto);
-  fflush(stdout);
-  printf("l3_proto:%d\n\t\t",p_conn_info->blli.l3_proto);
-  fflush(stdout);
-  printf("ipi:%x\tsnap:",p_conn_info->blli.l3.tr9577.ipi);
-  fflush(stdout);
-  for(i=0;i<5;i++) {
-    printf("%2.2x ",p_conn_info->blli.l3.tr9577.snap[i]);
-  }
-  printf("\n");
-}
diff -ur --new-file old/atm/led/le_disp.h new/atm/led/le_disp.h
--- old/atm/led/le_disp.h	Sat Jun  6 02:47:10 1998
+++ new/atm/led/le_disp.h	Thu Jan  1 01:00:00 1970
@@ -1,52 +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.
- * 
- */
-
-/* le_disp.h
- *
- * LE Frame Parser and Displayer
- *
- */
-#include <atm.h>
-#include "svc_info.h"
-
-const char *disp_status_text (UINT16 status);
-
-char *disp_atm_text (ADDR_ATM addr);
-
-char *disp_esi_text (ESI esi);
-
-void le_frame_display (void   *frame,
-                       UINT32  length,
-                       const char   *text);
-
-void disp_sockaddr(CONN_INFO *p_conn_info);
diff -ur --new-file old/atm/led/lec.h new/atm/led/lec.h
--- old/atm/led/lec.h	Tue Aug 11 16:53:57 1998
+++ new/atm/led/lec.h	Wed Jun  2 23:36:54 1999
@@ -1,269 +1,68 @@
-/*************************************************************************
-  (c) Copyright.  Digital Equipment Corporation, 1995.  All Rights
-  Reserved.
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
 
-  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.h
-*   
-* Overview:
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   13-Dec-94  TLR   Created.
-*    3-Jan-95  TLR   Updated based on changes to Connection Manager interface.
-*   10-Jan-95  TLR   Updated based on team review.
-*   10-May-95  TLR   Added Support for Event Logging.
-*   27-Jun-95  TLR   Added LEC Management Features.
-*
-* Dependencies:
-*   types.h    - Generally used type definitions.
-*   codes.h    - Completion codes.
-*   lane_atm.h - ATM specific definitions and types.
-*
-*/
-
-/*************************************************************************
- * Types that are specific to this interface.                            *
- *************************************************************************/
-
-/* LEC_EVENT
- *
- *   This enumerated type describes the possible events that the LEC reports
- *   to the registered LEC user.
- *
- *   LEC_NETWORK_AVAILABLE......The LEC has just successfully completed the
- *                              join process and is ready to provide
- *                              communication services with the newly
- *                              connected Emulated LAN.
- *
- *   LEC_NETWORK_UNAVAILABLE....The LEC has just detected a network error
- *                              that is severe enough to cause membership in
- *                              the ELAN to be dropped.  This is either due to
- *                              loss of a critical control connection or loss
- *                              of the ATM link to the adjacent switch.  In
- *                              either case, the LEC has begun to attempt to
- *                              rejoin the ELAN with the parameters supplied by
- *                              the registered user during registration.
- */
 #ifndef LEC_H
 #define LEC_H
-#include "lane_atm.h"
 
-typedef enum
-   {
-   LEC_NETWORK_AVAILABLE,
-   LEC_NETWORK_UNAVAILABLE
-   } LEC_EVENT;
+#include "conn.h"
 
-/* LAN_TYPE
- *
- *   This type enumerates the supported Emulated LAN types.  With the
- *   exception of LAN_FDDI, these are derived directly from the ATM Forum
- *   specification.
- *
- *   LAN_802_3......ATM Forum standard 802.3/ethernet LAN type.
- *
- *   LAN_802_5......ATM Forum standard 802.5/token ring LAN type.
- *
- *   LAN_FDDI.......Non-ATM Forum standard FDDI LAN type.  This is a possible
- *                  Digital value added frame type
- */
-typedef enum
-   {
-   LAN_802_3,
-   LAN_802_5,
-   LAN_FDDI
-   } LAN_TYPE;
-
-/* LAN_MTU
- *
- *   This enumerated type is used to request a maximum frame size when joining
- *   an emulated LAN.  These values are derived from the ATM Forum
- *   specification.
- *
- *   MTU_UNSPEC.....Unspecified maximum.  Will be assigned by the LES.
- *
- *   MTU_1516.......MTU for ethernet frame sizes.
- *
- *   MTU_4544.......MTU for FDDI frame sizes.
- *
- *   MTU_9234.......MTU for RFC1577 (Classical-IP) frame sizes.
- *
- *   MTU_18190......MTU for Token Ring frame sizes.
- */
-typedef enum
-   {
-   MTU_UNSPEC,
-   MTU_1516,
-   MTU_4544,
-   MTU_9234,
-   MTU_18190,
-   MTU_1580
-   } LAN_MTU;
-
-/* INIT_METHOD
- *
- *   This type is used to indicate to an instance of the LEC how it is to
- *   join an ELAN.
- *
- *   INIT_NORMAL...........Normal mode of initialization.  In this case, the
- *                         LEC first attempts to determine the LECS ATM address
- *                         via ILMI.  If it is unable to do so, it will try the
- *                         well-known LECS ATM address, and then the LECS PVC.
- *
- *   INIT_MANUAL_LECS......Use a manually entered LECS address.  If
- *                         configuration fails using this address, the LEC will
- *                         next attempt to use the well-known LECS address.
- *
- *   INIT_WELL_KNOWN_LECS..Use the well-known LECS address.  If configuration
- *                         fails using this address, try the LECS PVC.
- *
- *   INIT_LECS_PVC.........Use the LECS PVC for configuration.
- *
- *   INIT_MANUAL_LES.......Skip the configuration phase altogether and directly
- *                         contact the LES using the manually entered ATM
- *                         address.
+/*
+ * LANE client configuration and operation values.
+ * These are in host byte order since there are
+ * some values coming from network and some values
+ * which are used by the host only
  */
-typedef enum
-   {
-   INIT_NORMAL,
-   INIT_MANUAL_LECS,
-   INIT_WELL_KNOWN_LECS,
-   INIT_LECS_PVC,
-   INIT_MANUAL_LES
-   } INIT_METHOD;
-
-/*++
-* ========================
-* = (LEC_EVENT_CALLBACK) =
-* ========================
-*
-* Overview:
-*   Notifies the registered user of an important event that has taken place
-*   within the LEC.
-*
-* Arguments:
-*   context     - (IN) Context value provided at registration time.
-*   event       - (IN) Indication of the event that took place.
-*   mtu         - (IN) LAN MTU negotiated during the join.
-*   p_elan_name - (IN) Name of ELAN that was joined (if event is
-*                      "NETWORK_AVAILABLE").
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-
-typedef void (*LEC_EVENT_CALLBACK) (HANDLE      context,
-                                    LEC_EVENT   event,
-                                    LAN_MTU     mtu,
-                                    char       *p_elan_name);
-
-
-/*++
-* ======================
-* = (LEC_RCV_CALLBACK) =
-* ======================
-*
-* Overview:
-*   Callback that is called when a packet is received on the emulated LAN.
-*   A pointer to this routine is supplied at registration time by the user.
-*   Note that this callback will not be invoked for packets that were received
-*   but filtered by one of the receive packet filters.
-*
-* Arguments:
-*   context     - (IN) Context value supplied at registration time.
-*   length      - (IN) Length of the packet in bytes.
-*   pp_pkt      - (IO) Pointer to a pointer to the received packet structure.
-*                      The returned value of this pointer refers to a buffer
-*                      that may be freed by the lower driver.  If the received
-*                      packet was copied, the pointer may be returned
-*                      unchanged.  If a fresh buffer is to replace the
-*                      received one, a pointer to the fresh buffer must be
-*                      returned.  If there are no free buffers, a NULL pointer
-*                      must be returned.
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
-*
---*/
-typedef void (*LEC_RCV_CALLBACK) (HANDLE  context,
-                                  UINT32  length,
-                                  void  **pp_pkt);
-
-
-/*++
-* ===========================
-* = (LEC_XMT_DONE_CALLBACK) =
-* ===========================
-*
-* Overview:
-*   Callback for completed transmissions.  This call returns the context of
-*   the registered user and the actual transmitted buffer that may now be
-*   freed because the contents of the buffer were copied (via DMA or some
-*   such mechanism).
-*
-* Arguments:
-*   context     - (IN) Context value supplied at registration time.
-*   p_pkt       - (IN) Pointer to the transmitted packet.
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   The packet stored in the buffer is a packet that was previously
-*   transmitted by this registered client.
-*
-* Postconditions:
-*   None
-*
---*/
-typedef void (*LEC_XMT_DONE_CALLBACK) (HANDLE  context,
-                                       void   *p_packet);
-
+struct lec_params {
+        unsigned char c1n_my_atm_addr[ATM_ESA_LEN];
+        uint8_t  c2_lan_type;
+        uint8_t  c3_max_frame_size;
+        int      c4_proxy_flag;
+        char     c5_elan_name[32 + 1];
+        char     c6_mac_addr[ETH_ALEN];
+        int      c7_ctrl_timeout;
+        int      c7i_initial_ctrl_timeout;
+        int      c7x_timeout_multiplier;
+        int      c7c_current_timeout; /* sum of c7i and c7x, LANEv2 5.3.1.7 */
+        unsigned char c9_les_atm_addr[ATM_ESA_LEN];
+        int      c10_max_unknown_frames;
+        int      c11_max_unknown_frame_time;
+        int      c12_vcc_timeout;
+        int      c13_max_retry_count;
+        uint16_t c14_lec_id;
+        int      c17_aging_time;
+        int      c18_forward_delay_time;
+        int      c19_topology_change;
+        int      c20_le_arp_response_time;
+        int      c21_flush_timeout;
+        int      c22_path_switching_delay;
+        /* LANE2 variables follow */
+        int      c29_v2_capable;
+        uint32_t c31_elan_id;
+        unsigned char c35_preferred_les[ATM_ESA_LEN];
+        int      c35_contains_address;
+        int      c37_min_reconfig_delay; /* milliseconds */
+        int      c38_max_reconfig_delay; /* milliseconds */
+
+        /* other stuff */
+        int  itf_num;    /* 1 for lec1 and so forth */
+        int  sizeoftlvs; /* total size of TLVs associated with this LEC */
+        int  num_tlvs;   /* number of the TLVs */
+        unsigned char *tlvs; /* the TLVs */
+        char foreId[255];
+
+        /* connections to and from LES/BUS plus listen sockets */
+        Conn_t *kernel;
+        Conn_t *ctrl_direct;
+        Conn_t *ctrl_listen; /* Closed when join phase is over */
+        Conn_t *ctrl_dist;
+        Conn_t *mcast_send;  /* LANEv2 calls this Default Mcast Send VCC */
+        Conn_t *mcast_listen;
+        Conn_t *data_listen;
+};
+
+extern struct lec_params lec_params;
+
+#define LAN_TYPE_UNSPEC 0x00 /* Implies Ethernet/IEEE 802.3 */
+#define LAN_TYPE_8023   0x01 /* IEEE 802.3 */
+#define LAN_TYPE_8025   0x02 /* IEEE 802.5 */
 
 #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	Tue Feb  9 17:12:01 1999
+++ new/atm/led/lec_arp.c	Thu Jan  1 01:00:00 1970
@@ -1,374 +0,0 @@
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-/*
- * Lec arp cache daemon part
- *
- * $Id: lec_arp.c,v 1.13 1996/08/06 14:14:11 carnil Exp carnil $
- *
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <atm.h>
-#include <linux/atmlec.h>
-
-/* Include General Headers. */
-
-#include "g_types.h"    /* General Purpose Types      */
-#include "codes.h"      /* Return Status Codes        */
-#include "lane_atm.h"   /* ATM Specific Definitions   */
-#include "utl.h"        /* General Purpose Utilities  */
-#include "utl_os.h"     /* Operating System Utilities */
-#include "system.h"
-#include "g_event.h"
-
-#include "af_lane.h"
-#include "cm.h"
-#include "svc_info.h"
-#include "lec.h"
-#include "lec_arp.h"
-
-#include "kernel_itf.h"
-#include "conn.h"
-
-#define EMOD   MOD_LEC_ARP
-#define EINST  "lec_arp.c"
-#include "emask.h"
-
-typedef struct _elan {
-  struct _elan  *p_next;
-  char *p_text;
-  HANDLE la_handle;
-  HANDLE lc_elan_handle;
-  HANDLE lport_handle;
-  BOOLEAN configured;
-} LA_ELAN_CONTEXT;
-
-SIMPLE_LIST (LA_ELAN_CONTEXT, LA_ELAN_LIST);
-
-typedef struct {
-  HANDLE               lc_handle;
-  HANDLE               vc_list;
-  HANDLE               atm_list;
-  ARP_XMT_CALLBACK     arp_xmt_callback;
-  FLUSH_XMT_CALLBACK   flush_xmt_callback;
-  SVC_SETUP_CALLBACK   svc_setup_callback;
-  void                 (*associate_req_callback) (HANDLE lc_elan_handle,
-                                                  int sizeoftlvs); /* LANE2 */
-  void                 (*proxy_arp_rsp_callback) (HANDLE lc_elan_handle,
-                                                  UINT8 *mac_addr, UINT32 tran_id,
-                                                  UINT16 lec_id, UINT8 *atm_addr);
-  void                (*topo_req_xmt_callback)(HANDLE lc_elan_handle, UINT32 flag);
-  LA_ELAN_LIST         elan_list;
-} LA_CONTEXT;
-
-static LA_CONTEXT lec_arp_context;
-
-/*
- * LE_ARP request from kernel
- * LANE2: LE_ARP frames can now contain variable size TLVs
- */
-static void
-kernel_arp_xmt_callback(struct atmlec_msg *mesg)
-{
-  LA_ELAN_CONTEXT *p_elan;
-  ESI *to_pass;
-
-  if (mesg->content.normal.targetless_le_arp)
-    to_pass = NULL;
-  else
-    to_pass = (ESI*)mesg->content.normal.mac_addr;
-
-  utl_list_traverse(lec_arp_context.elan_list, p_elan) {
-    lec_arp_context.arp_xmt_callback(p_elan->lc_elan_handle,
-                                     *to_pass, mesg->sizeoftlvs);
-  }
-}
-
-void
-kernel_flush_xmt(unsigned char *to_pass)
-{
-  LA_ELAN_CONTEXT *p_elan;
-  UINT32 dumb;
-
-  utl_list_traverse(lec_arp_context.elan_list, p_elan) {
-    lec_arp_context.flush_xmt_callback(p_elan->lc_elan_handle, to_pass,&dumb);
-    EVENT(EM_DEBUG,("Setting flush transaction id to %lx\n",dumb));
-    kernel_sendmsg(l_flush_tran_id, NULL, to_pass,
-		   NULL, dumb, NULL, 0, 0, 0);
-  }
-}
-
-static void
-kernel_svc_setup_xmt_callback(struct atmlec_msg *mesg)
-{
-  LA_ELAN_CONTEXT *p_elan;
-  ADDR_ATM *to_pass;
-
-  to_pass = (ADDR_ATM*)mesg->content.normal.atm_addr;
-
-  utl_list_traverse(lec_arp_context.elan_list, p_elan) {
-    lec_arp_context.svc_setup_callback(p_elan->lc_elan_handle, *to_pass);
-  }
-}
-
-/* LANE2: LE_ASSOCIATE.request */
-static void
-kernel_associate_req_callback(struct atmlec_msg *mesg)
-{
-  LA_ELAN_CONTEXT *p_elan;
-
-  utl_list_traverse(lec_arp_context.elan_list, p_elan) {
-    lec_arp_context.associate_req_callback(p_elan->lc_elan_handle, mesg->sizeoftlvs);
-  }
-}
-
-static void
-kernel_proxy_arp_rsp_callback(struct atmlec_msg *mesg)
-{
-  LA_ELAN_CONTEXT *p_elan;
-
-  utl_list_traverse(lec_arp_context.elan_list, p_elan) {
-    lec_arp_context.proxy_arp_rsp_callback(p_elan->lc_elan_handle,
-                                           mesg->content.proxy.mac_addr,
-                                           mesg->content.proxy.tran_id,
-                                           mesg->content.proxy.lec_id,
-                                           mesg->content.proxy.atm_addr);
-  }
-}
-
-static void
-kernel_topo_req_xmt_callback(struct atmlec_msg *mesg)
-{
-  LA_ELAN_CONTEXT *p_elan;
-
-  utl_list_traverse(lec_arp_context.elan_list, p_elan) {
-    lec_arp_context.topo_req_xmt_callback(p_elan->lc_elan_handle,
-                                           mesg->content.normal.flag);
-  }
-}
-
-STATUS 
-la_create (HANDLE lc_handle, ARP_XMT_CALLBACK arp_xmt_callback,
-	   FLUSH_XMT_CALLBACK flush_xmt_callback,
-	   SVC_SETUP_CALLBACK svc_setup_callback,
-           void (*associate_req_callback)(HANDLE lc_elan_handle, int sizeoftlvs), /* LANE2 */
-           void (*proxy_arp_rsp_callback)(HANDLE lc_elan_handle, UINT8 *mac_addr,
-                                          UINT32 tran_id, UINT16 lec_id, UINT8 *atm_addr),
-           void (*topo_req_xmt_callback)(HANDLE lc_elan_handle, UINT32 flag),
-	   HANDLE *p_la_handle)
-{
-  lec_arp_context.lc_handle = lc_handle;
-  lec_arp_context.arp_xmt_callback    = arp_xmt_callback;
-  lec_arp_context.flush_xmt_callback  = flush_xmt_callback;
-  lec_arp_context.svc_setup_callback  = svc_setup_callback;
-  lec_arp_context.associate_req_callback = associate_req_callback; /* LANE2 */
-  lec_arp_context.proxy_arp_rsp_callback = proxy_arp_rsp_callback;
-  lec_arp_context.topo_req_xmt_callback = topo_req_xmt_callback;
-  
-  utl_list_init(lec_arp_context.elan_list);
-
-  kernel_register_callback(l_arp_xmt, kernel_arp_xmt_callback);
-  kernel_register_callback(l_svc_setup, kernel_svc_setup_xmt_callback);
-  kernel_register_callback(l_associate_req, kernel_associate_req_callback);
-  kernel_register_callback(l_should_bridge, kernel_proxy_arp_rsp_callback);
-  kernel_register_callback(l_topology_change, kernel_topo_req_xmt_callback);
-
-  *p_la_handle = (HANDLE)&lec_arp_context;
-
-  return STATUS_K_SUCCESS;
-}
-
-void 
-la_destroy(HANDLE la_handle)
-{
-  LA_CONTEXT *context;
-  LA_ELAN_CONTEXT *elan;
-
-  context = (LA_CONTEXT *)la_handle;
-  utl_list_traverse (context->elan_list, elan) {
-    la_deregister((HANDLE)elan);
-  }
-}
-
-STATUS 
-la_register(HANDLE la_handle, HANDLE lc_elan_handle,
-	    HANDLE lport_handle, char *p_text,
-	    HANDLE *p_la_elan_handle)
-{
-  LA_CONTEXT        *p_context;
-  LA_ELAN_CONTEXT   *p_elan;
-  
-  /* Obtain a pointer to the LA Context block. */
-  
-  p_context = (LA_CONTEXT *) la_handle;
-
-  /* Allocate space for the LA_ELAN context block.  If there is a problem,
-   * return error status.
-   */
-  p_elan = (LA_ELAN_CONTEXT *) mem_alloc(EINST, sizeof(LA_ELAN_CONTEXT));
-  if (p_elan == NULL)
-    return STATUS_K_RESOURCES;
-  
-  /* Initialize the fields of the LA_ELAN context block.  Mark the ELAN as
-   * unconfigured.
-   */
-  p_elan->la_handle      = la_handle;
-  p_elan->lc_elan_handle = lc_elan_handle;
-  p_elan->lport_handle   = lport_handle;
-  p_elan->configured     = FALSE;
-  p_elan->p_text         = p_text;
-
-  utl_list_add (p_context->elan_list, p_elan);
-  
-  *p_la_elan_handle = (HANDLE) p_elan;
-  return STATUS_K_SUCCESS;
-}
-
-void 
-la_deregister(HANDLE la_elan_handle)
-{
-  LA_CONTEXT        *p_context;
-  LA_ELAN_CONTEXT   *p_elan;
-
-  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_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,
-	  UINT16 max_retry_count, UINT32 aging_time,
-	  UINT16 forward_delay_time, UINT16 le_arp_response_time,
-	  UINT16 flush_timeout, UINT16 path_switching_delay,
-          unsigned int lane_version_number)
-{
-  LA_ELAN_CONTEXT   *p_elan;
-  struct atmlec_config_msg conf_mesg;
-
-  p_elan = (LA_ELAN_CONTEXT *) la_elan_handle;
-
-  p_elan->configured               = TRUE;
-  conf_mesg.maximum_unknown_frame_count = max_unknown_frame_count;
-  conf_mesg.max_unknown_frame_time = max_unknown_frame_time;
-  conf_mesg.max_retry_count = max_retry_count;
-  conf_mesg.aging_time = aging_time;
-  conf_mesg.forward_delay_time = forward_delay_time;
-  conf_mesg.arp_response_time = le_arp_response_time;
-  conf_mesg.flush_timeout = flush_timeout;
-  conf_mesg.path_switching_delay = path_switching_delay;
-  conf_mesg.lane_version = lane_version_number; /* LANE2 */
-  conf_mesg.is_proxy = (proxy_flag == TRUE) ? 1 : 0;
-  kernel_sendmsg(l_config, NULL, NULL, &conf_mesg, 0, NULL, 0, 0, 0);
-}
-
-STATUS 
-la_addr_delete(HANDLE la_elan_handle,
-	       unsigned char *atm_addr,
-	       BOOLEAN permanent)
-{
-  kernel_sendmsg(l_addr_delete, NULL, atm_addr, NULL,
-		  permanent==TRUE?1:0, NULL, 0, 0, 0);
-  return STATUS_K_SUCCESS;
-}
-
-/*
- * LANE2: tlv_list passing added
- *
- */
-void 
-la_arp_update(HANDLE       la_elan_handle,
-	      ESI          esi,
-	      ADDR_ATM     addr_atm,
-	      BOOLEAN      remote_flag,
-              char         *tlv_list,
-              int          sizeoftlvs,
-              int          targetless_le_arp,
-              int          no_source_le_narp)
-{
-  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,
-                 tlv_list, sizeoftlvs, targetless_le_arp, no_source_le_narp);
-}
-
-void 
-la_flush_complete(HANDLE la_elan_handle,
-		  UINT32   tran_id)
-{
-  EVENT(EM_DEBUG,("Flush complete for tran_id %lx\n", tran_id));
-  kernel_sendmsg(l_flush_complete, NULL,
-		 NULL, NULL, tran_id, NULL, 0, 0, 0);
-}
-
-void 
-la_topology_change_set(HANDLE  la_elan_handle,
-		       BOOLEAN topology_change_flag)
-{
-  kernel_sendmsg(l_topology_change, NULL, NULL, NULL,
-		 topology_change_flag==TRUE?1:0,
-                 NULL, 0, 0, 0);
-}
-
-
-/*
- *
- * $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
- *
- * Revision 1.11  1996/06/10 04:27:28  carnil
- * Unused funcs removed, compiler warning fix
- *
- * Revision 1.10  1996/04/25 19:42:13  carnil
- * Copyright notice
- *
- * Revision 1.9  1996/04/20 16:24:47  carnil
- * conn_convert removed
- *
- * Revision 1.8  1996/04/19 06:37:49  carnil
- * Kernel mesg bug fixes
- *
- * Revision 1.7  1996/03/18 16:43:50  carnil
- * Bug fixes
- *
- * Revision 1.6  1996/03/17 21:23:41  carnil
- * callbacks from kernel, transaction id
- *
- * Revision 1.5  1996/03/15 07:08:09  carnil
- * Converted to use kernel table
- *
- *
- */
diff -ur --new-file old/atm/led/lec_arp.h new/atm/led/lec_arp.h
--- old/atm/led/lec_arp.h	Tue Feb  9 17:12:01 1999
+++ new/atm/led/lec_arp.h	Thu Jan  1 01:00:00 1970
@@ -1,616 +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_arp.h
-*   
-* Overview:
-*   This file specifies the interface to the LE-ARP cache module (implemented
-*   in lec_arp.c).
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*    2-Feb-95  TLR   Created.
-*
-* Description:
-*   The LE-ARP cache module maintains the relationships between MAC addresses
-*   and VCCs.  It shares the ATM address list and VC list owned by the
-*   Connection Manager.  This module performs the following tasks:
-*
-*       1.  Resolves MAC addresses to VCCs for every transmitted data frame.
-*
-*       2.  Performs the two-tiered ARP refresh algorithm specified in the
-*           ATM Forum Specification.
-*
-*       3.  Keeps track of data frames flooded and limits the rate based on
-*           ATM Forum parameters C10 and C11.
-*
-*       4.  Drives the Flush protocol when data path switching takes place.
-*
-*   Note that this module does not deal with frame formats or data transmission
-*   or reception.  It uses the services of the LEC_CTRL module for these.
-*
-* Call Sequence Requirements:
-*
-*   The following diagram depicts the call sequence constraints:  Functions
-*   with lesser indentation must be called before function with greater
-*   indentation.
-*
-*   - la_create
-*     - la_register
-*       - la_config
-*         - la_arp_resolve
-*         - la_addr_delete
-*         - la_arp_update
-*         - la_flush_complete
-*         - la_topology_change_set
-*         - la_vc_added
-*         - la_vc_deleted
-*       - la_deregister
-*     - la_destroy
-*
-* Example Usage Scenario:
-*
-*   la_create...............This call is made as a result of the creation of
-*                           the LAN Emulation Client super-component.
-*                           la_create is called by lc_create.
-*
-*   la_register.............When a protocol registers with the LEC and requests
-*                           that an ELAN be joined, this call results.  A new
-*                           LE-ARP cache instance is allocated and initialized
-*                           to contain no entries.
-*
-*   la_config...............This call is used to configure the LE-ARP cache
-*                           with parameters needed to operate.  This call is
-*                           made once the configuration phase of the join is
-*                           complete and the parameters are known.
-*
-*   la_arp_resolve..........This is called each time a transmit data packet is
-*                           sent by the protocol.  In this case, the
-*                           destination MAC address is not in the LE-ARP cache
-*                           so a new entry is created and the cache begins to
-*                           attempt to resolve the address to a VC.
-*
-*   (arp_xmt_callback)......Still in the context of the above call, the cache
-*                           uses this callback to request the transmission of
-*                           an LE-ARP request frame.
-*
-*   la_arp_resolve..........This call is for the second data packet to the same
-*                           MAC address destination.  This time, the cache
-*                           finds an entry with the MAC address but since the
-*                           resolution to a VC is not complete, the packet must
-*                           be either flooded or discarded depending on how
-*                           many packets have been flooded recently.
-*
-*   la_arp_update...........The network has responded to the LE-ARP request
-*                           with an LE-ARP response.  The cache now knows the
-*                           mapping from the MAC address to the ATM address.
-*
-*   (svc_setup_callback)....Still in the context of the above call, the cache
-*                           finds that there is no SVC associated with the
-*                           ATM address in the new mapping so it uses this
-*                           callback to request that a VC be set up.
-*
-*   la_vc_added.............When the new SVC is finally set up, the LEC_CTRL
-*                           module uses this call to notify the LE-ARP cache.
-*                           The MAC address entry is now associated with a
-*                           data-direct VCC.
-*
-*   (flush_xmt_callback)....Still in the context of the above call, the cache
-*                           uses this callback to request the transmission of
-*                           a flush request on the broadcast channel.
-*
-*   la_arp_resolve..........The next packet to the same MAC address is being
-*                           resolved.  Since the fluch protocol is in process,
-*                           this packet must be discarded.  The return value
-*                           of this call indicates MUST_DISCARD.
-*
-*   la_flush_complete.......The flush protocol is complete because a flush
-*                           response has been received for the MAC address.
-*                           The cache updates the entry to allow data-direct
-*                           transmission.
-*
-*   la_arp_resolve..........The next packet is finally resolved to an open
-*                           data-direct VCC.
-*
-*   la_deregister...........This call is made when the ELAN is unjoined by the
-*                           protocol.
-*
-*   la_destroy..............This call destroys the instance of the LE-ARP
-*                           cache.
-*/
-
-/*************************************************************************
- * Types that are specific to this interface.                            *
- *************************************************************************/
-
-/* XMT_ACTION
- *  This type enumerates the actions that may be indicated by the arp_resolve
- *  function.
- *
- *  XMT_DISCARD.........The packet must be discarded.  This occurs when there
- *                      is no data-direct VCC and the max unknown frame count
- *                      has been exceeded or the flush protocol is in process.
- *
- *  XMT_FLOOD...........The packet may be flooded on the broadcast channel.
- *
- *  XMT_FORWARD.........The packet may be forwarded on the data-direct VCC.
- */
-typedef enum
-   {
-   XMT_DISCARD,
-   XMT_FLOOD,
-   XMT_FORWARD
-   } XMT_ACTION;
-
-
-/*************************************************************************
- * Definition of Interface that is used by the LEC_CTRL module
- *************************************************************************/
-
-
-/*++
-* ====================
-* = ARP_XMT_CALLBACK =
-* ====================
-*
-* Overview:
-*   Callback to the LEC_CTRL client.  Requests that an LE-ARP be sent on 
-*   the network.
-*
-* Arguments:
-*   lc_elan_handle  - (IN)  Handle of LEC CTRL instance to be used.
-*   esi             - (IN)  48-bit address for LE-ARP.
-*   sizeoftlvs      - (IN)  LANE2: total length of TLVs to send
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
-*
---*/
-typedef void (*ARP_XMT_CALLBACK) (HANDLE    lc_elan_handle,
-                                  ESI       esi,
-                                  int sizeoftlvs);
-
-/*++
-* ======================
-* = FLUSH_XMT_CALLBACK =
-* ======================
-*
-* Overview:
-*   Callback to the LEC_CTRL client.  Requests that a flush request be sent
-*   on the network for the specified MAC address.
-*
-* Arguments:
-*   lc_elan_handle  - (IN)  Handle of LEC_CTRL instance to be used.
-*   addr_atm        - (IN)  ATM address for the flush.
-*   esi_handle      - (IN)  Handle of the ESI record for the ESI being flushed.
-*                           This value is passed in the transaction_id field
-*                           of the flush request packet.
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
-*
---*/
-typedef void (*FLUSH_XMT_CALLBACK) (HANDLE    lc_elan_handle,
-                                    unsigned char*  addr_atm,
-                                    HANDLE    esi_handle);
-
-/*++
-* ======================
-* = SVC_SETUP_CALLBACK =
-* ======================
-*
-* Overview:
-*   Callback to the LEC_CTRL client.  Requests that a data-direct SVC be set up
-*   to the indicated ATM address.
-*
-* Arguments:
-*   lc_elan_handle  - (IN)  Handle of LEC_CTRL instance to be used.
-*   addr_atm        - (IN)  Callee ATM address for the setup.
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
-*
---*/
-typedef void (*SVC_SETUP_CALLBACK) (HANDLE   lc_elan_handle,
-                                    ADDR_ATM addr_atm);
-
-
-
-/*++
-* =============
-* = la_create =
-* =============
-*
-* Overview:
-*   Creates an instance of the LEC ARP-Cache.  This create is done once for
-*   each physical interface that is supported by the LEC.  Subsequent calls
-*   to la_register are required for each ELAN instance.
-*
-* Arguments:
-*   os_handle           - (IN)  OS Handle to be used for memory and timer
-*                               alloctaion.
-*
-*   lc_handle           - (IN)  Handle of the LEC_CTRL instance that creates
-*                               this ARP instance.
-*
-*   cm_handle           - (IN)  Handle of the associated CM instance.
-*
-*   arp_xmt_callback    - (IN)  Callback routine for ARP transmits.
-*
-*   flush_xmt_callback  - (IN)  Callback routine for Flush transmits.
-*
-*   svc_setup_callback  - (IN)  Callback for data-direct SVC setups.
-*
-*   p_la_handle         - (OUT) Handle of the created ARP instance.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Successful Completion, see postconditions.
-*   STATUS_K_RESOURCES  - Insufficient resources available to complete the
-*                         operation.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The p_la_handle is valid.
---*/
-STATUS la_create (HANDLE              lc_handle,
-                  ARP_XMT_CALLBACK    arp_xmt_callback,
-                  FLUSH_XMT_CALLBACK  flush_xmt_callback,
-                  SVC_SETUP_CALLBACK  svc_setup_callback,
-                  void                (*associate_req_callback)(HANDLE lc_elan_handle,
-                                                                int sizeoftlvs),  /* LANE2 */
-                  void                (*proxy_arp_rsp_callback)(HANDLE lc_elan_handle,
-                                                                UINT8 *mac_addr,
-                                                                UINT32 tran_id,
-                                                                UINT16 lec_id,
-                                                                UINT8 *atm_addr),
-                  void                (*topo_req_xmt_callback)(HANDLE lc_elan_handle,
-                                                               UINT32 flag),
-                  HANDLE              *p_la_handle);
-
-/*++
-* ==============
-* = la_destroy =
-* ==============
-*
-* Overview:
-*   Destroys an instance of the ARP module.
-*
-* Arguments:
-*   la_handle   - (IN) Handle returned by la_create.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   The la_handle is valid.
-*
-* Postconditions:
-*   The la_handle is invalid.
---*/
-void la_destroy (HANDLE  la_handle);
-
-/*++
-* ===============
-* = la_register =
-* ===============
-*
-* Overview:
-*   Registers an ELAN instance of the ARP module.  This routine is called
-*   by the LEC_CTRL module for each ELAN instance of the LEC.  It creates an
-*   instance of the LE-ARP cache to be used to support a single ELAN
-*   membership.
-*
-* Arguments:
-*   la_handle           - (IN)  Handle returned by la_create.
-*   lc_elan_handle      - (IN)  Handle of associated lc_elan instance.
-*   lport_handle        - (IN)  Logical Port handle for calls to proxy fast
-*                               path.
-*   p_text              - (IN)  Textual description for event logging.
-*   p_la_elan_handle    - (OUT) Handle that represents this LE-ARP cache
-*                               instance.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Successful Completion, see postconditions.
-*   STATUS_K_RESOURCES  - Insufficient resources available to complete the
-*                         operation.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The p_la_elan_handle is valid and ready for configuration.
---*/
-STATUS la_register (HANDLE    la_handle,
-                    HANDLE    lc_elan_handle,
-                    HANDLE    lport_handle,
-                    char     *p_text,
-                    HANDLE   *p_la_elan_handle);
-
-/*++
-* =================
-* = la_deregister =
-* =================
-*
-* Overview:
-*   Deletes a single LE-ARP cache entry.  This is called when membership in
-*   an ELAN is to be cancelled by request of higher layers.
-*
-* Arguments:
-*   la_elan_handle  - (IN) Handle returned by la_register.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   The la_elan_handle is valid.
-*
-* Postconditions:
-*   The la_elan_handle is not valid.
---*/
-void la_deregister (HANDLE la_elan_handle);
-
-/*++
-* =============
-* = la_config =
-* =============
-*
-* Overview:
-*   Configure the LE-ARP cache with the required operating parameters.
-*   This may be used repeatedly to change the operating parameters.  An example
-*   of when this might happen is if connection to a LES is lost and the rejoin
-*   operation results in a connection to a LES with different parameters.
-*
-* Arguments: (The C* specifications are from the ATM Forum LAN Emulation
-*             Specification V1.0).
-*
-*   la_elan_handle          - (IN) Handle returned by la_register.
-*   lan_type                - (IN) C2  - Lan Type for this ELAN.
-*   proxy_flag              - (IN) C4  - Indicates whether this LEC is a proxy.
-*   max_unknown_frame_count - (IN) C10 - For rate-limiting flooded unknowns.
-*   max_unknown_frame_time  - (IN) C11 - For rate-limiting flooded unknowns.
-*   vcc_timeout             - (IN) C12 - For aging out VCCs.
-*   max_retry_count         - (IN) C13 - Max retries for LE-ARP requests.
-*   aging_time              - (IN) C17 - Aging time for all addresses.
-*   forward_delay_time      - (IN) C18 - Aging time for remote addresses during
-*                                        topology changes.
-*   le_arp_response_time    - (IN) C20 - Expected response time for LE-ARPs.
-*   flush_timeout           - (IN) C21 - Timeout for flush operation.
-*   path_switching_delay    - (IN) C22 - Path switching time when flush is not
-*                                        successful.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   The la_elan_handle must be valid.
-*
-* Postconditions:
-*   The new parameters have taken effect and the ARP cache is ready for use.
---*/
-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,
-                UINT16     max_retry_count,
-                UINT32     aging_time,
-                UINT16     forward_delay_time,
-                UINT16     le_arp_response_time,
-                UINT16     flush_timeout,
-                UINT16     path_switching_delay,
-                unsigned int lane_version_num); /* LANE2 */
-
-/*++
-* =================
-* = la_elan_reset =
-* =================
-*
-* Overview:
-*   Resets an instance of the arp cache.  All entries in the cache are removed.
-*
-* Arguments:
-*   la_elan_handle   - (IN) Handle returned by la_register.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   The la_elan_handle must be valid.
-*
-* Postconditions:
-*   The arp cache is empty.
---*/
-void la_elan_reset (HANDLE   la_elan_handle);
-
-/*++
-* ==================
-* = la_addr_delete =
-* ==================
-*
-* Overview:
-*   Delete an entry from the LE-ARP cache.  Both permanent and non-permanent
-*   entries may be deleted.  This allows permanent addresses to be deleted by
-*   network management software and non-permanent addresses to be deleted via
-*   a Negative ARP (NARP) request.
-*
-* Arguments:
-*   la_elan_handle  - (IN) Handle returned by la_register.
-*   esi             - (IN) MAC Address of entry to be deleted.
-*   permanent       - (IN) If TRUE,  address may be permanent or non-permanent.
-*                          if FALSE, address must be non-permanent (NARP).
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Successful Completion, see postconditions.
-*   STATUS_K_NOT_FOUND  - The proper kind of address was not found.  This
-*                         status will be returned in the following cases:
-*
-*                         1. No entry was found with a matching MAC address,
-*                         2. The permanent flag was FALSE and a matching
-*                            permanent entry was found.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   If the permanent flag is set, there is no entry in the LE-ARP cache with 
-*   a matching ESI.
-*
-*   If the permanent flag is not set, there is no non-permanent entry in the
-*   LE-ARP cache with a matching ESI.
---*/
-STATUS la_addr_delete (HANDLE    la_elan_handle,
-                       unsigned char *atm_addr,
-                       BOOLEAN   permanent);
-
-/*++
-* =================
-* = la_arp_update =
-* =================
-*
-* Overview:
-*   Updates the LE-ARP cache with a fresh MAC address to ATM address mapping.
-*   This is generally called when a LE-ARP response is received.
-*
-* Arguments:
-*   la_elan_handle  - (IN) Handle returned by la_register.
-*   esi             - (IN) MAC Address in updated mapping.
-*   addr_atm        - (IN) ATM Address in the updated mapping.
-*   remote_flag     - (IN) Remote flag contained in the LE-ARP response frame.
-*   tlv_list        - (IN) LANE2: LE-ARP frames can now contain TLVs
-*   sizeoftlvs      - (IN) LANE2: The length of tlv_list in bytes
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The arp entry for this MAC address is up-to-date.  If this call indicates
-*   a change from the original mapping (i.e. the ATM address is different from
-*   what was originally in the mapping), the old mapping is discarded and the
-*   flush mechanism is invoked to facilitate the path switch.
-*   LANE2: The TLV association is also up-to-date
---*/
-void la_arp_update (HANDLE       la_elan_handle,
-                    ESI          esi,
-                    ADDR_ATM     addr_atm,
-                    BOOLEAN      remote_flag,
-                    char         *tlv_list,
-                    int          sizeoftlvs,
-                    int          targetless_le_arp,
-                    int          no_source_le_narp);
-
-/*++
-* =====================
-* = la_flush_complete =
-* =====================
-*
-* Overview:
-*   This call is made when the LEC_CTRL module receives a flush response frame
-*   from the network.  It notifies the LE-ARP cache that the flush protocol
-*   has successfully completed.
-*
-* Arguments:
-*   la_elan_handle  - (IN) Handle returned by la_register.
-*   addr_atm        - (IN) ATM address that was indicated in the flush
-*                          response.
-*   tran_id         - (IN) Transaction ID of original flush request.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The LE-ARP cache data structure specifies that packets sent to the
-*   requested MAC address may now be forwarded to the data-direct VCC.
---*/
-void la_flush_complete (HANDLE   la_elan_handle,
-                        UINT32   tran_id);
-
-/*++
-* ==========================
-* = la_topology_change_set =
-* ==========================
-*
-* Overview:
-*   This call indicates to the LE-ARP cache that the topology change flag
-*   has changed value.  This causes the LE-ARP cache to change its policy
-*   regarding the aging and refreshing of remote address mappings.
-*
-* Arguments:
-*   la_elan_handle       - (IN) The handle returned by la_register.
-*   topology_change_flag - (IN) The new value of the topology change flag.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The aging and refresh policy for the indicated address has been changed
-*   to be appropriate to the value of the topology change flag.
---*/
-void la_topology_change_set (HANDLE  la_elan_handle,
-                             BOOLEAN topology_change_flag);
-
-void kernel_flush_xmt(unsigned char *to_pass);
diff -ur --new-file old/atm/led/lec_ctrl.c new/atm/led/lec_ctrl.c
--- old/atm/led/lec_ctrl.c	Tue Feb  9 17:12:04 1999
+++ new/atm/led/lec_ctrl.c	Thu Jan  1 01:00:00 1970
@@ -1,3865 +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_ctrl.c
-*   
-* Overview:
-*   This module handles the control aspects of LAN Emulation Clienthood
-*   (with the exception of LE-ARP functions which are handled by the
-*   lec_arp.c module).  This module is responsible for the following:
-*
-*   - Setup and Teardown of all LAN Emulation SVCs.
-*   - Handling of all received LE Control Frames.
-*   - Composition and Transmission of all LE Control Frames.
-*   - Sequencing of Emulated LAN Join procedures.
-*
-*   One of the central parts of this module is the ELAN Join state machine.
-*   The state machine controls the sequencing of actions necessary to join
-*   an Emulated LAN.  The state machine provides the option to join with or
-*   without the help of a LAN Emulation Configuration Server.
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   18-Jan-95  TLR   Created.
-*    1-Aug-95  TLR   Proxy hooks added.
-*   21-Sep-95  TLR   Added address registration feature.
-*
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/time.h>    /* for select() */
-#include <sys/types.h>   /* for select() */
-
-#include <atm.h>
-
-/* Include General Headers. */
-
-#include "g_types.h"    /* General Purpose Types                 */
-#include "codes.h"      /* Return Status Codes                   */
-#include "g_endian.h"   /* Host/Network Data Conversion Routines */
-#include "utl.h"        /* General Purpose Utilities             */
-#include "utl_os.h"     /* Operating System Utilities            */
-#include "lane_atm.h"   /* ATM Specific Definitions and Macros   */
-#include "atmsap.h"	/* ATM SAP definition			 */
-#include "system.h"     /* ATM Subsystem Specific Stuff          */
-#include "g_event.h"
-#include "lane2.h"      /* New stuff in LANE v2                  */
-#include "conn.h"       /* for maxframe2maxsdu()                 */
-/* Include Headers for Mapping Module Interfaces. */
-
-#include "af_lane.h"    /* ATM Forum LAN Emulation Definitions   */
-#include "cm.h"
-#include "svc_info.h"   /* SVC Data Structures                   */
-#include "cm_sap.h"     /* CM SAP Interface                      */
-#include "addr_reg.h"   /* Address Registration Interface        */
-#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 "kernel_itf.h" /* read_from_kernel()                    */
-
-#define EMOD   MOD_LEC_CTRL
-#define EINST  "lec_ctrl.c"
-#include "emask.h"
-
-typedef struct _reg_dest {
-  ESI                mac_addr;
-  BOOLEAN            registered;
-  BOOLEAN            unregistering;
-  UINT32             tran_id;
-} REG_DEST;
-
-/*  LEC_STATE
- *
- *    This structure contains the state values defined in the ATM Forum LAN
- *    Emulation Specification V1.0 (see section 5.1.1).  The values in this
- *    structure are prefixed with their C# designation used in the
- *    specification.  Refer to the specification for detailed descriptions of
- *    these values.
- *
- *    LANE2: C2c, C3c, C5c, C29c, C32c and C34c from LANE spec V2.0
- *    (section 5.1.1) are not needed since lc_register() copies the values
- *    and the originals are hence never changed.
- *
- */
-typedef struct {
-  ADDR_ATM       c1n_my_atm_addr; /* LANE2: LEC's non-muxed ATM address */
-  LAN_TYPE       c2_lan_type;
-  LAN_MTU        c3_lan_mtu;
-  LAN_MTU        c3c_lan_mtu;    /* LANE2: configured (static) lan mtu */
-  BOOLEAN        c4_proxy_flag;
-  UINT8          elan_name_size; /* For config request */
-  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 */
-  REG_DEST       c6_my_mac_addr; 
-  UINT16         c7_control_timeout;
-  ADDR_ATM       c9_les_atm_addr;
-  UINT16         c10_max_unknown_frame_count;
-  UINT16         c11_max_unknown_frame_time;
-  UINT32         c12_vcc_timeout;
-  UINT16         c13_max_retry_count;
-  UINT16         c14_lec_id;
-  UINT32         c17_aging_time;
-  UINT16         c18_forward_delay_time;
-  BOOLEAN        c19_topology_change_flag;
-  UINT16         c20_le_arp_response_time;
-  UINT16         c21_flush_timeout;
-  UINT16         c22_path_switching_delay;
-  BOOLEAN        c29_v2_capable;            /* LANE2 stuff below */
-  UINT32         c31_elan_id;               /* for llc-muxed frames */
-  BOOLEAN        c32_selective_mcast;       /* not supported currently */
-  UINT16         c33_fwd_disc_timeout;
-  BOOLEAN        c34_llc_mux_capable;       /* not supported */
-  ADDR_ATM       c35_preferred_les;
-  ADDR_L3        c36_l3_address;            /* only IP is supported */
-  UINT16         c36_l3_address_size;       /* size of the above in bytes */
-  UINT32         c37_min_reconfig_delay;    /* in milliseconds */
-  UINT32         c38_max_reconfig_delay;    /* in milliseconds */ 
-  /* add c34 and c39 later if needed */
-  int            sizeoftlvs;                /* total size of TLVs associated with this LEC */
-  char           *tlvs;                     /* the TLVs */
-  const char     *foreId;
-  UINT8          extra_tlvs[7];
-} LEC_STATE;
-
-typedef struct
-   {
-   UINT16   new_state;
-   UINT16   event;
-   } SM_STATE_HISTORY;
-
-#define SM_STATE_HISTORY_DEPTH   4
-
-/*  LC_ELAN_CONTEXT
- *
- *    This structure contains the data required for each ELAN that this module
- *    is joined to.  An instance of this structure is created each time
- *    lc_register is executed.
- *
- *  p_next
- *    Pointer to enother instance of this structure.  This allows the struture
- *    to be stored in a simple list.
- *
- *  lc_handle
- *    Handle of the created LEC_CTRL module.  This handle is generated by the
- *    lc_create function.
- *
- *  la_elan_handle
- *    The handle of the LEC_ARP ELAN instance generated by la_register.  The
- *    LEC_ARP ELAN instance is a peer to this LEC_CTRL instance.
- *
- *  ld_elan_handle
- *    The handle of the LEC_DATA ELAN instance that called lc_register.  The
- *    LEC_DATA ELAN instance is a peer to this LEC_CTRL instance.
- *
- *  cm_handle
- *    The Connection Manager handle generated by cm_create.  This handle
- *    represents the instance of the CM that is to be used by this LEC_CTRL
- *    instance.
- *
- *  addr_reg_handle
- *    The Address Registration handle to be used when taking advantage of the
- *    services of the Address Registration Module.
- *
- *  addr_reg_client_handle
- *    The handle returned by the address registration client registration.
- *
- *  sap_handle
- *    The handle returned by cm_sap_register for the LAN Emulation NSAP.
- *    This SAP instance carries all LAN Emulation traffic.
- *
- *  direct_conn_context
- *    Connection context for data-direct VCCs.
- *
- *  mcast_conn_context
- *    Connection context for multicast VCCs.
- *
- *  ctrl_conn_context
- *    Connection context for control VCCs (both LECS and LES VCCs).
- *
- *  ctrl_direct_conn_handle
- *    Connection handle of the Control Direct VCC.
- *
- *  ctrl_dist_conn_handle
- *    Connection handle of the Control Distribute VCC.
- *
- *  mcast_send_conn_handle
- *    Connection handle of the Multicast Send VCC.
- *
- *  mcast_rcv_conn_handle
- *    Connection handle of the Multicast Receive VCC.
- *
- *  lecs_conn_handle
- *    Connection handle of the Configuration Direct VCC.
- *
- *  sm_timer
- *    Handle of the State-Machine timer.  This timer is used to implement
- *    time-outs in the state machine.
- *
- *  sm_state
- *    The current state of the LEC_CTRL state machine.
- *
- *  sm_timer_retry_count
- *    The number of remaining retries for the current state machine state.
- *
- *  sm_timer_duration
- *    The time (in seconds) that was used in the last timer set.
- *
- *  lec_state
- *    The current LEC state (see LEC_STATE structure).
- *
- *  lecs_addr
- *    The ATM address of the LECS that is currently being contacted.
- *
- *  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
- *    the lec_state.c9_les_atm_addr has been pre-loaded with the correct ATM
- *    address for the LAN Emulation Server.
- *
- *  bus_addr
- *    The ATM Address of the BUS being contacted.
- *
- *  qos_spec
- *    The QOS specification string for SVCs. NULL if default values (i.e. UBR
- *    at link speeed) should be used. This data is obtained from the UME.
- *
- *  current_tran_id
- *    Current transaction ID to be used for the next LE Control frame.
- *
- *  vc_ready_mask
- *    Bit mask of required LAN Emulation VCCs.  This is used to get a quick
- *    indication of which VCCs are ready for use.
- *
- *  illegal_frame_rcv_count
- *    Count of illegal frames received.
- *
- *  ctrl_xmt_failure_count
- *    Count of failures during control frame transmits
- *
- *  illegal_transition_count
- *    Count of illegal state machine transitions.
- */
-typedef struct _lc_elan
-   {
-   struct _lc_elan  *p_next;
-   char             *p_text;
-   HANDLE            lc_handle;
-   HANDLE            la_elan_handle;
-   HANDLE            ld_elan_handle;
-   HANDLE            addr_reg_handle;
-   HANDLE            addr_reg_client_handle;
-   HANDLE            lport_handle;
-   ATM_LINK_STATE    link_state;
-   HANDLE            sap_handle;
-   HANDLE            direct_conn_context;
-   HANDLE            mcast_conn_context;
-   HANDLE            ctrl_conn_context;
-   HANDLE            ctrl_direct_conn_handle;
-   HANDLE            ctrl_dist_conn_handle;
-   HANDLE            mcast_send_conn_handle;
-   HANDLE            mcast_rcv_conn_handle;
-   HANDLE            lecs_conn_handle;
-   HANDLE            sm_timer;
-   UINT16            sm_state;
-   UINT8             sm_timer_retry_count;
-   BOOLEAN           sm_timer_retry_flag;
-   UINT16            sm_timer_duration;
-   LEC_STATE         lec_state;
-   ADDR_ATM          lecs_addr;
-   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;
-   const char       *qos_spec;
-   UINT32            current_tran_id;
-   UINT8             vc_ready_mask;
-   UINT32            illegal_frame_rcv_count;
-   UINT32            ctrl_xmt_failure_count;
-   UINT32            illegal_transition_count;
-   UINT32            ctrl_frames_sent;
-   UINT32            ctrl_frames_rcvd;
-   UINT32            arps_sent;
-   UINT32            arps_rcvd;
-   } LC_ELAN_CONTEXT;
-
-SIMPLE_LIST (LC_ELAN_CONTEXT, ELAN_LIST);
-
-typedef void (*ACTION_ROUTINE) (HANDLE lc_elan_handle);
-
-typedef struct _sm_table
-   {
-   struct _sm_table  *p_next;
-   UINT16             curr_state;
-   UINT16             sm_event;
-   UINT16             next_state;
-   ACTION_ROUTINE     action1;
-   ACTION_ROUTINE     action2;
-   ACTION_ROUTINE     action3;
-   } STATE_TBL_ENTRY;
-
-SIMPLE_LIST (STATE_TBL_ENTRY, STATE_LIST);
-
-/* LC_CONTEXT
- *
- *  This structure contains data used by the LEC_CTRL super-component.  An
- *  instance of this strutcure is created each time lc_create is executed.
- *
- *  os_handle
- *    Handle of the OS utilities.  Used for memory allocation and timer
- *    operations.
- *
- *  cm_handle
- *    Handle of the Connection Manager instance to be used by this LEC_CTRL
- *    instance.
- *
- *  la_handle
- *    Handle of the peer LEC_ARP module instance used by this LEC_CTRL
- *    instance.
- *
- *  elan_status_callback
- *    Callback to indicate changes in the ELAN availability.
- *
- *  elan_list
- *    List of ELAN Context blocks under this LEC_CTRL instance.  There is one
- *    for every ELAN that is joined to.
- */
-typedef struct _lc_context
-   {
-   HANDLE                  line_up_handle;
-   HANDLE                  la_handle;
-   ELAN_STATUS_CALLBACK    elan_status_callback;
-   ELAN_LIST               elan_list;
-   STATE_LIST              sm_use_lecs;
-   STATE_LIST              sm_skip_lecs;
-   } LC_CONTEXT;
-
-/* Bit mask definitions for the vc_ready_mask. */
-
-#define READY_LECS         1
-#define READY_CTRL_DIRECT  2
-#define READY_CTRL_DIST    4
-#define READY_MCAST_SEND   8
-#define READY_MCAST_RCV    16
-
-
-/* Protos */
-static const char *state_name (UINT16 s);
-static const char *event_name (UINT16 s);
-static int tlv_parse (LC_ELAN_CONTEXT  *p_elan,
-		       UINT8             buffer[],
-		       UINT32            length,
-		       UINT8            *p_tlv_index);
-/*++
-* =====================
-* = lc_conn_info_make =
-* =====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*   Generates a CONN_INFO block for SVC setup.
-*
-* Arguments:
-*   lc_elan_handle   - (IN)  Handle returned by lc_register.
-*   called_party     - (IN)  ATM address of called party.
-*   blli_codepoint   - (IN)  16-bit BLLI codepoint for the connection.
-*   calling_party    - (IN)  ATM address of calling party.
-*   p_conn_info      - (OUT) Generated CONN_INFO block.
-*
-* Returns:
-*   None
-*
-* Description:
-*   Fill the required SVC information elements based on the currently
-*   supported UNI version.
-*
-* Issues:
-*   None
-*
---*/
-static void lc_conn_info_make (HANDLE      lc_elan_handle,
-                               ADDR_ATM    called_party,
-                               UINT16      blli_codepoint,
-                               BOOLEAN     pmp,
-                               CONN_INFO  *p_conn_info)
-{
-  LC_ELAN_CONTEXT   *p_elan;
-  unsigned int bllicode;
-  int i, sdu;
-  
-  EVENT(EM_DEBUG,("Lc_conn_info_make, blli codepoint %x\n",blli_codepoint));
-
-  p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-  
-  svcinit_conn_info (p_conn_info);
-  
-  p_conn_info->addr.sas_family = AF_ATMSVC;
-  p_conn_info->conqos.aal = ATM_AAL5;
-  
-    /* Set the forward and backward Max CPCS-SDU Size */
-  switch(blli_codepoint) {
-  case BLLI_CONTROL:
-    p_conn_info->conqos.rxtp.max_sdu = 1516;
-    p_conn_info->conqos.txtp.max_sdu = 1516;
-    break;
-  case BLLI_DIRECT_802_3:
-  case BLLI_BUS_802_3:
-    sdu = maxframe2maxsdu(p_elan->lec_state.c3_lan_mtu);
-    p_conn_info->conqos.rxtp.max_sdu = sdu;
-    p_conn_info->conqos.txtp.max_sdu = sdu;
-    break;
-  case BLLI_DIRECT_802_5:
-  case BLLI_BUS_802_5:
-    p_conn_info->conqos.rxtp.max_sdu = 4544;
-    p_conn_info->conqos.txtp.max_sdu = 4544;
-    break;
-  default:
-    EVENT(EM_ASSERT,("Unknown BLLI codepoint %x\n",blli_codepoint));
-  }
-  /* ATM User Cell Rate/ATM Traffic Descriptor. */
-  p_conn_info->conqos.txtp.traffic_class = ATM_UBR;
-  p_conn_info->conqos.rxtp.traffic_class = ATM_UBR;
-   
-  if (p_elan->qos_spec)
-    if (text2qos(p_elan->qos_spec,&p_conn_info->conqos,T2Q_DEFAULTS) < 0)
-      EVENT(EM_ASSERT,("text2qos failed in lc_conn_info_make\n"));
-
-  if (pmp==TRUE) {
-    /* Asdf */
-  } else {
-    /* Fdsa */
-  }
-
-  /* Broadband Lower Layer Information. */
-  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;
-  p_conn_info->blli.l3.tr9577.snap[1] = 0xa0;
-  p_conn_info->blli.l3.tr9577.snap[2] = 0x3e;
-  bllicode = hton16(blli_codepoint);
-  p_conn_info->blli.l3.tr9577.snap[3] = (unsigned char)(0xff&bllicode);
-  p_conn_info->blli.l3.tr9577.snap[4] = (unsigned char)(0xff&(bllicode>>8));
-
-  if (EMASK & EM_DEBUG)
-    for(i=0;i<5;i++) {
-      printf("snap[%d] = 0x%2.2x\n",i,p_conn_info->blli.l3.tr9577.snap[i]);
-    }
-   /* Called Party Number. */
-  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];
-  p_conn_info->addr.sas_addr.prv[3] = called_party.prefix[3];
-  p_conn_info->addr.sas_addr.prv[4] = called_party.prefix[4];
-  p_conn_info->addr.sas_addr.prv[5] = called_party.prefix[5];
-  p_conn_info->addr.sas_addr.prv[6] = called_party.prefix[6];
-  p_conn_info->addr.sas_addr.prv[7] = called_party.prefix[7];
-  p_conn_info->addr.sas_addr.prv[8] = called_party.prefix[8];
-  p_conn_info->addr.sas_addr.prv[9] = called_party.prefix[9];
-  p_conn_info->addr.sas_addr.prv[10] = called_party.prefix[10];
-  p_conn_info->addr.sas_addr.prv[11] = called_party.prefix[11];
-  p_conn_info->addr.sas_addr.prv[12] = called_party.prefix[12];
-  p_conn_info->addr.sas_addr.prv[13] = called_party.esi[0];
-  p_conn_info->addr.sas_addr.prv[14] = called_party.esi[1];
-  p_conn_info->addr.sas_addr.prv[15] = called_party.esi[2];
-  p_conn_info->addr.sas_addr.prv[16] = called_party.esi[3];
-  p_conn_info->addr.sas_addr.prv[17] = called_party.esi[4];
-  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. */
-}
-
-
-/*++
-* ======================
-* = lc_conn_info_check =
-* ======================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*   Check the information elements of an incoming SVC request and determine if
-*   it is valid to be accepted.  Furthermore, extract certain information from
-*   the IEs.
-*
-* Arguments:
-*   lc_elan_handle    - (IN)  Handle returned by lc_register.
-*   p_conn_info       - (IN)  Conn Info block containing the IEs.
-*   p_blli_codepoint  - (OUT) The BLLI codepoint of the received request.
-*   p_pmp             - (OUT) Point-to-Multipoint indication.  Iff true, this
-*                             is a point-to-multipoint connection.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - The connection info is valid and appropriate for
-*                         this ELAN instance.
-*   STATUS_K_MISMATCH   - The connection is not appropriate for this ELAN
-*                         instance but might be for another NSAP.
-*   STATUS_K_REJECT     - The connection is destined for this ELAN instance
-*                         but has a problem (i.e. missing information) that
-*                         makes it necessary to reject the connection.
-*
-* Description:
-*   Check the information elements based on the currently supported UNI
-*   version.
-*
-* Issues:
-*   None
-*
---*/
-static STATUS lc_conn_info_check (HANDLE      lc_elan_handle,
-                                  CONN_INFO  *p_conn_info,
-                                  UINT16     *p_blli_codepoint,
-                                  BOOLEAN    *p_pmp)
-{
-   LC_ELAN_CONTEXT   *p_elan;
-/*   int                len, i, ie_count;
-   unsigned int       rate;
-*/
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   assert(p_conn_info);
-   /* Check the called party address.  If it is not equal to our address,
-    * return STATUS_K_MISMATCH.
-    */
-
-
-   /* Check the BLLI.  If it is not relevant to LAN Emulation, return
-    * STATUS_K_MISMATCH.
-    */
-
-   if (p_conn_info->blli.l2_proto == ATM_L2_ISO8802)  /* 0x12 */
-     return STATUS_K_REJECT;       /* LANE2: LLC-muxed VCCs not supported here */
-
-      /* Make sure the first bytes are 6B.40.80.80.00.A0.3E */
-
-
-   /* Extract the BLLI Codepoint from the BLLI data. */
-   
-      /* Put codepoint in *p_blli_codepoint */
-
-   *p_blli_codepoint = 
-     ((unsigned short)0xff00&(p_conn_info->blli.l3.tr9577.snap[3]<<8)) |
-     ((unsigned short)0xff&(p_conn_info->blli.l3.tr9577.snap[4]));
-
-   /* Check the AAL Parameters. */
-
-   /* Check the ATM Traffic Descriptor. */
-
-   /* Check Broadband Bearer Capability. */
-
-   /* Check QoS. */
-
-   return STATUS_K_SUCCESS;
-}
-
-
-/*++
-* ====================
-* = lc_ctrl_hdr_make =
-* ====================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*   Initialize the general header of a LEC control frame.  The status and
-*   flags fields are set to zero.
-*
-* Arguments:
-*   lc_elan_handle  - (IN)  Handle returned by lc_elan_register.
-*   p_hdr           - (OUT) Header of a LEC frame.
-*   op_code         - (IN)  Op code to be placed in the LEC header.
-*
-* Returns:
-*   The transaction ID that was placed in this header (in host byte-order).
-*
-* Preconditions:
-*   Sufficient memory is allocated at p_hdr to hold the header.
-*
-* Postconditions:
-*   The header contains the op_code, success status, null flags, the correct
-*   lec_id, and appropriate constant data.
-*
-* Description:
-*   Data is placed in the header structure using the endian conversion
-*   routines.
-*
-* Issues:
-*   None
-*
---*/
-static UINT32 lc_ctrl_hdr_make (HANDLE       lc_elan_handle,
-                                LE_CTRL_HDR *p_hdr,
-                                UINT16       op_code)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   UINT32             tran_id;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   p_hdr->marker     = hton16 (LE_CTRL_MARKER);
-   p_hdr->protocol   = LE_CTRL_PROTOCOL;
-   p_hdr->version    = LE_CTRL_VERSION;
-   p_hdr->op_code    = hton16 (op_code);
-   p_hdr->status     = hton16 (0);
-   p_hdr->tran_id    = hton32 (p_elan->current_tran_id);
-   p_hdr->req_lec_id = hton16 (p_elan->lec_state.c14_lec_id);
-   p_hdr->flags      = hton16 (0);
-
-   tran_id = p_elan->current_tran_id;
-   p_elan->current_tran_id += 1;
-
-   return tran_id;
-   }
-
-/****************************************************************************
- *  LAN Destination Registration Code
- ****************************************************************************/
-
-static void reg_req_xmt (HANDLE     lc_elan_handle,
-                         REG_DEST  *p_dest,
-                         BOOLEAN    reg)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   LE_REG_FRAME      *frame;
-   STATUS             status;
-   int               framesize;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   framesize = sizeof(LE_REG_FRAME)+ p_elan->lec_state.sizeoftlvs;
-   frame = (LE_REG_FRAME *)os_mem_alloc(framesize);
-   if (frame == NULL) {
-           EVENT(EM_SERR, ("reg_req_xmt: out of memory\n"));
-           return;
-   }
-
-   memset(frame, 0, framesize);
-
-   if (reg)
-      {
-      p_dest->tran_id = lc_ctrl_hdr_make (lc_elan_handle,
-                                          &frame->hdr,
-                                          LE_REGISTER_REQ);
-      }
-   else
-      {
-      p_dest->tran_id = lc_ctrl_hdr_make (lc_elan_handle,
-                                          &frame->hdr,
-                                          LE_UNREGISTER_REQ);
-      }
-
-   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.c1n_my_atm_addr, frame->src_atm_addr);
-
-   frame->tlv_count++;
-   memcpy(frame + 1, p_elan->lec_state.tlvs, p_elan->lec_state.sizeoftlvs);
-
-   if (reg)
-      {
-      EVENT (EM_XCTRL, ("Sending Register Request.\n"));
-      }
-   else
-      {
-      EVENT (EM_XCTRL, ("Sending Unregister Request.\n"));
-      }
-
-   if (p_elan->ctrl_direct_conn_handle != NULL)
-      {
-      status =  cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle,
-                               frame,
-                               framesize,
-                               USER_DATA_INTERNAL,
-                               NULL);
-      if (status != STATUS_K_SUCCESS)
-         p_elan->ctrl_xmt_failure_count += 1;
-      else
-         p_elan->ctrl_frames_sent += 1;
-      }
-   }
-
-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
- ****************************************************************************/
-
-/*
- * State Values
- */
-#define S_INITIAL             101
-#define S_ATM_WAIT            102
-#define S_ILMI_WAIT           103
-#define S_LECS_SVC_WAIT       104
-#define S_LECS_WSVC_WAIT      105
-#define S_LECS_PVC_WAIT       106
-#define S_CONFIG_WAIT         107
-#define S_LES_SVC_WAIT        108
-#define S_JOIN_WAIT           109
-#define S_BUS_ARP_WAIT        110
-#define S_BUS_SVC_WAIT        111
-#define S_OPERATIONAL         112
-#define S_DISABLED            113
-
-/*
- * Event Values
- */
-#define E_JOIN_START          201
-#define E_AREG_DONE           202
-#define E_ILMI_NEW_ADDR       203
-#define E_ILMI_NO_MORE        204
-#define E_LECS_SVC_READY      205
-#define E_LECS_SVC_RELEASE    206
-#define E_LECS_PVC_READY      207
-#define E_LES_SVC_READY       208
-#define E_LES_SVC_RELEASE     209
-#define E_BUS_SVC_READY       210
-#define E_BUS_SVC_REL_NORM    211
-#define E_BUS_SVC_REL_ABNORM  212
-#define E_TIMEOUT_RETRY       213
-#define E_TIMEOUT_NORETRY     214
-#define E_RCV_CONFIG_RSP      215
-#define E_RCV_JOIN_RSP        216
-#define E_RCV_BUS_ARP_RSP     217
-#define E_AREG_CANCELED       218
-
-/*
- * Event Handlers (Function Prototypes)
- */
-static void act_atm_addr_req        (HANDLE lc_elan_handle);
-static void act_atm_addr_cancel     (HANDLE lc_elan_handle);
-static void act_ilmi_ld_1st_get     (HANDLE lc_elan_handle);
-static void act_ilmi_next_get       (HANDLE lc_elan_handle);
-static void act_wait_random         (HANDLE lc_elan_handle);  /* LANE2: 5.2.1.4 */
-static void act_lecs_svc_setup      (HANDLE lc_elan_handle);
-static void act_lecs_wsvc_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);
-static void act_bus_arp_req_xmt     (HANDLE lc_elan_handle);
-static void act_bus_svc_setup       (HANDLE lc_elan_handle);
-static void act_lecs_vc_teardown    (HANDLE lc_elan_handle);
-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)                       \
-   {                                                                       \
-   p_tran = os_mem_alloc (sizeof (STATE_TBL_ENTRY)); \
-   if (p_tran == NULL)                                                     \
-      return STATUS_K_RESOURCES;                                           \
-                                                                           \
-   p_tran->curr_state = curr;                                              \
-   p_tran->sm_event   = in_event;                                          \
-   p_tran->next_state = next;                                              \
-   p_tran->action1    = act1;                                              \
-   p_tran->action2    = act2;                                              \
-   p_tran->action3    = act3;                                              \
-                                                                           \
-   utl_list_add (*p_sm, p_tran);                                           \
-   }
-
-const char *state_name (UINT16 s)
-   {
-   switch (s)
-      {
-      case S_INITIAL:         return ("S_INITIAL");
-      case S_ATM_WAIT:        return ("S_ATM_WAIT");
-      case S_ILMI_WAIT:       return ("S_ILMI_WAIT");
-      case S_LECS_SVC_WAIT:   return ("S_LECS_SVC_WAIT");
-      case S_LECS_WSVC_WAIT:  return ("S_LECS_WSVC_WAIT");
-      case S_LECS_PVC_WAIT:   return ("S_LECS_PVC_WAIT");
-      case S_CONFIG_WAIT:     return ("S_CONFIG_WAIT");
-      case S_LES_SVC_WAIT:    return ("S_LES_SVC_WAIT");
-      case S_JOIN_WAIT:       return ("S_JOIN_WAIT");
-      case S_BUS_ARP_WAIT:    return ("S_BUS_ARP_WAIT");
-      case S_BUS_SVC_WAIT:    return ("S_BUS_SVC_WAIT");
-      case S_OPERATIONAL:     return ("S_OPERATIONAL");
-      case S_DISABLED:        return ("S_DISABLED");
-      default:                return ("<unknown>");
-      }
-   }
-
-const char *event_name (UINT16 s)
-   {
-   switch (s)
-      {
-      case E_JOIN_START:         return ("E_JOIN_START");
-      case E_AREG_DONE:          return ("E_AREG_DONE");
-      case E_ILMI_NEW_ADDR:      return ("E_ILMI_NEW_ADDR");
-      case E_ILMI_NO_MORE:       return ("E_ILMI_NO_MORE");
-      case E_LECS_SVC_READY:     return ("E_LECS_SVC_READY");
-      case E_LECS_SVC_RELEASE:   return ("E_LECS_SVC_RELEASE");
-      case E_LECS_PVC_READY:     return ("E_LECS_PVC_READY");
-      case E_LES_SVC_READY:      return ("E_LES_SVC_READY");
-      case E_LES_SVC_RELEASE:    return ("E_LES_SVC_RELEASE");
-      case E_BUS_SVC_READY:      return ("E_BUS_SVC_READY");
-      case E_BUS_SVC_REL_NORM:   return ("E_BUS_SVC_REL_NORM");
-      case E_BUS_SVC_REL_ABNORM: return ("E_BUS_SVC_REL_ABNORM");
-      case E_TIMEOUT_RETRY:      return ("E_TIMEOUT_RETRY");
-      case E_TIMEOUT_NORETRY:    return ("E_TIMEOUT_NORETRY");
-      case E_RCV_CONFIG_RSP:     return ("E_RVC_CONFIG_RSP");
-      case E_RCV_JOIN_RSP:       return ("E_RCV_JOIN_RSP");
-      case E_RCV_BUS_ARP_RSP:    return ("E_RCV_BUS_ARP_RSP");
-      case E_AREG_CANCELED:      return ("E_AREG_CANCELED");
-      default:                   return ("<unknown>");
-      }
-   }
-
-
-/*++
-* ==================
-* = state_tbl_init =
-* ==================
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*   Initialize the control state machine table.  This table contains entries
-*   for each of the transitions in the LEC state machine.
-*
-* Arguments:
-*   None
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The state machine is ready to operate
-*
-* Description:
-*
-* Issues:
-*   None
-*
---*/
-static STATUS state_tbl_init (HANDLE lc_handle)
-   {
-   LC_CONTEXT       *p_context;
-   STATE_TBL_ENTRY  *p_tran;
-   STATE_LIST       *p_sm;
-
-   p_context = (LC_CONTEXT *) lc_handle;
-
-   utl_list_init (p_context->sm_use_lecs);
-   utl_list_init (p_context->sm_skip_lecs);
-
-   p_sm = &p_context->sm_use_lecs;
-
-   /*    Current State     Event                  Next State        Action 1              Action 2              Action 3
-    *-------------------------------------------------------------------------------------------------------------------*/
-   TRAN (S_INITIAL,        E_JOIN_START,          S_ATM_WAIT,       act_atm_addr_req,     NULL,                 NULL);
-   TRAN (S_ATM_WAIT,       E_AREG_DONE,           S_ILMI_WAIT,      act_ilmi_ld_1st_get,  NULL,                 NULL);
-   TRAN (S_ILMI_WAIT,      E_ILMI_NEW_ADDR,       S_LECS_SVC_WAIT,  act_timer_cancel,     act_lecs_svc_setup,   NULL);
-   TRAN (S_ILMI_WAIT,      E_ILMI_NO_MORE,        S_LECS_WSVC_WAIT, act_timer_cancel,     act_lecs_wsvc_setup,  NULL);
-   TRAN (S_ILMI_WAIT,      E_TIMEOUT_NORETRY,     S_ILMI_WAIT,      act_ilmi_ld_1st_get,  NULL,                 NULL);
-   TRAN (S_LECS_SVC_WAIT,  E_LECS_SVC_READY,      S_CONFIG_WAIT,    act_timer_cancel,     act_config_req_xmt,   NULL);
-   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_wait_random,      act_ilmi_next_get,    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_ILMI_WAIT,      act_timer_cancel,     act_ilmi_ld_1st_get,  NULL);
-   TRAN (S_LECS_WSVC_WAIT, E_TIMEOUT_NORETRY,     S_ILMI_WAIT,      act_wait_random,      act_ilmi_ld_1st_get,  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_wait_random,      act_ilmi_next_get);
-   TRAN (S_CONFIG_WAIT,    E_LECS_SVC_RELEASE,    S_ILMI_WAIT,      act_timer_cancel,     act_wait_random,      act_ilmi_next_get);
-   TRAN (S_LES_SVC_WAIT,   E_LES_SVC_READY,       S_JOIN_WAIT,      act_timer_cancel,     act_join_req_xmt,     NULL);
-   TRAN (S_LES_SVC_WAIT,   E_LES_SVC_RELEASE,     S_ILMI_WAIT,      act_timer_cancel,     act_ilmi_next_get,    NULL);
-   TRAN (S_LES_SVC_WAIT,   E_TIMEOUT_NORETRY,     S_ILMI_WAIT,      act_ilmi_next_get,    NULL,                 NULL);
-   TRAN (S_JOIN_WAIT,      E_RCV_JOIN_RSP,        S_BUS_ARP_WAIT,   act_timer_cancel,     act_bus_arp_req_xmt,  NULL);
-   TRAN (S_JOIN_WAIT,      E_TIMEOUT_RETRY,       S_JOIN_WAIT,      act_join_req_xmt,     NULL,                 NULL);
-   TRAN (S_JOIN_WAIT,      E_TIMEOUT_NORETRY,     S_ILMI_WAIT,      act_les_svc_teardown, act_ilmi_next_get,    NULL);
-   TRAN (S_JOIN_WAIT,      E_LES_SVC_RELEASE,     S_ILMI_WAIT,      act_timer_cancel,     act_ilmi_next_get,    NULL);
-   TRAN (S_BUS_ARP_WAIT,   E_RCV_BUS_ARP_RSP,     S_BUS_SVC_WAIT,   act_timer_cancel,     act_bus_svc_setup,    NULL);
-   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,     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);
-   TRAN (S_BUS_SVC_WAIT,   E_LES_SVC_RELEASE,     S_ILMI_WAIT,      act_timer_cancel,     act_bus_svc_teardown, act_ilmi_ld_1st_get);
-   TRAN (S_OPERATIONAL,    E_BUS_SVC_REL_ABNORM,  S_BUS_ARP_WAIT,   act_bus_arp_req_xmt,  NULL,                 NULL);
-   TRAN (S_OPERATIONAL,    E_BUS_SVC_REL_NORM,    S_ATM_WAIT,       act_les_svc_teardown, act_atm_addr_cancel,  act_atm_addr_req);
-   TRAN (S_OPERATIONAL,    E_LES_SVC_RELEASE,     S_ATM_WAIT,       act_bus_svc_teardown, act_atm_addr_cancel,  act_atm_addr_req);
-
-   TRAN (S_ILMI_WAIT,      E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_LECS_SVC_WAIT,  E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_LECS_WSVC_WAIT, E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_LECS_PVC_WAIT,  E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_CONFIG_WAIT,    E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_LES_SVC_WAIT,   E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_JOIN_WAIT,      E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_BUS_ARP_WAIT,   E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_BUS_SVC_WAIT,   E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_OPERATIONAL,    E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-
-   TRAN (S_DISABLED,       E_JOIN_START,          S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_AREG_DONE,           S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_ILMI_NEW_ADDR,       S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_ILMI_NO_MORE,        S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_LECS_SVC_READY,      S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_LECS_SVC_RELEASE,    S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_LECS_PVC_READY,      S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_LES_SVC_READY,       S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_LES_SVC_RELEASE,     S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_BUS_SVC_READY,       S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_BUS_SVC_REL_NORM,    S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_BUS_SVC_REL_ABNORM,  S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_TIMEOUT_RETRY,       S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_TIMEOUT_NORETRY,     S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_RCV_CONFIG_RSP,      S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_RCV_JOIN_RSP,        S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_RCV_BUS_ARP_RSP,     S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_AREG_CANCELED,       S_DISABLED,       NULL,                 NULL,                 NULL);
-
-
-   p_sm = &p_context->sm_skip_lecs;
-
-   /*    Current State     Event                  Next State        Action 1              Action 2              Action 3
-    *-------------------------------------------------------------------------------------------------------------------*/
-   TRAN (S_INITIAL,        E_JOIN_START,          S_ATM_WAIT,       act_atm_addr_req,     NULL,                 NULL);
-   TRAN (S_ATM_WAIT,       E_AREG_DONE,           S_LES_SVC_WAIT,   act_les_svc_setup,    NULL,                 NULL);
-   TRAN (S_LES_SVC_WAIT,   E_LES_SVC_READY,       S_JOIN_WAIT,      act_timer_cancel,     act_join_req_xmt,     NULL);
-/* TRAN (S_LES_SVC_WAIT,   E_LES_SVC_RELEASE,     S_LES_SVC_WAIT,   act_timer_cancel,     act_les_svc_setup,    NULL); */
-   TRAN (S_LES_SVC_WAIT,   E_TIMEOUT_NORETRY,     S_LES_SVC_WAIT,   act_les_svc_setup,    NULL,                 NULL);
-   TRAN (S_JOIN_WAIT,      E_RCV_JOIN_RSP,        S_BUS_ARP_WAIT,   act_timer_cancel,     act_bus_arp_req_xmt,  NULL);
-   TRAN (S_JOIN_WAIT,      E_TIMEOUT_RETRY,       S_JOIN_WAIT,      act_join_req_xmt,     NULL,                 NULL);
-   TRAN (S_JOIN_WAIT,      E_TIMEOUT_NORETRY,     S_LES_SVC_WAIT,   act_les_svc_teardown, act_les_svc_setup,    NULL);
-   TRAN (S_JOIN_WAIT,      E_LES_SVC_RELEASE,     S_LES_SVC_WAIT,   act_timer_cancel,     act_les_svc_setup,    NULL);
-   TRAN (S_BUS_ARP_WAIT,   E_RCV_BUS_ARP_RSP,     S_BUS_SVC_WAIT,   act_timer_cancel,     act_bus_svc_setup,    NULL);
-   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,     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);
-   TRAN (S_BUS_SVC_WAIT,   E_LES_SVC_RELEASE,     S_LES_SVC_WAIT,   act_timer_cancel,     act_bus_svc_teardown, act_les_svc_setup);
-   TRAN (S_OPERATIONAL,    E_BUS_SVC_REL_ABNORM,  S_BUS_ARP_WAIT,   act_bus_arp_req_xmt,  NULL,                 NULL);
-   TRAN (S_OPERATIONAL,    E_BUS_SVC_REL_NORM,    S_ATM_WAIT,       act_les_svc_teardown, act_atm_addr_cancel,  act_atm_addr_req);
-   TRAN (S_OPERATIONAL,    E_LES_SVC_RELEASE,     S_ATM_WAIT,       act_bus_svc_teardown, act_atm_addr_cancel,  act_atm_addr_req);
-
-   TRAN (S_ILMI_WAIT,      E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_LECS_SVC_WAIT,  E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_LECS_WSVC_WAIT, E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_LECS_PVC_WAIT,  E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_CONFIG_WAIT,    E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_LES_SVC_WAIT,   E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_JOIN_WAIT,      E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_BUS_ARP_WAIT,   E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_BUS_SVC_WAIT,   E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-   TRAN (S_OPERATIONAL,    E_AREG_CANCELED,       S_ATM_WAIT,       act_timer_cancel,     act_atm_addr_req,     NULL);
-
-   TRAN (S_DISABLED,       E_JOIN_START,          S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_AREG_DONE,           S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_ILMI_NEW_ADDR,       S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_ILMI_NO_MORE,        S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_LECS_SVC_READY,      S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_LECS_SVC_RELEASE,    S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_LECS_PVC_READY,      S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_LES_SVC_READY,       S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_LES_SVC_RELEASE,     S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_BUS_SVC_READY,       S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_BUS_SVC_REL_NORM,    S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_BUS_SVC_REL_ABNORM,  S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_TIMEOUT_RETRY,       S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_TIMEOUT_NORETRY,     S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_RCV_CONFIG_RSP,      S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_RCV_JOIN_RSP,        S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_RCV_BUS_ARP_RSP,     S_DISABLED,       NULL,                 NULL,                 NULL);
-   TRAN (S_DISABLED,       E_AREG_CANCELED,       S_DISABLED,       NULL,                 NULL,                 NULL);
-
-   return STATUS_K_SUCCESS;
-   }
-
-/*++
-* ===========
-* = sm_exec =
-* ===========
-*
-* Status:   IMPLEMENTATION COMPLETE
-*
-* Overview:
-*   Execute one transition of the state machine.
-*
-* Arguments:
-*   lc_elan_handle - (IN) Handle returned by lc_register.
-*   sm_event       - (IN) Event value to be handled by the state machine.
-*
-* Returns:
-*   none
-*
-* Description:
-*   Search the appropriate state machine transition list based on the
-*   skip_lecs value.
-*
-* Issues:
-*   None
-*
---*/
-static void sm_exec (HANDLE   lc_elan_handle,
-                     UINT16   sm_event)
-   {
-   LC_CONTEXT        *p_context;
-   LC_ELAN_CONTEXT   *p_elan;
-   STATE_TBL_ENTRY   *p_tran;
-   STATE_LIST        *p_sm;
-
-   p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
-   p_context = (LC_CONTEXT      *) p_elan->lc_handle;
-
-   /* Choose the appropriate state machine representation to use. */
-
-   if (p_elan->init_method == INIT_MANUAL_LES)
-      p_sm = &p_context->sm_skip_lecs;
-   else
-      p_sm = &p_context->sm_use_lecs;
-
-   /* Search the state machine list for a matching state-event pair. */
-
-   utl_list_traverse (*p_sm, p_tran)
-      {
-      if ((p_tran->curr_state == p_elan->sm_state) &&
-          (p_tran->sm_event   == sm_event))
-         {
-         p_elan->sm_state = p_tran->next_state;
-
-         EVENT (EM_TRAN, ("(%s, %s) -> %s\n",
-                          state_name (p_tran->curr_state),
-                          event_name (sm_event),
-                          state_name (p_tran->next_state)));
-
-         p_elan->sm_state_history[p_elan->sm_state_history_index].new_state =
-            p_tran->next_state;
-         p_elan->sm_state_history[p_elan->sm_state_history_index].event =
-            sm_event;
-         p_elan->sm_state_history_index = (p_elan->sm_state_history_index + 1)
-            % SM_STATE_HISTORY_DEPTH;
-
-
-         /* If the ELAN state goes from non-operational to operational,
-          * notify the upper layers that the ELAN is now available for use.
-          */
-         if ((p_tran->curr_state != S_OPERATIONAL) &&
-             (p_tran->next_state == S_OPERATIONAL))
-            p_context->elan_status_callback (p_elan->ld_elan_handle,
-                                             TRUE,
-                                             p_elan->lec_state.c3_lan_mtu,
-                                             p_elan->lec_state.c5_elan_name,
-                                             p_elan->lec_state.c14_lec_id);
-
-         /* If the ELAN state goes from operational to non-operational,
-          * reset the le-arp cache and notify the upper layers that the ELAN
-          * is no longer available.  The le-arp cache must be reset to ensure
-          * that arp-retries are not attempted on a closed control VCC.
-          */
-         if ((p_tran->curr_state == S_OPERATIONAL) &&
-             (p_tran->next_state  != S_OPERATIONAL))
-            {
-	      /*
-		la_elan_reset (p_elan->la_elan_handle);
-		*/
-            lc_elan_reset (p_elan);
-
-            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);
-            }
-
-
-         /* Execute the transition's action routines. */
-
-         if (p_tran->action1 != NULL)
-            p_tran->action1 (lc_elan_handle);
-
-         if (p_tran->action2 != NULL)
-            p_tran->action2 (lc_elan_handle);
-
-         if (p_tran->action3 != NULL)
-            p_tran->action3 (lc_elan_handle);
-
-         return;
-         }
-      }
-
-   p_elan->illegal_transition_count += 1;
-   }
-
-/*++
-* ================
-* = sm_timer_set =
-* ================
---*/
-static void sm_timer_set (HANDLE lc_elan_handle,
-                          UINT16 duration,
-                          UINT8  retry_count)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   if (!p_elan->sm_timer_retry_flag)
-      {
-      p_elan->sm_timer_retry_count = retry_count;
-      p_elan->sm_timer_duration    = duration;
-      }
-
-   os_timer_set (p_elan->sm_timer, duration * 1000);
-   }
-
-/*++
-* ====================
-* = sm_timer_handler =
-* ====================
---*/
-static void sm_timer_handler (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   if (p_elan->sm_timer_retry_count > 0)
-      {
-      p_elan->sm_timer_retry_count -= 1;
-      p_elan->sm_timer_retry_flag   = TRUE;
-      os_timer_set (p_elan->sm_timer, p_elan->sm_timer_duration * 1000);
-      sm_exec (lc_elan_handle, E_TIMEOUT_RETRY);
-      }
-   else
-      {
-      p_elan->sm_timer_retry_flag = FALSE;
-      sm_exec (lc_elan_handle, E_TIMEOUT_NORETRY);
-      }
-   }
-
-static void 
-act_ctrl_list_close(HANDLE lc_elan_handle)
-{
-  /*
-  cm_kill_ctrl_listens();
-  */
-}
-
-/*++
-* ====================
-* = act_atm_addr_req =
-* ====================
-* Description:
-*  Request a new ATM address from the Address-Registration Service.
---*/
-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 =
-* =======================
-* Description:
-*  Cancel registration of an ATM address.
---*/
-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.c1n_my_atm_addr); 
-}
-
-/*++
-* =======================
-* = act_ilmi_ld_1st_get =
-* =======================
---*/
-static void act_ilmi_ld_1st_get (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   if ((p_elan->init_method == INIT_WELL_KNOWN_LECS) ||
-       (p_elan->init_method == INIT_LECS_PVC))
-      {
-      sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 0);
-      sm_exec (lc_elan_handle, E_ILMI_NO_MORE);
-      return;
-      }
-
-   if (p_elan->init_method == INIT_MANUAL_LECS)
-      {
-      sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 0);
-      sm_exec (lc_elan_handle, E_ILMI_NEW_ADDR);
-      return;
-      }
-
-   if (p_elan->init_method == INIT_NORMAL)
-      {
-      /* This is temporary!!! */
-
-      sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 0);
-      sm_exec (lc_elan_handle, E_ILMI_NO_MORE);
-      return;
-      }
-
-   assert (FALSE);
-   }
-
-
-/*++
-* =====================
-* = act_ilmi_next_get =
-* =====================
---*/
-static void act_ilmi_next_get (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   sm_exec (lc_elan_handle, E_ILMI_NO_MORE);
-
-   sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 0);
-   }
-
-/*++
-* ===================
-* = act_wait_random =
-* ===================
-*
-* LANE2: 5.2.1.4 sleep random time before trying to reconnect
---*/
-static void act_wait_random (HANDLE lc_elan_handle)
-   {
-
-     struct timeval tv;
-     int millis, interval;
-     LC_ELAN_CONTEXT *p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-     srand(time(NULL));
-     interval = p_elan->lec_state.c38_max_reconfig_delay - p_elan->lec_state.c37_min_reconfig_delay;
-     millis = (rand() % interval) + p_elan->lec_state.c37_min_reconfig_delay;
-     tv.tv_sec  = (millis - (millis % 1000)) / 1000;
-     tv.tv_usec = (millis % 1000) * 1000;
-
-     (void)select(0, NULL, NULL, NULL, &tv);
-
-     return;
-   }
-/*++
-* ======================
-* = act_lecs_svc_setup =
-* ======================
---*/
-static void act_lecs_svc_setup (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   CONN_INFO          conn_info;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   lc_conn_info_make (lc_elan_handle,
-                      p_elan->lecs_addr,
-                      BLLI_CONTROL,
-                      FALSE,           /* point to point */
-                      &conn_info);
-
-   (void) cm_sap_svc_setup (p_elan->sap_handle,
-                            p_elan->ctrl_conn_context,
-                            &conn_info,
-                            0,
-                            &p_elan->lecs_conn_handle);   
-
-   sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 0);
-   }
-
-/*++
-* =======================
-* = act_lecs_wsvc_setup =
-* =======================
-*
---*/
-static void act_lecs_wsvc_setup (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   ADDR_ATM           addr;
-   CONN_INFO          conn_info;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   if (p_elan->init_method == INIT_LECS_PVC)
-      {
-      sm_exec (lc_elan_handle, E_TIMEOUT_NORETRY);
-      return;
-      }
-
-   addr.prefix[0]  = 0x47;
-   addr.prefix[1]  = 0x00;
-   addr.prefix[2]  = 0x79;
-   addr.prefix[3]  = 0x00;
-   addr.prefix[4]  = 0x00;
-   addr.prefix[5]  = 0x00;
-   addr.prefix[6]  = 0x00;
-   addr.prefix[7]  = 0x00;
-   addr.prefix[8]  = 0x00;
-   addr.prefix[9]  = 0x00;
-   addr.prefix[10] = 0x00;
-   addr.prefix[11] = 0x00;
-   addr.prefix[12] = 0x00;
-   addr.esi[0]     = 0x00;
-   addr.esi[1]     = 0xa0;
-   addr.esi[2]     = 0x3e;
-   addr.esi[3]     = 0x00;
-   addr.esi[4]     = 0x00;
-   addr.esi[5]     = 0x01;
-   addr.sel        = 0x00;
-
-   lc_conn_info_make (lc_elan_handle,
-                      addr,
-                      BLLI_CONTROL,
-                      FALSE,           /* point to point */
-                      &conn_info);
-
-   (void) cm_sap_svc_setup (p_elan->sap_handle,
-                            p_elan->ctrl_conn_context,
-                            &conn_info,
-                            0,
-                            &p_elan->lecs_conn_handle);   
-
-   sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 0);
-   }
-
-/*++
-* ======================
-* = act_config_req_xmt =
-* ======================
---*/
-static void act_config_req_xmt (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   LE_CONFIG_FRAME   *frame;
-   STATUS             status;
-   int               frame_size;
-   char              *tlvdata; /* for filling in the TLVs */
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   /* allocate size for the frame and both TLVs that can be
-      present, X5 adjustement TLV and l3 address TLV */
-   frame_size = ( sizeof(LE_CONFIG_FRAME) +
-                  5 + 0 +
-                  5 + p_elan->lec_state.c36_l3_address_size );
-   frame = os_mem_alloc(frame_size);
-   tlvdata = (char *)(frame +1);
-
-   lc_ctrl_hdr_make (lc_elan_handle, &frame->hdr, LE_CONFIG_REQ);
-   frame->hdr.req_lec_id = hton16 (0);
-   if (p_elan->lec_state.c29_v2_capable) /* LANE2 */
-     frame->hdr.flags = hton16(LE_FLAG_V2_CAPABLE);
-
-   ATM_COPY (p_elan->lec_state.c1n_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_1580   : frame->max_frame_size = 1;  break; /* LANE2 5.3.1.2 */
-      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->elan_name_size = p_elan->lec_state.elan_name_size;   
-   memcpy(frame->elan_name, p_elan->lec_state.c5_elan_name,                 
-	  MIN (frame->elan_name_size, 32));
-
-   frame->tlv_count = 0;
-   frame_size = sizeof (LE_CONFIG_FRAME);
-
-   /* LANE2: add X5 adjustement TLV */
-   if (p_elan->lec_state.c3_lan_mtu == MTU_1580) {
-#if 0
-       *tlvdata++ = 0x00; *tlvdata++ = 0xa0;
-       *tlvdata++ = 0x3e; *tlvdata++ = 0x2c;
-#endif
-       *(UINT32 *)tlvdata = hton32(TLV_X5_ADJUSTEMENT);
-       tlvdata += sizeof(TLV_X5_ADJUSTEMENT); /* should be 4 */
-       *tlvdata++ = 0x00; /* length 0 */
-       frame_size += 5;
-       frame->tlv_count += 1;
-   }
-
-   /* LANE2: 5.3.1.1, add L3 Address TLV if l3_address not empty */
-   if (p_elan->lec_state.c36_l3_address_size != 0) {
-       int l3_address_size = p_elan->lec_state.c36_l3_address_size;
-       ADDR_L3 l3_addr     = hton32(p_elan->lec_state.c36_l3_address);
-
-#if 0
-       *tlvdata++ = 0x00; *tlvdata++ = 0xa0;
-       *tlvdata++ = 0x3e; *tlvdata++ = 0x11;
-#endif
-       *(UINT32 *)tlvdata = hton32(TLV_L3_ADDRESS);
-       tlvdata += sizeof(TLV_L3_ADDRESS);
-       *tlvdata++ = l3_address_size;
-       memcpy(tlvdata, &l3_addr, l3_address_size);
-       tlvdata += l3_address_size;
-       frame_size += l3_address_size;
-       frame->tlv_count += 1;
-   }
-
-
-#if 0 /* sleep() disabled, hessu@cs.tut.fi 13.2.1998 */
-   sleep(1);
-#endif
-   status =  cm_sap_xmt_vc (p_elan->lecs_conn_handle,
-                            frame,
-                            frame_size,
-                            USER_DATA_INTERNAL,
-                            NULL);
-   os_mem_dealloc(frame);
-   if (status != STATUS_K_SUCCESS)
-      p_elan->ctrl_xmt_failure_count += 1;
-   else
-      p_elan->ctrl_frames_sent += 1;
-
-   sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 1);
-   }
-
-/*++
-* =====================
-* = act_les_svc_setup =
-* =====================
---*/
-static void act_les_svc_setup (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   CONN_INFO          conn_info;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   lc_conn_info_make (lc_elan_handle,
-                      p_elan->lec_state.c9_les_atm_addr,
-                      BLLI_CONTROL,
-                      FALSE,           /* point to point */
-                      &conn_info);
-
-   (void) cm_sap_svc_setup (p_elan->sap_handle,
-                            p_elan->ctrl_conn_context,
-                            &conn_info,
-                            0,
-                            &p_elan->ctrl_direct_conn_handle);   
-
-   sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 0);
-   }
-
-/*++
-* ====================
-* = act_join_req_xmt =
-* ====================
---*/
-static void 
-act_join_req_xmt(HANDLE lc_elan_handle)
-{
-  LC_ELAN_CONTEXT   *p_elan;
-  LE_JOIN_FRAME      *frame;
-  STATUS             status;
-  int                frame_size;
-  char               *tlvdata;
-
-  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;
-
-  frame_size = ( sizeof(LE_JOIN_FRAME) + 
-                 5 + p_elan->lec_state.c36_l3_address_size +
-                 5 + 0 +          /* X5 adjustement */
-                 5 + 20);         /* preferred LES  */
-
-  if (strlen(p_elan->lec_state.foreId) > 0)
-    frame_size += 5 + strlen(p_elan->lec_state.foreId);
-                 
-  frame = os_mem_alloc(frame_size);
-  memset(frame, 0, frame_size);
-  tlvdata = (char *)(frame + 1);
-
-  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;
-  frame->hdr.flags |= (p_elan->lec_state.c29_v2_capable) ?
-                       hton16 (LE_FLAG_V2_CAPABLE) : 0; /* LANE2 */
-
-  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.c1n_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_1580  : frame->max_frame_size = 1;  break; /* LANE2 5.4.3 */
-  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;   
-   memcpy(frame->elan_name, p_elan->lec_state.c5_elan_name_join,
-	  MIN (frame->elan_name_size, 32));
-   EVENT(EM_DEBUG,("ELAN NAME:%s len:%d\n",p_elan->lec_state.c5_elan_name_join,
-		   MIN(frame->elan_name_size, 32)));
-
-   /* LANE2: add X5 adjustement TLV */
-   if (p_elan->lec_state.c3_lan_mtu == MTU_1580) {
-#if 0
-       *tlvdata++ = 0x00; *tlvdata++ = 0xa0;
-       *tlvdata++ = 0x3e; *tlvdata++ = 0x2c;
-#endif
-       *(UINT32 *)tlvdata = hton32(TLV_X5_ADJUSTEMENT);
-       tlvdata += sizeof(TLV_X5_ADJUSTEMENT); /* should be 4 */
-       *tlvdata++ = 0x00; /* length 0 */
-       frame_size += 5;
-       frame->tlv_count += 1;
-   }
-
-   /* LANE2: 5.3.1.1, add L3 Address TLV if l3_address not empty */
-   if (p_elan->lec_state.c36_l3_address_size != 0) {
-       int l3_address_size = p_elan->lec_state.c36_l3_address_size;
-       ADDR_L3 l3_addr     = hton32(p_elan->lec_state.c36_l3_address);
-
-#if 0
-       *tlvdata++ = 0x00; *tlvdata++ = 0xa0;
-       *tlvdata++ = 0x3e; *tlvdata++ = 0x11;
-#endif
-       *(UINT32 *)tlvdata = hton32(TLV_L3_ADDRESS);
-       tlvdata += sizeof(TLV_L3_ADDRESS);
-       *tlvdata++ = l3_address_size;
-       memcpy(tlvdata, &l3_addr, l3_address_size);
-       tlvdata += l3_address_size;
-       frame_size += l3_address_size;
-       frame->tlv_count += 1;
-   }
-
-   /* strictly Fore specific hack */
-   if ( strlen(p_elan->lec_state.foreId) > 0) {
-       *tlvdata++ = 0x00; *tlvdata++ = 0x20;
-       *tlvdata++ = 0x48; *tlvdata++ = 0x08;
-       *tlvdata++ = strlen(p_elan->lec_state.foreId);
-       strncpy(tlvdata, p_elan->lec_state.foreId, strlen(p_elan->lec_state.foreId));
-       tlvdata += strlen(p_elan->lec_state.foreId);
-       frame->tlv_count += 1;
-   }
-
-   sleep(1);
-   status =  cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle,
-                            frame,
-                            frame_size,
-                            USER_DATA_INTERNAL,
-                            NULL);
-
-   os_mem_dealloc(frame);
-   if (status != STATUS_K_SUCCESS)
-      p_elan->ctrl_xmt_failure_count += 1;
-   else
-      p_elan->ctrl_frames_sent += 1;
-
-   sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 1);
-   }
-
-/*++
-* =======================
-* = act_bus_arp_req_xmt =
-* =======================
---*/
-static void act_bus_arp_req_xmt (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   LE_ARP_FRAME       frame;
-   STATUS             status;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   memset(&frame, 0, sizeof (LE_ARP_FRAME));
-
-   lc_ctrl_hdr_make (lc_elan_handle, &frame.hdr, LE_ARP_REQ);
-
-   frame.src_lan_dst.tag            = hton16 (TAG_NOT_PRESENT);
-   frame.target_lan_dst.tag         = hton16 (TAG_MAC_ADDR);
-   frame.target_lan_dst.mac_addr[0] = 0xff;
-   frame.target_lan_dst.mac_addr[1] = 0xff;
-   frame.target_lan_dst.mac_addr[2] = 0xff;
-   frame.target_lan_dst.mac_addr[3] = 0xff;
-   frame.target_lan_dst.mac_addr[4] = 0xff;
-   frame.target_lan_dst.mac_addr[5] = 0xff;
-
-   ATM_COPY (p_elan->lec_state.c1n_my_atm_addr, frame.src_atm_addr);
-
-   p_elan->arps_sent += 1;
-
-   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
-      p_elan->ctrl_frames_sent += 1;
-
-   sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 1);
-   }
-
-/*++
-* =====================
-* = act_bus_svc_setup =
-* =====================
---*/
-static void act_bus_svc_setup (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   CONN_INFO          conn_info;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   lc_conn_info_make (lc_elan_handle,
-                      p_elan->bus_addr,
-                      BLLI_BUS_802_3,
-                      FALSE,           /* Point to Point */
-                      &conn_info);
-
-   (void) cm_sap_svc_setup (p_elan->sap_handle,
-                            p_elan->mcast_conn_context,
-                            &conn_info,
-                            0,
-                            &p_elan->mcast_send_conn_handle);   
-
-   sm_timer_set (lc_elan_handle, p_elan->lec_state.c7_control_timeout, 0);
-   }
-
-/*++
-* ========================
-* = act_lecs_vc_teardown =
-* ========================
---*/
-static void act_lecs_vc_teardown (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-
-   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->link_state == LINK_SIG_UP)
-	  {
-            cm_sap_svc_teardown (p_elan->lecs_conn_handle);
-	  }
-
-      p_elan->lecs_conn_handle = NULL;
-      }
-
-   }
-
-/*++
-* ========================
-* = act_les_svc_teardown =
-* ========================
---*/
-static void act_les_svc_teardown (HANDLE lc_elan_handle)
-{
-  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_wait_random(p_elan); /* LANE2 */
-}
-
-/*++
-* ========================
-* = act_bus_svc_teardown =
-* ========================
---*/
-static void act_bus_svc_teardown (HANDLE lc_elan_handle)
-{
-  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_wait_random(p_elan); /* LANE2 */
-}
-
-
-/*++
-* ====================
-* = act_timer_cancel =
-* ====================
---*/
-static void act_timer_cancel (HANDLE lc_elan_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   p_elan->sm_timer_retry_count = 0;
-   p_elan->sm_timer_retry_flag  = FALSE;
-
-   os_timer_cancel (p_elan->sm_timer);
-   }
-
-
-/*++
-* =====================
-* = addr_reg_callback =
-* =====================
---*/
-static void addr_reg_callback (HANDLE               context,
-                               ADDR_ATM            *p_atm_addr,
-                               ADDR_REG_ADDR_EVENT  ar_event)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-
-   p_elan = (LC_ELAN_CONTEXT *) context;
-
-   EVENT(EM_DEBUG,("Addr_reg_callback:%s\n",disp_atm_text(*p_atm_addr)));
-   switch (ar_event)
-      {
-      case ADDR_REG_EVENT_ATM_ADDR_ALLOCATED :
-      
-         ATM_COPY (*p_atm_addr, p_elan->lec_state.c1n_my_atm_addr);
-         sm_exec (context, E_AREG_DONE);
-         break;
-
-      case ADDR_REG_EVENT_ATM_ADDR_INVALIDATED :
-
-         sm_exec (context, E_AREG_CANCELED);
-         break;
-
-      default :
-      
-         assert (FALSE);
-      }
-   }
-
-/*++
-* ==============
-* = lc_arp_xmt = arp request from kernel
-* ==============
-*
-* LANE2: LE_ARP_FRAME can now contain TLVs and therefore has
-* variable size. Total length of TLVs is in sizeoftlvs
-* Note: this does _not_ update the TLV info in p_elan->tlvs
-* If sizeofltvs == 0 then the default TLVs associated with this lec
-* will be used. Also, if esi == NULL sends targetless LE_ARP
-*
---*/
-static void lc_arp_xmt (HANDLE   lc_elan_handle,
-                        ESI      esi, int sizeoftlvs)
-   {
-   LC_ELAN_CONTEXT    *p_elan;
-   LE_ARP_FRAME       *frame;
-   STATUS             status = 0;     /* silence gcc 2.7.2.1 */
-   size_t             framelength;
-   int                retval;
-   char               *buff;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   if (sizeoftlvs == 0)
-	   framelength = sizeof(LE_ARP_FRAME) + p_elan->lec_state.sizeoftlvs;
-   else
-	   framelength = sizeof(LE_ARP_FRAME) + sizeoftlvs;
-
-   frame = (LE_ARP_FRAME*)os_mem_alloc(framelength);
-   memset(frame, 0, framelength);
-
-   lc_ctrl_hdr_make (lc_elan_handle, &frame->hdr, LE_ARP_REQ);
-
-   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);
-   if (esi != NULL) {   /* esi == NULL means targetless LE_ARP */
-       frame->target_lan_dst.tag = hton16 (TAG_MAC_ADDR);
-       ESI_COPY (esi, frame->target_lan_dst.mac_addr);
-   }
-   else
-       frame->target_lan_dst.tag = hton16 (TAG_NOT_PRESENT);
-
-   ATM_COPY (p_elan->lec_state.c1n_my_atm_addr, frame->src_atm_addr);
-
-   if (sizeoftlvs != 0) {
-           buff = os_mem_alloc(sizeoftlvs);
-           retval = read_from_kernel(buff, sizeoftlvs);
-           if (retval != sizeoftlvs)
-                   EVENT (EM_SERR, ("lc_arp_xmt(): short read\n"));         
-           fprintf(stderr, "TLV-ARP-DEBUG: 0x");
-           for (retval = 0; retval < sizeoftlvs; retval++)
-                   fprintf(stderr, "%x", buff[retval]);
-           fprintf(stderr, "\n");
-           memcpy(frame + 1, buff, sizeoftlvs);
-           fprintf(stderr, "lc_arp_xmt(): after memcpy\n");
-           os_mem_dealloc(buff);
-   }
-   else {
-	  memcpy(frame + 1, p_elan->lec_state.tlvs, p_elan->lec_state.sizeoftlvs);
-          EVENT(EM_DEBUG,("lc_arp_xmt(): length of tlvs %d\n", p_elan->lec_state.sizeoftlvs));
-   }
-   if (sizeoftlvs != 0 || p_elan->lec_state.sizeoftlvs != 0)
-	   frame->tlv_count++;
-   
-   if (esi != NULL) {
-       EVENT (EM_XDATA, ("Sending LE-ARP for address: %02x-%02x-%02x-%02x-%02x-%02x\n",
-              esi[0], esi[1], esi[2], esi[3], esi[4], esi[5]));
-   }
-   else
-       EVENT (EM_XDATA, ("Sending targetless LE-ARP\n"));
-
-   p_elan->arps_sent += 1;
-
-   if (p_elan->sm_state == S_OPERATIONAL) {
-     status =  cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle,
-			      frame,
-			      framelength,
-			      USER_DATA_INTERNAL,
-			      NULL);
-   }
-   os_mem_dealloc(frame);
-   if (status != STATUS_K_SUCCESS)
-      p_elan->ctrl_xmt_failure_count += 1;
-   else
-      p_elan->ctrl_frames_sent += 1;
-   }
-
-/*++
-* ================
-* = lc_flush_xmt =
-* ================
---*/
-static void lc_flush_xmt (HANDLE    lc_elan_handle,
-                          unsigned char *addr_atm,
-                          HANDLE    flush_tran_id)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   LE_FLUSH_FRAME     frame;
-   STATUS             status = 0;   /* silence gcc 2.7.2.1 */
-   UINT32            *p_tran_id;
-   int i;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-   p_tran_id  = (UINT32 *)flush_tran_id;
-
-   memset(&frame, 0, sizeof (LE_FLUSH_FRAME));
-
-   *p_tran_id = lc_ctrl_hdr_make (lc_elan_handle,
-				  &frame.hdr,
-				  LE_FLUSH_REQ);
-
-   ATM_COPY (p_elan->lec_state.c1n_my_atm_addr, frame.src_atm_addr);
-   for(i=0;i<sizeof(PREFIX);i++)
-     frame.target_atm_addr.prefix[i] = addr_atm[i];
-   for(;i<sizeof(PREFIX)+sizeof(ESI);i++)
-     frame.target_atm_addr.esi[i-sizeof(PREFIX)] = addr_atm[i];
-   frame.target_atm_addr.sel = addr_atm[19];
-
-   /*
-   ATM_COPY (addr_atm,                         frame.target_atm_addr);
-   */
-   EVENT (EM_XDATA, ("Sending Flush Request for %s.\n",
-          disp_atm_text (frame.target_atm_addr)));
-
-   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 =
-* ================
---*/
-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);
-  
-  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);   
-  }
-}
-
-/*++
-* LANE2, l_associate_req msg from kernel causes
-*        this function to be called
-* =================
-* = associate_req =
-* =================
---*/
-static void associate_req (HANDLE lc_elan_handle, int sizeoftlvs)
-{
-    char *buff;
-    int  retval;
-    LC_ELAN_CONTEXT *p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-    EVENT(EM_DEBUG, ("About to associate TLVs, total length %d\n", sizeoftlvs));
-
-    buff = os_mem_alloc(sizeoftlvs);
-    if (buff == NULL)
-        return;
-
-    retval = read_from_kernel(buff, sizeoftlvs);
-    if (retval != sizeoftlvs)
-        EVENT (EM_SERR, ("associate_req(): short read\n"));         
-    
-    if (p_elan->lec_state.tlvs != NULL)
-        os_mem_dealloc(p_elan->lec_state.tlvs);       /* free old TLVs (if any) */
-    p_elan->lec_state.sizeoftlvs = sizeoftlvs;
-    p_elan->lec_state.tlvs = buff;
-
-    reg_req_xmt(lc_elan_handle, &p_elan->lec_state.c6_my_mac_addr, TRUE);
-
-}
-    
-
-/*++
-* l_should_bridge msg from kernel causes this function to be called.
-* We are acting as a bridge and know mac_addr is behind us.
-*
-* =================
-* = proxy_arp_rsp =
-* =================
---*/
-static void proxy_arp_rsp(HANDLE lc_elan_handle, UINT8 *mac_addr,
-                          UINT32 tran_id, UINT16 lec_id, UINT8 *atm_addr)
-{
-   LE_ARP_FRAME *frame;
-   size_t framelength;
-   LC_ELAN_CONTEXT *p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   framelength = sizeof(LE_ARP_FRAME) + p_elan->lec_state.sizeoftlvs;
-   frame = (LE_ARP_FRAME *)os_mem_alloc(framelength);
-   memset(frame, 0 , framelength);
-
-   /* construct frame with the parameters supplied by requestor */
-   lc_ctrl_hdr_make(lc_elan_handle, &frame->hdr, LE_ARP_RSP);
-   frame->hdr.tran_id = tran_id;
-   frame->hdr.req_lec_id = lec_id;
-   frame->hdr.flags = hton16(LE_FLAG_REMOTE_ADDR);
-   frame->target_lan_dst.tag = hton16(TAG_MAC_ADDR);
-   ESI_COPY(mac_addr, frame->target_lan_dst.mac_addr);
-   ATM_COPY (p_elan->lec_state.c1n_my_atm_addr, frame->target_atm_addr);
-   memcpy(&frame->src_atm_addr, atm_addr, ATM_ESA_LEN);
-
-   /* add TLVs, if any */
-   if (p_elan->lec_state.sizeoftlvs != 0) {
-      memcpy(frame + 1, p_elan->lec_state.tlvs, p_elan->lec_state.sizeoftlvs);
-      frame->tlv_count++;
-   }
-
-   cm_sap_xmt_vc(p_elan->ctrl_direct_conn_handle,
-                 frame, framelength,
-                 USER_DATA_INTERNAL, NULL);
-
-   os_mem_dealloc(frame);
-   return;
-}
-
-
-/*++
-* Kernel sent a Configuration Bridge PDU to BUS and asks us to send a
-* respective LE_TOPOLOGY_REQUEST to LES
-*
-* ====================
-* = lc_topo_req_xmt =
-* ====================
---*/
-static void lc_topo_req_xmt (HANDLE   lc_elan_handle,
-                             UINT32   flag)
-{
-  LE_TOPOLOGY_FRAME frame;
-  LC_ELAN_CONTEXT *p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-  memset(&frame, 0, sizeof(LE_TOPOLOGY_FRAME));
-  lc_ctrl_hdr_make(lc_elan_handle, &frame.hdr, LE_TOPOLOGY_REQ);
-
-  if (flag)
-    frame.hdr.flags = hton16(LE_FLAG_TOPOLOGY_CHANGE);
-
-  cm_sap_xmt_vc(p_elan->ctrl_direct_conn_handle, &frame,
-                sizeof(LE_TOPOLOGY_FRAME), USER_DATA_INTERNAL, NULL);
-
-  return;
-}
-
-/*++
-* ====================
-* = lc_ready_ind_xmt =
-* ====================
---*/
-static void lc_ready_ind_xmt (HANDLE   lc_elan_handle,
-                              HANDLE   conn_handle)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   LE_READY_FRAME     frame;
-   UINT32             user_data;
-   STATUS             status;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   frame.hdr.marker     = hton16 (LE_CTRL_MARKER);
-   frame.hdr.protocol   = LE_CTRL_PROTOCOL;
-   frame.hdr.version    = LE_CTRL_VERSION;
-   frame.hdr.op_code    = hton16 (READY_IND);
-
-   user_data = USER_DATA_INTERNAL;
-   status = cm_sap_xmt_vc (conn_handle,
-                           (void *) &frame,
-                           sizeof (LE_READY_FRAME),
-                           user_data,
-                           NULL);
-   if (status != STATUS_K_SUCCESS)
-      {
-      p_elan->ctrl_xmt_failure_count += 1;
-      }
-   else
-      {
-      p_elan->ctrl_frames_sent += 1;
-      }
-   }
-
-/****************************************************************************
- *  Implementations of LC Interface Functions
- ****************************************************************************/
-
-/*++
-* =============
-* = lc_create =
-* =============
---*/
-STATUS lc_create (HANDLE                line_up_handle,
-                  ELAN_STATUS_CALLBACK  elan_status_callback,
-                  HANDLE               *p_lc_handle)
-   {
-   LC_CONTEXT  *p_context;
-   STATUS       status;
-
-   /* Allocate memory for the module context. */
-
-   p_context = (LC_CONTEXT *) os_mem_alloc (sizeof (LC_CONTEXT));
-   if (p_context == NULL)
-      {
-      return STATUS_K_RESOURCES;
-      }
-
-   EVENT(EM_DEBUG,("Lc_create: lc_handle:%p\n",p_context));
-   /* Initialize the fields of the context structure. */
-
-   p_context->line_up_handle       = line_up_handle;
-   p_context->elan_status_callback = elan_status_callback;
-   utl_list_init (p_context->elan_list);
-
-   /* Create an instance of the LE_ARP module. */
-
-   status = la_create ((HANDLE) p_context,
-                       lc_arp_xmt,
-                       lc_flush_xmt,
-                       lc_svc_setup,
-                       associate_req,     /* LANE2 */
-                       proxy_arp_rsp,
-                       lc_topo_req_xmt,
-                       &p_context->la_handle);
-   if (status != STATUS_K_SUCCESS)
-      {
-      os_mem_dealloc (p_context);
-      return STATUS_K_RESOURCES;
-      }
-
-   status = state_tbl_init((HANDLE) p_context);
-
-   /* Return the handle with success status. */
-
-   *p_lc_handle = (HANDLE) p_context;
-   return STATUS_K_SUCCESS;
-   }
-
-/*++
-* ==============
-* = lc_destroy =
-* ==============
---*/
-void lc_destroy (HANDLE  lc_handle)
-   {
-   LC_CONTEXT        *p_context;
-   LC_ELAN_CONTEXT   *p_elan;
-
-   /* Do nothing if the handle is already NULL. */
-
-   if (lc_handle == NULL)
-      return;
-
-   p_context = (LC_CONTEXT *) lc_handle;
-
-   /* Deregister each registered elan instance. */
-
-   p_elan = p_context->elan_list.p_root;
-   while (p_elan != NULL)
-      {
-      lc_deregister ((HANDLE) p_elan);
-      p_elan = p_context->elan_list.p_root;
-      }
-
-   /* Destroy the LEC_ARP instance. */
-
-   la_destroy (p_context->la_handle);
-
-   /* Destroy the State Tables. */
-
-   utl_list_dealloc (p_context->sm_use_lecs);
-   utl_list_dealloc (p_context->sm_skip_lecs);
-
-   /* Free the memory used for this instance context. */
-
-   os_mem_dealloc (p_context);
-   return;
-   }
-
-/*++
-* ===============
-* = lc_register =
-* ===============
---*/
-STATUS lc_register (HANDLE       lc_handle,
-                    HANDLE       ld_elan_handle,
-                    HANDLE       addr_reg_handle,
-                    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_lc_elan_handle,
-                    BOOLEAN      v2_capable,
-                    ADDR_ATM     preferred_les,
-                    ADDR_L3      l3_address,
-                    const char  *foreId)
-{
-  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));
-  
-  p_elan->lec_state.extra_tlvs[0] = 0x00;
-  p_elan->lec_state.extra_tlvs[1] = 0xa0;
-  p_elan->lec_state.extra_tlvs[2] = 0x3e;
-  p_elan->lec_state.extra_tlvs[3] = 0x13;
-  p_elan->lec_state.extra_tlvs[4] = 0x02;
-  p_elan->lec_state.extra_tlvs[5] = 0x00;
-  p_elan->lec_state.extra_tlvs[6] = 0x0f;
-
-  /* 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;
-  if (p_elan->lec_state.c29_v2_capable)
-    p_elan->lec_state.c7_control_timeout          = 30; /* LANE2 */
-  p_elan->lec_state.c10_max_unknown_frame_count   = 1;
-  if (p_elan->lec_state.c29_v2_capable)
-    p_elan->lec_state.c10_max_unknown_frame_count = 10; /* LANE2 */
-  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;
-  
-  /* LANE2 configuration variables follow */
-  p_elan->lec_state.c29_v2_capable         = v2_capable;
-  p_elan->lec_state.c31_elan_id            = 0;
-  p_elan->lec_state.c32_selective_mcast    = FALSE;
-  p_elan->lec_state.c33_fwd_disc_timeout   = 60;
-  p_elan->lec_state.c34_llc_mux_capable    = FALSE;
-  p_elan->lec_state.c35_preferred_les      = preferred_les;
-  p_elan->lec_state.c36_l3_address         = l3_address;
-  p_elan->lec_state.c37_min_reconfig_delay = 1;    /* milliseconds */
-  p_elan->lec_state.c38_max_reconfig_delay = 5000; /* milliseconds */
-      
-  /* Fore switches can display some extra data about client
-   * if asked with a correct TLV
-   */
-  if (strlen(foreId) > 0)
-    p_elan->lec_state.foreId = foreId;
-  else
-    p_elan->lec_state.foreId = "\0";
-
-  /* LANE counters */
-  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;
-  }
-
-  /* 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;
-  }
-
-  /* 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,
-             (v2_capable)? 2 : 1);
-  
-  /* 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 =
-* =================
---*/
-void lc_deregister (HANDLE lc_elan_handle)
-   {
-   LC_CONTEXT       *p_context;
-   LC_ELAN_CONTEXT  *p_elan;
-   STATUS            status;
-
-   p_elan    = (LC_ELAN_CONTEXT *) lc_elan_handle;
-   p_context = (LC_CONTEXT      *) p_elan->lc_handle;
-
-   p_elan->sm_state = S_DISABLED;
-
-   os_timer_dealloc (p_elan->sm_timer);
-   os_timer_dealloc (p_elan->reg_timer);
-
-#if 0
-   act_bus_svc_teardown (lc_elan_handle);
-   act_les_svc_teardown (lc_elan_handle);
-   act_lecs_vc_teardown (lc_elan_handle);
-#endif
-
-   status = addr_reg_atm_addr_dealloc (p_elan->addr_reg_client_handle,
-                                       &p_elan->lec_state.c1n_my_atm_addr);
-
-   addr_reg_client_deregister(p_elan->addr_reg_client_handle);
-   
-   la_deregister (p_elan->la_elan_handle);
-
-   utl_list_delete (p_context->elan_list, p_elan);
-
-   if (p_elan->lec_state.tlvs != NULL) /* LANE2 */
-       os_mem_dealloc(p_elan->lec_state.tlvs);       /* free old TLVs (if any) */  
-   os_mem_dealloc (p_elan);
-   }
-
-/*++
-* =========================
-* = lc_dest_is_registered =
-* =========================
---*/
-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;
-
-  /* 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 =
-* =================
---*/
-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.c1n_my_atm_addr);
-
-  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 =
-* =================
---*/
-void lc_join_start (HANDLE  lc_elan_handle,
-                    HANDLE  sap_handle,
-                    HANDLE  direct_conn_context,
-                    HANDLE  mcast_conn_context,
-		    const char *qos_spec,
-                    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->qos_spec = qos_spec;
-  
-  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 =
-* ====================
---*/
-void lc_sap_vc_notify (HANDLE           conn_context,
-                       HANDLE           conn_handle,
-                       NOTIFY_EVENT     vc_event,
-                       UINT16           reason,
-                       UINT32           endpoint_ref,
-                       BOOLEAN          calling_party)
-{
-  LC_ELAN_CONTEXT   *p_elan;
-  LEC_CONN_CONTEXT  *p_conn;
-  
-  p_conn = (LEC_CONN_CONTEXT *) conn_context;
-  p_elan = (LC_ELAN_CONTEXT  *) p_conn->lc_elan_handle;
-  
-  switch (vc_event) {
-  case CONN_VC_READY :
-    switch (p_conn->conn_type) {
-    case LEC_DIRECT :
-      
-      /* Send a READY_IND message on the new connection. */
-      
-      EVENT (EM_EVENT, ("New Data Direct VCC Ready\n"));
-      lc_ready_ind_xmt ((HANDLE) p_elan, conn_handle);
-      break;
-      
-    case LEC_MCAST :
-      
-      if (calling_party) {
-	assert (conn_handle == p_elan->mcast_send_conn_handle);
-	EVENT (EM_EVENT, ("Multicast Send VCC Ready\n"));
-	p_elan->vc_ready_mask |= READY_MCAST_SEND;
-#ifdef PROXY
-	proxy_mcast_send_add (p_elan->lport_handle,
-			      vpi,
-			      vci,
-			      p_elan->lec_state.c14_lec_id,
-			      PROXY_FORMAT_802_3,
-			      conn_handle);
-#endif
-	sm_exec ((HANDLE) p_elan, E_BUS_SVC_READY);
-      } else {
-	assert (conn_handle == p_elan->mcast_rcv_conn_handle);
-	EVENT (EM_EVENT, ("Multicast Forward VCC Ready\n"));
-	p_elan->vc_ready_mask |= READY_MCAST_RCV;
-#ifdef PROXY
-	proxy_mcast_rcv_add (p_elan->lport_handle,
-			     vpi,
-			     vci,
-			     p_elan->lec_state.c14_lec_id,
-			     PROXY_FORMAT_802_3,
-			     conn_handle);
-#endif
-      }
-      
-      break;
-      
-    case LEC_CTRL :
-      
-      if (calling_party) {
-	if (conn_handle == p_elan->lecs_conn_handle) {
-	  EVENT (EM_EVENT, ("Configuration Direct VCC Ready\n"));
-	  p_elan->vc_ready_mask |= READY_LECS;
-	  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"));
-	  p_elan->vc_ready_mask |= READY_CTRL_DIRECT;
-	  sm_exec ((HANDLE) p_elan, E_LES_SVC_READY);
-	}
-      } else {
-	assert (conn_handle == p_elan->ctrl_dist_conn_handle);
-	EVENT (EM_EVENT, ("Control Distribute VCC Ready\n"));
-	p_elan->vc_ready_mask |= READY_CTRL_DIST;
-      }
-      break;
-      
-    default:
-      assert (FALSE);
-    }
-    break;
-    
-  case CONN_RELEASE :
-    switch (p_conn->conn_type) {
-    case LEC_DIRECT :
-      
-      /* No Action Necessary. */
-#ifdef PROXY
-      proxy_vcc_del (p_elan->lport_handle, vpi, vci);
-#endif
-      EVENT (EM_EVENT, ("Data Direct VCC Torn Down\n"));
-      cm_sap_svc_teardown(conn_handle);
-      break;
-      
-    case LEC_MCAST :
-      
-      EVENT (EM_EVENT, ("Multicast VCC Torn Down\n"));
-#ifdef PROXY
-      proxy_vcc_del (p_elan->lport_handle, vpi, vci);
-#endif
-      act_bus_svc_teardown ((HANDLE) p_elan);
-      sm_exec ((HANDLE) p_elan, E_BUS_SVC_REL_NORM);
-      break;
-      
-    case LEC_CTRL :
-      
-      if (conn_handle == p_elan->lecs_conn_handle) {
-	EVENT (EM_EVENT, ("Configuration Direct VCC Torn Down\n"));
-	act_lecs_vc_teardown ((HANDLE) p_elan);
-	sm_exec ((HANDLE) p_elan, E_LECS_SVC_RELEASE);
-      }
-      else if ((conn_handle == p_elan->ctrl_direct_conn_handle) ||
-	       (conn_handle == p_elan->ctrl_dist_conn_handle)) {
-	EVENT (EM_EVENT, ("Control VCC Torn Down\n"));
-	act_les_svc_teardown ((HANDLE) p_elan);
-	sm_exec ((HANDLE) p_elan, E_LES_SVC_RELEASE);
-      }
-      break;
-      
-    default:
-      assert (FALSE);
-    }
-  default:
-    break;
-  }
-}
-
-/*++
-* ==================
-* = lc_sap_connect =
-* ==================
---*/
-BOOLEAN lc_sap_connect (HANDLE       lc_elan_handle,
-                        CONN_INFO   *p_conn_info,
-                        HANDLE       conn_handle,
-                        HANDLE      *p_conn_context,
-                        UINT32      *p_age_limit,
-                        UINT32      *p_reject_reason)
-   {
-   LC_ELAN_CONTEXT   *p_elan;
-   UINT16             blli_codepoint;
-   BOOLEAN            pmp;
-   STATUS             status;
-
-   p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-   status = lc_conn_info_check ((HANDLE) p_elan,
-                                p_conn_info,
-                                &blli_codepoint,
-                                &pmp);
-
-   switch (status)
-      {
-      case STATUS_K_SUCCESS :
-
-         switch (blli_codepoint)
-            {
-            case BLLI_CONTROL :
-
-               /* This must be an incoming Control Distribute VCC.  Make sure
-                * we are in the correct state to accept this connection and
-                * that there isn't already a control distribute VCC open.
-                */
-               if ((p_elan->sm_state == S_JOIN_WAIT) &&
-                   (p_elan->ctrl_dist_conn_handle == NULL))
-                  {
-                  p_elan->ctrl_dist_conn_handle = conn_handle;
-                  *p_conn_context               = p_elan->ctrl_conn_context;
-                  *p_age_limit                  = 0;
-                   EVENT (EM_EVENT, ("Accepting Control Distribute VCC.\n"));
-                  return TRUE;
-                  }
-               else
-                  {
-                  *p_reject_reason = CAUSE_NORMAL;
-                  EVENT (EM_EVENT, ("Rejecting Spurious BLLI_control VCC.\n"));
-                  return FALSE;
-                  }
-
-            case BLLI_DIRECT_802_3 :
-
-               /* This is an incoming data-direct VCC.  If we are in the
-                * operational state, accept the connection.
-                */
-               if (p_elan->sm_state == S_OPERATIONAL)
-                  {
-                  *p_conn_context   = p_elan->direct_conn_context;
-                  *p_age_limit      = p_elan->lec_state.c12_vcc_timeout;
-                  EVENT (EM_EVENT, ("Accepting Data Direct VCC.\n"));
-                  return TRUE;
-                  }
-               else
-                  {
-                  *p_reject_reason = CAUSE_NORMAL;
-                  EVENT (EM_EVENT,
-                         ("Rejecting Data Direct VCC (not operational).\n"));
-                  return FALSE;
-                  }
-
-            case BLLI_BUS_802_3 :
-
-               /* This is an incoming BUS distribute VCC.  If we are in the
-                * S_BUS_SVC_WAIT state and there is no currently open BUS
-                * distribute VCC, accept the connection.
-                *
-                * Also accept incoming BUS connections if we're in the
-                * operational state.  Some BUS implementations may take a long
-                * time to establish a BUS distribute VCC due to an ambiguity
-                * in the LUNI spec.
-                */
-               if (((p_elan->sm_state == S_BUS_SVC_WAIT) ||
-                    (p_elan->sm_state == S_OPERATIONAL)) &&
-                   (p_elan->mcast_rcv_conn_handle == NULL))
-                  {
-                  p_elan->mcast_rcv_conn_handle = conn_handle;
-                  *p_conn_context         = p_elan->mcast_conn_context;
-                  *p_age_limit            = 0;
-                  EVENT (EM_EVENT, ("Accepting Multicast Distribute VCC.\n"));
-                  return TRUE;
-                  }
-               else
-                  {
-                  *p_reject_reason = CAUSE_NORMAL;
-                  EVENT (EM_EVENT, ("Rejecting Spurious BLLI_mcast VCC.\n"));
-                  return FALSE;
-                  }
-
-            case BLLI_DIRECT_802_5 :
-            case BLLI_BUS_802_5 :
-
-               EVENT (EM_EVENT, ("Rejecting 802.5 VCC - not supported.\n"));
-               *p_reject_reason = CAUSE_NORMAL;
-               return FALSE;
-
-            default :
-               assert (FALSE);
-            }
-
-      case STATUS_K_MISMATCH :
-
-         return FALSE;
-
-      case STATUS_K_REJECT :
-
-         if (p_conn_info->blli.l2_proto == ATM_L2_ISO8802)  /* 0x12 */
-             EVENT (EM_EVENT, ("Rejecting LANE2 LLC-muxed VCC - not supported.\n"));
-         *p_reject_reason = CAUSE_NORMAL; /*???*/
-         return FALSE;
-
-      default :
-         assert (FALSE);
-      }
-
-   return FALSE;
-   }
-
-
-/*++
-* ==================
-* = lec_config_req =
-* ==================
---*/
-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;
-}
-
-/*++
-* =============
-* = tlv_parse =
-* =============
-*
-* Status:
-*
-* Description:
-*
-* Issues:
-*   None
-*
-* Returns:
-*         0 for successful parsing
-*         1 type value all 0s type
-*         2 for unknown type
-*         3 for short TLV
-*         4 for incorrect length for Value
---*/
-int 
-tlv_parse (LC_ELAN_CONTEXT  *p_elan,
-	   UINT8             buffer[],      /* pointer to the frame       */
-	   UINT32            length,        /* length of packet inc. TLVs */
-	   UINT8            *p_tlv_index)   /* pointer to the current TLV */
-{
-  LE_CONFIG_FRAME *p_frame = (LE_CONFIG_FRAME *)buffer;
-  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 (3);
-  }
-  
-  /* 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;
-  *p_tlv_index = i;
-
-  if (tlv_type == (UINT32)0) {
-    EVENT (EM_EVENT, ("TLV type missing.\n"));   /* LANE2: 4.3.12 */
-    return (1);
-  }
-  
-  if ((UINT32) (i + tlv_length) > length) {
-    EVENT (EM_EVENT, ("TLV value missing, type = %08lx.\n", tlv_type));
-    return (3);
-  }
-
-  tlv_value1 = 0;
-  tlv_value2 = 0;
-  tlv_value4 = 0;
-  
-  switch (tlv_length) {
-  case 0 :     /* LANE2 has 0-length TLVs */
-    break;
-  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;
-
-  case 20 : /* LANE2: e.g. preferred LES */
-    *p_tlv_index = i + 20;
-    break;
-
-  default: /* LANE2: Config-Frag-Info and L3-Address have variable lengths */
-    *p_tlv_index = i + tlv_length;
-    break;
-
-  }
-
-
-  /* Verify correct TVL lengths */
-
-  switch (tlv_type) {
-  case TLV_X5_ADJUSTEMENT: /* LANE2 */
-    if (tlv_length != 0) {
-      EVENT (EM_EVENT, ("Incorrect TLV length=%d for type %08lx.\n",
-                        tlv_length, tlv_type));
-      return (4);
-    }
-    break;
-
-  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 :
-  case TLV_SERVICE_CATEGORY : /* LANE2 */
-    if (tlv_length != 2) {
-      EVENT (EM_EVENT, ("Incorrect TLV length=%d for type=%08lx.\n",
-			tlv_length, tlv_type));
-      return (4);
-    }
-    break;
-    
-  case TLV_VCC_TIMEOUT :
-  case TLV_AGING_TIME :
-  case TLV_MCAST_VCC_AVG_RATE :
-  case TLV_MCAST_VCC_PEAK_RATE :
-  case TLV_ELAN_ID : /* LANE2 */
-    if (tlv_length != 4) {
-      EVENT (EM_EVENT, ("Incorrect TLV length=%d for type=%08lx.\n",
-			tlv_length, tlv_type));
-      return (4);
-    }
-    break;
-
-  case TLV_PREFERRED_LES :  /* Both here LANE2 */
-  case TLV_LLC_MUXED_ATM_ADDRESS :
-    if (tlv_length != 20) {
-      EVENT (EM_EVENT, ("Incorrect TLV length=%d for type=%08lx.\n",
-			tlv_length, tlv_type));
-      return(4);
-    }
-    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_X5_ADJUSTEMENT :
-    if (lane_version() != 2) {
-      EVENT (EM_EVENT, ("Acting as non LANEv2 client, ignoring X5 Adj. TLV\n"));
-      return(0);
-    }
-    if (ntoh16(p_frame->hdr.op_code) == LE_JOIN_RSP) {
-        EVENT (EM_EVENT, ("X5 Adjustement TLV received with LE_JOIN_RSP frame. See LANE2: 5.3.1.2\n"));
-        return(0);
-    }
-    switch (p_frame->max_frame_size) {
-    case 1:
-    case 2:
-      if (ntoh16(p_frame->hdr.flags) & LE_FLAG_V2_CAPABLE)
-          p_elan->lec_state.c3_lan_mtu = MTU_1580;
-      break;
-    case 5:
-      if (ntoh16(p_frame->hdr.flags) & LE_FLAG_V2_CAPABLE)
-          p_elan->lec_state.c3_lan_mtu = MTU_1580;
-      else
-          EVENT (EM_EVENT, ("Received X5 max. frame size but V2 Capable flag was not set\n"));
-      break;
-    default:
-      break;
-    }
-    break;
-
-  case TLV_PREFERRED_LES :  /* toimiiko ??? */
-    memcpy (&p_elan->lec_state.c35_preferred_les, buffer + i, 20);
-#if 0
-    ATM_COPY (buffer + i, p_elan->lec_state.c35_preferred_les);
-#endif
-    break;
-
-  case TLV_CONFIG_FRAG_INFO :
-    EVENT (EM_SERR, ("Config-Frag-Info received but not supported. Tough luck.\n"));
-    break;
-
-  case TLV_ELAN_ID :  /* LANE2: LLC-muxed stuff */
-    p_elan->lec_state.c31_elan_id = tlv_value4;
-  case TLV_LLC_MUXED_ATM_ADDRESS : /* LANE2 */
-  case TLV_SERVICE_CATEGORY :      /* LANE2 */
-  case TLV_L3_ADDRESS :            /* LANE2 */
-  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;
-  }
-  return (0);
-}  
-
-/*++
-* ==================
-* = lec_config_rsp =
-* ==================
---*/
-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;
-
-  if (length < sizeof (LE_CONFIG_FRAME)) {
-    EVENT (EM_EVENT, ("Received runt Config Response frame - %ld bytes.\n",
-		      length));
-    return;
-  }
-
-  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;
-  }
-
-  if (length > sizeof (LE_CONFIG_FRAME)) {
-    EVENT (EM_EVENT, ("Received Config Response with TLVs\n"));
-  }
-
-  /* LANE2: If X5 Adj. TLV is present these values may change
-   *        during tlv_parse(). In other words, do not move this
-   *        switch block below tvl_parse(). These values will stay
-   *        if X5 Adj. TLV is not received with LE_CONFIG_RSP frame.
-   * The correct handling of different flag, client version and TLV
-   * value combinations needs to be checked later.
-   */
-  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;
-  case 5  : /* LANE2 */
-    if (lane_version() == 2)
-      p_elan->lec_state.c3_lan_mtu = MTU_1580;
-    else
-      EVENT (EM_EVENT, ("Acting as non LANEv2 client, ignoring X5 max. frame size\n"));
-    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);
-
-  if (tlv_index < length) {
-    while (tlv_index < length) {
-      if ( 1 == tlv_parse(p_elan, p_packet, length, &tlv_index) &&
-           p_elan->lec_state.c29_v2_capable)
-        return;    /* TLV type was 0 with LANE2 => discard frame */
-    }
-    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,
-	      lane_version());
-  }
-  sm_exec ((HANDLE) p_elan, E_RCV_CONFIG_RSP);
-}
-
-/*++
-* ================
-* = lec_join_req =
-* ================
---*/
-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 =
-* ================
---*/
-STATIC void 
-lec_join_rsp (LC_ELAN_CONTEXT *p_elan,
-	      void            *p_packet,
-	      UINT32           length)
-{
-  LE_JOIN_FRAME   *frame;
-
-  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);
-
-  
-  /* LANE2: If LES is not v2 capable we can't be either */
-  if (frame->hdr.flags & hton16(LE_FLAG_V2_REQUIRED) &&
-      p_elan->lec_state.c29_v2_capable == FALSE) {
-    EVENT (EM_NERR, ("LES requires LANEv2 but I'm not v2 capable\n"));
-    return;
-  }
-  if (!frame->hdr.flags & hton16(LE_FLAG_V2_REQUIRED)) { /* LES not v2 */
-    p_elan->lec_state.c29_v2_capable = FALSE;
-    p_elan->lec_state.c32_selective_mcast = FALSE;
-  }
-  /* Note: ELAN-ID and Local-Segment-ID TLVs are ignored
-   * since we do not use LLC-MUXED VCCs and know nothing
-   * about token ring
-   */
-  if (frame->tlv_count != 0)
-    EVENT (EM_WARN, ("Got %d TLV(s), ignoring\n", frame->tlv_count));
-
-
-  /* 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. */
-  
-  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;
-  case 5  : p_elan->lec_state.c3_lan_mtu = MTU_1580;     break; /* LANE2 */
-  default : return;
-  }
-
-  /* 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));
-
-  /* Provide the state machine with a received-join-response event. */
-  
-  sm_exec ((HANDLE) p_elan, E_RCV_JOIN_RSP);
-}
-
-/*++
-* ===================
-* = lec_ready_query =
-* ===================
---*/
-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 =
-* =================
---*/
-STATIC void 
-lec_ready_ind (LC_ELAN_CONTEXT *p_elan,
-	       HANDLE           conn_handle)
-{
-  /* No Action Necessary. */
-}
-
-/*++
-* ===============
-* = lec_reg_req =
-* ===============
---*/
-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 =
-* ===============
---*/
-STATIC void 
-lec_reg_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_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 =
-* =================
---*/
-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 =
-* =================
---*/
-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 =
-* ===============
---*/
-STATIC void 
-lec_arp_req (LC_ELAN_CONTEXT *p_elan,
-	     void            *p_packet,
-	     UINT32           length)
-{
-  LE_ARP_FRAME   *frame;
-  LE_ARP_FRAME   *response;     /* LANE2 */
-  STATUS         status;
-  UINT32         user_data;
-  int            sizeoftlvs;
-  size_t         framelength;   /* LANE2 */
-
-  /* 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;
-
-  framelength = sizeof(LE_ARP_FRAME) + p_elan->lec_state.sizeoftlvs; /* LANE2: Create new response frame */
-  response = (LE_ARP_FRAME *)os_mem_alloc(framelength);
-  memset(response, 0, framelength);
-  memcpy(response, frame, sizeof(LE_ARP_FRAME));
-
-  sizeoftlvs = length - sizeof(LE_ARP_FRAME);
-  EVENT (EM_DEBUG, ("lec_arp_req: sizeoftlvs=%d\n", sizeoftlvs));
-
-  switch (ntoh16 (frame->target_lan_dst.tag)) {
-  case TAG_NOT_PRESENT: /* LANE2: Targetless LE_ARP_REQUEST possible */
-    if (p_elan->lec_state.c29_v2_capable)
-      la_arp_update (p_elan->la_elan_handle,
-                     frame->src_lan_dst.mac_addr,
-                     frame->src_atm_addr,
-                     (ntoh16(frame->hdr.flags) &
-                      LE_FLAG_REMOTE_ADDR) ? TRUE : FALSE,
-                     (char *)frame + 1,
-                     sizeoftlvs,
-                     1,  /* LANE2, targetless LE_ARP */
-                     0); /* LANE2, not no-source LE_NARP */
-
-    break;
-  case TAG_MAC_ADDR:
-    if (lc_dest_is_registered ((HANDLE) p_elan,
-			       frame->target_lan_dst.mac_addr))
-      {
-	response->hdr.op_code = hton16 (LE_ARP_RSP);
-	response->hdr.status  = hton16 (LE_STATUS_SUCCESS);
-	response->hdr.flags   = hton16 (0);        /* Clear Remote Flag */
-	ATM_COPY (p_elan->lec_state.c1n_my_atm_addr, response->target_atm_addr);
-	memcpy(response + 1, p_elan->lec_state.tlvs, p_elan->lec_state.sizeoftlvs);
-	if (p_elan->lec_state.sizeoftlvs != 0) frame->tlv_count++;
-	user_data = USER_DATA_INTERNAL;
-	status = cm_sap_xmt_vc (p_elan->ctrl_direct_conn_handle,
-				(void *) response,
-				framelength,
-				user_data,
-				NULL);
-	break;
-      } else { /* check if our bridging tables knows this MAC */
-        if (p_elan->lec_state.c4_proxy_flag == TRUE)
-          kernel_sendmsg(l_should_bridge, frame->target_lan_dst.mac_addr,
-                         NULL, NULL, frame->hdr.tran_id,
-                         NULL, 0, 0, frame->hdr.req_lec_id);
-        break;
-      }
-    
-    break;
-  case TAG_ROUTE_DESC:
-    break;
-  } /* switch */
-  os_mem_dealloc(response);
-  return;
-}
-
-/*++
-* ===============
-* = lec_arp_rsp =
-* ===============
-*
-* LANE2: LE_ARP_FRAME can now contain TLVs and therefore has
-* variable size. 
-*
---*/
-STATIC void 
-lec_arp_rsp (LC_ELAN_CONTEXT *p_elan,
-	     void            *p_packet,
-	     UINT32           length)
-{
-  LE_ARP_FRAME  *frame;
-  char *tmp = p_packet;
-  int sizeoftlvs;
-
-  frame = (LE_ARP_FRAME *)p_packet;
-  
-  if (length < sizeof (LE_ARP_FRAME))
-    return;
-  sizeoftlvs = length - sizeof(LE_ARP_FRAME);
-  tmp += sizeof(LE_ARP_FRAME);
-  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,
-			   (char *)(frame + 1),
-			   sizeoftlvs,
-			   0,   /* LANE2, not targetless LE_ARP */
-			   0);   /* LANE2, not no-source  LE_ARP */
-          
-	}
-      }
-      break;
-    case TAG_ROUTE_DESC:
-      break;
-    }
-  }  
-  return;
-}
-
-/*++
-* =================
-* = lec_flush_req =
-* =================
---*/
-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\n",
-                 disp_atm_text(p_elan->lec_state.c1n_my_atm_addr)));
-  EVENT(EM_DEBUG,("                              for :%s\n",             
-		  disp_atm_text(frame->target_atm_addr)));
-  if (ATM_EQUAL (p_elan->lec_state.c1n_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 =
-* =================
---*/
-STATIC void 
-lec_flush_rsp(LC_ELAN_CONTEXT *p_elan,
-	      void            *p_packet,
-	      UINT32           length)
-{
-  LE_FLUSH_FRAME *frame;
-
-  frame = (LE_FLUSH_FRAME *)p_packet;
-  EVENT (EM_RDATA, ("Received flush response.\n"));
-
-  if (length < sizeof(LE_CTRL_HDR))
-    return;
-
-  if ((frame->hdr.status == ntoh16 (LE_STATUS_SUCCESS)) &&
-      (ntoh16(frame->hdr.req_lec_id) == p_elan->lec_state.c14_lec_id)) {
-    la_flush_complete(p_elan->la_elan_handle,
-		      ntoh32 (frame->hdr.tran_id));
-  }
-  return;
-}
-
-/*++
-* ================
-* = lec_narp_req =
-* ================
-*
-* LANE2 client must react to LE_NARP_REQUEST, see 7.1.35
---*/
-STATIC void 
-lec_narp_req (LC_ELAN_CONTEXT *p_elan,
-	      void            *p_packet,
-	      UINT32           length)
-{
-  
-  LE_NARP_FRAME *frame = (LE_NARP_FRAME *)p_packet;
-  int sizeoftlvs, no_source;
-  char empty[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
-  EVENT (EM_RDATA, ("Received LE_NARP_REQUEST.\n"));
-
-  if (length < sizeof(LE_NARP_FRAME))
-    return;
-
-  if (p_elan->sm_state != S_OPERATIONAL)
-    return;
-
-  if ( (frame->hdr.status != ntoh16(LE_STATUS_SUCCESS)) ||
-       (ntoh16(frame->hdr.req_lec_id) == p_elan->lec_state.c14_lec_id) )
-    return;
-
-  sizeoftlvs = length - sizeof(LE_NARP_FRAME);
-  no_source = ( memcmp(&frame->src_atm_addr, &empty, 20) == 0); /* true if source == 0 */
-  if (p_elan->lec_state.c29_v2_capable)
-    la_arp_update (p_elan->la_elan_handle,
-                   frame->src_lan_dst.mac_addr,
-                   frame->src_atm_addr,
-                   (ntoh16(frame->hdr.flags) &
-                    LE_FLAG_REMOTE_ADDR) ? TRUE : FALSE,
-                   (char *)frame + 1,
-                   sizeoftlvs,
-                   0, /* LANE2, not targetless LE_ARP */
-                   no_source);
-
-}
-
-/*++
-* ===============
-* = lec_top_req =
-* ===============
---*/
-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;
-
-  if (length < sizeof (LE_TOPOLOGY_FRAME))
-    return;
-
-  la_topology_change_set (p_elan->la_elan_handle,
-			  (ntoh16(frame->hdr.flags) &
-			   LE_FLAG_TOPOLOGY_CHANGE) ? TRUE : FALSE);
-  
-  return;
-}
-
-/*++
-* ==============
-* = lc_sap_rcv =
-* ==============
---*/
-void lc_sap_rcv (HANDLE     conn_context,
-                 HANDLE     conn_handle,
-                 UINT32     length,
-                 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;
-  /* Convert handles to structure pointers. */
-  
-   p_conn = (LEC_CONN_CONTEXT *) conn_context;
-   p_elan = (LC_ELAN_CONTEXT  *) p_conn->lc_elan_handle;   
-   hdr = (LE_READY_HDR *)*pp_packet;
-   
-   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;
-
-   /* Check the version field, discard if it does not match. */
-
-   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;
-}
-
-void 
-lc_addr_delete(HANDLE lc_elan_handle, unsigned char *atm_addr)
-{
-  LC_ELAN_CONTEXT *p_elan;
-
-  p_elan = (LC_ELAN_CONTEXT *) lc_elan_handle;
-
-  la_addr_delete(p_elan->la_elan_handle, atm_addr, FALSE);
-}
diff -ur --new-file old/atm/led/lec_ctrl.h new/atm/led/lec_ctrl.h
--- old/atm/led/lec_ctrl.h	Sat Dec  5 01:36:17 1998
+++ new/atm/led/lec_ctrl.h	Thu Jan  1 01:00:00 1970
@@ -1,465 +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_ctrl.h
-*   
-* Overview:
-*   The LEC_CTRL module is a subcomponent of the LAN Emulation client (LEC)
-*   module.  It is responsible for all of the control aspects of LAN Emulation
-*   clienthood.  It implements the LEC state machine and handles all LE control
-*   packets.
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*    4-Oct-94  TLR   Created.
-*
-* Description:
-*
-* Data SAP Requirements:
-*   The LEC_DATA module is the user of this interface to the LEC_CTRL module.
-*   Each instance of the LEC_DATA module joins an ELAN.  In the process, it
-*   must first register with the LEC_CTRL module (via lc_register) to obtain
-*   an lc_elan_handle.  This handle uniquely represents this ELAN's LEC_CTRL
-*   instance.
-*
-*   Once LEC_CTRL registration is successful, the LEC_DATA instance must
-*   register with the Connection Manager (CM) as a SAP client.  In so doing,
-*   it MUST provide the following arguments:
-*
-*     - The 'sap_context' MUST be the lc_elan_handle returned by lc_register.
-*
-*     - The 'vc_notify_callback' MUST be the lc_sap_vc_notify function
-*       described in this interface.
-*
-*     - The 'svc_connect_callback' MUST be the lc_sap_connect function
-*       described in this interface.
-*
-*     - The 'link_status_callback' MAY be ignored by specifying it as NULL.
-*
-* Call Sequence Requirements:
-*
-*   - lc_create
-*     - lc_register
-*       - lc_join_start
-*         - (ELAN_STATUS_CALLBACK)
-*           - lc_addr_resolve
-*       - lc_deregister
-*     - lc_destroy
-*
-* Example Usage Scenario  (callbacks are shown in parentheses):
-*
-*   lc_create...............At system initialization time, an instance of the
-*                           LEC module is created.  
-*   lc_register.............
-*   lc_join_start...........
-*   (elan_status_callback)..
-*   lc_addr_resolve.........
-*   lc_addr_resolve.........
-*   (elan_status_callback)..
-*   (elan_status_callback)..
-*   lc_deregister...........
-*   lc_destroy..............
-*/
-#ifndef LEC_CTRL_H
-#define LEC_CTRL_H
-#include "cm_sap.h"
-#include "lane2.h"   /* LANE2 */
-/*************************************************************************
- * Callbacks
- *************************************************************************/
-
-/*++
-* ==========================
-* = (ELAN_STATUS_CALLBACK) =
-* ==========================
-*
-* Overview:
-*   This callback is invoked from within the LEC_CTRL module and informs its
-*   user (the LEC_DATA module) that the availability of a specific ELAN has
-*   changed.  Either the ELAN has become available or it has become
-*   unavailable.
-*
-*   ELAN availability differs from Link Status in that an ELAN is not available
-*   until the link becomes available AND the join process is completed.
-*
-* Arguments:
-*   ld_elan_handle  - (IN) Handle describing the ELAN instance of the data
-*                          module.
-*
-*   elan_available  - (IN) Boolean value indicating whether the ELAN has become
-*                          available or unavailable.
-*
-*   mac_addr        - (IN) The MAC address for this station in this ELAN.
-*
-*   lan_mtu         - (IN) MTU size of the ELAN.
-*
-*   p_elan_name     - (IN) Name of the ELAN.
-*
-*   lec_id          - (IN) LEC_ID of this LEC in the newly joined ELAN.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-typedef void (*ELAN_STATUS_CALLBACK) (HANDLE     ld_elan_handle,
-                                      BOOLEAN    elan_available,
-                                      LAN_MTU    lan_mtu,
-                                      char      *p_elan_name,
-                                      UINT16     lec_id);
-
-/*************************************************************************
- * Function Prototypes
- *************************************************************************/
-
-/*++
-* =============
-* = lc_create =
-* =============
-*
-* Overview:
-*   Create an instance of the LEC_CTRL module.  This occurs during port
-*   initialization.  This instance is not related to Emulated LANs.  A single
-*   instance of this module must exist to support multiple ELANs on a single
-*   physical interface.
-*
-* Arguments:
-*   os_handle            - (IN)  The handle of the OS module.  This is used to
-*                                allocate memory and timers.
-*
-*   cm_handle            - (IN)  Handle of the associated CM instance.
-*
-*   line_up_handle       - (IN)  Handle of the associated Line-Up instance.
-*
-*   elan_status_callback - (IN)  Address of ELAN status callback.
-*
-*   p_lc_handle          - (OUT) The returned handle for the newly created
-*                                instance of the LEC_CTRL module.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Success, see postconditions.
-*   STATUS_K_RESOURCES  - Insufficient resources to complete the operation.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The new ctrl_handle is valid.
-*
-*   A le_cache module instance was also created.
---*/
-STATUS lc_create (HANDLE                line_up_handle,
-                  ELAN_STATUS_CALLBACK  elan_status_callback,
-                  HANDLE               *p_lc_handle);
-
-
-/*++
-* ==============
-* = lc_destroy =
-* ==============
-*
-* Overview:
-*   Destroys an instance of the LEC_CTRL module.  This is called when a
-*   physical ATM port is disabled or removed.
-*
-* Arguments:
-*   lc_handle     - (IN)  The handle returned by lc_create.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The handle is now invalid.
-*
---*/
-void lc_destroy (HANDLE  lc_handle);
-
-
-/*++
-* ===============
-* = lc_register =
-* ===============
-*
-* Overview:
-*   Register a new ELAN with the LEC_CTRL module.  This is called by the
-*   LEC_DATA module when a protocol registers with the LAN Emulation Client.
-*
-* Arguments:
-*   lc_handle           - (IN)  Handle returned by lc_create.
-*
-*   ld_elan_handle      - (IN)  Handle of LEC_DATA ELAN instance.
-*
-*   addr_reg_handle     - (IN)  Handle of the associated Address Registration
-*                               module instance.
-*
-*   mac_addr            - (IN)  This station's MAC address.  If this argument
-*                               is not all zeros, this address shall override
-*                               the internal address read from hardware.
-*
-*   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)  Specification of the initialization method to
-*                               be used when joining the ELAN.
-*
-*   manual_atm_addr     - (IN)  Manually entered ATM address which may be needed
-*                               for certain init methods that may be specified
-*                               in init_method.
-*
-*   proxy_flag          - (IN)  Proxy flag for this ELAN join.
-*
-*   lport_handle        - (IN)  Logical Port Handle.  This is used when the
-*                               LEC is a proxy.  It identifies the ELAN's
-*                               logical port to the fast-path.
-*
-*   p_text              - (IN)  Descriptive text constant.
-*
-*   p_lc_elan_handle    - (OUT) Handle for this ELAN instance of the control
-*                               module.
-*
-* Returns:
-*   STATUS_K_SUCCESS    - Success, see postconditions.
-*   STATUS_K_RESOURCES  - Insufficient resources to complete operation.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The new handle (*p_lc_elan_handle) is valid.
---*/
-STATUS lc_register (HANDLE       lc_handle,
-                    HANDLE       ld_elan_handle,
-                    HANDLE       addr_reg_handle,
-                    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_lc_elan_handle,
-                    BOOLEAN      v2_capable,
-                    ADDR_ATM     preferred_les,
-                    ADDR_L3      l3_address,
-                    const char  *foreId); /* Info string displayed by Fore switches */
-
-
-/*++
-* =================
-* = lc_deregister =
-* =================
-*
-* Overview:
-*   Deregisters an instance of an ELAN from the LEC_CONTROL module.  This is
-*   called by the LEC_DATA module when a protocol deregisters with the LAN
-*   Emulation Client.
-*
-* Arguments:
-*   lc_elan_handle  - (IN) Handle returned by lc_register.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The lc_elan_handle is invalid.
---*/
-void lc_deregister (HANDLE lc_elan_handle);
-
-/*++
-* =========================
-* = lc_dest_is_registered =
-* =========================
-*
-* Overview:
-*   Checks to see if the specified LAN destination is a registered LAN
-*   destination of this LEC
-*
-* Arguments:
-*   lc_elan_handle  - (IN) Handle returned by lc_register.
-*   p_lan_dest      - (IN) Pointer to LAN destination to be looked up.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-BOOLEAN lc_dest_is_registered (HANDLE  lc_elan_handle,
-                               ESI     p_dst_addr);
-
-/*++
-* =================
-* = lc_elan_reset =
-* =================
-*
-* Overview:
-*
-* Arguments:
-*   lc_elan_handle  - (IN) Handle returned by lc_register.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*
-* Postconditions:
---*/
-void lc_elan_reset (HANDLE lc_elan_handle);
-
-
-/*++
-* =================
-* = lc_join_start =
-* =================
-*
-* Overview:
-*   Requests the initiation of the join process.  The LEC_CTRL module is
-*   given the handle of the data SAP so it can request SVCs on its behalf.
-*
-* Arguments:
-*   lc_elan_handle          - (IN) Handle returned by lc_register.
-*   data_sap_handle         - (IN) Handle returned by cm_sap_register.
-*   direct_conn_context     - (IN) Connection Context to be used in setting up
-*                                  Data-Direct VCCs.
-*   mcast_conn_context      - (IN) Connection Context to be used in setting up
-*                                  Multicast VCCs.
-*   ctrl_conn_context       - (IN) Connection Context to be used in setting up
-*                                  Control VCCs.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   The Data SAP for this instance must be registered according to the above
-*   mentioned requirements.
-*
-* Postconditions:
-*   None
---*/
-void lc_join_start (HANDLE  lc_elan_handle,
-                    HANDLE  data_sap_handle,
-                    HANDLE  direct_conn_context,
-                    HANDLE  mcast_conn_context,
-		    const char *qos_spec,
-                    HANDLE  ctrl_conn_context);
-
-/*++
-* ====================
-* = lc_sap_vc_notify =
-* ====================
-*
-* Overview:
-*   SAP VC notification callback to be used when registering with the CM as
-*   a SAP.
-*
-*   Refer to cm_sap.h for the full description of this function.
-*
---*/
-void lc_sap_vc_notify (HANDLE           conn_context,
-                       HANDLE           conn_handle,
-                       NOTIFY_EVENT     event,
-                       UINT16           reason,
-                       UINT32           endpoint_ref,
-                       BOOLEAN          calling_party_flag);
-
-/*++
-* ==================
-* = lc_sap_connect =
-* ==================
-*
-* Overview:
-*   SAP connect notification callback to be used when registering with the
-*   CM as a SAP.
-*
-*   Refer to cm_sap.h for the full description of this function.
-*
---*/
-BOOLEAN lc_sap_connect (HANDLE       sap_context,
-                        CONN_INFO   *p_conn_info,
-                        HANDLE       conn_handle,
-                        HANDLE      *p_conn_context,
-                        UINT32      *p_age_limit,
-                        UINT32      *p_reject_reason);
-
-/*++
-* ==============
-* = lc_sap_rcv =
-* ==============
-*
-* Overview:
-*   SAP receive notification callback to be used when registering with the
-*   CM as a SAP.
-*
-*   Refer to cm_sap.h for the full description of this function.
-*
---*/
-void lc_sap_rcv (HANDLE     conn_context,
-                 HANDLE     conn_handle,
-                 UINT32     length,
-                 UINT32     user_data,
-                 AAL_DATA  *p_aal_data,
-                 void     **pp_packet);
-
-/* 
- * Forwards address deletion request to lec_arp module.
- */
-void lc_addr_delete(HANDLE lc_elan_handle, unsigned char *atm_addr);
-
-#endif /* LEC_CTRL_H */
-
-
-
-
diff -ur --new-file old/atm/led/main.c new/atm/led/main.c
--- old/atm/led/main.c	Thu Apr 22 17:13:23 1999
+++ new/atm/led/main.c	Wed Jun  2 23:36:55 1999
@@ -1,3 +1,5 @@
+/* main.c - Do what ever a LANE client does */
+
 /*
  * Marko Kiiskila carnil@cs.tut.fi 
  * 
@@ -21,12 +23,8 @@
  * SOFTWARE.
  * 
  */
-/*
- *
- * Initialization, main loop
- * 
- * $Id: main.c,v 1.19 1996/08/06 14:14:11 carnil Exp carnil $
- */
+
+/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
 
 /* Global includes */
 #include <stdlib.h>
@@ -36,761 +34,418 @@
 #include <signal.h>
 #include <string.h>
 #include <getopt.h>
+#include <errno.h>
 
 #include <atm.h>
+#include <atmd.h>
 
-/* Digital includes */
-#include "codes.h"
-#include "g_types.h"
-#include "lec.h"
-#include "af_lane.h"
-#include "utl.h"
-#include "lec_ctrl.h"
-#include "utl_os.h"
-#include "g_event.h"
-#include "addr_reg.h"
-#include "le_disp.h"
-#include "cm.h"
+#include <linux/atmlec.h>
 
 /* Local incs */
-#include "conn.h"
-#include "timers.h"
-#include "kernel_itf.h"
-#include "lane2.h"
-
-/* LD_ELAN_CONTEXT
- *  Context block for a single ELAN membership.  An instance of this structure
- *  is created each time the LEC_DATA module registers a new ELAN membership.
- *
- *  p_next.................Next pointer that allows this structure to be
- *                         stored in a simple list.
- *
- *  lec_handle.............The handle of this LEC module instance.  This is
- *                         the handle that was generated by the lec_create
- *                         function.
- *
- *  client_context.........The context supplied by the ELAN client during
- *                         lec registration.  There is one context for each
- *                         ELAN.
- *
- *
- *  lc_elan_handle.........Handle for the ELAN instance of the LEC_CTRL module.
- *
- *  sap_handle.............Handle of the registered DATA SAP.
- *
- *  lan_type...............LAN Type of the joined (or joining) ELAN.
- *
- *  direct_conn_context....Connection Context for data direct VCCs.
- *
- *  bus_conn_context.......Connection Context for BUS VCCs.
- *
- *  lec_id.................LEC_ID of this LEC in the ELAN.  Used in the LAN
- *                         emulation header for data packets.
- *
- *  lec_event_callback.....Callback for ELAN events.
- *
- *  lec_rcv_callback.......Callback for received packets.
- *
- *  lec_xmt_done_callback..Callback for transmit done indications.
- */
+#include "join.h"
+#include "lec.h"
+#include "address.h"
+#include "display.h"
+#include "kernel.h"
 
-typedef struct _ld_elan {
-  struct _ld_elan        *p_next;
-  char                   *p_text;
-  HANDLE                  lec_handle;
-  HANDLE                  client_context;
-  HANDLE                  lc_elan_handle;
-  HANDLE                  sap_handle;
-  LAN_TYPE                lan_type;
-  LEC_CONN_CONTEXT        direct_conn_context;
-  LEC_CONN_CONTEXT        mcast_conn_context;
-  LEC_CONN_CONTEXT        ctrl_conn_context;
-  UINT16                  lec_id;
-  LEC_EVENT_CALLBACK      lec_event_callback;
-  LEC_RCV_CALLBACK        lec_rcv_callback;
-  LEC_XMT_DONE_CALLBACK   lec_xmt_done_callback;
-} LD_ELAN_CONTEXT;
+#define COMPONENT "main.c"
 
-/*
- * Declare a simple list type for ELAN Contexts.
- */
-SIMPLE_LIST (LD_ELAN_CONTEXT, ELAN_LIST);
-
-/* LD_CONTEXT
- *  Context structure for LEC instances.  There is one such instance for each
- *  physical port that provides LAN Emulation Client capabilities.
- *
- *  lc_handle..LEC_CTRL handle for this physical port.
- *
- *  elan_list..List of ELAN contexts that are registered to this physical port.
- */
-typedef struct {
-  HANDLE      lc_handle;
-  HANDLE      addr_reg_handle;
-  ELAN_LIST   elan_list;
-} LD_CONTEXT;
-
-int stay_alive =1;
-int reset=0;
-static int spec_version = 1;  /* By default act like LANE v1 device */
-
-#define EMOD   MOD_LEC_DATA
-#define EINST  "main.c"
-
-#define FORE_ID_LEN 256
-
-/* Mask for messages, include emask.h */
-UINT32 EMASK = (EM_SERR | EM_NERR | EM_WARN | EM_MSG);
-
-/* Protos */
-void lec_event_callback(HANDLE context, LEC_EVENT event,
-			LAN_MTU mtu, char *p_elan_name);
-static void elan_status_callback(HANDLE elan_handle, BOOLEAN elan_available,
-				 LAN_MTU lan_mtu, char *p_elan_name,
-				 UINT16 lec_id);
-void lec_rcv_callback(HANDLE context, UINT32 length,
-		      void  **pp_pkt);
-void lec_xmt_done_callback(HANDLE context, void *p_packet);
-static void sig_die(int a);
-static void usage(const char *progname);
-static int esi_convert(char *parsestring, unsigned char *mac_addr);
+static void main_loop(void);
+static int reset = 0;
 
-static void
-sig_die(int a)
+void sig_reset(int a)
 {
-  stay_alive = 0;
-  reset = 1;
+        reset = 1;  
+
+        return;
 }
 
-void
-sig_reset(int a)
+static void usage(const char *progname)
 {
-  reset = 1;  
+  printf("Usage: %s [-c LECS_address | -s LES_address] [-e esi] [-n VLAN_name]"
+    " [-m mesg_mask] [-l listen_address] [-i interface_number]"
+    " [-t 1516|1580|4544|9234|18190] [-1] [-2] [-p] [-F logfile]"
+    " [-f Fore specific name]\n", progname);
 }
 
-int lane_version(void)
+/*
+ * My First C function (TM), hessu@cs.tut.fi
+ */
+static int esi_convert(char *parsestring, unsigned char *mac_addr)
 {
-  return spec_version;
+        const char *hexchars = "abcdefABCDEF0123456789";
+        char hexnum [17+1], curr;
+        int i = 0, j = -1, hexindex = 0, tmp;
+        char *k, *string;
+        
+        if (strchr(parsestring,'.') ||     /* do we have separators like */
+            strchr(parsestring,':')) {     /* 00:20:22:23:04:05 */
+                k = parsestring;
+                for (i = 0; i < strlen(parsestring); i++) {
+                        curr = *k;
+                        if (curr == ':' || curr == '.') {   /* separator ? */
+                                if (i - j == 3) {  /* there were 2 hex characters */
+                                        ;
+                                }
+                                else if (i - j == 2) {  /* there was only 1 hex char */
+                                        hexnum [hexindex] = hexnum [hexindex-1];
+                                        hexnum [hexindex-1] = '0';
+                                        hexindex +=1;
+                                }
+                                else   /* too many hexchars in a byte */
+                                        return -1;
+                                j = i;  /* j is the location of the last separator */
+                        }
+                        else if (strchr(hexchars, curr) == NULL) /* not a hexchar ? */
+                                return -1;
+                        else {  /* we have a hex character */
+                                hexnum [hexindex] = curr;
+                                hexindex +=1;
+                        }
+                        k++;
+                }
+                hexnum [hexindex] = '\0';
+                string = hexnum;
+        } else {   /* no separators */
+                k = parsestring;
+                while (*k != '\0') {
+                        if (strchr(hexchars, *k) == NULL)
+                                return -1;
+                        k++;
+                }
+                
+                string = parsestring;
+        }
+        
+        /* the esi now looks like 002022230405 */
+        i = strlen(string);
+        if (i != 12)
+                return -1;
+        for(i=0; i<6; i++) {
+                sscanf(&string[i*2], "%2x", &tmp);
+                mac_addr[i] = (unsigned char)tmp;
+        }
+        return 0;
 }
 
-static void 
-elan_status_callback(HANDLE elan_handle, BOOLEAN elan_available,
-		     LAN_MTU lan_mtu, char *p_elan_name,
-		     UINT16 lec_id)
+/* Tells kernel what our LEC_ID is.
+ * Returns < 0 for serisous error
+ */
+static int set_lec_id(uint16_t lec_id)
 {
-  LD_ELAN_CONTEXT *elan;
+        struct atmlec_msg msg;
 
-  EVENT(EM_DEBUG,("elan_status_callback\tavailable:%d\n",elan_available));
+        memset(&msg, 0, sizeof(struct atmlec_msg));
+        msg.type = l_set_lecid;
+        msg.content.normal.flag = lec_id;
+        if (msg_to_kernel(&msg, sizeof(struct atmlec_msg)) < 0) {
+                diag(COMPONENT, DIAG_ERROR, "Could not tell kernel LEC_ID\n");
+                return -1;
+        }
 
-  elan = (LD_ELAN_CONTEXT *)elan_handle;
-  elan->lec_id = lec_id;
-  kernel_sendmsg(l_set_lecid, NULL, NULL, NULL, lec_id, NULL, 0, 0, 0);
+        return 0;
 }
 
-void
-lec_event_callback(HANDLE context, LEC_EVENT event,
-		   LAN_MTU mtu, char *p_elan_name)
+/* Tell kernel the parameters this ELAN has.
+ * Returns < 0 for serious error
+ */
+static int config_kernel(void)
 {
-  EVENT(EM_DEBUG,("lec_event_callback\t %s: %s\n",
-		  event==LEC_NETWORK_AVAILABLE?"LEC_NETWORK_AVAILABLE":"LEC_NETWORK_UNAVAILABLE",p_elan_name));
-}
+        struct atmlec_msg msg;
 
-void 
-lec_rcv_callback(HANDLE context, UINT32 length,
-		 void  **pp_pkt)
-{
-  return;
-}
+        memset(&msg, 0, sizeof(struct atmlec_msg));
+        msg.type = l_config;
+        msg.content.config.maximum_unknown_frame_count = lec_params.c10_max_unknown_frames;
+        msg.content.config.max_unknown_frame_time = lec_params.c11_max_unknown_frame_time;
+        msg.content.config.max_retry_count = lec_params.c13_max_retry_count;
+        msg.content.config.aging_time = lec_params.c17_aging_time;
+        msg.content.config.forward_delay_time = lec_params.c18_forward_delay_time;
+        msg.content.config.arp_response_time = lec_params.c20_le_arp_response_time;
+        msg.content.config.flush_timeout = lec_params.c21_flush_timeout;
+        msg.content.config.path_switching_delay = lec_params.c22_path_switching_delay;
+        msg.content.config.lane_version = (lec_params.c29_v2_capable) ? 2 : 1;
+
+        if (msg_to_kernel(&msg, sizeof(struct atmlec_msg)) < 0) {
+                diag(COMPONENT, DIAG_ERROR, "Could not tell kernel ELAN parameters\n");
+                return -1;
+        }
 
-void 
-lec_xmt_done_callback(HANDLE context, void *p_packet)
-{
-  EVENT(EM_DEBUG,("lec_xmt_done_callback\n"));
+        return 0;
 }
 
-/*++
-* ========================
-* = ld_xmt_done_callback =
-* ========================
-*
-* Overview:
-*
-* Arguments:
-*   conn_context
-*   p_packet
-*   user_data
-*              
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The elan_up state variable takes on the value of elan_available.
---*/
-
-static void 
-ld_xmt_done_callback(HANDLE conn_context, void *p_packet,
-		     UINT32 user_data)
+int main(int argc, char **argv)
 {
-  LEC_CONN_CONTEXT *p_conn;
-  LD_ELAN_CONTEXT  *p_elan;
+        char mac_addr[ETH_ALEN];
+        char elan_name[32 + 1];
+        char preferred_les[ATM_ESA_LEN]; /* LANE2 */
+        char foreId[255]; /* Max size for a TLV */
+        char atm2textbuff[100];
+        char esibuff[20];
+        int esi_set = 0;
+        int atm_set=0;
+        int proxy_flag = 0;
+        int lane_version = 0;              /* LANE2 */
+        int max_frame_size = MTU_UNSPEC;
+        int lecs_method = LECS_WELLKNOWN;
+        int poll_ret = 0, itf = 0;
+        struct sockaddr_atmsvc manual_atm_addr;
+        struct sockaddr_atmsvc listen_addr;
+        
+        memset(elan_name, '\0', sizeof(elan_name));
+        memset(foreId, '\0', sizeof(foreId));
+        memset(preferred_les, 0, ATM_ESA_LEN);
+        memset(&manual_atm_addr, 0, sizeof(struct sockaddr_atmsvc));
+        memset(&listen_addr, 0, sizeof(struct sockaddr_atmsvc));
+
+        set_application("zeppelin"); /* for debug msgs */
+
+        if (get_listenaddr(listen_addr.sas_addr.prv) < 0) {
+                diag(COMPONENT, DIAG_FATAL, "Could not figure out my ATM address\n");
+                exit(-1);
+        }
 
-  p_conn = (LEC_CONN_CONTEXT *) conn_context;
-  p_elan = (LD_ELAN_CONTEXT  *) p_conn->ld_elan_handle;
-  
-  if (user_data) {
-    fprintf(stdout, ("Transmit-Done Indication on Internal Data\n"));
-  }
-  
-  p_elan->lec_xmt_done_callback(p_elan->client_context, p_packet);
-  
-  return;
-}
+        while(poll_ret != -1) {
+                poll_ret = getopt(argc, argv, "c:e:n:s:m:l:i:q:12pf:t:F:");
+                switch(poll_ret) {
+                case 'c':
+                        if (atm_set) {
+                                usage(argv[0]);
+                                exit(-1);
+                        }
+                        if (text2atm(optarg, (struct sockaddr *)&manual_atm_addr,
+                                     sizeof(struct sockaddr_atmsvc), T2A_NAME) < 0) {
+                                diag(COMPONENT, DIAG_ERROR, "Invalid LECS address\n");
+                                usage(argv[0]);
+                                exit(-1);
+                        }
+                        atm2text(atm2textbuff, sizeof(atm2textbuff),
+                                 (struct sockaddr *)&manual_atm_addr, 0);
+                        diag(COMPONENT, DIAG_INFO, "LECS address: %s\n", atm2textbuff);
+                        lecs_method = LECS_MANUAL;
+                        atm_set=1;
+                        break;
+                case 'e':
+                        if(esi_convert(optarg, mac_addr)<0) {
+                                diag(COMPONENT, DIAG_ERROR, "Invalid ESI format\n");
+                                usage(argv[0]);
+                                exit(-1);
+                        }
+                        mac2text(esibuff, mac_addr);
+                        diag(COMPONENT, DIAG_DEBUG, "LEC ESI:%s\n", esibuff);
+                        esi_set=1;
+                        break;
+                case 'n':
+                        if (strlen(optarg) > 32) {
+                                diag(COMPONENT, DIAG_ERROR, "ELAN name too long\n");
+                                exit(-1);
+                        }
+                        strcpy(elan_name, optarg);
+                        diag(COMPONENT, DIAG_INFO, "Vlan name :'%s'\n", elan_name);
+                        break;
+                case 's':
+                        if (atm_set) {
+                                usage(argv[0]);
+                                exit(-1);
+                        }
+                        if (text2atm(optarg, (struct sockaddr *)&manual_atm_addr,
+                                     sizeof(struct sockaddr_atmsvc), T2A_NAME) < 0) {
+                                diag(COMPONENT, DIAG_ERROR, "Invalid LES address\n");
+                                usage(argv[0]);
+                                exit(-1);
+                        }
+                        atm2text(atm2textbuff, sizeof(atm2textbuff),
+                                 (struct sockaddr *)&manual_atm_addr, 0);
+                        diag(COMPONENT, DIAG_INFO, "LES address: %s\n", atm2textbuff);
+                        lecs_method = LECS_NONE;
+                        atm_set=1;
+                        break;
+                case 'm':
+                        set_verbosity(NULL, DIAG_DEBUG);
+                        break;
+                case 'l':
+                        if (text2atm(optarg, (struct sockaddr *)&listen_addr,
+                                     sizeof(struct sockaddr_atmsvc), T2A_NAME) < 0) {
+                                diag(COMPONENT, DIAG_ERROR, "Invalid ATM listen address\n");
+                                usage(argv[0]);
+                                exit(-1);
+                        }
+                        atm2text(atm2textbuff, sizeof(atm2textbuff),
+                                 (struct sockaddr *)&listen_addr, 0);
+                        diag(COMPONENT, DIAG_INFO, "Our ATM address: %s\n", atm2textbuff);
+                        break;
+                case 'i':
+                        if (sscanf(optarg, "%d", &itf) <= 0 || itf >= MAX_LEC_ITF) {
+                                diag(COMPONENT, DIAG_ERROR, "Invalid interface number\n");
+                                usage(argv[0]);
+                                exit(-1);
+                        }
+                        diag(COMPONENT, DIAG_INFO, "Interface number set to %d\n", itf);
+                        break;
+                case 'q':
+#if 0
+                        if (text2qos(optarg,NULL,0) < 0) {
+                                diag(COMPONENT, DIAG_ERROR, "Invalid QOS specification\n");
+                                usage(argv[0]);
+                                exit(-1);
+                        }
+                        qos_spec = optarg;
+#endif
+                        diag(COMPONENT, DIAG_INFO, "-q is deprecated, ignoring it\n");
+                        break;
+                case '1':
+                        lane_version = 1;
+                        break;
+                case '2':
+                        lane_version = 2;
+                        break;
+                case 'p':
+                        proxy_flag = 1;
+                        break;
+                case 'f':
+                        if (strlen(optarg) > 255) {
+                                diag(COMPONENT, DIAG_ERROR, "foreId too long\n");
+                                exit(-1);
+                        }
+                        memcpy (foreId, optarg, strlen(optarg));
+                        foreId[strlen(optarg)] = '\0';
+                        diag(COMPONENT, DIAG_INFO, "foreId :'%s'\n", foreId);
+                        break;
+                case 't':	/* ERIC */
+                        if( !strncmp( optarg, "1516", 4 )) max_frame_size = MTU_1516;
+                        else if( !strncmp( optarg, "1580", 4 )) max_frame_size = MTU_1580;
+                        else if( !strncmp( optarg, "4544", 4 )) max_frame_size = MTU_4544;
+                        else if( !strncmp( optarg, "9234", 4 )) max_frame_size = MTU_9234;
+                        else if( !strncmp( optarg, "18190", 5 )) max_frame_size = MTU_18190;
+                        break;
+                case 'F':
+                        set_logfile(optarg);
+                        diag(COMPONENT, DIAG_DEBUG, "logfile set to %s\n", optarg);
+                        break;
+                case -1:
+                        break;
+                default:
+                        usage(argv[0]);
+                        exit(-1);
+                }
+        }
+        if (argc != optind) {
+                usage(argv[0]);
+                exit(1);
+        }
+        if (lane_version == 1 && max_frame_size == MTU_1580) {
+                diag(COMPONENT, DIAG_ERROR, "MTU 1580 not defined with LANEv1\n");
+                exit(-1);
+        }
 
-static void 
-ld_rcv_callback(HANDLE conn_context, HANDLE conn_handle, UINT32 length, 
-		UINT32 user_data, AAL_DATA *p_aal_data, void **pp_packet)
-{
-  /* 
-   * We should get only control messages here. 
-   */
-  lc_sap_rcv (conn_context,
-	      conn_handle,
-	      length,
-	      user_data,
-	      p_aal_data,
-	      pp_packet);
-  return;
-}
+        /* Reserve signals */
+        signal(SIGHUP, sig_reset);
 
-static void
-usage(const char *progname)
-{
-  printf("Usage: %s [-c LECS_address]|[-s LES_address] [-e esi] [-n VLAN_name]"
-    " [-m mesg_mask] [-l listen_address] [-i interface_number]"
-    " [-q qos_spec] [-1] [-2] [-f Fore specific name]"
-    " [-t 1516|1580|4544|9234|18190] [-p]\n", progname);
-}
+        if (!esi_set) {
+                if(addr_getesi(mac_addr) < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "Can't get ESI from kernel!\n");
+                        return -1;
+                }
+                mac2text(esibuff, mac_addr);
+                diag(COMPONENT, DIAG_DEBUG, "LEC ESI:%s\n", esibuff);
+        }
 
-static int
-esi_convert(char *parsestring, unsigned char *mac_addr)
-{
-  const char *hexchars = "abcdefABCDEF0123456789";
-  char hexnum [17+1], curr;
-  int i = 0, j = -1, hexindex = 0, tmp;
-  char *k, *string;
-
-  if (strchr(parsestring,'.') ||     /* do we have separators like */
-      strchr(parsestring,':')) {     /* 00:20:22:23:04:05 */
-    k = parsestring;
-    for (i = 0; i < strlen(parsestring); i++) {
-      curr = *k;
-      if (curr == ':' || curr == '.') {   /* separator ? */
-        if (i - j == 3) {  /* there were 2 hex characters */
-          ;
-        }
-        else if (i - j == 2) {  /* there was only 1 hex char */
-          hexnum [hexindex] = hexnum [hexindex-1];
-          hexnum [hexindex-1] = '0';
-          hexindex +=1;
-        }
-        else   /* too many hexchars in a byte */
-          return -1;
-        j = i;  /* j is the location of the last separator */
-      }
-      else if (strchr(hexchars, curr) == NULL) /* not a hexchar ? */
-        return -1;
-      else {  /* we have a hex character */
-        hexnum [hexindex] = curr;
-        hexindex +=1;
-      }
-      k++;
-    }
-    hexnum [hexindex] = '\0';
-    string = hexnum;
-  }
-  else {   /* no separators */
-    k = parsestring;
-    while (*k != '\0') {
-      if (strchr(hexchars, *k) == NULL)
-	return -1;
-      k++;
-    }
-
-    string = parsestring;
-  }
-
-  /* the esi now looks like 002022230405 */
-  i = strlen(string);
-  if (i != 12)
-    return -1;
-  for(i=0;i<6;i++) {
-    sscanf(&string[i*2],"%2x",&tmp);
-    mac_addr[i]=(unsigned char)tmp;
-  }
-  return 0;
+        /* Loop here until the Sun gets cold */
+        while (1) {
+                if ((itf = kernel_init(mac_addr, itf)) < 0 ) {
+                        diag(COMPONENT, DIAG_FATAL, "Kernel interface creation failed, exiting...\n");
+                        return -1;
+                } 
+
+                diag(COMPONENT, DIAG_DEBUG, "initializing lec parameters\n");
+                init_lec_params(mac_addr, elan_name, listen_addr.sas_addr.prv,
+                                itf, foreId, max_frame_size, proxy_flag, lane_version);
+
+                diag(COMPONENT, DIAG_DEBUG, "About to connect LECS\n");
+                if (lec_configure(lecs_method, &manual_atm_addr, &listen_addr) < 0) {
+                        close_connections();
+                        random_delay();
+                        continue;
+                }
+                diag(COMPONENT, DIAG_DEBUG, "About to connect LES\n");
+                if (les_connect(lecs_method, &manual_atm_addr, &listen_addr) < 0) {
+                        close_connections();
+                        random_delay();
+                        continue;
+                }
+                diag(COMPONENT, DIAG_DEBUG, "About to connect BUS\n");
+                if (bus_connect() < 0) {
+                        close_connections();
+                        random_delay();
+                        continue;
+                }
+                diag(COMPONENT, DIAG_DEBUG, "About to create data direct listen socket\n");
+                if (create_data_listen() < 0) {
+                        close_connections();
+                        random_delay();
+                        continue;
+                }
+                diag(COMPONENT, DIAG_DEBUG, "About to tell kernel our LEC_ID %d\n", lec_params.c14_lec_id);
+                if (set_lec_id(lec_params.c14_lec_id) < 0) {
+                        close_connections();
+                        continue;
+                }
+                diag(COMPONENT, DIAG_DEBUG, "About to tell kernel LEC parameters\n");
+                if (config_kernel() < 0) {
+                        close_connections();
+                        continue;
+                }
+
+                diag(COMPONENT, DIAG_DEBUG, "Joined ELAN '%s' successfully\n", lec_params.c5_elan_name);
+
+                main_loop();
+                diag(COMPONENT, DIAG_INFO, "Resetting...\n");
+                close_connections();
+                random_delay();
+
+                reset = 0;
+        }
+
+        return 0; /* not reached */
 }
 
-int
-main(int argc, char **argv)
+/* zeppelin loops here when it is in operational state.  The check
+ * against reset variable is probably not needed since select() will
+ * return < 0 when a signal interrupts it.
+ */
+static void main_loop(void)
 {
-  HANDLE line_up_handle = NULL;
-  HANDLE callback_context = NULL;
-  HANDLE addr_reg_handle = NULL;
-  int esi_set=0;
-  ESI mac_addr;
-  LAN_TYPE lan_type = LAN_802_3;
-  /* LAN_MTU max_frame_size = MTU_1516; */
-  LAN_MTU max_frame_size = MTU_UNSPEC;
-  char p_elan_name[32] = { 00 };
-  INIT_METHOD init_method = INIT_WELL_KNOWN_LECS;
-  int atm_set=0;
-  ADDR_ATM manual_atm_addr;
-  BOOLEAN proxy_flag = FALSE;
-  HANDLE lport_handle = NULL;
-  char p_text[] = "Lec Control Unit";
-  BOOLEAN v2_capable = FALSE;   /* LANE2 stuff follows */
-  ADDR_ATM preferred_les;
-  ADDR_L3 l3_address = 0;
-
-  LD_CONTEXT *p_context;
-  LD_ELAN_CONTEXT *p_elan;
-  STATUS status;
-
-  fd_set fds;
-  fd_set efds;
-  int poll_ret =0;
-  struct timeval *timeout;
-  HANDLE current_timer;
-  ADDR_ATM *listen_address = NULL;
-  int itf_num = 0;
-  const char *qos_spec = NULL;
-  char foreId[FORE_ID_LEN];
-
-  memset(foreId, '\0', FORE_ID_LEN);
-  memset(&preferred_les, 0, sizeof(ADDR_ATM));
-  while(poll_ret != -1) {
-    poll_ret = getopt(argc, argv, "c:e:n:s:m:l:i:q:12pf:t:");
-    switch(poll_ret) {
-    case 'c':
-      if (atm_set) {
-	usage(argv[0]);
-	exit(-1);
-      }
-      if (address_convert(optarg, &manual_atm_addr)<0) {
-	EVENT(EM_SERR,("Invalid LECS address\n"));
-	usage(argv[0]);
-	exit(-1);
-      } 
-      EVENT(EM_MSG,("LECS address: %s\n",disp_atm_text(manual_atm_addr)));
-      init_method = INIT_MANUAL_LECS;
-      atm_set=1;
-      break;
-    case 'e':
-      if(esi_convert(optarg, mac_addr)<0) {
-	EVENT(EM_SERR,("Invalid ESI format\n"));
-	usage(argv[0]);
-	exit(-1);
-      }
-      EVENT(EM_MSG,("LEC ESI:%s\n",disp_esi_text(mac_addr)));
-      esi_set=1;
-      break;
-    case 'n':
-      memcpy(p_elan_name, optarg, strlen(optarg));
-      p_elan_name[strlen(optarg)] = '\0';
-      EVENT(EM_MSG,("Vlan name :'%s'\n", p_elan_name));
-      break;
-    case 's':
-      if (atm_set) {
-	usage(argv[0]);
-	exit(-1);
-      }
-      if (address_convert(optarg, &manual_atm_addr)<0) {
-	EVENT(EM_SERR,("Invalid LES address\n"));
-	usage(argv[0]);
-	exit(-1);
-      }
-      EVENT(EM_MSG,("LES address: %s\n", disp_atm_text(manual_atm_addr)));
-      init_method = INIT_MANUAL_LES;
-      atm_set=1;
-      break;
-    case 'm':
-      if (sscanf(optarg, "%lx",&EMASK)<0) {
-	EVENT(EM_SERR,("Invalid mask value"));
-	exit(-1);
-      }
-      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 'i':
-      if (sscanf(optarg, "%d",&itf_num)<0 || itf_num >= MAX_LEC_ITF) {
-	EVENT(EM_SERR,("Invalid interface number\n"));
-	usage(argv[0]);
-	exit(-1);
-      }
-      EVENT(EM_MSG,("Interface number set to %d\n",itf_num));
-      break;
-    case 'q':
-      if (text2qos(optarg,NULL,0) < 0) {
-	EVENT(EM_SERR,("Invalid QOS specification\n"));
-	usage(argv[0]);
-	exit(-1);
-      }
-      qos_spec = optarg;
-      break;
-    case '1':
-      spec_version = 1;
-      break;
-    case '2':
-      spec_version = 2;
-      v2_capable = TRUE;
-      break;
-    case 'p':
-      proxy_flag = TRUE;
-      break;
-    case 'f':
-      memcpy (foreId, optarg, FORE_ID_LEN);
-      foreId[FORE_ID_LEN-1] = '\0';
-      EVENT(EM_MSG, ("foreId :'%s'\n", foreId));
-      printf("foreId '%s'\n", foreId);
-      break;
-    case 't':	/* ERIC */
-      if( !strncmp( optarg, "1516", 4 )) max_frame_size = MTU_1516;
-      else if( !strncmp( optarg, "1580", 4 )) max_frame_size = MTU_1580;
-      else if( !strncmp( optarg, "4544", 4 )) max_frame_size = MTU_4544;
-      else if( !strncmp( optarg, "9234", 4 )) max_frame_size = MTU_9234;
-      else if( !strncmp( optarg, "18190", 5 )) max_frame_size = MTU_18190;
-    break;
-    case -1:
-      break;
-    default:
-      usage(argv[0]);
-      exit(-1);
-    }
-  }
-  if (argc != optind) {
-     usage(argv[0]);
-     exit(1);
-  }
-  if (!esi_set) {
-    if(addr_getesi(mac_addr)<0) {
-      EVENT(EM_SERR,("Can't get ESI from kernel!\n"));
-      return STATUS_K_HW_FAULT;
-    } 
-    EVENT(EM_MSG,("LEC ESI:%s\n",disp_esi_text(mac_addr)));
-  }
-  while (stay_alive) {
-
-    /* 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);
-    
-    /* 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));
-    
-    if (p_context == NULL)
-      return STATUS_K_RESOURCES;
-    
-    /* Initialize the list of ELANs. */
-    
-    utl_list_init (p_context->elan_list);
-    
-    if ((itf_num=kernel_init(mac_addr, itf_num))<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;
-    }
+        fd_set rfds, cfds;
+        int retval, ret1, ret2, ret3;
+
+        while(!reset) {
+                retval = ret1 = ret2 = ret3 = 0;
+                FD_ZERO(&rfds);
+                conn_get_fds(&rfds);
+                FD_ZERO(&cfds);
+                conn_get_connecting_fds(&cfds);
+
+                retval = select(FD_SETSIZE, &rfds, &cfds, NULL, NULL);
+                diag(COMPONENT, DIAG_DEBUG, "main_loop: select returned %d\n", retval);
+                if (retval < 0) {
+                        diag(COMPONENT, DIAG_ERROR, "main_loop: select: %s\n", strerror(errno));
+                        break; /* leave main_loop */
+                }
+                if (retval == 0) {
+                        /* Timeout, funny, since we have no timers */
+                        continue;
+                }
+                if (FD_ISSET(lec_params.kernel->fd, &rfds)) {
+                        ret1 = msg_from_kernel();
+                        FD_CLR(lec_params.kernel->fd, &rfds);
+                }
+                ret2 = complete_connections(&cfds);
+                ret3 = check_connections(&rfds);
+                
+                if (ret1 < 0 || ret2 < 0 || ret3 < 0)
+                        break; /* leave main_loop */
+        }
         
-    /* 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,
-                          v2_capable,
-                          preferred_les,
-                          l3_address,
-                          foreId);
-    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);
-  
-    /* 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,
-			     ld_xmt_done_callback,
-			     itf_num,
-			     "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,
-				 qos_spec,
-				 max_frame_size)<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,
-				 qos_spec,
-				 max_frame_size)<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,
-				 qos_spec,
-				 max_frame_size)<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,
-		   qos_spec,
-		   (HANDLE) &p_elan->ctrl_conn_context);
-
-
-    /* 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 %ld secs....\n",(long)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);
-        /* the NULL argument used to be &efds, changed in pre-0.33-x */
-	poll_ret = select(FD_SETSIZE, &fds, &efds, NULL, 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);
-      }
-      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);
-
-      /* 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);
+        diag(COMPONENT, DIAG_DEBUG, "exiting main_loop\n");
 
-#if 0
-      /* Now we should be able to restart from empty table? */
-      mem_usage();
-      timer_usage();
-#endif
-      reset = 0;
-    }
-  }
-  return STATUS_K_SUCCESS; 
+        return;
 }
-
-/*
- *
- * $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
- *
- * Revision 1.17  1996/06/10 04:27:28  carnil
- * compiler warning fixes
- *
- * Revision 1.15  1996/05/13 08:53:27  carnil
- * *** empty log message ***
- *
- * Revision 1.14  1996/04/25 19:42:13  carnil
- * Copyright notice
- *
- * Revision 1.13  1996/04/19 06:37:49  carnil
- * options from command line, ELAN name, kernel_itf.c call order fixed
- *
- * Revision 1.12  1996/04/11 09:16:14  carnil
- * data direct listen
- *
- * Revision 1.11  1996/03/30 15:14:23  carnil
- * Configuration vcc callback before loop
- *
- * Revision 1.10  1996/03/22 11:26:23  carnil
- * *** empty log message ***
- *
- * Revision 1.9  1996/03/19 11:03:36  carnil
- * *** empty log message ***
- *
- * Revision 1.8  1996/03/17 21:23:41  carnil
- * kernel_init()
- *
- * Revision 1.7  1996/03/04 08:55:39  carnil
- * listen socket creation works
- * Communication to servers works
- *
- * Revision 1.6  1996/02/29 11:24:12  carnil
- * Main loop alteration
- *
- * Revision 1.5  1996/02/16 06:16:20  carnil
- * oshandle,cmhandle removed
- *
- * Revision 1.4  1996/02/06  11:23:41  carnil
- * Main loop functionality enhanced
- *
- * Revision 1.3  1996/01/30  15:20:49  carnil
- * Main loop
- *
- * Revision 1.2  1996/01/23  10:02:12  carnil
- * *** empty log message ***
- *
- * Revision 1.1  1996/01/22  12:59:50  carnil
- * Initial revision
- *
- *
- */
diff -ur --new-file old/atm/led/svc_info.h new/atm/led/svc_info.h
--- old/atm/led/svc_info.h	Tue Aug 11 16:53:58 1998
+++ new/atm/led/svc_info.h	Thu Jan  1 01:00:00 1970
@@ -1,100 +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:
-*   svc_info.h
-*   
-* Abstract:
-*  This header file describes the information elements needed to support the
-*  svc to connection manager interface.
-*
-* Authors:
-*  JAD - John A. DeNisco
-*
-* Modification History:
-*
-* Description:
-*
-*/
-#ifndef SVC_INFO_H
-#define SVC_INFO_H
-
-#include <atm.h>
-
-/* Cause Values */
-
-#define CAUSE_NORMAL                     31
-
-/*++
- * CONN_INFO
- *
- * This structure contains all of the information needed to setup a a virtual
- * connection.
- *
- --*/
-typedef struct {
-  struct sockaddr_atmsvc addr;
-  struct atm_blli blli;
-  struct atm_qos conqos;
-} CONN_INFO;
-
-/*++
- * =====================
- * = svcinit_conn_info =
- * =====================
- *
- * Overview:
- *  This function initilizes the connection information structure.
- *  Initilization simply involves setting all the present flags to 
- *  "not present".
- *
- * Arguments:
- *
- *  p_svc_conn_info - Pointer to the connection information.
- *
- * Returns:
- *
- * None
- *
- --*/
-void svcinit_conn_info (CONN_INFO *p_svc_conn_info);
-
-
-#endif /* SVC_INFO_H */
-
-
-
-
-
-
diff -ur --new-file old/atm/led/system.h new/atm/led/system.h
--- old/atm/led/system.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/system.h	Thu Jan  1 01:00:00 1970
@@ -1,210 +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:
-*   system.h
-*   
-* Abstract:
-*   This module defines system specific items.  The definitions in this file
-*   are available to all of the system modules.
-*
-* Authors:
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date        Name   Description 
-*   27-Oct-94   TLR    Created.
-*   03-Feb-95   PJR    Updated bit masks to allow for 32 bit user_data.
-*                      Added USER_DATA_LEH_MASK to extract the header.
-*                      Removed len field from INT_BUF, length is passed
-*                       separately to the lower driver.
-*                      Added USER_DATA_ADD_HDR_MASK to test the add
-*                       lan emulation header bit.
-*   06-Mar-95   JAD    Removed INT_BUF.
-*
-* Description:
-*
---*/
-
-/* USER_DATA
- *
- *  This value is passed between upper layer SAPs and the lower device
- *  driver through the Connection Manager (CM) with every packet.  For transmit
- *  packets, it contains information about the buffer format and how the buffer
- *  should be deallocated by the driver.
- *
- *    +---+---+---+----------------+-------------------------------------+
- *    | 1 | 1 | 1 |      13        |                  16                 |
- *    +---+---+---+----------------+-------------------------------------+
- *      |   |   |         |                |
- *      |   |   |         |                +-- header_data
- *      |   |   |         +------------------- reserved
- *      |   |   +----------------------------- add_snap_header
- *      |   +--------------------------------- add_le_header
- *      +------------------------------------- internal_source
- *
- *  USER_DATA contains the following fields:
- *
- *    internal_source...If this bit is set, the transmit packet associated
- *                      with this user_data was generated internally.  This
- *                      means that the packet was generated by a component of
- *                      the ATM system (i.e. Signaling, UME, Lan Emulation,
- *                      etc.).  The driver must treat this buffer as an
- *                      internal buffer and not as an operating system
- *                      generated packet.
- *
- *    add_le_header.....If this bit is set, the transmit packet associated
- *                      with this user_data is a LAN Emulation packet.  The
- *                      driver must add the supplied LAN Emulation header to
- *                      the packet as an added fragment.
- *
- *    add_snap_header...If this bit is set, the transmit packet associated
- *                      with this user_data is a Classical-IP (RFC 1577)
- *                      packet.  The driver must prepend a SNAP header with
- *                      the supplied Protocol ID (PID).
- *
- *    reserved..........Reserved for future extension.
- *
- *    header_data.......Either the two octet LAN Emulation header or the PID
- *                      of the SNAP header to be prepended to the packet if
- *                      the 'add_le_header' or 'add_snap_header' bits are set
- *                      respectively.
- *
- *  Invariant:
- *
- *    At most one of the following bits may be set in the user_data:
- *
- *       internal_source
- *       add_le_header
- *       add_snap_header
- *
- *    The lower driver must never be required to prepend a header on an
- *    internally generated packet.
- */
-#ifndef SYSTEM_H
-#define SYSTEM_H
-
-#define USER_DATA_NORMAL            (0x00000000L)
-#define USER_DATA_NORMAL_LE(leh)    (0x40000000L | (leh))
-#define USER_DATA_NORMAL_SNAP(pid)  (0x20000000L | (pid))
-#define USER_DATA_ADD_HDR_MASK      (0x40000000L)        /* Obsolete */
-#define USER_DATA_ADD_LEH_MASK      (0x40000000L)
-#define USER_DATA_ADD_SNAP_MASK     (0x20000000L)
-#define USER_DATA_INTERNAL          (0x80000000L)
-#define USER_DATA_LEH_MASK          (0x0000FFFFL)
-#define USER_DATA_PID_MASK          (0x0000FFFFL)
-
-/* ATM_LINK_STATUS
- *
- *   This type enumerates the possible link states that are visible to
- *   registered SAP clients.
- *
- *   LINK_DOWN......The physical link is not available.  This occurs
- *                  when signal synchronization with the network peer is
- *                  lost.
- *
- *   LINK_PHY_UP....The physical link has become available.  This
- *                  signifies that the ATM port has detected the presence
- *                  of a peer on the other end of the wire/fiber.
- *
- *   LINK_LINE_UP...The Line-Up protocol has completed successfully.
- *                  This indication allows protocols like SSCOP to begin
- *                  bringing themselves to life.
- *
- *   LINK_SIG_UP....SSCOP has initialized and the signaling stack is ready
- *                  to accept SVC requests.
- *
- */
-
-typedef enum
-   {
-   LINK_DOWN,
-   LINK_PHY_UP,
-   LINK_LINE_UP,
-   LINK_SIG_UP
-   } ATM_LINK_STATE;
-
-/* ATM_LINK_EVENT
- *
- *   This type enumerates the possible link state events that can be
- *   reported to the Connection Manager.  These events may result in
- *   changes to the link state.
- *
- *   LINK_EVENT_PHY_DOWN........Carrier was lost on the physical port.
- *                              The link state will transition to
- *                              LINK_DOWN after a hysteresis period
- *                              elapses (around 3 seconds).
- *
- *   LINK_EVENT_PHY_UP..........Carrier is up on the physical port.
- *                              Link state transitions immediately from
- *                              LINK_DOWN to LINK_PHY_UP.
- *
- *   LINK_EVENT_LINE_UP.........The Line-Up exchange with the network
- *                              peer is complete.  Link state transitions
- *                              immediately from LINK_PHY_UP to LINK_LINE_UP.
- *
- *   LINK_EVENT_SIG_UP..........The Signaling transport (i.e. QSAAL) has
- *                              completed its connection with its peer.
- *                              The link state transitions immediately from
- *                              LINK_LINE_UP to LINK_SIG_UP.
- *
- *   LINK_EVENT_SIG_DOWN........The Signaling transport has lost contact
- *                              with its peer.  The link state transitions
- *                              immediately from LINK_SIG_UP to LINK_LINE_UP.
- *                              All SVCs are deleted in an orderly way (i.e.
- *                              the driver is asked to teardown the VCs).
- *
- *   LINK_EVENT_RESET_START.....The driver is resetting.  The link state
- *                              transitions immediately from wherever it is
- *                              to LINK_DOWN.  All SVCs are deleted harshly
- *                              (i.e. the records are simply deleted, no
- *                              notification goes to either the signaling
- *                              function or the device driver).
- *
- *   LINK_EVENT_RESET_COMPLETE..Driver reset is complete, link state stays
- *                              at LINK_DOWN.  All PVCs are re-opened on
- *                              the driver.
- */
-typedef enum
-   {
-   LINK_EVENT_PHY_DOWN,
-   LINK_EVENT_PHY_UP,
-   LINK_EVENT_LINE_UP,
-   LINK_EVENT_SIG_UP,
-   LINK_EVENT_SIG_DOWN,
-   LINK_EVENT_RESET_START,
-   LINK_EVENT_RESET_COMPLETE
-   } ATM_LINK_EVENT;
-
-#endif /* SYSTEM_H */
diff -ur --new-file old/atm/led/timers.c new/atm/led/timers.c
--- old/atm/led/timers.c	Wed Nov 19 12:59:16 1997
+++ new/atm/led/timers.c	Thu Jan  1 01:00:00 1970
@@ -1,289 +0,0 @@
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-/*
- *
- * Timer creation, setting and allocation. Protypes defined in
- * utl_os.h
- *
- * $Id: timers.c,v 1.9 1996/08/06 14:14:11 carnil Exp carnil $
- *
- */
-
-/* Global protypes */
-#include <sys/time.h>
-#include <unistd.h>
-#include <assert.h>
-#include <stdio.h>
-
-/* Digital prototypes */
-#include "g_types.h"
-#include "utl_os.h"
-#include "codes.h"
-#include "g_event.h"
-
-/* Own prototypes */
-#include "timers.h"
-
-#define EMOD MOD_UTL_OS
-#define EINST "timers.c"
-#include "emask.h"
-
-typedef struct _Timer_t_ {
-  void (*callback) (HANDLE context); /* Pointer to the routine to callback 
-					when the timer expires. */
-  HANDLE context; /* Value to pass to the callback routine. */
-  struct timeval *alarm_time; /* Time to expire timer */
-  struct _Timer_t_ *previous;
-  struct _Timer_t_ *next;
-} Timer_t;
-
-static Timer_t *timerlist = NULL;
-
-static struct timeval g_timer;
-
-STATUS 
-os_timer_alloc (OS_TIMER_CALLBACK callback, 
-		HANDLE context, HANDLE *p_timer_handle)
-{
-  Timer_t *new;
-
-  new = (Timer_t *)mem_alloc(EINST,sizeof(Timer_t));
-  if (!new)
-    return STATUS_K_RESOURCES;
-  EVENT(EM_TIMER, ("Os_timer_alloc timer:%p callback:%p\n",
-		   new, callback));
-  new->callback = callback;
-  new->context = context;
-  new->alarm_time = NULL;
-  new->previous = NULL;
-  new->next = timerlist;
-  if (timerlist)
-    timerlist->previous = new;
-  timerlist = new;
-  *p_timer_handle = (HANDLE)new;
-  return STATUS_K_SUCCESS;
-}
-
-void 
-os_timer_dealloc (HANDLE timer_handle)
-{
-  Timer_t *old;
-
-  assert(timer_handle);
-
-  EVENT(EM_TIMER,("Os_timer_dealloc timer: %p\n",timer_handle));
-  old = (Timer_t *)timer_handle;
-
-  if (old->alarm_time)
-    mem_free(EINST,old->alarm_time);
-  if (old->previous)
-    (old->previous)->next = old->next;
-  if (old->next)
-    (old->next)->previous = old->previous;
-  if (timerlist == old)
-    timerlist = old->next;
-  mem_free(EINST,old);
-}
-
-STATUS 
-os_timer_set (HANDLE timer_handle, UINT32 timeset)
-{
-  Timer_t *to_set;
-
-  assert(timer_handle);
-  EVENT(EM_TIMER,("Os_timer_set timer:%p %ld ms\n",
-		  timer_handle, timeset));
-  to_set = (Timer_t *)timer_handle;
-
-  if (!(to_set->alarm_time)) {
-    to_set->alarm_time = (struct timeval *)mem_alloc(EINST,
-						     sizeof(struct timeval));
-    if (!(to_set->alarm_time))
-      return STATUS_K_RESOURCES;
-  }
-  gettimeofday(to_set->alarm_time, NULL);
-  (to_set->alarm_time)->tv_usec = 
-    (to_set->alarm_time)->tv_usec+(long)(timeset%1000)*1000;
-  if ((to_set->alarm_time)->tv_usec>=1000000) {
-    (to_set->alarm_time)->tv_usec-=1000000;
-    (to_set->alarm_time)->tv_sec++;
-  }
-  (to_set->alarm_time)->tv_sec = 
-    (to_set->alarm_time)->tv_sec + (long)(timeset/999);
-
-  return STATUS_K_SUCCESS;
-}
-
-STATUS 
-os_timer_cancel (HANDLE timer_handle)
-{
-  Timer_t *to_cancel;
-
-  assert(timer_handle);
-  EVENT(EM_TIMER,("Os_timer_cancel %p\n",timer_handle));
-
-  to_cancel = (Timer_t *)timer_handle;
-
-  if (to_cancel->alarm_time) {
-    mem_free(EINST,to_cancel->alarm_time);
-    to_cancel->alarm_time = NULL;
-  }
-  return STATUS_K_SUCCESS;
-}
-
-/* Returns Timer_t_ with soonest expiration time, can be
-   NULL if there are no timers set */
-HANDLE
-timer_find_soonest(void)
-{
-  Timer_t *current, *soonest;
-
-  soonest = current = timerlist;
-  EVENT(EM_TIMER,("Timer_find_soonest\n"));
-
-  while(current) {
-    if (current->alarm_time) {
-      if (!soonest->alarm_time ||
-	  ((current->alarm_time->tv_sec <
-	    soonest->alarm_time->tv_sec) ||
-	   (current->alarm_time->tv_sec ==
-	    soonest->alarm_time->tv_sec &&
-	    current->alarm_time->tv_usec <
-	    soonest->alarm_time->tv_usec))) {
-	soonest = current;
-      }
-    }
-    current = current->next;
-  }
-  return soonest;
-}
-
-/* Returns timers expiration time from current moment 
-   (fit for select()'s time parameter), allocates memory
-   for timeval, in case timer is set. If timer should already 
-   have expired, structure's fields are set to zero.
-   If HANDLE is NULL, returns NULL. */
-struct timeval *
-timer_get_expiration(HANDLE timer_handle)
-{
-  Timer_t *to_get;
-  struct timezone tz;
-
-  EVENT(EM_TIMER,("Timer_get_expiration\n"));
-  if (!timer_handle)
-    return NULL;
-
-  to_get = (Timer_t *)timer_handle;
-
-  if (to_get->alarm_time) {
-    gettimeofday(&g_timer, &tz);
-    EVENT(EM_TIMER,("G_timer:%ld sec %ld usec\n",
-		    (long)g_timer.tv_sec,(long)g_timer.tv_usec));
-    EVENT(EM_TIMER,("Timer  :%ld sec %ld usec\n",
-		    (long)to_get->alarm_time->tv_sec,
-		    (long)to_get->alarm_time->tv_usec));
-    if (g_timer.tv_sec > (to_get->alarm_time)->tv_sec || 
-	(g_timer.tv_sec == (to_get->alarm_time)->tv_sec &&
-	 g_timer.tv_usec >= (to_get->alarm_time)->tv_usec)) {
-      g_timer.tv_sec = g_timer.tv_usec = 0;
-    } else {
-      g_timer.tv_sec = (to_get->alarm_time)->tv_sec - g_timer.tv_sec;
-      if (g_timer.tv_usec > (to_get->alarm_time)->tv_usec) {
-	g_timer.tv_sec--;
-	g_timer.tv_usec = 
-	  1000000 + (to_get->alarm_time)->tv_usec - g_timer.tv_usec;
-      } else
-	g_timer.tv_usec = 
-	  (to_get->alarm_time)->tv_usec - g_timer.tv_usec;
-    }
-    EVENT(EM_TIMER,("Return:%ld sec %ld usec\n",
-		    (long)g_timer.tv_sec,(long)g_timer.tv_usec));
-    return &g_timer;
-  } else
-    return NULL;
-}
-
-/* Calls timer's callback function */
-void
-timer_call_callback(HANDLE timer_handle)
-{
-  Timer_t *to_call;
-
-  EVENT(EM_TIMER,("Timer_call_callback timer:%lx\n",(long)timer_handle));
-  assert(timer_handle);
-
-  to_call = (Timer_t *)timer_handle;
-
-  mem_free(EINST, to_call->alarm_time);
-  to_call->alarm_time = NULL;
-
-  if (to_call->callback)
-    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 %ld sec %ld usec\n",
-	   tmp->callback, tmp->context, 
-	   tmp->alarm_time?(long)tmp->alarm_time->tv_sec:0,
-	   tmp->alarm_time?(long)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
- *
- * Revision 1.7  1996/04/25 19:42:13  carnil
- * Copyright notice
- *
- * Revision 1.6  1996/02/29 11:24:12  carnil
- * *** empty log message ***
- *
- * Revision 1.5  1996/02/16 06:16:20  carnil
- * oshandle,cmhandle removed
- *
- * Revision 1.4  1996/02/06  11:23:41  carnil
- * callback calling, select time
- *
- * Revision 1.3  1996/01/29  09:30:43  carnil
- * mem_alloc, mem_free
- *
- * Revision 1.2  1996/01/23  10:02:12  carnil
- * Debug info added
- *
- * Revision 1.1  1996/01/19  06:21:43  carnil
- * Initial revision
- *
- *
- */
diff -ur --new-file old/atm/led/timers.h new/atm/led/timers.h
--- old/atm/led/timers.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/timers.h	Thu Jan  1 01:00:00 1970
@@ -1,53 +0,0 @@
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-/*
- * Include file for timer funcs not used in DIGITAL's code
- *
- * $Id: timers.h,v 1.3 1996/08/06 14:14:11 carnil Exp carnil $
- *
- */
-/* Global includes */
-#include <sys/time.h>
-
-/* Digital includes */
-#include "g_types.h"
-
-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
- *
- * Revision 1.1  1996/01/19 06:21:43  carnil
- * Initial revision
- *
- *
- */
diff -ur --new-file old/atm/led/utils.c new/atm/led/utils.c
--- old/atm/led/utils.c	Wed Nov 19 12:59:16 1997
+++ new/atm/led/utils.c	Thu Jan  1 01:00:00 1970
@@ -1,165 +0,0 @@
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-/*
- *
- * Utility functions which are used, but not defined in DIGITAL's 
- * code are defined here.
- *
- * $Id: utils.c,v 1.7 1996/08/06 14:14:11 carnil Exp carnil $
- *
- */
-
-/* Global includes */
-#include <string.h>
-#include <stdio.h>
-
-/* Digital includes */
-#include "utl.h"
-#include "utl_os.h"
-#include "codes.h"
-#include "g_event.h"
-
-#define EMOD MOD_UTL_OS
-#define EINST "utils.c"
-#include "emask.h"
-
-/* List of allocated memory blocks */
-typedef struct _MemList_t {
-  void *mem;
-  size_t memsize;
-  char *unit;
-  struct _MemList_t *next;
-} MemList_t;
-
-static MemList_t *memlist = NULL;
-
-void*
-os_mem_alloc(UINT32 size)
-{
-  return(mem_alloc("utils.c",size));
-}
-
-void 
-os_mem_dealloc(void *p_mem)
-{
-  mem_free("utils.c", p_mem);
-}
-
-void*
-mem_alloc(const char *unit, unsigned long nbytes)
-{
-  MemList_t *tmp;
-
-  tmp = (MemList_t *)malloc(sizeof(MemList_t));
-  memset (tmp, 0, sizeof(*tmp));
-
-  tmp->mem = malloc(nbytes);
-  memset (tmp->mem, 0, nbytes);
-
-  tmp->memsize = nbytes;
-  tmp->unit = (char*)malloc(strlen(unit)+1);
-  sprintf(tmp->unit,"%s",unit);
-  tmp->unit[strlen(unit)] = '\0';
-  tmp->next = memlist;
-  memlist = tmp;
-  EVENT(EM_MEM,("Unit %s allocates %ld bytes of memory from 0x%lx\n",
-		unit, nbytes, (unsigned long)tmp->mem));
-  return tmp->mem;
-
-}
-
-void
-mem_free(const char *unit, const void *mem)
-{
-  MemList_t *tmp, *prev = NULL;
- 
-  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) {
-      break;
-    }
-  }
-  /* Found a match? */
-  if (tmp) {
-    if (strcmp(tmp->unit, unit) != 0) {
-      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));
-    }
-    if (memlist == tmp) {
-      memlist = tmp->next;
-    }
-    if (prev != NULL) {
-      prev->next = tmp->next;
-    }
-    free(tmp->unit);
-    free(tmp->mem);
-    free(tmp);
-  }
-  else {
-    EVENT(EM_MEM, ("could not find block 0x%lx for freeing\n", 
-		   (unsigned long)mem));
-  }
-}
-
-void
-mem_usage(void)
-{
-  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
- *
- * Revision 1.5  1996/04/25 19:42:13  carnil
- * Copyright notice
- *
- * Revision 1.4  1996/02/16 06:16:20  carnil
- * oshandle,cmhandle removed
- *
- * Revision 1.3  1996/01/29  09:30:43  carnil
- * mem_alloc, mem_free
- *
- * Revision 1.2  1996/01/22  12:59:50  carnil
- * os_buff_hdr_copy
- *
- * Revision 1.1  1996/01/17  08:48:41  carnil
- * Initial revision
- *
- *
- */
diff -ur --new-file old/atm/led/utl.h new/atm/led/utl.h
--- old/atm/led/utl.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/utl.h	Thu Jan  1 01:00:00 1970
@@ -1,493 +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:
-*   utl.h
-*   
-* Abstract:
-*   This is the interface for the basic functions that are provided by the OS.
-*
-* Authors:
-*   DMW - Douglas M. Washabaugh
-*   JAD - John A. Denisco
-*   TLR - Theodore L. Ross
-*
-* Modification History:
-*   Date       Name  Description 
-*   08-Aug-94  DMW   Created.
-*   04-Oct-94  DMW   Changed ULONG to UINT32.
-*   19-Oct-94  TLR   Added Simple List Utilities.
-*   26-Oct-94  TLR   Updated Simple List Utilities based on review, retested.
-*   10-Nov-94  DMW   Added the buffer descriptor and basic access macros.
-*   05-Dec-94  DMW   Added an ALIGN macro.
-*   11-Jan-95  TLR   Added utl_list_insert_after
-*   12-Jan-95  DMW   Added MIN and MAX macros.
-*   18-Jan-95  JAD   Moved BUFFER_DESCR and associated maros from here to
-*                    ss_ptsp.c (signaling module).
-*   22-Mar-95  TLR   Added utl_buff_zero, utl_buff_copy, and utl_list_dealloc.
-*   23-Mar-95  DMW   Changed name of utl_buff_zero and utl_buff_copy to 
-*                    utl_mem_zero and utl_mem_copy to avoid confusion with
-*                    operating system buffers.
-*
-* Description:
-*   This module contains general utility routines that are independent of the
-*   operating system.
-*
-*   Many of the functions deal with setting default values.  This assists in
-*   the situation that the caller has a value with several distinct fields,
-*   all of which but one must be left with their "current" (default) values.
-*   Without a helper routine, the caller should have to perform shifts, and
-*   "and" operations.
-* 
-*/
-
-/* Define minimum and maximum macros.  Each return the value of the min or max. */
-
-#ifndef VW_DEFS
-#define MAX(A,B) ((A) > (B) ? (A) : (B))
-#define MIN(A,B) ((A) < (B) ? (A) : (B))
-#endif
-
-/* SIMPLE_LIST
- *
- *  SIMPLE_LIST is a macro that creates a list of elements of a certain type.
- *  The macro has two arguments:
- *
- *      type    - The data type for elements that will be stored in the list.
- *      name    - The name of the resulting list type.  
- *
- *  For a structure to be stored in a simple list, its first member must be a
- *  pointer to that same kind of structure.  For example, a list of names
- *  would use a structure like the following:
- *
- *      struct name_tag
- *         {
- *         struct name_tag *p_next;
- *         char            *text;
- *         } NAME_RECORD;
- *
- *  To create a type for a simple list of names, the following declaration
- *  can be used:
- *
- *      SIMPLE_LIST (NAME_RECORD, NAME_LIST);
- *
- *  NAME_LIST is now a type for a list of elements of type NAME_RECORD.  An
- *  example of its usage is:
- *
- *      NAME_LIST   list_of_names;
- *
- */
-#define SIMPLE_LIST(type, name) typedef struct     \
-                                   {               \
-                                   type   *p_root; \
-                                   type   *p_tmp;  \
-                                   int     size;   \
-                                   } name
-
-/*++
-* =========================
-* = utl_list_init (macro) =
-* =========================
-*
-* Overview:
-*   Initializes an instance of a simple list.  Simple lists MUST be
-*   initialized before they can be used for any other purpose.
-*
-* Arguments:
-*   list    - (IO) Simple List to be initialized.
-* 
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The simple list contains zero entries.
---*/
-#define utl_list_init(list) \
-   {                        \
-   (list).p_root = NULL;    \
-   (list).size   = 0;       \
-   }
-
-/*++
-* ========================
-* = utl_list_add (macro) =
-* ========================
-*
-* Overview:
-*   Adds a single element to a simple list.  The element is added to the
-*   head of the list.
-*
-* Arguments:
-*   list        - (IO) Simple list to be modified (not a pointer to the list).
-*   p_element   - (IN) Pointer to the element that is to be added to the list.
-* 
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The element is a member of the list.
-*
-*   The size of the list stored in the list header has been incremented by one.
---*/
-#define utl_list_add(list, p_element)   \
-   {                                    \
-   (p_element)->p_next = (list).p_root; \
-   (list).p_root       = p_element;     \
-   (list).size        += 1;             \
-   }
-
-/*++
-* =================================
-* = utl_list_insert_after (macro) =
-* =================================
-*
-* Overview:
-*   Adds a single element to a simple list.  The element is inserted after
-*   a specified key element.
-*
-* Usage:
-*   This macro may be used to insert an element into an ordered list.
-*   The following is an example of such an application:
-*
-*       typedef struct _int_tag
-*          {
-*          struct _int_tag  *p_next;
-*          int               data;
-*          } INT_RECORD;
-*
-*       SIMPLE_LIST (INT_RECORD, INT_LIST);
-*       .
-*       .
-*       .
-*       INT_RECORD  *p_current, *p_prev;
-*       INT_LIST    int_list
-*
-*       p_prev = NULL;
-*       utl_list_traverse (int_list, p_current);
-*          {
-*          if (p_new_data->data <= p_current->data)
-*             {
-*             utl_list_insert_after (int_list, p_prev, p_new_data);
-*             break;
-*             }
-*          p_prev = p_current;
-*          }
-*       if (p_current == NULL)
-*          utl_list_insert_after (int_list, p_prev, p_new_data);
-*
-* Arguments:
-*   list        - (IO) Simple list to be modified (not a pointer to the list).
-*   p_key       - (IN) Pointer to the key element.
-*   p_element   - (IN) Pointer to the element that is to be added to the list.
-* 
-* Returns:
-*   None
-*
-* Preconditions:
-*   p_key points to an element that is a member of the list or is NULL.
-*
-* Postconditions:
-*   The element is a member of the list and directly follows the key element.
-*   If the key pointer is NULL, the new element is at the head of the list.
-*
-*   The size of the list stored in the list header has been incremented by one.
---*/
-#define utl_list_insert_after(list, p_key, p_element) \
-   {                                                  \
-   if ((p_key) == NULL)                               \
-      {                                               \
-      (p_element)->p_next = (list).p_root;            \
-      (list).p_root       = (p_element);              \
-      }                                               \
-   else                                               \
-      {                                               \
-      (p_element)->p_next = (p_key)->p_next;          \
-      (p_key)->p_next     = (p_element);              \
-      }                                               \
-   (list).size        += 1;                           \
-   }
-
-/*++
-* ===========================
-* = utl_list_delete (macro) =
-* ===========================
-*
-* Overview:
-*   Deletes a single element from a simple list.  The element to be deleted
-*   is identified by its address.
-*
-* Arguments:
-*   list        - (IO) Simple list to be modified.
-*   p_element   - (IN) Pointer to the element that is to be removed from
-*                      the list.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The element is a not member of the list.
-*
-*   If the element was a member of the list, the size of the list has been
-*   decremented  by one.  Otherwise, nothing happens.
---*/
-#define utl_list_delete(list, p_element)                                     \
-	{                                                                         \
-	if ((list).p_root == p_element)                                           \
-		{                                                                      \
-		/* First, handle the case in which the element to be deleted is at */  \
-		/* the root of the list.                                           */  \
-		(list).p_root = (p_element)->p_next;                                   \
-		(list).size  -= 1;                                                     \
-		}                                                                      \
-	else                                                                      \
-		{                                                                      \
-		/* Handle the case in which the element to be deleted is deeper */     \
-		/* into the list than the root element.                         */     \
-		(list).p_tmp = (list).p_root;                                          \
-		while (((list).p_tmp != NULL) && ((list).p_tmp->p_next != p_element))  \
-			(list).p_tmp = (list).p_tmp->p_next;                                \
-																									  \
-		/* If the target element has been found (not the end of the list), */  \
-		/* unlink the target element and decrement the size by 1.          */  \
-		if ((list).p_tmp != NULL)                                              \
-			{                                                                   \
-			(list).p_tmp->p_next = (p_element)->p_next;                         \
-			(list).size         -= 1;                                           \
-			}                                                                   \
-		}                                                                      \
-	}
-
-/*++
-* =============================
-* = utl_list_find_del (macro) =
-* =============================
-*
-* Overview:
-*   Removes a single element from a simple list.  The element to be removed
-*   is identified by its address. If the element is found on the list is
-*   found "found" is set to TRUE, if not it is set to FALSE.
-*
-* Arguments:
-*   list        - (IO)  Simple list to be modified.
-*   p_element   - (IN)  Pointer to the element that is to be removed from
-*                       the list.
-*   found       - (OUT) TRUE iff the element on the list is found.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The element is a not member of the list.
-*
-*   If the element was a member of the list, the size of the list has been
-*   decremented  by one.  Otherwise, nothing happens.
---*/
-
-#define utl_list_find_del(list, p_element, found)                                     \
-	{                                                                         \
-	if ((list).p_root == p_element)                                           \
-		{                                                                      \
-		/* First, handle the case in which the element to be deleted is at */  \
-		/* the root of the list.                                           */  \
-		(list).p_root = (p_element)->p_next;                                   \
-		(list).size  -= 1;                                                     \
-		found = TRUE;                                                          \
-		}                                                                      \
-	else                                                                      \
-		{                                                                      \
-		/* Handle the case in which the element to be deleted is deeper */     \
-		/* into the list than the root element.                         */     \
-		(list).p_tmp = (list).p_root;                                          \
-		while (((list).p_tmp != NULL) && ((list).p_tmp->p_next != p_element))  \
-			(list).p_tmp = (list).p_tmp->p_next;                                \
-																									  \
-		/* If the target element has been found (not the end of the list), */  \
-		/* unlink the target element and decrement the size by 1.          */  \
-		if ((list).p_tmp != NULL)                                              \
-			{                                                                   \
-			(list).p_tmp->p_next = (p_element)->p_next;                         \
-			(list).size         -= 1;                                           \
-			found = TRUE;                                                       \
-			}                                                                   \
-		else                                                                   \
-			{                                                                   \
-			found = FALSE;                                                      \
-			}                                                                   \
-		}                                                                      \
-	}
-
-/*++
-* =========================
-* = utl_list_find (macro) =
-* =========================
-*
-* Overview:
-*   Finds a specified element on a list. If the element is found on the
-*   list is "found" is set to TRUE, if not it is set to FALSE.
-*
-* Arguments:
-*   list        - (IO)  Simple list to be examined.
-*   p_element   - (IN)  Pointer to the element that is to be tested for.
-*   found       - (OUT) TRUE iff the element on the list is found.
-*
-* Returns:
-*   None
-*
---*/
-
-#define utl_list_find(list, p_element, found)                                     \
-	{                                                                         \
-	if ((list).p_root == p_element)                                           \
-		{                                                                      \
-		/* First, handle the case in which the element to be found is at   */  \
-		/* the root of the list.                                           */  \
-		found = TRUE;                                                          \
-		}                                                                      \
-	else                                                                      \
-		{                                                                      \
-		/* Handle the case in which the element to be deleted is deeper */     \
-		/* into the list than the root element.                         */     \
-		(list).p_tmp = (list).p_root;                                          \
-		while (((list).p_tmp != NULL) && ((list).p_tmp->p_next != p_element))  \
-			(list).p_tmp = (list).p_tmp->p_next;                                \
-																									  \
-		/* If the target element has been found (not the end of the list), */  \
-		/* set the flag.                                                   */  \
-		if ((list).p_tmp != NULL)                                              \
-			found = TRUE;                                                       \
-		else                                                                   \
-			found = FALSE;                                                      \
-		}                                                                      \
-	}
-
-/*++
-* =============================
-* = utl_list_traverse (macro) =
-* =============================
-*
-* Overview:
-*   Allows a simple list to be easily traversed.  This macro is not in the
-*   form of a function but in the form of a loop.
-*
-* Usage:
-*   The utl_list_traverse macro should be used as a loop construct much like
-*   a 'for' loop is used.  utl_list_traverse must be followed by a statement
-*   or bracketed group of statements.  For example:
-*
-*       NAME_LIST    name_list;
-*       NAME_RECORD *p_name_record;
-*
-*       printf ("Names in the List:\n");
-*       utl_list_traverse (name_list, p_name_record)
-*          {
-*          printf ("  %s\n", p_name_record->text);
-*          }
-*
-*   Note that if the list is empty, the body of the loop will not execute.
-*
-*   Do NOT use the utl_list_traverse macro to iteratively deallocate all of
-*   the elements in the list!  Use the utl_list_dealloc macro for this.
-*
-* Arguments:
-*   list    - (IN)  The simple list to be traversed.
-*
-*   p_index - (OUT) The loop index.  This is a pointer to the structure stored
-*                   in the list.  The loop executes once for each element
-*                   in the list and the p_index points to the element being
-*                   processed for each iteration.
-* 
-* Returns:
-*   Not Applicable
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-#define utl_list_traverse(list, p_index) for (p_index  = (list).p_root; \
-                                              p_index != NULL;          \
-                                              p_index  = (p_index)->p_next)
-
-/*++
-* ============================
-* = utl_list_dealloc (macro) =
-* ============================
-*
-* Overview:
-*   Delete and deallocate (using os_mem_dealloc) all elements in the simple
-*   list.
-*
-*   Note that if the list elements contain pointers to allocated data, this
-*   data will be lost.  First use utl_list_traverse to deallocate all pointers
-*   within the element structure.  Use utl_list_dealloc to deallocate the
-*   actual element structures within the list.
-*
-* Arguments:
-*   os_handle  - (IN)  Handle of the appropriate utl_os instance.
-*   list       - (IN)  Simple list to be cleared.
-* 
-* Returns:
-*   Not Applicable
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   The list is empty and each element has been deallocated.
---*/
-#define utl_list_dealloc(list)       \
-   {                                            \
-   while ((list).p_root)                        \
-      {                                         \
-      (list).p_tmp  = (list).p_root;            \
-      (list).p_root = (list).p_root->p_next;    \
-      os_mem_dealloc ((list).p_tmp); \
-      (list).size  -= 1;                        \
-      }                                         \
-   }
-
-
diff -ur --new-file old/atm/led/utl_os.h new/atm/led/utl_os.h
--- old/atm/led/utl_os.h	Wed Nov 19 12:59:15 1997
+++ new/atm/led/utl_os.h	Thu Jan  1 01:00:00 1970
@@ -1,291 +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:
-*   utl_os.h
-*   
-* Abstract:
-*   This is the interface for the basic functions that are provided by the OS.
-*
-* Authors:
-*   DMW - Douglas M. Washabaugh
-*
-* Modification History:
-*   Date       Name  Description 
-*   08-Aug-94  DMW   Created.
-*   02-Nov-94  DMW   Updated to use handles, added timer routines.
-*   10-Nov-94  DMW   Updated with error log and print routines.
-*   01-Jan-95  DMW   Allocated memory is now zeroed.
-*   10-Jan-95  DMW   Remove obsolete phys mem routines, added mem statistics.
-*   03-Feb-95  PJR   Added test string input to os_create.
-*   16-Mar-95  DMW   Added two new routines os_buff_hdr_copy, os_buff_hdr_get.
-*
-* Description:
-*   There will be one instantiation of this module for each adapter in the 
-*   system.
-*
-* Call Sequence:
-*   The following shows a rough sequence of how calls can be made to this
-*   module.  Because this module is a collection of miscellaneous routines,
-*   a different method is used to represent the call sequence.  The method
-*   says that a given routine cannot be called unless all routines with 
-*   a smaller indention are called first.  For example, the following shows
-*   that os_timer_cancel cannot be called until os_timer_set is called, which
-*   cannot be called before os_timer_allocate, which cannot be called before
-*   os_create.
-*
-*     - os_create
-*        - os_timer_allocate
-*           - os_timer_set
-*              - os_timer_cancel
-*           - os_timer_deallocate
-*        - os_reg_get
-*        - os_reg_set
-*        - os_mem_alloc
-*           - os_mem_dealloc
-*        - os_phys_mem_alloc
-*           - os_phys_mem_dealloc
-*        - os_print
-*        - os_err_log
-*        - os_destroy   
-*/
-
-/*++
-* ---------------------
-* - OS_TIMER_CALLBACK -
-* ---------------------
-*
-* Overview:
-*   Routine that is called when a timer expires.
-*
-* Arguments:
-*   context - (IN) The value that was specified when the timer was allocated.
-*   
-* Returns:
-*   none
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   none
---*/
-#ifndef UTL_OS_H
-#define UTL_OS_H
-#include <stdlib.h>
-#include "g_types.h"
-
-typedef void (*OS_TIMER_CALLBACK) (HANDLE context);
-
-
-/*++
-* ==================
-* = os_timer_alloc =
-* ==================
-*
-* Overview:
-*   Allocates and initializes a timer.  Some implementations of this
-*   routine may allocate memory or other resources.  This routine can be
-*   called from the coded path that processes receives or "transmit dones"
-*   (which may include interrupt level for some operating systems).
-*
-* Arguments:
-*  os_handle      - (IN)  The handle returned from os_create.
-*
-*  callback       - (IN)  Pointer to the routine to callback when the timer
-*                         expires.
-*
-*  context        - (IN)  Value to pass to the callback routine.
-*
-*  p_timer_handle - (OUT) Pointer to a timer handle.  This value must be used
-*                         when setting, canceling, or deallocating a timer.
-*                         It will have the os_handle associated with it so that
-*                         if the timer is specified in a call, the os_handle
-*                         does not also need to be specified.
-* Returns:
-*   STATUS_K_SUCCESS   - Timer was successfully allocated
-*   STATUS_K_RESOURCES - Timer was NOT allocated.
-*
-* Preconditions:
-*   none
-*
-* Postconditions:
-*   A timer may have been allocated.
---*/
-STATUS os_timer_alloc (OS_TIMER_CALLBACK  callback,
-                       HANDLE             context,
-                       HANDLE            *p_timer_handle);
-/*++
-* ================
-* = os_timer_set =
-* ================
-*
-* Overview:
-*   Sets a timer to expire after a specified time.  When the timer expires,
-*   its associated callback routine is called.
-*
-* Arguments:
-*  timer_handle - (IN)  The value returned from os_timer_alloc.
-*
-*  time         - (IN)  Number of milliseconds until the callback is called.
-*
-* Returns:
-*   STATUS_K_SUCCESS
-*   STATUS_K_FAILURE
-*
-* Preconditions:
-*   - The timer was allocated.
-*
-* Postconditions:
-*   A timer is set.                    
---*/
-STATUS os_timer_set (HANDLE timer_handle,
-                     UINT32  timeset);
-
-/*++
-* ===================
-* = os_timer_cancel =
-* ===================
-*
-* Overview:
-*   Cancels the specified timer.   The timer callback routine is guaranteed
-*   not be called after this routine completes.  Also, it is permissible to
-*   cancel a timer that has not been set.
-*
-* Arguments:
-*  timer_handle - (IN)  The value returned from os_timer_alloc.
-*
-* Returns:
-*   STATUS_K_SUCCESS       - Timer was successfully canceled.
-*
-*   STATUS_K_NO_WORK_TO_DO - Timer was not set.
-*
-* Preconditions:
-*   - The timer was allocated.
-*
-* Postconditions:
-*   - The timer is canceled.
-*   - The timer callback will not be called.                    
---*/
-STATUS os_timer_cancel (HANDLE timer_handle);
-
-
-/*++
-* ====================
-* = os_timer_dealloc =
-* ====================
-*
-* Overview:
-*   Deallocates the specified timer.  Even though some implementations may not 
-*   support this feature, it must be called.  Note that this routine can be
-*   called even if the timer has been started, but not yet expired.
-*
-*   After this routine completes, it is guaranteed that the timer callback will
-*   not be called.
-*
-* Arguments:
-*  timer_handle - (IN)  The value returned from os_timer_alloc.
-*
-* Returns:
-*   none
-*
-* Preconditions:
-*   - The timer was allocated.
-*
-* Postconditions:
-*   - A timer was deallocated
-*   - The timer callback will not be called.
---*/
-void os_timer_dealloc (HANDLE timer_handle);
-
-/*++
-* ================
-* = os_mem_alloc =
-* ================
-*
-* Overview:
-*   Allocates the specified number of bytes from virtual memory, and returns
-*   the virtual address of the memory.  The allocated memory is zeroed.
-*
-*   This routine can be called from the coded path that processes receives or
-*   "transmit dones" (which may include interrupt level for some operating
-*   systems).
-*
-* Arguments:
-*   os_handle - (IN) The handle that was returned by os_create.
-*
-*   size      - (IN) The number of bytes to allocate.
-*  
-* Returns:
-*   - Null, if call failed, else pointer to allocated memory.
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-
-void *os_mem_alloc (UINT32 size);
-
-/*++
-* ==================
-* = os_mem_dealloc =
-* ==================
-*
-* Overview:
-*   Deallocates the specified virtual memory.  This routine must not be called
-*   from interrupt level.
-*
-* Arguments:
-*   os_handle - (IN) The handle that was returned by os_create.
-* 
-*   p_mem     - (IN) Pointer to the memory to return.
-*
-* Returns:
-*   None
-*
-* Preconditions:
-*   None
-*
-* Postconditions:
-*   None
---*/
-
-void os_mem_dealloc (void   *p_mem);
-
-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/led/zeppelin.8 new/atm/led/zeppelin.8
--- old/atm/led/zeppelin.8	Tue Feb  9 17:12:05 1999
+++ new/atm/led/zeppelin.8	Wed Jun  2 23:36:55 1999
@@ -1,4 +1,4 @@
-.TH zeppelin 8 "Feb 6, 1998" "Linux" "Maintenance Commands"
+.TH zeppelin 8 "Feb 6, 1999" "Linux" "Maintenance Commands"
 .SH NAME
 zeppelin \- ATM LAN Emulation client demon (LED) Zeppelin
 .SH SYNOPSIS
@@ -9,11 +9,11 @@
 .RB [ \-m\ \fImesg_mask\fP ]
 .RB [ \-l\ \fIlisten_address\fP ]
 .RB [ \-i\ \fIinterface_number\fP ]
-.RB [ \-q\ \fIqos_spec\fP ]
+.RB [ \-t\ \fI1516|1580|4544|9234|18190\fP ]
 .RB [ \-1\ ]
 .RB [ \-2\ ]
-.RB [ \-t\ \fI1516|1580|4544|9234|18190\fP ]
 .RB [ \-p\ ]
+.RB [ \-F\ \fIlogfile\fP ]
 .RB [ \-f\ \fIFore_specific_name\fP ]
 .SH DESCRIPTION
 A LAN Emulation Client is an entity in an ATM endstation that performs 
@@ -56,9 +56,11 @@
 signalling. Use this if you are running more than one client or
 a set of LE servers.
 .IP \fB\-i\ \fIinterface_number\fP
-Linux LEC supports up to 16 network interfaces. This number tells
-zeppelin to which of these to attach. Network interfaces are
-numbered from "lec0" to "lec15".
+Linux LEC supports up to 40+8 network interfaces. The interface_number
+tells zeppelin to which of these to attach. Ethernet type network
+interfaces are numbered from "lec0" to "lec39" and Token Ring
+interfaces are from "lec40" to "lec47". These parameters are tweakable
+during the kernel compile, see <linux/atmlec.h>.
 .IP \fB\-t\ \fIMTU\fP
 The MTU of ELAN to join. You need to also use \fBifconfig(8)\fP to
 set the MTU of the LANE interface.
@@ -70,17 +72,29 @@
 Enable proxy. When started with this option, it is possible to bridge
 packets between ATM and Ethernet. That is, you can use LANE interfaces
 with normal bridging. See the Bridging mini-Howto for more info.
+.IP \fB\-F\ \fIlogfile\fP
+Instead of writing debug messages to \fBstderr\fP, write the messages
+to the file \fBlogfile\fP. Use \fBsyslog\fP as the file name to use
+the \fBsyslog(3)\fP facility.
 .IP \fB\-f\ \fIFore\ specific\ name\fP
 The LANE servers on Fore ATM switches can display a special
 name if a client can supply one. This name shows with command
 \'conf lane les show advanced\'.
+.SH TOKEN RING CONSIDERATIONS
+A number of lec interfaces is reserved for Token Ring ELANs when the
+kernel is compiled with Token Ring (CONFIG_TR) support. See the
+discussion about interface_number command line option above. The Linux
+Token Ring LANE client does not support bridging between legacy Token
+Ring and ATM parts of the ELAN, so using the -p option is not
+recommended. Token Ring support has received less testing than its
+Ethernet counterpart.
 .SH BUGS
-Supports only IEEE 802.3 / Ethernet type of ELANs. Please report any
-new bugs to Heikki Vatiainen <hessu@cs.tut.fi>
-.PP
 John Bonham died 1980 and Led Zeppelin broke.
-.SH AUTHOR
-Marko Kiiskila, TUT <carnil@cs.tut.fi>
+.PP
+Please report any other bugs to Heikki Vatiainen <hessu@cs.tut.fi>
+.SH AUTHORS
+Marko Kiiskila, TUT <carnil@cs.tut.fi> and Heikki Vatiainen, TUT
+<hessu@cs.tut.fi>
 .SH "SEE ALSO"
 lecs(8), mpcd(8), atmsigd(8), les(8), qos(7)
 .\"{{{}}}
diff -ur --new-file old/atm/led.new/COPYRIGHT.TUT new/atm/led.new/COPYRIGHT.TUT
--- old/atm/led.new/COPYRIGHT.TUT	Sat Feb  6 14:49:41 1999
+++ new/atm/led.new/COPYRIGHT.TUT	Thu Jan  1 01:00:00 1970
@@ -1,21 +0,0 @@
-/*
- * 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/led.new/Makefile new/atm/led.new/Makefile
--- old/atm/led.new/Makefile	Thu Feb 18 16:13:21 1999
+++ new/atm/led.new/Makefile	Thu Jan  1 01:00:00 1970
@@ -1,10 +0,0 @@
-LIBS=-latm -latmd
-OBJS=join.o conn.o main.o address.o frames.o display.o kernel.o
-BOOTPGMS=zeppelin.new
-MAN8=zeppelin.new.8
-CFLAGS_PRIVATE=
-
-include ../Rules.make
-
-zeppelin.new:$(OBJS)
-	$(CC) $(LDFLAGS) -o $(BOOTPGMS) $(OBJS) $(LIBD) $(LDLIBS) $(LIBS)
diff -ur --new-file old/atm/led.new/address.c new/atm/led.new/address.c
--- old/atm/led.new/address.c	Sat Feb  6 15:11:34 1999
+++ new/atm/led.new/address.c	Thu Jan  1 01:00:00 1970
@@ -1,92 +0,0 @@
-/* address.c - functions to query ESI and local ATM address from kernel */
-
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-
-/*  Copyright (C) 1999  Heikki Vatiainen hessu@cs.tut.fi */
-
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <atm.h>
-#include <linux/atmdev.h>
-#include <atmd.h>
-
-#include "address.h"
-
-#define COMPONENT "address.c"
-
-/* Gets End System Identifier (MAC address) from kernel
- * Returns < 0 for error
- */
-int addr_getesi(unsigned char *mac_addr)
-{
-        int fd, retval;
-        struct atmif_sioc req;
-        
-        fd = socket(PF_ATMSVC, SOCK_DGRAM, 0);
-        if (fd < 0) {
-                diag(COMPONENT, DIAG_ERROR, "addr_getesi: socket: %s\n",
-                     strerror(errno));
-                return -1;
-        }
-        req.number = 0;
-        req.arg = mac_addr;
-        req.length = ESI_LEN;
-        retval = ioctl(fd, ATM_GETESI, &req);
-        if (retval < 0) diag(COMPONENT, DIAG_ERROR, "ioctl ATM_GETESI: %s\n",
-                             strerror(errno));
-        close(fd);
-
-        return retval;
-}
-
-/* Gets our ATM address from kernel. Useful for binding listen sockets.
- * Returns < 0 for error
- */
-int get_listenaddr(unsigned char *atm_addr)
-{
-        int fd, retval;
-        struct atmif_sioc req;
-        struct sockaddr_atmsvc listen_addr;
-        
-        fd = socket(PF_ATMSVC, SOCK_DGRAM, 0);
-        if (fd < 0) {
-                diag(COMPONENT, DIAG_ERROR, "get_listenaddr: socket: %s\n",
-                     strerror(errno));
-                return -1;
-        }
-        req.number = 0;
-        req.arg = &listen_addr;
-        req.length = sizeof(struct sockaddr_atmsvc);
-        retval = ioctl(fd, ATM_GETADDR, &req);
-        if (retval < 0) diag(COMPONENT, DIAG_ERROR, "ioctl ATM_GETADDR: %s\n",
-                             strerror(errno));
-        close(fd);
-
-        memcpy(atm_addr, listen_addr.sas_addr.prv, ATM_ESA_LEN);
-
-        return retval;
-}
diff -ur --new-file old/atm/led.new/address.h new/atm/led.new/address.h
--- old/atm/led.new/address.h	Sat Feb  6 15:06:08 1999
+++ new/atm/led.new/address.h	Thu Jan  1 01:00:00 1970
@@ -1,31 +0,0 @@
-/*
- * 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.
- * 
- */
-
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#ifndef ADDRESS_H
-#define ADDRESS_H
-
-int addr_getesi(unsigned char *mac_addr);
-int get_listenaddr(unsigned char *atm_addr);
-
-#endif /* ADDRESS_H */
diff -ur --new-file old/atm/led.new/conn.c new/atm/led.new/conn.c
--- old/atm/led.new/conn.c	Thu Feb 18 16:20:24 1999
+++ new/atm/led.new/conn.c	Thu Jan  1 01:00:00 1970
@@ -1,900 +0,0 @@
-/* conn.c - functions for handling SVCs, create, accept, send, etc. */
-
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-
-#include <atm.h>
-#include <atmsap.h>
-#include <linux/atmlec.h>
-
-#include <atmd.h>
-
-#include "conn.h"
-#include "display.h"
-#include "lec.h"
-#include "frames.h"
-#include "kernel.h"
-
-#define COMPONENT "conn.c"
-
-/* status */
-#define CONNECTED  42    /* Operational socket */
-#define CONNECTING 43    /* Non-blocking socket, not yet connected */
-
-/* type */
-#define WEMADE 7
-#define THEYMADE 8
-#define LISTENING 9
-#define KERNEL_SOCK 10
-
-static Conn_t *connlist = NULL;
-
-/* Local protos */
-static void list_remove_conn(Conn_t *conn);
-static Conn_t *list_add_conn(unsigned char *dest_atm_addr);
-static Conn_t *conn_already_exists(unsigned char *atm_addr, Conn_t *current);
-static const char *get_type_string(int type);
-static int maxmtu2maxsdu(uint8_t mtu);
-
-static void delete_addr(unsigned char *atm_addr)
-{
-        struct atmlec_msg msg;
-
-        msg.type = l_addr_delete;
-        memcpy(msg.content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
-        msg_to_kernel(&msg, sizeof(struct atmlec_msg));
-
-        return;
-}
-
-/* Checks if connection to atm_addr already exists. Does not
- * check against current though.
- * Returns NULL for no connection, or Conn_t of existing connection.
- */
-static Conn_t *conn_already_exists(unsigned char *atm_addr, Conn_t *current)
-{
-        Conn_t *conn;
-
-        conn = connlist;
-        while (conn) {
-                if (conn != current &&
-                    conn->type != LISTENING && 
-                    conn->type != KERNEL_SOCK) {
-                        if (memcmp(conn->atm_address, atm_addr, ATM_ESA_LEN) == 0)
-                                return conn;
-                }
-                conn = conn->next;
-        }
-        
-        return NULL;
-}
-
-/* Initializes and fills in *sap and *qos according to Blli
- * code point value specified in conn_type.
- */
-void init_conn_params(struct atm_sap *sap, struct atm_qos *qos,
-                      uint16_t conn_type)
-{
-
-        unsigned int bllicode;
-        int i, sdu;
-        char qos_text[MAX_ATM_QOS_LEN + 1];
-  
-        diag(COMPONENT, DIAG_DEBUG, "init_conn_params, conn_type %x\n", conn_type);
-
-        memset(qos, 0, sizeof(struct atm_qos));
-        memset(sap, 0, sizeof(struct atm_sap));
-        qos->aal = ATM_AAL5;
-  
-        /* Set the forward and backward Max CPCS-SDU Size */
-        switch(conn_type) {
-        case CONTROL_CONN:
-                qos->rxtp.max_sdu = 1516;
-                qos->txtp.max_sdu = 1516;
-                break;
-        case DATA_DIRECT_CONN:
-        case MCAST_CONN:
-                sdu = maxmtu2maxsdu(lec_params.c3_max_frame_size);
-                qos->rxtp.max_sdu = sdu;
-                qos->txtp.max_sdu = sdu;
-                break;
-        default:
-                diag(COMPONENT, DIAG_ERROR, "unknown conn_type %x\n", conn_type);
-                break;
-        }
-        
-        /* ATM User Cell Rate/ATM Traffic Descriptor. */
-        qos->txtp.traffic_class = ATM_UBR;
-        qos->rxtp.traffic_class = ATM_UBR;
-   
-        if (get_verbosity(COMPONENT) >= DIAG_DEBUG) {
-                if (qos2text(qos_text, sizeof(qos_text), qos, 0) < 0)
-                        sprintf(qos_text, "<bad qos>");
-                diag(COMPONENT, DIAG_DEBUG, "init_conn_params, QoS '%s'\n", qos_text);
-        }
-
-        /* No Broadband High Layer Information in LANE. */
-        sap->bhli.hl_type = ATM_HL_NONE;
-
-        /* Broadband Lower Layer Information. */
-        sap->blli[0].l3_proto = ATM_L3_TR9577;
-        sap->blli[0].l3.tr9577.ipi = NLPID_IEEE802_1_SNAP;
-        sap->blli[0].l3.tr9577.snap[0] = 0x00;
-        sap->blli[0].l3.tr9577.snap[1] = 0xa0;
-        sap->blli[0].l3.tr9577.snap[2] = 0x3e;
-        bllicode = htons(conn_type);
-        sap->blli[0].l3.tr9577.snap[3] = (unsigned char)(0xff&bllicode);
-        sap->blli[0].l3.tr9577.snap[4] = (unsigned char)(0xff&(bllicode>>8));
-
-        if (get_verbosity(COMPONENT) == DIAG_DEBUG) {
-                for(i=0; i < 5; i++) {
-                        diag(COMPONENT, DIAG_DEBUG, "snap[%d] = 0x%2.2x",
-                             i, sap->blli[0].l3.tr9577.snap[i]);
-                }
-        }
-
-        return;
-}
-
-/* Returns != 0 if blli indicates Data Direct
- * connection
- */
-static int is_data_direct(struct atm_blli *blli)
-{
-        return (blli->l3.tr9577.snap[4] == DATA_DIRECT_CONN);
-}
-
-/* Creates a socket with the specified parameters.
- * If listen_addr is non NULL binds to it.
- * Returns < 0 for error or new socket descriptor.
- */
-static int get_socket(struct sockaddr_atmsvc *listen_addr,
-                      struct atm_sap *sap, struct atm_qos *qos)
-{
-        int s, ret;
-
-        s = socket(PF_ATMSVC, SOCK_DGRAM, 0);
-        if (s < 0) {
-                diag(COMPONENT, DIAG_ERROR, "socket creation failure: %s\n",
-                     strerror(errno));
-                return -1;
-        }
-        diag(COMPONENT, DIAG_DEBUG, "get_socket: got fd %d\n", s);
-        
-        if (setsockopt(s, SOL_ATM, SO_ATMQOS, qos, sizeof(struct atm_qos)) < 0) {
-                diag(COMPONENT, DIAG_ERROR, "get_socket: setsockopt SO_ATMQOS: %s\n", strerror(errno));
-                close(s);
-                return -1;
-        }
-        if (setsockopt(s, SOL_ATM, SO_ATMSAP, sap, sizeof(struct atm_sap)) < 0) {
-                diag(COMPONENT, DIAG_ERROR, "setup_svc setsockop(SO_ATMSAP)\n");
-                close(s);
-                return -1;
-        }
-        
-        /* Bind the socket to our local address */
-        if (listen_addr == NULL)
-                return s;
-        ret = bind(s, (struct sockaddr *)listen_addr, sizeof(struct sockaddr_atmsvc));
-        if (ret < 0) {
-                diag(COMPONENT, DIAG_ERROR, "bind error: %s\n", strerror(errno));
-                close(s);
-                return -1;
-        }
-        
-        return s;
-}
-
-
-/*
- * You need to check this if setup_svc() returns NULL
- */
-#if 0
-        if (is_data_direct(&sap->blli[0])) {
-                /* Try to remove possible entry in kernel */
-                delete_addr(conn->atm_address);
-        }
-#endif
-/* Does an active open to dst_addr using pre-filled
- * parameters in sap and qos.
- * If listen_addr is non NULL, binds to it.
- * Data direct SVCs are non-blocking, others block
- * Returns NULL for error or new connections.
- */
-Conn_t *setup_svc(struct sockaddr_atmsvc *dst_addr,
-                  struct sockaddr_atmsvc *listen_addr,
-                  struct atm_sap *sap, struct atm_qos *qos)
-{
-        Conn_t *conn;
-        int s, ret;
-        char buff[MAX_ATM_ADDR_LEN+1];
-
-        diag(COMPONENT, DIAG_DEBUG, "Outgoing call setup\n");
-        
-        /* The code below is commented out due to the following scenario:
-           We have made a connection to another LEC and our address was
-           numerically lower than theirs (LANEv2 8.1.13).
-           The other end has also connected us, but we must not use that
-           VCC.
-           However, if the connection we made gets closed, we can not open
-           it again since a connection to the destination LEC already exists.
-        */
-#if 0
-        /* We don't create connection to an entity where we already have
-           a connection. */
-        if (conn_already_exists(dst_addr->sas_addr.prv, NULL) &&
-            is_data_direct(&sap->blli[0]))
-                return NULL;
-#endif
-
-        dst_addr->sas_family = AF_ATMSVC;
-        listen_addr->sas_family = AF_ATMSVC;
-        
-        switch(sap->blli[0].l3.tr9577.snap[4]) { /* Kludge.  Eh? */
-        case CONTROL_CONN:
-                diag(COMPONENT, DIAG_DEBUG, "LE Control SVC setup\n");
-                break;
-        case DATA_DIRECT_CONN:
-                diag(COMPONENT, DIAG_DEBUG, "Data direct 802.3\n");
-                break;
-        case MCAST_CONN:
-                diag(COMPONENT, DIAG_DEBUG, "Multicast 802.3\n");
-                break;
-        default:
-                diag(COMPONENT, DIAG_ERROR, "Unknown codepoint in svc setup\n");
-        }
- 
-        s = get_socket(listen_addr, sap, qos);
-        if (s < 0) return NULL;
-        if (atm2text(buff, sizeof(buff), (struct sockaddr *)dst_addr, A2T_PRETTY | A2T_NAME | A2T_LOCAL) < 0)
-                sprintf(buff, "<Unknown ATM address>");
-        diag(COMPONENT, DIAG_DEBUG, "Call to %s", buff);
-
-        /* Make data direct SVCs non-blocking */
-        if (is_data_direct(&sap->blli[0])) {
-                ret = fcntl(s, F_GETFL);
-                if (ret < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "fcntl(s, F_GETFL)\n");
-                        close(s);
-                } else if (fcntl(s, F_SETFL, ret|O_NONBLOCK) < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "fcntl(s, F_SETFL, x|O_NONBLOCK)\n");
-                        close(s);
-                        return NULL;
-                }
-        }
-
-        ret = connect(s, (struct sockaddr *)dst_addr, sizeof(struct sockaddr_atmsvc));
-        if (ret < 0 && errno != EINPROGRESS) {
-                diag(COMPONENT, DIAG_ERROR, "connect error: %s\n", strerror(errno));
-                close(s);
-                return NULL;
-        }
-
-        conn = list_add_conn(dst_addr->sas_addr.prv);
-        diag(COMPONENT, DIAG_DEBUG, "Conn:%p\n", conn);
-        if (conn == NULL) {
-                close(s);
-                return NULL;
-        }
-        conn->fd = s;
-        conn->type = WEMADE;
-        conn->codepoint = sap->blli[0].l3.tr9577.snap[4];
-
-        if (is_data_direct(&sap->blli[0]))
-                conn->status = CONNECTING;
-        else
-                conn->status = CONNECTED;
-        
-        return conn;
-}
-
-/* Creates listen socket for incoming data direct connections.
- * Only for data direct, not for Control or Multicast listen sockets.
- * Returns < 0 for error
- */
-int create_data_listen(void)
-{
-        struct atm_sap sap;
-        struct atm_qos qos;
-        struct sockaddr_atmsvc addr;
-
-        memset(&addr, 0, sizeof(struct sockaddr_atmsvc));
-        memcpy(addr.sas_addr.prv, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-        addr.sas_family = AF_ATMSVC;
-        init_conn_params(&sap, &qos, DATA_DIRECT_CONN);
-
-        lec_params.data_listen = create_listensocket(&addr, &sap, &qos);
-        if (lec_params.data_listen == NULL) {
-                diag(COMPONENT, DIAG_FATAL, "Could not create listen socket for incoming Data Direct VCCs\n");
-                return -1;
-        }
-
-        return 0;
-}
-
-/* Opens a non-blocking Data Direct VCC to atm_addr.
- * Not for Control or Multicast connections.
- * Returns < 0 for error
- */
-int create_data_svc(unsigned char *atm_addr, int codepoint)
-{
-        struct atm_sap sap;
-        struct atm_qos qos;
-        struct sockaddr_atmsvc my_addr, dst_addr;
-        Conn_t *conn;
-
-        memset(&my_addr, 0, sizeof(struct sockaddr_atmsvc));
-        memcpy(my_addr.sas_addr.prv, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-        memset(&dst_addr, 0, sizeof(struct sockaddr_atmsvc));
-        memcpy(dst_addr.sas_addr.prv, atm_addr, ATM_ESA_LEN);
-        my_addr.sas_family = dst_addr.sas_family = AF_ATMSVC;
-        init_conn_params(&sap, &qos, codepoint);
-
-        conn = setup_svc(&dst_addr, &my_addr, &sap, &qos);
-        if (conn == NULL) {
-                diag(COMPONENT, DIAG_ERROR, "Could not create Data Direct VCC\n");
-                delete_addr(dst_addr.sas_addr.prv);
-                return -1;
-        }
-
-        return 0;
-}
-
-/* Creates a listen socket with parameters specified with
- * arguments.
- * Returns NULL for error or Conn_t for new listen socket.
- */
-Conn_t *create_listensocket(struct sockaddr_atmsvc *listen_addr,
-                            struct atm_sap *sap, struct atm_qos *qos)
-{
-        int fd, ret;
-        Conn_t *conn;
-
-        diag(COMPONENT, DIAG_DEBUG, "conn_create_listensocket\n");
-        
-        fd = get_socket(listen_addr, sap, qos);
-        if (fd < 0) return NULL;
-        
-        ret = listen(fd, 5);
-        if (ret != 0) {
-                diag(COMPONENT, DIAG_DEBUG, "Listen failed: %s\n", strerror(errno));
-                close(fd);
-                return NULL;
-        }
-        
-        conn = list_add_conn(NULL);
-        if (conn == NULL) {
-                diag(COMPONENT, DIAG_ERROR, "List_add_conn failed\n");
-                close(fd);    
-                return NULL;
-        }
-
-        conn->type = LISTENING;
-        conn->fd = fd;
-        diag(COMPONENT, DIAG_DEBUG, "Listen socket created blli:%2.2x %2.2x fd: %d\n",
-             sap->blli[0].l3.tr9577.snap[3],
-             sap->blli[0].l3.tr9577.snap[4],
-             conn->fd);
-        
-        return conn;
-}
-
-/* Accepts a new connection from listen socket in conn.
- * Returns NULL for error
- */
-Conn_t *accept_conn(Conn_t *conn)
-{
-        Conn_t *new;
-        struct sockaddr_atmsvc addr;
-        size_t len;
-        int fd;
-        char buff[MAX_ATM_ADDR_LEN+1];
-
-        diag(COMPONENT, DIAG_DEBUG, "Accepting connection on fd %d\n", conn->fd);
-        len = sizeof(addr);
-        fd = accept(conn->fd, (struct sockaddr *)&addr, &len);
-        diag(COMPONENT, DIAG_DEBUG, "accept returned %d\n", fd);
-        if (fd < 0) {
-                diag(COMPONENT, DIAG_ERROR, "accept: %s\n", strerror(errno));
-                return NULL;
-        }
-        if (atm2text(buff, sizeof(buff), (struct sockaddr *)&addr, A2T_PRETTY | A2T_NAME | A2T_LOCAL) < 0)
-                sprintf(buff, "<Unknown ATM address>");
-        diag(COMPONENT, DIAG_DEBUG, "Call from %s", buff);
-
-        new = list_add_conn(addr.sas_addr.prv);
-        if (new == NULL) return NULL;
-        new->fd = fd;
-        new->status = CONNECTED;
-        new->type = THEYMADE;
-        if (conn == lec_params.ctrl_listen) new->codepoint  = CONTROL_CONN;
-        if (conn == lec_params.mcast_listen) new->codepoint = MCAST_CONN;
-        if (conn == lec_params.data_listen) new->codepoint  = DATA_DIRECT_CONN;
-
-        return new;
-}
-
-/* Close all connections, important or not.
- */
-void close_connections(void)
-{
-        Conn_t *conn, *next;
-
-        for(conn = connlist; conn; conn = next) {
-                diag(COMPONENT, DIAG_DEBUG, "Destroying:%p fd:%d type:%d\n",
-                     conn, conn->fd, conn->type);
-                next = conn->next;
-                close(conn->fd);
-                list_remove_conn(conn);
-                free(conn);
-        }
-
-        return;
-}
-
-/* Closes a connection and checks its importance.
- * Important connections are kernel socket, LES connections,
- * BUS Default Multicast Send VCC, last Multicast Forward VCC from Bus
- * and any of the listen sockets.
- * Returns < 0 for important connection.
- */
-int close_connection(Conn_t *conn)
-{
-        int bad = 0;
-        Conn_t *mcast;
-
-        diag(COMPONENT, DIAG_DEBUG, "close_connection %p\n", conn);
-
-        if (conn == lec_params.kernel ||
-            conn == lec_params.ctrl_direct  ||
-            conn == lec_params.ctrl_dist    ||
-            conn == lec_params.mcast_send   ||
-            conn == lec_params.mcast_listen ||
-            conn == lec_params.data_listen)
-                bad = -1;
-        else {
-                bad = -1;
-                for (mcast = connlist; mcast; mcast = mcast->next)
-                        if (mcast != conn &&
-                            mcast->type == THEYMADE &&
-                            mcast->codepoint == MCAST_CONN)
-                                bad = 0;
-        }
-
-        close(conn->fd);
-        list_remove_conn(conn);
-        free(conn);
-        
-        return bad;
-}
-
-/* Accepts a new incoming Data Direct or Multicast Forward connection.
- * Control connections (LECS/LES) are accepted during configuration/join.
- * Returns < 0 for serious error such as broken listen socket.
- */
-static int handle_accept(Conn_t *conn)
-{
-        Conn_t *new;
-        struct atmlec_ioc ioc;
-        
-        new = accept_conn(conn);
-        if (new == NULL) return -1;
-
-        if (conn == lec_params.mcast_listen) {
-                diag(COMPONENT, DIAG_DEBUG, "Multicast Forward VCC accepted\n");
-                ioc.receive = 2;
-        } else {
-                diag(COMPONENT, DIAG_DEBUG, "Data Direct VCC accepted\n");
-                ioc.receive = 0;
-                if (conn_already_exists(new->atm_address, new) &&
-                    memcmp(lec_params.c1n_my_atm_addr, new->atm_address,  ATM_ESA_LEN) < 0) {
-                        diag(COMPONENT, DIAG_DEBUG, "Using it only to receive, spec 8.1.1\n");
-                        ioc.receive = 1;
-                }
-        }
-        memcpy(ioc.atm_addr, new->atm_address, ATM_ESA_LEN);
-        ioc.dev_num = lec_params.itf_num;
-        diag(COMPONENT, DIAG_DEBUG, "Attaching a new VCC, fd %d\n", new->fd);
-        if (ioctl(new->fd, ATMLEC_DATA, &ioc) < 0) {
-                diag(COMPONENT, DIAG_ERROR, "VCC attach failed: ioctl: %s\n", strerror(errno));
-                return -1;
-        }
-
-        return 0;
-}
-
-/* Reads a LE control frame from conn, usually Data Direct or
- * Multicast Forward connection. Calls the incoming packet
- * handler function.
- * Returns < 0 for serious error such as broken LES connection
- */
-static int handle_data(Conn_t *conn)
-{
-        char buff[MAX_CTRL_FRAME];
-        int retval;
-
-        retval = recv_frame(conn, buff, sizeof(buff));
-        if (retval < 0) {
-                diag(COMPONENT, DIAG_ERROR, "handle_data: read: %s\n", strerror(errno));
-                return (close_connection(conn));
-        }
-        if (retval == 0) {
-                diag(COMPONENT, DIAG_DEBUG, "fd %d, Data or Multicast VCC closed\n", conn->fd);
-                return (close_connection(conn));
-        }
-
-        return handle_frame(conn, buff, retval);
-}
-
-/* Checks connections in *fds. The only allowed sockets
- * in *fds are listen sockets, data direct and control
- * sockets.
- * Returns < 0 for serious error such as broken LES connection
- */
-int check_connections(fd_set *fds)
-{
-        Conn_t *conn, *next;
-
-        conn = connlist;
-        while (conn != NULL) {
-                next = conn->next;
-                if (!FD_ISSET(conn->fd, fds)) {
-                        conn = next;
-                        continue;
-                }
-
-                switch (conn->type) {
-                case LISTENING:
-                        if (handle_accept(conn) < 0)
-                                return -1;
-                        break;
-                case WEMADE:
-                case THEYMADE:
-                        if (handle_data(conn) < 0)
-                                return -1;
-                        break;
-                default:
-                        diag(COMPONENT, DIAG_ERROR, "check_connections: bad_type '%s'\n",
-                             get_type_string(conn->type));
-                        break;
-                }
-                
-                conn = next;
-        }
-        
-        return 0;
-}
-
-/* Completes a non-blocking connect.
- * Returns < 0 for serious error
- */
-static int handle_connect(Conn_t *conn)
-{
-        int retval;
-        struct sockaddr_atmsvc dummy;
-        struct atmlec_msg msg;
-        struct atmlec_ioc ioc;
-
-        diag(COMPONENT, DIAG_DEBUG, "handle_connect: completing fd %d\n", conn->fd);
-        /* this seems to be common method in Linux-ATM
-         * making sure that nonblocking connect was
-         * completed successfully
-         */
-        conn->status = CONNECTED;
-        retval = connect(conn->fd, (struct sockaddr *)&dummy, sizeof(struct sockaddr_atmsvc));
-        if (retval < 0) {
-                diag(COMPONENT, DIAG_DEBUG, "handle_connect: connect: %s\n", strerror(errno));
-                delete_addr(conn->atm_address);
-                close_connection(conn);
-                return 0;
-        }
-
-        send_ready_ind(conn);
-
-        memcpy(ioc.atm_addr, conn->atm_address, ATM_ESA_LEN);
-        ioc.dev_num = lec_params.itf_num;
-        ioc.receive = 0;
-        diag(COMPONENT, DIAG_DEBUG, "Attaching a new active VCC, fd %d\n", conn->fd);
-        if (ioctl(conn->fd, ATMLEC_DATA, &ioc) < 0) {
-                diag(COMPONENT, DIAG_ERROR, "VCC attach failed: ioctl: %s\n", strerror(errno));
-                return -1;
-        }
-
-        memset(&msg, 0, sizeof(struct atmlec_msg));
-        msg.type = l_flush_tran_id;
-        memcpy(msg.content.normal.atm_addr, conn->atm_address, ATM_ESA_LEN);
-        msg.content.normal.flag = send_flush_req(conn);
-        
-        msg_to_kernel(&msg, sizeof(struct atmlec_msg));
-
-
-        return 0;
-}
-
-/* Complete non-blocking connections in *fds.
- * Returns < 0 for serious error (problems with kernel). 
- */
-int complete_connections(fd_set *fds)
-{
-        Conn_t *conn, *next;
-        int retval;
-
-        conn = connlist;
-        while (conn) {
-                next = conn->next;
-                if (FD_ISSET(conn->fd, fds)) {
-                        retval = handle_connect(conn);
-                        if (retval < 0) return -1;
-                }
-                conn = next;
-        }
-                
-        return 0;
-}
-
-/* Send a LE control frame using *conn.
- * Returns < 0 for serious error
- */
-int send_frame(Conn_t *conn, void *frame, int length)
-{
-        struct frame_hdr *hdr;
-        int ret;
-
-        diag(COMPONENT, DIAG_DEBUG, "send_frame: fd:%d len:%ld\n", conn->fd, length);
-        hdr = (struct frame_hdr *)frame;
-        if (hdr->opcode == htons(READY_QUERY) ||
-            hdr->opcode == htons(READY_IND))
-                diag(COMPONENT, DIAG_DEBUG, "%s\n", opcode2text(hdr->opcode));
-        else 
-                display_frame(frame);
-
-        ret = write(conn->fd, frame, length);
-        if (ret < 0) {
-                diag(COMPONENT, DIAG_ERROR, "send_frame: write: %s\n", strerror(errno));
-                return -1;
-        } 
-
-        return ret;
-}
-
-/* Receive a LE control frame from *conn.
- * Returns < 0 for serious error.
- */
-int recv_frame(Conn_t *conn, void *buff, int length)
-{
-        int ret;
-
-        diag(COMPONENT, DIAG_DEBUG, "recv_frame: fd:%d\n", conn->fd);
-        ret = read(conn->fd, buff, length);
-        if (ret < 0) {
-                diag(COMPONENT, DIAG_ERROR, "Read failed: %s\n", strerror(errno));
-                return -1;
-        } 
-
-#if 0
-        diag(COMPONENT, DIAG_DEBUG, "recv_frame: read %d bytes\n", ret);
-        if (get_verbosity(COMPONENT) >= DIAG_DEBUG) {
-                int i;
-                for (i = 0; i < 11; i++)
-                        diag(COMPONENT, DIAG_DEBUG, "0x%2x", ((unsigned char *)buff)[i]);
-        }
-#endif
-
-        return ret;
-}
-
-
-/*
- * LANE2: 5.2.1.4 and others, sleep random time before trying to reconnect
- */
-void random_delay(void)
-{
-        struct timeval tv;
-        int millis, interval;
-        
-        srand(time(NULL));
-        interval = lec_params.c38_max_reconfig_delay - lec_params.c37_min_reconfig_delay;
-        millis = (rand() % interval) + lec_params.c37_min_reconfig_delay;
-        tv.tv_sec  = (millis - (millis % 1000)) / 1000;
-        tv.tv_usec = (millis % 1000) * 1000;
-        
-        diag(COMPONENT, DIAG_DEBUG, "random_delay: sleeping %d.%d seconds\n", tv.tv_sec, tv.tv_usec);
-        (void)select(0, NULL, NULL, NULL, &tv);
-        
-        return;
-}
-
-/* Collect already connected sockets in *fds
- */
-void conn_get_fds(fd_set *fds)
-{
-        Conn_t *conn;
-
-        diag(COMPONENT, DIAG_DEBUG, "collecting ready fds ");
-        conn = connlist;
-        while (conn) {
-                if (conn->status != CONNECTING) {
-                        FD_SET(conn->fd, fds);
-                        diag(COMPONENT, DIAG_DEBUG, "%d type %s", conn->fd, get_type_string(conn->type));
-                }
-                conn = conn->next;
-        }
-        
-        return;
-}
-
-/* Collect non-blocking connecting sockets in *fds
- */
-void conn_get_connecting_fds(fd_set *fds)
-{
-        Conn_t *conn;
-
-        diag(COMPONENT, DIAG_DEBUG, "collecting connecting fds ");
-        conn = connlist;
-        while (conn) {
-                if (conn->status == CONNECTING) {
-                        FD_SET(conn->fd, fds);
-                        diag(COMPONENT, DIAG_DEBUG, "%d", conn->fd);
-                }
-                conn = conn->next;
-        }
-        
-}
-
-/* Creates Conn_t for fd and marks it as kernel socket
- * Returns < 0 for error
- */
-int conn_set_kernel_socket(int fd)
-{
-        Conn_t *conn;
-
-        conn = list_add_conn(NULL);
-        if (conn == NULL) {
-                diag(COMPONENT, DIAG_ERROR, "conn_set_kernel_socket: list_add_conn failed\n");
-                return -1;
-        }
-        conn->type = KERNEL_SOCK;
-        conn->status = CONNECTED;
-        conn->fd = fd;
-        lec_params.kernel = conn;
-
-        return fd;
-}
-
-/* Creates new Conn_t object and allocates memory for it.
- * atm_addr should be the ATM address of the other end
- * or NULL if not applicable
- */
-static Conn_t *list_add_conn(unsigned char *atm_addr)
-{
-        Conn_t *conn;
-
-        conn = (Conn_t *)malloc(sizeof(Conn_t));
-        if (!conn)
-                return NULL;
-
-        memset(conn, 0, sizeof(Conn_t));
-        if (atm_addr)
-                memcpy(conn->atm_address, atm_addr, ATM_ESA_LEN);
-
-        conn->next = connlist;
-        conn->previous = NULL;
-        if (connlist)
-                connlist->previous = conn;
-        connlist = conn;
-        diag(COMPONENT, DIAG_DEBUG, "Added conn:%p\n", conn);
-
-        return conn;
-}
-
-/* Helper for close_connection and close_connections
- */
-static void list_remove_conn(Conn_t *conn)
-{
-
-        if (conn->next == NULL && conn->previous == NULL
-            && connlist != conn) return;
-        diag(COMPONENT, DIAG_DEBUG, "Removing conn:%p fd:%d previous:%p next:%p ",
-             conn, conn->fd, conn->previous, conn->next);
-
-        if (conn->previous) 
-                diag(COMPONENT, DIAG_DEBUG, "Previous:%p, fd:%d, next:%p, previous:%p ",
-                     conn->previous, conn->previous->fd,
-                     conn->previous->next, conn->previous->previous);
-        if (conn->next)
-                diag(COMPONENT, DIAG_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;
-        } else /* First in line */
-                connlist = conn->next;
-        if (conn->next)
-                conn->next->previous = conn->previous;  
-        diag(COMPONENT, DIAG_DEBUG, "Connlist: %p\n", connlist);
-        conn->next=conn->previous= NULL;
-        
-        return;
-}
-
-static const char *get_type_string(int type)
-{
-        switch(type) {
-        case WEMADE:
-                return "WEMADE";
-                break;
-        case THEYMADE:
-                return "THEYMADE";
-                break;
-        case LISTENING:
-                return "LISTENING";
-                break;
-        case KERNEL_SOCK:
-                return "KERNEL_SOCK";
-                break;
-        default:
-                break;
-        }
-        
-        return "UNKNOWN";
-}
-
-static int maxmtu2maxsdu(uint8_t mtu)
-{
-
-    int sdu;
-
-    switch (mtu) {
-    case MTU_1516:
-        sdu = 1516;
-        break;
-    case MTU_1580:  /* LANE2: MTU can be 1580 too (IEEE 802.1p/Q) */
-        sdu = 1580;
-        break;
-    case MTU_4544:
-        sdu = 4544;
-        break;
-    case MTU_9234:
-        sdu = 9234;
-        break;
-    case MTU_18190:
-        sdu = 18190;
-        break;
-    default:
-        sdu = 1516;
-        break;
-    }
-
-    return sdu;
-}
diff -ur --new-file old/atm/led.new/conn.h new/atm/led.new/conn.h
--- old/atm/led.new/conn.h	Thu Feb 18 16:13:39 1999
+++ new/atm/led.new/conn.h	Thu Jan  1 01:00:00 1970
@@ -1,83 +0,0 @@
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#ifndef CONN_H
-#define CONN_H
-
-typedef struct _conn_t_ {
-        int fd;                  /* Socket connected to this connection */
-        int status;              /* Connection status */
-        int type;                /* We made, they made, listen socket */
-        int codepoint;           /* One of the below, MCAST_CONN etc. */
-        unsigned char atm_address[ATM_ESA_LEN]; 
-                                 /* Destination address, not in listen or
-                                    kernel sockets */
-        struct _conn_t_ *next;
-        struct _conn_t_ *previous;
-} Conn_t;
-
-void close_connections(void);
-void init_conn_params(struct atm_sap *sap, struct atm_qos *qos,
-                      uint16_t blli_codepoint);
-int create_data_svc(unsigned char *atm_addr, int codepoint);
-Conn_t *setup_svc(struct sockaddr_atmsvc *dst_addr,
-                  struct sockaddr_atmsvc *listen_addr,
-                  struct atm_sap *sap, struct atm_qos *qos);
-int create_data_listen(void);
-Conn_t *create_listensocket(struct sockaddr_atmsvc *listen_addr,
-                            struct atm_sap *sap, struct atm_qos *qos);
-Conn_t *accept_conn(Conn_t *conn);
-int close_connection(Conn_t *conn);
-int check_connections(fd_set *fds);
-int complete_connections(fd_set *fds);
-
-int send_frame(Conn_t *conn, void *frame, int length);
-int recv_frame(Conn_t *conn, void *buff, int length);
-
-void conn_get_fds(fd_set *fds);
-void conn_get_connecting_fds(fd_set *fds);
-
-int conn_set_kernel_socket(int fd);
-void random_delay(void);
-
-/*
- * Connection types for BLLI codepoints.
- */
-#define CONTROL_CONN      1
-#define DATA_DIRECT_CONN  2
-#define MCAST_CONN        4
-
-/*
- * MTU sizes
- */
-#define MTU_UNSPEC 0
-#define MTU_1516   1
-#define MTU_1580   5   /* LANEv2 */
-#define MTU_4544   2
-#define MTU_9234   3
-#define MTU_18190  4
-
-#endif /* CONN_H */
diff -ur --new-file old/atm/led.new/display.c new/atm/led.new/display.c
--- old/atm/led.new/display.c	Sat Feb  6 21:54:37 1999
+++ new/atm/led.new/display.c	Thu Jan  1 01:00:00 1970
@@ -1,307 +0,0 @@
-/* display.c - display frames, addresses, opcodes, etc. */
-
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#include <atm.h>
-#include <atmd.h>
-
-#include "display.h"
-#include "frame_defs.h"
-
-#define COMPONENT "display.c"
-
-#define MAX_TEXT 1024  /* Buffer size for displaying LE control frames */
-
-static int my_atm2text(unsigned char *atm_addr, char *dest);
-static const char *lan_dst2text(struct lan_dst *dst);
-static void display_ready(void *buff);
-
-/* Prints out more or less human readable summary of
- * LE Control Frame pointed by frame.
- */
-void display_frame(void *frame)
-{
-        struct frame_hdr *hdr;
-        struct ctrl_frame *f;
-        char text[MAX_TEXT];
-        char *p;
-
-        hdr = (struct frame_hdr *)frame;
-        if (hdr->opcode == htons(READY_QUERY) ||
-            hdr->opcode == htons(READY_IND))
-                display_ready(frame);
-       
-        p = text;
-        p += sprintf(p, "\n");
-        p += sprintf(p, "Marker         0x%x\n", ntohs(hdr->marker));
-        p += sprintf(p, "Protocol       0x%x\n", hdr->protocol);
-        p += sprintf(p, "Version        0x%x\n", hdr->version);
-        p += sprintf(p, "Op-Code        0x%x (%s)\n", ntohs(hdr->opcode), opcode2text(hdr->opcode));
-        p += sprintf(p, "Status           %d (%s)\n", hdr->status, status2text(hdr->status));
-        p += sprintf(p, "Trans-ID         %d\n", ntohl(hdr->tran_id));
-        p += sprintf(p, "Req Lec-ID       %d\n", ntohs(hdr->lec_id));
-        p += sprintf(p, "Flags          0x%x", ntohs(hdr->flags));
-        if (hdr->flags & htons(REMOTE_ADDRESS)) p+= sprintf(p, " 'Remote Address'");
-        if (hdr->flags & htons(V2_CAPABLE))     p+= sprintf(p, " 'V2 Capable'");
-        if (hdr->flags & htons(V2_REQUIRED))    p+= sprintf(p, " 'V2 Required'");
-        if (hdr->flags & htons(PROXY_FLAG))     p+= sprintf(p, " 'Proxy Flag'");
-        if (hdr->flags & htons(TOPO_CHANGE))    p+= sprintf(p, " 'Topology Change'");
-        p += sprintf(p, "\n");
-        
-        f = (struct ctrl_frame *)frame;
-        p += sprintf(p, "Source Lan     0x%x (%s)\n", ntohs(f->src_lan_dst.tag), lan_dst2text(&f->src_lan_dst));
-        p += sprintf(p, "Target Lan     0x%x (%s)\n", ntohs(f->target_lan_dst.tag), lan_dst2text(&f->target_lan_dst));
-        p += sprintf(p, "Source ATM     "); p += my_atm2text(f->src_atm_addr, p); p += sprintf(p, "\n");
-        p += sprintf(p, "Lan type       0x%x\n", f->lan_type);
-        p += sprintf(p, "Lan MTU        0x%x\n", f->max_frame_size);
-        p += sprintf(p, "# of TLVs      0x%x\n", f->num_tlvs);
-        p += sprintf(p, "Elan Name size 0x%x\n", f->elan_name_size);
-        p += sprintf(p, "Target ATM     "); p += my_atm2text(f->target_atm_addr, p); p += sprintf(p, "\n");
-        p += sprintf(p, "Elan Name          (");
-        memcpy(p, f->elan_name, f->elan_name_size); p += f->elan_name_size;
-        p += sprintf(p, ")\n");
-
-
-        *p = '\0';
-        diag(COMPONENT, DIAG_DEBUG, "%s\n", text);
-
-        return;
-}
-
-static void display_ready(void *ready_frame)
-{
-        diag(COMPONENT, DIAG_DEBUG, "ready frame\n");
-
-        return;
-}
-
-/* Poor man's atm2text */
-static int my_atm2text(unsigned char *atm_addr, char *dest)
-{
-        int i, len;
-        
-        len = 0;
-        for (i = 0; i < ATM_ESA_LEN; i++)
-                len += sprintf(dest + len, "%2.2x ", *(atm_addr + i));
-        
-        return len;
-}
-
-static const char *lan_dst2text(struct lan_dst *dst)
-{
-        static char text[42]; /* big enough for text + MAC */
-        char *p = text;
-
-        switch(ntohs(dst->tag)) {
-        case LAN_DST_NOT_PRESENT:
-                sprintf(text, "Not present");
-                break;
-        case LAN_DST_MAC_ADDR:
-                p += sprintf(p, "MAC address");
-                p += sprintf(p, " ");
-                mac2text(p, dst->mac);
-                break;
-        case LAN_DST_ROUTE_DESC:
-                p += sprintf(p, "Route Descriptor");
-                p += sprintf(p, " ");
-                mac2text(p, dst->mac);
-                break;
-        default:
-                sprintf(text, "<Unknown Lan destination>");
-                break;
-        }
-
-        return text;
-}
-
-void mac2text(char *buff, unsigned char *mac_addr)
-{
-        sprintf(buff, "%02x-%02x-%02x-%02x-%02x-%02x",
-                mac_addr[0], mac_addr[1], mac_addr[2], 
-                mac_addr[3], mac_addr[4], mac_addr[5]);
-        
-        return;
-}
-
-const char *opcode2text(uint16_t opcode) {
-        switch (ntohs(opcode)) {
-        case LE_CONFIG_REQ:
-                return "LE_CONFIG_REQUEST";
-                break;
-        case LE_CONFIG_RSP:
-                return "LE_CONFIG_RESPONSE";
-                break;
-        case LE_JOIN_REQ:
-                return "LE_JOIN_REQUEST";
-                break;
-        case LE_JOIN_RSP:
-                return "LE_JOIN_RESPONSE";
-                break;
-        case LE_REG_REQ:
-                return "LE_REGISTER_REQUEST";
-                break;
-        case LE_REG_RSP:
-                return "LE_REGISTER_RESPONSE";
-                break;
-        case LE_ARP_REQ:
-                return "LE_ARP_REQUEST";
-                break;
-        case LE_ARP_RSP:
-                return "LE_ARP_RESPONSE";
-                break;
-        case LE_FLUSH_REQ:
-                return "LE_FLUSH_REQUEST";
-                break;
-        case LE_FLUSH_RSP:
-                return "LE_FLUSH_RESPONSE";
-                break;
-        case READY_QUERY:
-                return "READY_QUERY";
-                break;
-        case READY_IND:
-                return "READY_INDICATION";
-                break;
-        case LE_TOPO_REQ:
-                return "LE_TOPOLOGY_REQUEST";
-                break;
-        case LE_NARP_REQ:
-                return "LE_NARP_REQUEST";
-                break;
-        default:
-                break;
-        }
-
-        return "<Unknown OP-CODE>";
-}
-
-const char *tlv2text(uint32_t type)
-{
-        switch (type) {
-        case MAX_CUM_CTRL_TIMEOUT:
-                return "Max-Cumulative-Control-Time-out";
-                break;
-        case MAX_UNKNOWN_FRAME_CNT:
-                return "Max-Unknown-Frame-Count";
-                break;
-        case MAX_UNKNOWN_FRAME_TIME:
-                return "Max-Unknown-Frame-Time";
-                break;
-        case VCC_TIMEOUT_PERIOD:
-                return "VCC-Timeout-Period";
-                break;
-        case MAX_RETRY_COUNT:
-                return "Max-Retry-Count";
-                break;
-        case AGING_TIME:
-                return "Aging-Time";
-                break;
-        case FORWARD_DELAY_TIME:
-                return "Forward-Delay-Time";
-                break;
-        case EXPECTED_LE_ARP_TIME:
-                return "Expected-LE_ARP-Response-Time";
-                break;
-        case FLUSH_TIMEOUT:
-                return "Flush-Time-out";
-                break;
-        case PATH_SWITCHING_DELAY:
-                return "Path-Switching-Delay";
-                break;
-        case LOCAL_SEGMENT_ID:
-                return "Local-Segment-ID";
-                break;
-        case DEF_MCAST_SND_VCC_TYPE:
-                return "Default-Mcast-Send-VCC-Type";
-                break;
-        case DEF_MCAST_SND_VCC_AVG:
-                return "Default-Mcast-Send-VCC-AvgRate";
-                break;
-        case DEF_MCAST_SEND_PEAK_RT:
-                return "Default-Mcast-Send-VCC-PeakRate";
-                break;
-        case CONN_COMPLETION_TIMER:
-                return "Connection-Completion-Timer";
-                break;
-        case CONFIG_FRAG_INFO:
-                return "Config-Frag-Info";
-                break;
-        case LAYER3_ADDRESS:
-                return "Layer-3-Address";
-                break;
-        case ELAN_ID:
-                return "ELAN-ID";
-                break;
-        case SERVICE_CATEGORY:
-                return "Service-Category";
-                break;
-        case LLC_MUXED_ATM_ADDR:
-                return "LLC-Muxed-ATM-Address";
-                break;
-        case X5_ADJUSTMENT:
-                return "X5-Adjustment";
-                break;
-        case PREFERRED_LES:
-                return "Preferred-LES";
-                break;
-        case FORE_NAME:
-                return "Fore's LANE client name";
-                break;
-        default:
-                break;
-        }
-
-        return "<Unknown TLV type>";
-}
-
-const char *status2text(uint16_t status)
-{
-
-        switch (ntohs(status)) {
-        case 0:
-                return "Success";
-                break;
-        case 1:
-                return "Version Not Supported";
-                break;
-        case 2:
-                return "Invalid request parameters";
-                break;
-        case 4:
-                return "Duplicate LAN Destination registration";
-                break;
-        case 5:
-                return "Dupliate ATM address";
-                break;
-        case 6:
-                return "Insufficient resources to grant request";
-                break;
-        case 7:
-                return "Access denied";
-                break;
-        case 8:
-                return "Invalid REQUESTOR-ID";
-                break;
-        case 9:
-                return "Invalid LAN Destination";
-                break;
-        case 10:
-                return "Invalid ATM Address";
-                break;
-        case 20:
-                return "No Configuration";
-                break;
-        case 21:
-                return "LE_CONFIGURE Error";
-                break;
-        case 22:
-                return "Insufficient Information";
-                break;
-        case 24:
-                return "TLV Not Found";
-                break;
-        default:
-                break;
-        }
-
-        return "<Something not supported in LANEv2>";
-}
diff -ur --new-file old/atm/led.new/display.h new/atm/led.new/display.h
--- old/atm/led.new/display.h	Sat Feb  6 14:44:23 1999
+++ new/atm/led.new/display.h	Thu Jan  1 01:00:00 1970
@@ -1,13 +0,0 @@
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#ifndef DISPLAY_H
-#define DISPLAY_H
-
-void display_frame(void *frame);
-
-void mac2text(char *buff, unsigned char *mac_addr);
-const char *opcode2text(uint16_t opcode);
-const char *tlv2text(uint32_t type);
-const char *status2text(uint16_t status);
-
-#endif /* DISPLAY_H */
diff -ur --new-file old/atm/led.new/frame_defs.h new/atm/led.new/frame_defs.h
--- old/atm/led.new/frame_defs.h	Sun Feb  7 12:05:21 1999
+++ new/atm/led.new/frame_defs.h	Thu Jan  1 01:00:00 1970
@@ -1,125 +0,0 @@
-/* frame_defs.h - definitions for LANE control frames, TLVs etc. */
-
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#ifndef FRAMES_DEFS_H
-#define FRAMES_DEFS_H
-
-#ifndef ETH_ALEN
-#define ETH_ALEN 6
-#endif
-
-/* Try to squeeze out all the padding from the structs so that we
- * can use them as templates for filling in and examining frames.
- * From the gcc documentation:
- *    This attribute, attached to an `enum', `struct', or `union' type
- *    definition, specified that the minimum required memory be used to
- *    represent the type.
- */
-#ifndef PACKED
-#define PACKED __attribute__((packed))
-#endif
-
-/* READY_QUERY and READY_IND frame format
- */
-struct ready_frame {
-        uint16_t marker;
-        uint8_t  protocol;
-        uint8_t  version;
-        uint16_t opcode;
-};
-
-/* Fields common to all control frames,
- * not including READY_*
- */
-struct frame_hdr {
-        uint16_t marker;
-        uint8_t  protocol;
-        uint8_t  version;
-        uint16_t opcode;
-        uint16_t status;
-        uint32_t tran_id;
-        uint16_t lec_id;
-        uint16_t flags;
-} PACKED;
-
-/* values for lan_dst.tag
- */
-#define LAN_DST_NOT_PRESENT 0x0000
-#define LAN_DST_MAC_ADDR    0x0001
-#define LAN_DST_ROUTE_DESC  0x0002
-
-struct lan_dst { /* Token Ring route descriptors omitted */
-        uint16_t tag;
-        uint8_t  mac[ETH_ALEN];
-} PACKED;
-
-/* All frames except STATUS_INQ and STATUS_REPLY look like this
- */
-struct ctrl_frame {
-        struct frame_hdr header;
-        struct lan_dst src_lan_dst;
-        struct lan_dst target_lan_dst;
-        uint8_t src_atm_addr[ATM_ESA_LEN];
-        uint8_t lan_type;
-        uint8_t max_frame_size;
-        uint8_t num_tlvs;
-        uint8_t elan_name_size;
-        uint8_t target_atm_addr[ATM_ESA_LEN];
-        uint8_t elan_name[32];
-        /* TLVs if any follow elan_name */
-} PACKED;
-
-/* Frame types
- */
-#define LE_CONFIG_REQ 0x0001
-#define LE_CONFIG_RSP 0x0101
-#define LE_JOIN_REQ   0x0002
-#define LE_JOIN_RSP   0x0102
-#define LE_REG_REQ    0x0004
-#define LE_REG_RSP    0x0104
-#define LE_ARP_REQ    0x0006
-#define LE_ARP_RSP    0x0106
-#define LE_FLUSH_REQ  0x0007
-#define LE_FLUSH_RSP  0x0107
-#define LE_NARP_REQ   0x0008
-#define LE_TOPO_REQ   0x0009
-#define READY_QUERY   0x0003 /* READY_* are not in ctrl_frame format */
-#define READY_IND     0x0103
-
-/* Flags for LE Control Frames
- */
-#define REMOTE_ADDRESS  0x0001
-#define V2_CAPABLE      0x0002
-#define V2_REQUIRED     0x0008
-#define PROXY_FLAG      0x0080
-#define TOPO_CHANGE     0x0100
-
-/* TLV types defined in LANEv1 and v2 + one Fore specific TLV
- */
-#define MAX_CUM_CTRL_TIMEOUT   0x00A03E01
-#define MAX_UNKNOWN_FRAME_CNT  0x00A03E02
-#define MAX_UNKNOWN_FRAME_TIME 0x00A03E03
-#define VCC_TIMEOUT_PERIOD     0x00A03E04
-#define MAX_RETRY_COUNT        0x00A03E05
-#define AGING_TIME             0x00A03E06
-#define FORWARD_DELAY_TIME     0x00A03E07
-#define EXPECTED_LE_ARP_TIME   0x00A03E08
-#define FLUSH_TIMEOUT          0x00A03E09
-#define PATH_SWITCHING_DELAY   0x00A03E0A
-#define LOCAL_SEGMENT_ID       0x00A03E0B
-#define DEF_MCAST_SND_VCC_TYPE 0x00A03E0C
-#define DEF_MCAST_SND_VCC_AVG  0x00A03E0D
-#define DEF_MCAST_SEND_PEAK_RT 0x00A03E0E
-#define CONN_COMPLETION_TIMER  0x00A03E0F
-#define CONFIG_FRAG_INFO       0x00A03E10 /* This and the rest are LANEv2 only */
-#define LAYER3_ADDRESS         0x00A03E11
-#define ELAN_ID                0x00A03E12
-#define SERVICE_CATEGORY       0x00A03E13
-#define LLC_MUXED_ATM_ADDR     0x00A03E2B
-#define X5_ADJUSTMENT          0x00A03E2C /* length 0 */
-#define PREFERRED_LES          0x00A03E2D
-
-#define FORE_NAME              0x00204808 /* check zeppelin(8), -f option */
-
-#endif /* FRAMES_DEFS_H */
diff -ur --new-file old/atm/led.new/frames.c new/atm/led.new/frames.c
--- old/atm/led.new/frames.c	Sat Feb  6 21:45:03 1999
+++ new/atm/led.new/frames.c	Thu Jan  1 01:00:00 1970
@@ -1,582 +0,0 @@
-/* frames.c - handle incoming frames, prefill outgoing frames, parse TLVs etc. */
-
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-/* Functions for handling LANE control frames used when joining an
- * ELAN are in lec.c
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <atm.h>
-#include <linux/atmlec.h>
-#include <atmd.h>
-
-#include "conn.h"
-#include "lec.h"
-#include "frames.h"
-#include "display.h"
-#include "kernel.h"
-
-#define COMPONENT "frames.c"
-
-static uint32_t transaction_id = 0;
-static void extract_tlv_value(uint16_t opcode, uint32_t type, unsigned char *tlvp, int len);
-static void handle_x5(uint16_t opcode);
-
-/* Initializes LANE Control frame of type 'type'
- */
-void prefill_frame(void *buff, uint16_t type)
-{
-        struct frame_hdr *header;
-        
-        memset(buff, 0, sizeof(struct ctrl_frame));
-        header = (struct frame_hdr *)buff;
-        header->marker   = htons(0xff00);
-        header->protocol = 0x01;
-        header->version  = 0x01;
-        header->opcode   = htons(type);
-        header->status   = htons(0x0000);
-        header->tran_id  = htonl(transaction_id);
-        header->lec_id   = htons(lec_params.c14_lec_id);
-        header->flags    = htons(0x0000);
-        
-        transaction_id++;
-        
-        return;
-}
-
-/* Validates incoming Control frames except READY_IND and
- * READY_QUERY which do not start with the common header.
- * Also calls display_frame() to print out conforming frames.
- * Returns < 0 for error
- */
-int validate_frame(unsigned char *buff, int size)
-{
-        struct ready_frame *hdr; /* Ready is the shortest possible */
-
-        if (size < sizeof(struct ready_frame)) {
-                diag(COMPONENT, DIAG_DEBUG, "short frame, size %d\n", size);
-                return -1;
-        }
-
-        hdr = (struct ready_frame *)buff;
-        if (hdr->marker   != htons(0xff00) ||
-            hdr->protocol != 0x01 ||
-            hdr->version  != 0x01)
-                return -1;
-
-        /* READY_* frames are shorter than others */
-        if (hdr->opcode == htons(READY_QUERY) ||
-            hdr->opcode == htons(READY_IND)) {
-                diag(COMPONENT, DIAG_DEBUG, "Received a %s\n", opcode2text(hdr->opcode));
-                return 0;
-        }
-
-        if (size < sizeof(struct ctrl_frame)) {
-                diag(COMPONENT, DIAG_DEBUG, "short frame, size %d\n", size);
-                return -1;
-        }
-
-        display_frame(buff);
-
-        return 0;
-}
-
-/* Handle incoming LE_FLUSH_REQUEST frames.
- */
-static void handle_flush_req(struct ctrl_frame *f)
-{
-        if (memcmp(lec_params.c1n_my_atm_addr, f->target_atm_addr, ATM_ESA_LEN) != 0)
-                return;
-        f->header.opcode = htons(LE_FLUSH_RSP);
-        if (send_frame(lec_params.ctrl_direct, f, sizeof(struct ctrl_frame)) < 0)
-                diag(COMPONENT, DIAG_DEBUG, "could not send LE_FLUSH_RESPONSE\n");
-
-        return;
-}
-
-/* Handle incoming LE_FLUSH_RESPONSE frames.
- */
-static void handle_flush_rsp(struct ctrl_frame *f)
-{
-        struct atmlec_msg msg;
-
-        if (f->header.lec_id != htons(lec_params.c14_lec_id)) {
-                diag(COMPONENT, DIAG_DEBUG, "Wrong lec_id, ignoring\n");
-                return;
-        }
-
-        memset(&msg, 0, sizeof(struct atmlec_msg));
-        msg.type = l_flush_complete;
-        msg.content.normal.flag = ntohl(f->header.tran_id);
-        msg_to_kernel(&msg, sizeof(struct atmlec_msg));
-        
-        return;
-}
-
-/* Handle incoming READY_QUERY frames.
- */
-static void handle_ready_query(Conn_t *conn, struct ready_frame *f)
-{
-        f->opcode = htons(READY_IND);
-        send_frame(conn, f, sizeof(struct ready_frame));
-
-        return;
-}
-
-/* Helper for handle_le_arp_req.
- * If the target_lan_dst was not our MAC address, try to
- * see if the bridging table in the kernel knows about it.
- * Returns < 0 for serious error
- */
-static int check_bridge(struct ctrl_frame *frame, int size)
-{
-        struct atmlec_msg msg;
-
-        if (lec_params.c4_proxy_flag == 0)
-                return 0;
-
-        memset(&msg, 0, sizeof(struct atmlec_msg));
-        msg.type = l_should_bridge;
-        memcpy(msg.content.proxy.mac_addr, frame->target_lan_dst.mac, ETH_ALEN);
-        memcpy(msg.content.proxy.atm_addr, frame->src_atm_addr, ATM_ESA_LEN);
-        msg.content.proxy.tran_id = frame->header.tran_id;
-        msg.content.proxy.lec_id = frame->header.lec_id;
-
-        return msg_to_kernel(&msg, sizeof(struct atmlec_msg));
-}
-
-/* Handles incoming LE_ARP_REQ and targetless LE_ARP_REQ.
- * See LANEv2, 7.1.5 and 7.1.30
- * Returns < 0 for serious error
- */
-static int handle_le_arp_req(struct ctrl_frame *frame, int size)
-{
-        int sizeoftlvs, sizeofrsp, retval;
-        struct ctrl_frame *rsp;
-        struct atmlec_msg *msg;
-
-        if (frame->header.lec_id == htons(lec_params.c14_lec_id)) {
-                diag(COMPONENT, DIAG_DEBUG, "Ignoring own LE_ARP_REQUEST\n");
-                return 0;
-        }
-
-        retval = 0;
-        if (frame->target_lan_dst.tag == htons(LAN_DST_MAC_ADDR)) {
-                if (memcmp(frame->target_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN) != 0)
-                        return (check_bridge(frame, size)); /* target was not us */
-                sizeofrsp = sizeof(struct ctrl_frame) + lec_params.sizeoftlvs;
-                rsp = (struct ctrl_frame *)malloc(sizeofrsp);
-                if (rsp == NULL) return 0;
-                memcpy(rsp, frame, sizeof(struct ctrl_frame));
-                rsp->header.opcode = htons(LE_ARP_RSP);
-                memcpy(rsp->target_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-                rsp->num_tlvs = lec_params.num_tlvs;
-                if (lec_params.num_tlvs > 0)
-                        memcpy(rsp + 1, lec_params.tlvs, lec_params.sizeoftlvs);
-
-                retval = send_frame(lec_params.ctrl_direct, rsp, sizeofrsp);
-                free(rsp);
-        } else if (frame->target_lan_dst.tag == htons(LAN_DST_NOT_PRESENT) &&
-                   lec_params.c29_v2_capable) {
-                sizeoftlvs = size - sizeof(struct ctrl_frame);
-                msg = (struct atmlec_msg *)malloc(sizeof(struct atmlec_msg) + sizeoftlvs);
-                if (msg == NULL) return -1;
-                memset(msg, 0, sizeof(struct atmlec_msg));
-                msg->type = l_arp_update;
-                memcpy(msg->content.normal.mac_addr, frame->src_lan_dst.mac, ETH_ALEN);
-                memcpy(msg->content.normal.atm_addr, frame->src_atm_addr, ATM_ESA_LEN);
-                msg->content.normal.flag = (frame->header.flags & REMOTE_ADDRESS) ? 1 : 0;
-                msg->content.normal.targetless_le_arp = 1;
-                msg->sizeoftlvs = sizeoftlvs;
-                if (sizeoftlvs > 0) memcpy(msg + 1, frame + 1, sizeoftlvs);
-
-                retval = msg_to_kernel(msg, sizeof(struct atmlec_msg) + sizeoftlvs);
-                free(msg);
-        }
-        
-        return retval;
-}
-
-/* Handles incoming LE_NARP_REQUESTS frames.
- * Mandatory only in LANEv2. If we are LANEv1, we'll just ignore these.
- * See LANEv2, 7.1.31-35 LE_NARP_REQUEST/RESPONSE.
- * For no-source, i.e. no source ATM address, we remove the LE_ARP cache entry.
- * If the source is non-zero, we first remove the entry
- * and then add the new entry in the LE_ARP cache.
- * Returns < 0 for serious error.
- */
-static int handle_narp_req(struct ctrl_frame *frame, int size)
-{
-        int sizeoftlvs, no_source = 0, retval;
-        struct atmlec_msg *msg;
-        unsigned char empty[ATM_ESA_LEN];
-
-        if (frame->header.lec_id == htons(lec_params.c14_lec_id) ||
-            lec_params.c29_v2_capable == 0) {
-                diag(COMPONENT, DIAG_DEBUG, "Ignoring LE_NARP_REQUEST\n");
-                return 0;
-        }
-
-        memset(empty, 0, ATM_ESA_LEN);
-        if (memcmp(empty, frame->src_atm_addr, ATM_ESA_LEN) == 0)
-                no_source = 1;
-
-        sizeoftlvs = size - sizeof(struct ctrl_frame);
-        msg = (struct atmlec_msg *)malloc(sizeof(struct atmlec_msg) + sizeoftlvs);
-        if (msg == NULL) return -1;
-        memset(msg, 0, sizeof(struct atmlec_msg));
-        msg->type = l_narp_req;
-        memcpy(msg->content.normal.mac_addr, frame->src_lan_dst.mac, ETH_ALEN);
-        memcpy(msg->content.normal.atm_addr, frame->src_atm_addr, ATM_ESA_LEN);
-        msg->content.normal.flag = (frame->header.flags & REMOTE_ADDRESS) ? 1 : 0;
-        msg->content.normal.no_source_le_narp = no_source;
-        msg->sizeoftlvs = sizeoftlvs;
-        if (sizeoftlvs > 0) memcpy(msg + 1, frame + 1, sizeoftlvs);
-        retval = msg_to_kernel(msg, sizeof(struct atmlec_msg) + sizeoftlvs);
-        
-        free(msg);
-        
-        return retval;
-}
-
-/* Handles incoming LE_ARP_RESPONSE frames.
- * Returns < 0 for serious error
- */
-static int handle_arp_rsp(struct ctrl_frame *frame, int size)
-{
-        int sizeoftlvs, msglen, retval;
-        char buff[MAX_CTRL_FRAME];
-        struct atmlec_msg *msg;
-        
-        if (frame->header.lec_id != htons(lec_params.c14_lec_id)) {
-                diag(COMPONENT, DIAG_DEBUG, "Wrong lec_id, ignoring\n");
-                return 0;
-        }
-
-        sizeoftlvs = size - sizeof(struct ctrl_frame);
-        msglen = sizeof(struct atmlec_msg) + sizeoftlvs;
-        msg = (struct atmlec_msg *)buff;
-        memset(msg, 0, msglen);
-        
-        msg->type = l_arp_update;
-        memcpy(msg->content.normal.mac_addr, frame->target_lan_dst.mac, ETH_ALEN);
-        memcpy(msg->content.normal.atm_addr, frame->target_atm_addr, ATM_ESA_LEN);
-        msg->content.normal.flag = (frame->header.flags & REMOTE_ADDRESS) ? 1 : 0;
-        msg->sizeoftlvs = sizeoftlvs;
-        if (sizeoftlvs > 0) memcpy(msg + 1, frame + 1, sizeoftlvs);
-
-        retval = msg_to_kernel(msg, msglen);
-
-        return retval;
-}
-
-/* Handles incoming LE_TOPOLOGY_REQUEST frames.
- * Returns < 0 for serious error
- */
-static int handle_topo_req(struct ctrl_frame *frame)
-{
-        struct atmlec_msg msg;
-
-        memset(&msg, 0, sizeof(struct atmlec_msg));
-        msg.type = l_topology_change;
-        if (frame->header.flags & htons(TOPO_CHANGE))
-                msg.content.normal.flag = 1;
-
-        return(msg_to_kernel(&msg, sizeof(struct atmlec_msg)));
-}
-
-/* Processes and validates incoming frames. Calls frame
- * dependant handler functions.
- * Returns < 0 for serious error
- */
-int handle_frame(Conn_t *conn, char *buff, int size)
-{
-        struct ctrl_frame *frame;
-
-        if (validate_frame(buff, size) < 0)
-                return 0;
-
-        frame = (struct ctrl_frame *)buff;
-
-        switch (ntohs(frame->header.opcode)) {
-        case LE_FLUSH_REQ:
-                handle_flush_req(frame);
-                break;
-        case LE_FLUSH_RSP:
-                handle_flush_rsp(frame);
-                break;
-        case READY_QUERY:
-                handle_ready_query(conn, (struct ready_frame *)frame);
-                break;
-        case READY_IND:
-                /* We can ignore these */
-                break;
-        case LE_ARP_REQ:
-                if (handle_le_arp_req(frame, size) < 0)
-                        return -1;
-                break;
-        case LE_ARP_RSP:
-                if (handle_arp_rsp(frame, size) < 0)
-                        return -1;
-                break;
-        case LE_TOPO_REQ:
-                if (handle_topo_req(frame) < 0)
-                        return -1;
-                break;
-        case LE_REG_RSP:
-                /* FIXME: Should we do something? */
-                break;
-        case LE_NARP_REQ:
-                if (handle_narp_req(frame, size) < 0)
-                        return -1;
-                break;
-        default:
-                diag(COMPONENT, DIAG_ERROR,
-                     "Unknown frame, opcode 0x%x %s\n", ntohs(frame->header.opcode),
-                     opcode2text(frame->header.opcode));
-                break;
-        }
-
-        return 0;
-}
-
-/* Sends a READY_INDICATION when a non-blocking connect completes.
- */
-void send_ready_ind(Conn_t *conn)
-{
-        struct ready_frame frame;
-        int retval;
-
-        frame.marker   = htons(0xff00);
-        frame.protocol = 0x01;
-        frame.version  = 0x01;
-        frame.opcode   = htons(READY_IND);
-
-        retval = send_frame(conn, &frame, sizeof(struct ready_frame));
-        if (retval < 0)
-                diag(COMPONENT, DIAG_DEBUG, "Could not send READY_IND, fd %d\n", conn->fd);
-
-        return;
-}
-
-/* Sends a LE_FLUSH_REQUEST
- * Returns the transaction used with this flush REQ/RSP pair.
- */
-uint32_t send_flush_req(Conn_t *conn)
-{
-        struct ctrl_frame frame;
-
-        prefill_frame(&frame, LE_FLUSH_REQ);
-        memcpy(frame.src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-        memcpy(frame.target_atm_addr, conn->atm_address, ATM_ESA_LEN);
-
-        send_frame(lec_params.mcast_send, &frame, sizeof(struct ctrl_frame));
-
-        return ntohl(frame.header.tran_id);
-}
-
-/* Registers our MAC address and associated TLVs with LES.
- * See LANEv2, 6. Registaration Protocol
- */
-void send_register_req(void)
-{
-        char buff[MAX_CTRL_FRAME];
-        struct ctrl_frame *frame;
-
-        frame = (struct ctrl_frame *)buff;
-        prefill_frame(frame, LE_REG_REQ);
-        frame->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
-        memcpy(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN);
-        memcpy(frame->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-        frame->num_tlvs = lec_params.num_tlvs;
-        if (lec_params.sizeoftlvs > 0)
-                memcpy((frame + 1), lec_params.tlvs, lec_params.sizeoftlvs);
-
-        send_frame(lec_params.ctrl_direct, frame, sizeof(struct ctrl_frame) + lec_params.sizeoftlvs);
-        
-        return;
-}
-
-/* Goes through the TLVs trailing a frame while passing them
- * one by one to the TLV handler.
- */
-void parse_tlvs(uint16_t opcode, unsigned char *tlvp, int numtlvs, int sizeoftlvs)
-{
-        uint32_t type;
-        uint8_t len;
-        unsigned char *end_of_tlvs;
-
-        end_of_tlvs = tlvp + sizeoftlvs;
-        while (numtlvs-- > 0 && end_of_tlvs - tlvp >= 5) {
-                type = *(uint32_t *)tlvp;
-                type = ntohl(type);
-                len  = tlvp[4];
-                tlvp += 5;
-                diag(COMPONENT, DIAG_DEBUG, "parse_tlvs: type %s len %d\n",
-                     tlv2text(type), len);
-                if (tlvp + len > end_of_tlvs)
-                        return; /* value too long */
-                
-                extract_tlv_value(opcode, type, tlvp, len);
-                tlvp += len;
-        }
-
-        return;
-}
-
-/* Does something depending on the frame type this TLV arrived with,
- * TLV type, and contents of TLV.
- */
-static void extract_tlv_value(uint16_t opcode, uint32_t type, unsigned char *tlvp, int len)
-{
-
-        uint16_t value16;
-        uint32_t value32;
-
-        /* LE_JOIN_RESPONSE does not support all the TLVs */
-        if (opcode == htons(LE_JOIN_RSP) && type != htonl(ELAN_ID))
-                return;
-
-        switch(len) {
-        case 0:
-                switch (type) {
-                case X5_ADJUSTMENT:
-                        handle_x5(opcode);
-                        break;
-                default:
-                        goto whine;
-                        break;
-                }
-                break;
-        case 2:
-                value16 = *(uint16_t *)tlvp;
-                value16 = ntohs(value16);
-                diag(COMPONENT, DIAG_DEBUG, "value of TLV %d\n", value16);
-                switch (type) {
-                case MAX_CUM_CTRL_TIMEOUT:
-                        lec_params.c7_ctrl_timeout = value16;
-                        break;
-                case MAX_UNKNOWN_FRAME_CNT:
-                        lec_params.c10_max_unknown_frames = value16;
-                        break;
-                case MAX_UNKNOWN_FRAME_TIME:
-                        lec_params.c11_max_unknown_frame_time = value16;
-                        break;
-                case MAX_RETRY_COUNT:
-                        lec_params.c13_max_retry_count = value16;
-                        break;
-                case FORWARD_DELAY_TIME:
-                        lec_params.c18_forward_delay_time = value16;
-                        break;
-                case EXPECTED_LE_ARP_TIME:
-                        lec_params.c20_le_arp_response_time = value16;
-                        break;
-                case FLUSH_TIMEOUT:
-                        lec_params.c21_flush_timeout = value16;
-                        break;
-                case PATH_SWITCHING_DELAY:
-                        lec_params.c22_path_switching_delay = value16;
-                        break;
-                case LOCAL_SEGMENT_ID:
-                case DEF_MCAST_SND_VCC_TYPE:
-                case CONN_COMPLETION_TIMER:
-                case SERVICE_CATEGORY:
-                        /* do nothing */
-                        break;
-                default:
-                        goto whine;
-                        break;
-                }
-                break;
-        case 4:
-                value32 = *(uint32_t *)tlvp;
-                value32 = ntohl(value32);
-                diag(COMPONENT, DIAG_DEBUG, "value of TLV %d\n", value32);
-                switch (type) {
-                case VCC_TIMEOUT_PERIOD:
-                        lec_params.c12_vcc_timeout = value32;
-                        break;
-                case AGING_TIME:
-                        lec_params.c17_aging_time = value32;
-                        break;
-                case ELAN_ID:
-                        lec_params.c31_elan_id = value32;
-                        break;
-                case DEF_MCAST_SND_VCC_AVG:
-                case DEF_MCAST_SEND_PEAK_RT:
-                        /* do nothing */
-                        break;
-                default:
-                        goto whine;
-                        break;
-                }
-                break;
-        case 20:
-                switch(type) {
-                case PREFERRED_LES:
-                        memcpy(lec_params.c35_preferred_les, tlvp, ATM_ESA_LEN);
-                        lec_params.c35_contains_address = 1;
-                        break;
-                case LLC_MUXED_ATM_ADDR:
-                        /* do nothing */
-                        break;
-                default:
-                        goto whine;
-                        break;
-                }
-                break;
-        default:
-                /* handle variable length TLVs */
-                switch(type) {
-                case CONFIG_FRAG_INFO:
-                        diag(COMPONENT, DIAG_INFO, "Got Config-Frag-Info TLV\n");
-                        break;
-                case LAYER3_ADDRESS:
-                        /* do nothing */
-                        break;
-                default:
-                        goto whine;
-                        break;
-                }
-                break;
-        }
-
-        return;
-
- whine:
-        diag(COMPONENT, DIAG_DEBUG, "Unknown TLV, type 0x%x, len %d\n", type, len);
-
-        return;
-}
-
-/* Figures out what to do when we get a X5-Adjustment TLV
- */
-static void handle_x5(uint16_t opcode)
-{
-        if (!lec_params.c29_v2_capable)
-                return;
-        if (opcode != ntohs(LE_CONFIG_RSP)) {
-                diag(COMPONENT, DIAG_WARN, "X5-Adjustment TLV received but not with LE_CONFIG_RSP\n");
-                return;
-        }
-
-        switch(lec_params.c3_max_frame_size) {
-        case 1:
-                lec_params.c3_max_frame_size = 5; /* 1580 */
-                return;
-                break;
-        case 2:
-                lec_params.c3_max_frame_size = 5; /* 1580 */
-                return;
-                break;
-        default:
-                /* rest of the values are not affected by X5 */
-                break;
-        }
-
-        return;
-}
diff -ur --new-file old/atm/led.new/frames.h new/atm/led.new/frames.h
--- old/atm/led.new/frames.h	Sat Feb  6 21:54:23 1999
+++ new/atm/led.new/frames.h	Thu Jan  1 01:00:00 1970
@@ -1,21 +0,0 @@
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#ifndef FRAMES_H
-#define FRAMES_H
-
-#include "frame_defs.h"
-
-#define MAX_CTRL_FRAME 512
-
-void prefill_frame(void *ctrl_frame, uint16_t type);
-int validate_frame(unsigned char *buff, int size);
-
-void send_ready_ind(Conn_t *conn);
-void send_register_req(void);
-
-int handle_frame(Conn_t *conn, char *buff, int size);
-uint32_t send_flush_req(Conn_t *conn);
-
-void parse_tlvs(uint16_t opcode, unsigned char *tlvp, int numtlvs, int sizeoftlvs);
-
-#endif /* FRAMES_H */
diff -ur --new-file old/atm/led.new/join.c new/atm/led.new/join.c
--- old/atm/led.new/join.c	Sat Feb  6 21:58:04 1999
+++ new/atm/led.new/join.c	Thu Jan  1 01:00:00 1970
@@ -1,766 +0,0 @@
-/* join.c - functions which are only needed when joining an ELAN */
-
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h> /* for rand() */
-#include <sys/ioctl.h>
-#include <atm.h>
-
-#include <linux/atmlec.h>
-
-#include <atmd.h>
-
-#include "conn.h"
-#include "lec.h"
-#include "join.h"
-#include "frames.h"
-#include "display.h"
-
-#define COMPONENT "lec.c"
-
-struct lec_params lec_params;
-
-static unsigned char bus_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-static unsigned char well_known_lecs[ATM_ESA_LEN] = {0x47,0x00,0x79,0x00,0x00,
-                                                     0x00,0x00,0x00,0x00,0x00,
-                                                     0x00,0x00,0x00,0x00,0xA0,
-                                                     0x3E,0x00,0x00,0x01,0x00};
-static int do_lec_configure(Conn_t *conn);
-static int send_config_req(Conn_t *conn);
-static int read_config_rsp(Conn_t *conn, char *buff, int buffsize);
-static int parse_config_rsp(unsigned char *buff, int size);
-
-static int send_join_req(Conn_t *conn);
-static int read_join_rsp(char *buff, int buffsize);
-static int parse_join_rsp(unsigned char *buff, int size);
-
-static int get_bus_addr(struct sockaddr_atmsvc *addr);
-static int read_bus_arp(Conn_t *conn, struct sockaddr_atmsvc *addr, char *buff, int buffsize);
-
-/*
- * 5.1, Initial state
- */
-void init_lec_params(unsigned char *mac_addr, char *elan_name,
-                     unsigned char *listen_addr, int itf, char *foreId,
-                     int max_frame_size, int proxy_flag, int lane_version)
-{
-        memcpy(lec_params.c6_mac_addr, mac_addr, ETH_ALEN);
-        strcpy(lec_params.c5_elan_name, elan_name);
-        memcpy(lec_params.c1n_my_atm_addr, listen_addr, ATM_ESA_LEN);
-        lec_params.itf_num = itf;
-        strcpy(lec_params.foreId, foreId);
-        lec_params.c3_max_frame_size = max_frame_size;
-        lec_params.c4_proxy_flag = proxy_flag;
-
-        if (lane_version > 1 ) lec_params.c29_v2_capable = 1;
-        else lec_params.c29_v2_capable = 0;
-        
-        /* then come the defaults */
-        lec_params.c2_lan_type = 0x01; /* Ethernet/IEEE 802.3 */
-        if (lec_params.c29_v2_capable) {
-                lec_params.c7_ctrl_timeout = 30;
-                lec_params.c10_max_unknown_frames = 10;
-        }
-        else {
-                lec_params.c7_ctrl_timeout = 10;
-                lec_params.c10_max_unknown_frames = 1;
-        }
-        lec_params.c7i_initial_ctrl_timeout = 5;
-        lec_params.c7x_timeout_multiplier = 2;
-        lec_params.c7c_current_timeout = lec_params.c7i_initial_ctrl_timeout;
-        lec_params.c11_max_unknown_frame_time = 1;
-        lec_params.c12_vcc_timeout            = 1200;
-        lec_params.c13_max_retry_count        = 2;
-        lec_params.c14_lec_id                 = 0;
-        lec_params.c17_aging_time             = 300;
-        lec_params.c18_forward_delay_time     = 15;
-        lec_params.c19_topology_change        = 0;
-        lec_params.c20_le_arp_response_time   = 1;
-        lec_params.c21_flush_timeout          = 4;
-        lec_params.c22_path_switching_delay   = 6;
-        /* LANE2 added the following, only the ones used are listed */
-        memset(lec_params.c35_preferred_les, 0, ATM_ESA_LEN);
-        lec_params.c35_contains_address       = 0;
-        lec_params.c37_min_reconfig_delay     = 1;    /* milliseconds */
-        lec_params.c38_max_reconfig_delay     = 5000; /* milliseconds */
-
-        if (lec_params.tlvs != NULL) free (lec_params.tlvs);
-        lec_params.tlvs       = NULL;
-        lec_params.sizeoftlvs = 0;
-        lec_params.num_tlvs   = 0;
-
-        return;
-}
-
-/* ------------- Configure phase specific stuff starts ------------- */
-
-/*
- * 5.2 LECS connect phase
- * Returns < 0 for error
- */
-int lec_configure(int lecs_method, struct sockaddr_atmsvc *manual_atm_addr,
-                  struct sockaddr_atmsvc *listen_addr)
-{
-        int retval;
-        struct sockaddr_atmsvc addr_c5, addr_47;
-        struct atm_sap sap;
-        struct atm_qos qos;
-        Conn_t *conn;
-        
-        diag(COMPONENT, DIAG_DEBUG, "entering lec_configure\n");
-        
-        /* initialize well known LECS addresses */
-        memset(&addr_c5, 0, sizeof(struct sockaddr_atmsvc));
-        memset(&addr_47, 0, sizeof(struct sockaddr_atmsvc));
-        addr_c5.sas_family = addr_47.sas_family = AF_ATMSVC;
-        memcpy(addr_c5.sas_addr.prv, well_known_lecs, ATM_ESA_LEN);
-        memcpy(addr_47.sas_addr.prv, well_known_lecs, ATM_ESA_LEN);
-        addr_c5.sas_addr.prv[0] = 0xC5;
-
-        /* see if the user wants to skip LECS */
-        if (lecs_method == LECS_NONE)
-                return 0;
-        
-        init_conn_params(&sap, &qos, CONTROL_CONN);
-
-        while(1) {
-                if (lecs_method == LECS_MANUAL) {
-                        diag(COMPONENT, DIAG_DEBUG, "trying manual LECS address\n");
-                        conn = setup_svc(manual_atm_addr, listen_addr, &sap, &qos);
-                        if (conn) {
-                                retval = do_lec_configure(conn);
-                                close_connection(conn);
-                                return retval;
-                        }
-                        else random_delay();
-                }
-                diag(COMPONENT, DIAG_DEBUG, "trying well-known anycast LECS address\n");
-                conn = setup_svc(&addr_c5, listen_addr, &sap, &qos);
-                if (conn) {
-                        retval = do_lec_configure(conn);
-                        close_connection(conn);
-                        return retval;
-                }
-                else random_delay();
-                diag(COMPONENT, DIAG_DEBUG, "trying well-known LECS address\n");
-                conn = setup_svc(&addr_47, listen_addr, &sap, &qos);
-                if (conn) {
-                        retval = do_lec_configure(conn);
-                        close_connection(conn);
-                        return retval;
-                }
-                else random_delay();
-        }
-        
-        return -1; /* not reached */
-}
-
-/*
- * 5.3 Configuration phase, get configuration from LECS
- * Returns < 0 for error
- */
-static int do_lec_configure(Conn_t *conn)
-{
-        int frame_size = 0;
-        char buff[MAX_CTRL_FRAME];
-
-        lec_params.c7c_current_timeout = lec_params.c7i_initial_ctrl_timeout; /* reset it */
-        while (lec_params.c7c_current_timeout <= lec_params.c7_ctrl_timeout) {
-                if (send_config_req(conn) < 0) return -1;
-                frame_size = read_config_rsp(conn, buff, sizeof(buff));
-                if (frame_size < 0) return -1;
-                if (frame_size == 0) /* timeout */
-                        lec_params.c7c_current_timeout *= lec_params.c7x_timeout_multiplier;
-                else
-                        break; /* frame in */
-        }
-        lec_params.c7c_current_timeout = lec_params.c7i_initial_ctrl_timeout; /* reset it */
-        if (frame_size == 0) {
-                diag(COMPONENT, DIAG_INFO, "Timed out while waiting for LE_CONFIGURE_RESPONSE\n");
-                return -1; /* timeout */
-        }
-
-        if (parse_config_rsp(buff, frame_size) < 0) {
-                diag(COMPONENT, DIAG_ERROR, "Parsing LE_CONFIG_RESPONSE indicates failure\n");
-                return -1;
-        }
-
-        return 0;
-}
-
-/*
- * Compose a LE Config request frame and send it to LECS
- * Returns < 0 for error
- */
-static int send_config_req(Conn_t *conn)
-{
-        int frame_size;
-        struct ctrl_frame *config_req;
-        char buff[MAX_CTRL_FRAME];
-
-        diag(COMPONENT, DIAG_DEBUG, "Sending LE_CONFIGURE_REQUEST\n");
-
-        /* TLVs make config frame variable length */
-        frame_size = sizeof(struct ctrl_frame);
-        if (lec_params.c3_max_frame_size == MTU_1580) frame_size += 5;
-        config_req = (struct ctrl_frame *)buff;
-        memset(config_req, 0, frame_size);
-
-        prefill_frame(config_req, LE_CONFIG_REQ);
-        if (lec_params.c29_v2_capable)
-                config_req->header.flags = htons(V2_CAPABLE);
-        config_req->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
-        memcpy(config_req->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN);
-        memcpy(config_req->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-        config_req->lan_type = lec_params.c2_lan_type;
-        config_req->max_frame_size = lec_params.c3_max_frame_size;
-        config_req->elan_name_size = strlen(lec_params.c5_elan_name);
-        if (strlen(lec_params.c5_elan_name) > 0)
-                strcpy(config_req->elan_name, lec_params.c5_elan_name);
-        if (lec_params.c3_max_frame_size == MTU_1580) {
-                lec_params.c3_max_frame_size = MTU_1516;
-                *(uint32_t *)(config_req + 1) = htonl(X5_ADJUSTMENT);
-                config_req->num_tlvs++;
-        }
-
-        if (send_frame(conn, buff, frame_size) != frame_size)
-                return -1;
-
-        return 0;
-}
-
-/*
- * Reads in Config frame or timeouts
- * Returns Config frame length, < 0 for error, 0 for timeout
- */
-static int read_config_rsp(Conn_t *conn, char *buff, int buffsize)
-{
-        int frame_size, retval;
-        struct timeval tv;
-        fd_set rfds;
-
-        tv.tv_sec = lec_params.c7c_current_timeout;
-        tv.tv_usec = 0;
-        FD_ZERO(&rfds);
-        FD_SET(conn->fd, &rfds);
-
-        retval = select(conn->fd + 1, &rfds, NULL, NULL, &tv);
-        if (retval < 0) {
-                diag(COMPONENT, DIAG_ERROR, "read_ctrl_rsp: select: %s\n",
-                     strerror(errno));
-                return retval;
-        }
-        if (retval == 0) return 0; /* timeout */
-        
-        frame_size = recv_frame(conn, buff, buffsize);
-        if (frame_size < 0) {
-                diag(COMPONENT, DIAG_ERROR, "read_ctrl_rsp: recv_frame: %s\n",
-                     strerror(errno));
-                return frame_size;
-        }
-        if (frame_size == 0) {
-                diag(COMPONENT, DIAG_ERROR, "read_ctrl_rsp: conn closed: %s\n",
-                     strerror(errno));
-                return -1;
-        }
-
-        return frame_size;
-}
-
-/* Validates and parses a LE_CONFIGURE_RESPONSE.
- * See LANEv2, 5.3.x
- * Returns < 0 for error
- */
-static int parse_config_rsp(unsigned char *buff, int size)
-{
-        struct ctrl_frame *frame;
-
-        diag(COMPONENT, DIAG_DEBUG, "Parsing LE_CONFIG_RESPONSE\n");
-        if (validate_frame(buff, size) < 0) {
-                diag(COMPONENT, DIAG_ERROR, "parse_config_rsp: bad frame\n");
-                return -1;
-        }
-
-        frame = (struct ctrl_frame *)buff;
-        if (frame->header.opcode != htons(LE_CONFIG_RSP)) {
-                diag(COMPONENT, DIAG_ERROR, "parse_config_rsp: not a LE_CONFIG_RESPONSE\n");
-                return -1;
-        }
-        
-        if (frame->header.status != 0) {
-                diag(COMPONENT, DIAG_ERROR, "LECS said: %s\n",
-                     status2text(frame->header.status));
-                return -1;
-        }
-        if (frame->elan_name_size > 32) return -1;
-
-        /* looks good, now extract the information */
-        lec_params.c2_lan_type = frame->lan_type;
-        lec_params.c3_max_frame_size = frame->max_frame_size;
-        if (frame->elan_name_size != 0)
-                strncpy(lec_params.c5_elan_name, frame->elan_name, frame->elan_name_size);
-        lec_params.c5_elan_name[frame->elan_name_size] = '\0';
-        memcpy(lec_params.c9_les_atm_addr, frame->target_atm_addr, ATM_ESA_LEN);
-
-        parse_tlvs(frame->header.opcode, buff + sizeof(struct ctrl_frame),
-                   frame->num_tlvs, size - sizeof(struct ctrl_frame));
-
-        return 0;
-}
-
-/* ------------- Configure phase specific stuff ends ------------- */
-
-
-/* -------------- Join phase specific stuff starts --------------- */
-
-/*
- * 5.4 Join phase
- * Create control direct VCC and accept possible control distribute VCC
- * Returns < 0 for error
- */
-int les_connect(int lecs_method, struct sockaddr_atmsvc *manual_atm_addr,
-                  struct sockaddr_atmsvc *listen_addr)
-{
-        struct sockaddr_atmsvc les_addr;
-        struct atm_sap sap;
-        struct atm_qos qos;
-        char buff[MAX_CTRL_FRAME];
-        int frame_size = 0; /* shut up, GCC */
-
-        diag(COMPONENT, DIAG_DEBUG, "Entering Join phase\n");
-
-        if (lecs_method == LECS_NONE) {
-                diag(COMPONENT, DIAG_DEBUG, "Skipping LECS, connecting straight to LES\n");
-                memcpy(les_addr.sas_addr.prv, manual_atm_addr->sas_addr.prv, ATM_ESA_LEN);
-        } else memcpy(les_addr.sas_addr.prv, lec_params.c9_les_atm_addr, ATM_ESA_LEN);
-
-        init_conn_params(&sap, &qos, CONTROL_CONN);
-        lec_params.ctrl_direct = setup_svc(&les_addr, listen_addr, &sap, &qos);
-        if (lec_params.ctrl_direct == NULL) {
-                diag(COMPONENT, DIAG_ERROR, "Control direct SVC failed\n");
-                random_delay();
-                return -1;
-        }
-        lec_params.ctrl_listen = create_listensocket(listen_addr, &sap, &qos);
-        if (lec_params.ctrl_listen == NULL) {
-                diag(COMPONENT, DIAG_ERROR, "Control distribute listen socket failed\n");
-                random_delay();
-                return -1;
-        }
-
-        lec_params.c7c_current_timeout = lec_params.c7i_initial_ctrl_timeout; /* reset it */
-        while (lec_params.c7c_current_timeout <= lec_params.c7_ctrl_timeout) {
-                if (send_join_req(lec_params.ctrl_direct) < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "Sending LE_JOIN_REQUEST failed\n");
-                        random_delay();
-                        return -1;
-                }
-                frame_size = read_join_rsp(buff, sizeof(buff));
-                if (frame_size < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "Receiving LE_JOIN_RESPONSE failed\n");
-                        random_delay();
-                        return -1;
-                } else if (frame_size == 0) /* timeout */
-                        lec_params.c7c_current_timeout *= lec_params.c7x_timeout_multiplier;
-                else
-                        break; /* frame in */
-        }
-        lec_params.c7c_current_timeout = lec_params.c7i_initial_ctrl_timeout; /* reset it */
-        if (frame_size == 0) {
-                diag(COMPONENT, DIAG_ERROR, "LE_JOIN_RESPONSE timed out\n");
-                return -1;
-        }
-        
-        if (parse_join_rsp(buff, frame_size) < 0) {
-                diag(COMPONENT, DIAG_ERROR, "Parsing LE_JOIN_RESPONSE failed\n");
-                return -1;
-        }
-
-        return 0;
-}
-
-/* 5.4.1.2 Transmitting LE_JOIN_REQUEST
- * Note that the TLVs should be the same as in LE_CONFIG_REQUEST
- * excluding X5-Adjustment and Preferred-LES
- */
-static int send_join_req(Conn_t *conn)
-{
-        char buff[MAX_CTRL_FRAME], *tlvp;
-        struct ctrl_frame *frame;
-        int frame_size;
-
-        frame_size = sizeof(struct ctrl_frame);
-        if (lec_params.c3_max_frame_size == 5) frame_size += 5;
-        if (lec_params.c35_contains_address) frame_size += (5 + ATM_ESA_LEN);
-        if (strlen(lec_params.foreId) > 0) frame_size += (5 + strlen(lec_params.foreId));
-
-        frame = (struct ctrl_frame *)buff;
-        tlvp = (char *)(frame + 1);
-        prefill_frame(frame, LE_JOIN_REQ);
-        frame->lan_type = lec_params.c2_lan_type;
-        if (lec_params.c4_proxy_flag) frame->header.flags |= htons(PROXY_FLAG);
-        frame->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
-        strcpy(frame->elan_name, lec_params.c5_elan_name);
-        frame->elan_name_size = strlen(lec_params.c5_elan_name);
-        if (lec_params.c29_v2_capable) frame->header.flags |= htons(V2_CAPABLE);
-        memcpy(frame->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-        memcpy(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN);
-        frame->max_frame_size = lec_params.c3_max_frame_size;
-        if (lec_params.c3_max_frame_size == 5) {
-                frame->max_frame_size = 1;
-                *(uint32_t *)tlvp = htonl(X5_ADJUSTMENT);
-                tlvp += 4; *tlvp = 0; tlvp++;
-                frame->num_tlvs++;
-        }
-        if (lec_params.c35_contains_address) {
-                *(uint32_t *)tlvp = htonl(PREFERRED_LES);
-                tlvp +=4; *tlvp = (uint8_t)ATM_ESA_LEN; tlvp++;
-                memcpy(tlvp, lec_params.c35_preferred_les, ATM_ESA_LEN);
-                tlvp += 20;
-                frame->num_tlvs++;
-        }
-        if (strlen(lec_params.foreId) > 0) {
-                *(uint32_t *)tlvp = htonl(FORE_NAME);
-                tlvp +=4; *tlvp = (uint8_t)strlen(lec_params.foreId); tlvp++;
-                memcpy(tlvp, lec_params.foreId, strlen(lec_params.foreId));
-                tlvp += strlen(lec_params.foreId);
-                frame->num_tlvs++;
-        }
-
-        if (send_frame(conn, frame, frame_size) != frame_size)
-                return -1;
-
-        return 0;
-}
-
-/* LE_JOIN_RESPONSE can either come over ctrl_direct or ctrl_dist.
- * However, if LES uses Control Direct VCC, we can ignore connections
- * to ctrl_listen and if it connects to ctrl_listen we can wait
- * the reponse to arrive that route. Simple :)
- * 
- * Returns < 0 for error, 0 for timeout, > 0 for frame size
- */
-static int read_join_rsp(char *buff, int buffsize)
-{
-        Conn_t *dist;
-        int n, retval, frame_size = 0;
-        struct timeval tv;
-        fd_set rfds;
-
-        /* Idea here is always to listen for two sockets. One of the
-           sockets is always Control Direct and the other is either
-           listen socket for Control Distribute or the Control
-           Distribute itself. We can do it like this, since listen
-           socket gets closed as soon as it creates a new connection
-        */
-
-        dist = (lec_params.ctrl_listen != NULL) ? lec_params.ctrl_listen : lec_params.ctrl_dist;
-        n = (lec_params.ctrl_direct->fd > dist->fd) ? lec_params.ctrl_direct->fd : dist->fd;
-        n++;
-
-        tv.tv_sec = lec_params.c7c_current_timeout;
-        tv.tv_usec = 0;
-        FD_ZERO(&rfds);
-        FD_SET(lec_params.ctrl_direct->fd, &rfds);
-        FD_SET(dist->fd, &rfds);
-        
-        retval = select(n, &rfds, NULL, NULL, &tv);
-        if (retval < 0) {
-                diag(COMPONENT, DIAG_ERROR, "get_join_rsp: select: %s\n",
-                     strerror(errno));
-                return -1;
-        }
-        if (retval == 0) return 0; /* timeout */
-
-        /* Be careful here. The both sockets might be readable
-         * and the response can come from either one
-         */
-        if (FD_ISSET(lec_params.ctrl_direct->fd, &rfds)) {
-                /* Control Direct was changed */
-                frame_size = recv_frame(lec_params.ctrl_direct, buff, buffsize);
-                if (frame_size < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "get_join_rsp: recv_frame: %s\n",
-                             strerror(errno));
-                        return -1;
-                }
-                if (frame_size == 0) {
-                        diag(COMPONENT, DIAG_ERROR, "get_join_rsp: Control direct VCC closed\n");
-                        return -1;
-                }
-                diag(COMPONENT, DIAG_DEBUG, "LE_JOIN_RESPONSE over Control direct VCC\n");
-        }
-        if (FD_ISSET(dist->fd, &rfds)) {
-                /* Event in listen socket or Control Distribute */
-                if (dist == lec_params.ctrl_listen) {
-                        /* Connection to control listen */
-                        lec_params.ctrl_dist = accept_conn(lec_params.ctrl_listen);
-                        if (lec_params.ctrl_dist == NULL) {
-                                diag(COMPONENT, DIAG_ERROR, "accept of Ctrl distribute failed\n");
-                                return -1;
-                        }
-                        diag(COMPONENT, DIAG_DEBUG, "Closing listen socket for Ctrl distribute VCC\n");
-                        close_connection(lec_params.ctrl_listen);
-                        lec_params.ctrl_listen = NULL;
-
-                        /* let's see if this new socket has something for us */
-                        return (read_join_rsp(buff, buffsize));
-                }
-                /* Event in Control distribute */
-                frame_size = recv_frame(lec_params.ctrl_dist, buff, buffsize);
-                if (frame_size < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "get_join_rsp: recv_frame: %s\n",
-                             strerror(errno));
-                        return -1;
-                }
-                if (frame_size == 0) {
-                        diag(COMPONENT, DIAG_ERROR, "Control distribute VCC closed\n");
-                        return -1;
-                }
-                diag(COMPONENT, DIAG_DEBUG, "LE_JOIN_RESPONSE over Control distribute VCC\n");
-        }
-
-        return frame_size;
-}
-
-/* Validates and parses a LE_JOIN_RESPONSE.
- * See LANEv2 5.4.x
- * Returns < 0 for error
- */
-static int parse_join_rsp(unsigned char *buff, int size)
-{
-        struct ctrl_frame *frame;
-
-        diag(COMPONENT, DIAG_DEBUG, "Parsing LE_JOIN_RESPONSE\n");
-        if (validate_frame(buff, size) < 0)
-                return -1;
-
-        frame = (struct ctrl_frame *)buff;
-        if (frame->header.opcode != htons(LE_JOIN_RSP))
-                return -1;
-        
-        if (frame->header.status != 0) {
-                diag(COMPONENT, DIAG_ERROR, "LES said: %s\n",
-                     status2text(frame->header.status));
-                return -1;
-        }
-        if (frame->elan_name_size > 32) return -1;
-
-        /* looks good, now extract the information */
-        lec_params.c2_lan_type = frame->lan_type;
-        lec_params.c3_max_frame_size = frame->max_frame_size;
-        if (frame->elan_name_size != 0)
-                strncpy(lec_params.c5_elan_name, frame->elan_name, frame->elan_name_size);
-        lec_params.c5_elan_name[frame->elan_name_size] = '\0';
-        lec_params.c14_lec_id = ntohs(frame->header.lec_id);
-
-        if (!(frame->header.flags & htons(V2_REQUIRED)) && lec_params.c29_v2_capable) {
-                diag(COMPONENT, DIAG_INFO, "LES did not return V2 Required Flag, acting as V1 client\n");
-                lec_params.c29_v2_capable = 0;
-        }
-        if (!(frame->header.flags & htons(V2_REQUIRED)) &&
-            (lec_params.c3_max_frame_size == MTU_1580)) {
-                /* Against spec, but we'll accept the MTU and clear the flag */
-                diag(COMPONENT, DIAG_ERROR, "LES not LANEv2 but uses MTU of 1580 bytes\n");
-                lec_params.c29_v2_capable = 0;
-        }
-        parse_tlvs(frame->header.opcode, buff + sizeof(struct ctrl_frame),
-                   frame->num_tlvs, size - sizeof(struct ctrl_frame));
-
-        return 0;
-}
-
-/* --------------- Join phase specific stuff ends ---------------- */
-
-
-/* -------------- Bus connect specific stuff starts --------------- */
-
-int bus_connect(void)
-{
-        struct ctrl_frame *frame;
-        char buff[MAX_CTRL_FRAME];
-        struct sockaddr_atmsvc bus_addr, listen_addr;
-        int retval, tries, n;
-        struct atm_sap sap;
-        struct atm_qos qos;
-        struct timeval tv;
-        fd_set rfds;
-        Conn_t *mcast_fwd;
-        struct atmlec_ioc ioc_data;
-
-        frame = (struct ctrl_frame *)buff;
-        memset(&bus_addr, 0, sizeof(struct sockaddr_atmsvc));
-        memset(&listen_addr, 0, sizeof(struct sockaddr_atmsvc));
-        
-        /* try to arp BUS two times */
-        tries = 2;
-        while (tries > 0) {
-                prefill_frame(frame, LE_ARP_REQ);
-                frame->header.lec_id = htons(lec_params.c14_lec_id);
-                frame->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
-                memcpy(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN);
-                memcpy(frame->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-                frame->target_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
-                memcpy(frame->target_lan_dst.mac, bus_mac, ETH_ALEN);
-                retval = send_frame(lec_params.ctrl_direct, frame, sizeof(struct ctrl_frame));
-                if (retval < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "LE_ARP_REQUEST for BUS failed\n");
-                        return -1;
-                }
-                retval = get_bus_addr(&bus_addr);
-                if (retval < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "LE_ARP_RESPONSE for BUS failed\n");
-                        return -1;
-                } else if (retval > 0)
-                        break; /* got it */
-                tries--;
-        }
-        if (tries == 0) {
-                diag(COMPONENT, DIAG_ERROR, "LE_ARP_RESPONSE for BUS timed out\n");
-                return -1;
-        }
-
-        /* We got address for BUS. Make the listen socket for Multicast
-         * Forward first and then contact BUS.
-         */
-        memcpy(listen_addr.sas_addr.prv, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-        listen_addr.sas_family = bus_addr.sas_family = AF_ATMSVC;
-        init_conn_params(&sap, &qos, MCAST_CONN);
-        lec_params.mcast_listen = create_listensocket(&listen_addr, &sap, &qos);
-        if (lec_params.mcast_listen == NULL) {
-                diag(COMPONENT, DIAG_ERROR, "Listen socket for BUS failed\n");
-                return -1;
-        }
-
-        lec_params.mcast_send = setup_svc(&bus_addr, &listen_addr, &sap, &qos);
-        if (lec_params.mcast_send == NULL) {
-                diag(COMPONENT, DIAG_ERROR, "Connect to BUS failed\n");
-                return -1;
-        }
-        /* Default Multicast send VCC to BUS ready, notify kernel */
-        if (ioctl(lec_params.mcast_send->fd, ATMLEC_MCAST, lec_params.itf_num) < 0) {
-                diag(COMPONENT, DIAG_FATAL, "Can't change socket into LE mcast socket: %s\n", strerror(errno));
-                return -1;
-        }
-
-        diag(COMPONENT, DIAG_DEBUG, "About to wait for BUS to connect\n");
-        tv.tv_sec = lec_params.c7_ctrl_timeout;
-        tv.tv_usec = 0;
-        FD_ZERO(&rfds);
-        FD_SET(lec_params.mcast_listen->fd, &rfds);
-        n = lec_params.mcast_listen->fd + 1;
-        retval = select(n, &rfds, NULL, NULL, &tv);
-        if (retval == 0) {
-                diag(COMPONENT, DIAG_ERROR, "BUS connect to Multicast Forward listen socket timed out\n");
-                return -1;
-        }
-        if (retval < 0) {
-                diag(COMPONENT, DIAG_ERROR, "while waiting for Multicast Forward VCC: select: %s\n",
-                     strerror(errno));
-                return -1;
-        }
-        mcast_fwd = accept_conn(lec_params.mcast_listen);
-        if (mcast_fwd == NULL) {
-                diag(COMPONENT, DIAG_ERROR, "BUS connect to Multicast Forward listen socket failed\n");
-                return -1;
-        }
-        
-        memcpy(ioc_data.atm_addr, mcast_fwd->atm_address, ATM_ESA_LEN);
-        ioc_data.dev_num = lec_params.itf_num;
-        ioc_data.receive = 2; /* Multicast distribute */
-        diag(COMPONENT, DIAG_DEBUG, "About to notify kernel about Multicast Forward VCC\n");
-        if (ioctl(mcast_fwd->fd, ATMLEC_DATA, &ioc_data) < 0) {
-                diag(COMPONENT, DIAG_DEBUG, "Could not notify kernel: %s\n", strerror(errno));
-                return -1;
-        }
-
-        /* All done. We're in! */
-        return 0;
-}
-
-/*
- * Waits for LE_ARP_RESPONSE for BUS' ATM address to arrive.
- * Returns < 0 for error, 0 for timeout > 0 for success
- * BUS ATM address will be stored in *addr */
-static int get_bus_addr(struct sockaddr_atmsvc *addr)
-{
-
-        fd_set rfds;
-        struct timeval tv;
-        int n = 0, retval, timeout;
-        char buff[MAX_CTRL_FRAME];
-
-        timeout = 4; /* wait response for 4 seconds */
-        lec_params.c7c_current_timeout = 1;
-        while (lec_params.c7c_current_timeout <= timeout) {
-                tv.tv_sec = lec_params.c7c_current_timeout; /* actually not specified exactly */
-                tv.tv_usec = 0;
-                FD_ZERO(&rfds);
-                FD_SET(lec_params.ctrl_direct->fd, &rfds);
-                if (lec_params.ctrl_dist != NULL) {
-                        FD_SET(lec_params.ctrl_dist->fd, &rfds);
-                        n = lec_params.ctrl_dist->fd;
-                }
-                n = (lec_params.ctrl_direct->fd > n) ? lec_params.ctrl_direct->fd : n;
-                n++;
-                
-                retval = select(n, &rfds, NULL, NULL, &tv);
-                if (retval == 0) {
-                        lec_params.c7c_current_timeout++;
-                        continue; /* back to waiting */
-                }
-                if (retval < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "get_bus_addr: select: %s\n", strerror(errno));
-                        return -1;
-                }
-                if (FD_ISSET(lec_params.ctrl_direct->fd, &rfds)) {
-                        diag(COMPONENT, DIAG_DEBUG, "get_bus_addr: ctrl.direct changed:\n");
-                        retval = read_bus_arp(lec_params.ctrl_direct, addr, buff, sizeof(buff));
-                        if (retval < 0) return -1;
-                        if (retval > 0) return retval;
-                }
-                if (lec_params.ctrl_dist != NULL && FD_ISSET(lec_params.ctrl_dist->fd, &rfds)) {
-                        diag(COMPONENT, DIAG_DEBUG, "get_bus_addr: ctrl.dist changed:\n");
-                        retval = read_bus_arp(lec_params.ctrl_dist, addr, buff, sizeof(buff));
-                        if (retval < 0) return -1;
-                        if (retval > 0) return retval;
-                }
-                diag(COMPONENT, DIAG_DEBUG, "get_bus_addr: consumed a packet\n");
-        }
-
-        diag(COMPONENT, DIAG_ERROR, "Timeout while waiting for BUS LE_ARP response\n");
-        return 0;
-}
-/*
- * Tries to read BUS ATM address in *addr
- * returns < 0 for error, 0 for not found > 0 for success
- */
-static int read_bus_arp(Conn_t *conn, struct sockaddr_atmsvc *addr, char *buff, int buffsize)
-{
-        int frame_size;
-        struct ctrl_frame *frame;
-
-        frame_size = recv_frame(conn, buff, buffsize);
-        if (frame_size == 0) {
-                diag(COMPONENT, DIAG_ERROR, "LES Control connection closed\n");
-                return -1;
-        }
-        if (frame_size < 0) {
-                diag(COMPONENT, DIAG_ERROR, "get_bus_arp: recv_frame: %s\n", strerror(errno));
-                return -1;
-        }
-        frame = (struct ctrl_frame *)buff;
-        if (validate_frame(buff, frame_size) >= 0 &&
-            frame->header.opcode == htons(LE_ARP_RSP) &&
-            memcmp(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN) == 0) {
-                memcpy(addr->sas_addr.prv, frame->target_atm_addr, ATM_ESA_LEN);
-                return frame_size;
-        }
-
-        return 0; /* not found */
-}
-
-/* --------------- Bus connect specific stuff ends --------------- */
diff -ur --new-file old/atm/led.new/join.h new/atm/led.new/join.h
--- old/atm/led.new/join.h	Sat Feb  6 21:20:44 1999
+++ new/atm/led.new/join.h	Thu Jan  1 01:00:00 1970
@@ -1,20 +0,0 @@
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#ifndef JOIN_H
-#define JOIN_H
-
-void init_lec_params(unsigned char *mac_addr, char *elan_name,
-                     unsigned char *listen_addr, int itf, char *foreId,
-                     int max_frame_size, int proxy_flag, int lane_version);
-int lec_configure(int lecs_method, struct sockaddr_atmsvc *manual_atm_addr,
-                  struct sockaddr_atmsvc *listen_addr);
-int les_connect(int lecs_method, struct sockaddr_atmsvc *manual_atm_addr,
-                struct sockaddr_atmsvc *listen_addr);
-int bus_connect(void);
-
-/* Different ways to contact LECS */
-#define LECS_NONE      0
-#define LECS_WELLKNOWN 1
-#define LECS_MANUAL    2
-
-#endif /* JOIN_H */
diff -ur --new-file old/atm/led.new/kernel.c new/atm/led.new/kernel.c
--- old/atm/led.new/kernel.c	Thu Apr  8 06:06:40 1999
+++ new/atm/led.new/kernel.c	Thu Jan  1 01:00:00 1970
@@ -1,328 +0,0 @@
-/* kernel.c - send and receive messages from kernel and act accordingly */
-
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-/* System includes */
-#include <errno.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <string.h>
-#include <stdlib.h>
-
-/* Atm includes */
-#include <atm.h>
-#include <linux/atmdev.h>
-#include <linux/atmlec.h>
-
-#include <atmd.h>
-
-/* Local includes */
-#include "kernel.h"
-#include "lec.h"
-#include "frames.h"
-
-#define COMPONENT "kernel.c"
-
-/* Local vars */
-static int lec_socket;
-
-static const char* get_mesg_type_str(atmlec_msg_type type);
-static void send_le_arp_req(unsigned char *mac_addr, int sizeoftlvs);
-static void send_proxy_arp_rsp(unsigned char *target_mac, uint32_t tran_id,
-                               uint16_t lec_id, unsigned char *src_atm_addr);
-static void send_topology_req(int flag);
-static void associate_tlvs(int sizeoftlvs);
-
-/* Notify kernel that zeppelin is present and tell
- * kernel what MAC address this LEC uses
- */
-int kernel_init(unsigned char *mac_addr, int itf)
-{
-        int rvalue;
-        struct atmlec_msg msg;
-
-        lec_socket = socket(PF_ATMSVC, SOCK_DGRAM, 0);
-        if (lec_socket < 0) {
-                diag(COMPONENT, DIAG_FATAL, "Kernel socket creation failed: %s\n",
-                     strerror(errno));
-                return -1;
-        }
-        itf = ioctl(lec_socket, ATMLEC_CTRL, itf);
-        if (itf < 0) {
-                diag(COMPONENT, DIAG_FATAL, "Socket ioctl to lecd_ctrl failed:%s\n",
-                     strerror(errno));
-                close(lec_socket);
-                return -1;
-        }
-        msg.type = l_set_mac_addr;
-        memcpy(msg.content.normal.mac_addr, mac_addr, ETH_ALEN);
-        
-        rvalue = write(lec_socket, &msg, sizeof(msg));
-        if (rvalue < 0) {
-                diag(COMPONENT, DIAG_FATAL, "Can't write mac address to LEC:%s\n",
-                     strerror(errno));
-                close(lec_socket);
-                return -1;
-        }
-        diag(COMPONENT, DIAG_DEBUG, "Kernel interface initialized\n");
-        
-        if (conn_set_kernel_socket(lec_socket) < 0) {
-                close(lec_socket);
-                return -1;
-        }
-        
-        return itf;
-}
-
-/* Send a message to kernel
- * Returns < 0 for error
- */
-int msg_to_kernel(struct atmlec_msg *msg, int msg_size)
-{
-        int retval;
-
-        diag(COMPONENT, DIAG_DEBUG, "msg_to_kernel, type %s\n", get_mesg_type_str(msg->type));
-        retval = write(lec_params.kernel->fd, msg, msg_size);
-        if (retval < 0) {
-                diag(COMPONENT, DIAG_ERROR, "msg_to_kernel: write: %s\n", strerror(errno));
-                return -1;
-        }
-        if (retval != msg_size) {
-                diag(COMPONENT, DIAG_ERROR, "msg_to_kernel: partial write\n");
-                return -1;
-        }
-
-        return retval;
-}
-
-/* Read and process message from kernel
- * Returns < 0 for error
- */
-int msg_from_kernel(void)
-{
-        int retval;
-        struct atmlec_msg msg;
-        int codepoint;
-
-        retval = read(lec_params.kernel->fd, &msg, sizeof(struct atmlec_msg));
-        if (retval < 0) {
-                diag(COMPONENT, DIAG_FATAL, "msg_from_kernel: read: %s\n", strerror(errno));
-                return -1;
-        }
-        if (retval != sizeof(struct atmlec_msg)) {
-                diag(COMPONENT, DIAG_ERROR, "msg_from_kernel: msg size != sizeof(atmlec_msg)\n");
-                return 0;
-        }
-
-        diag(COMPONENT, DIAG_DEBUG, "msg_from_kernel: type %s\n", get_mesg_type_str(msg.type));
-        switch (msg.type) {
-        case l_arp_xmt:
-                if (msg.content.normal.targetless_le_arp)
-                        send_le_arp_req(NULL, msg.sizeoftlvs);
-                else
-                        send_le_arp_req(msg.content.normal.mac_addr, msg.sizeoftlvs);
-                break;
-        case l_svc_setup:
-                codepoint = (msg.content.normal.mac_addr[0] & 0x01) ? MCAST_CONN : DATA_DIRECT_CONN;
-                if (create_data_svc(msg.content.normal.atm_addr, codepoint) < 0)
-                        diag(COMPONENT, DIAG_ERROR, "Data direct VCC failed\n");
-                break;
-        case l_associate_req:
-                associate_tlvs(msg.sizeoftlvs);
-                break;
-        case l_should_bridge:
-                send_proxy_arp_rsp(msg.content.proxy.mac_addr, msg.content.proxy.tran_id,
-                                   msg.content.proxy.lec_id, msg.content.proxy.atm_addr);
-                break;
-        case l_topology_change:
-                send_topology_req(msg.content.normal.flag);
-                break;
-        default:
-                diag(COMPONENT, DIAG_ERROR, "no handler for kernel msg %s\n", get_mesg_type_str(msg.type));
-                break;
-        }
-
-        return 0;
-}
-
-/* Send LE_ARP_REQUEST. If mac_addr is NULL, sends a targetless LE_ARP.
- * If sizeoftlvs != 0, reads TLVs waiting in the kernel socket and
- * adds them to the frame. If sizeoftlvs == 0 then the TLVs (if any)
- * associated with this LEC are used.
- * FIXME: add TLV count in kernel messages
- */
-static void send_le_arp_req(unsigned char *mac_addr, int sizeoftlvs)
-{
-        struct ctrl_frame *frame;
-        int frame_size;
-        char buff[MAX_CTRL_FRAME];
-
-        diag(COMPONENT, DIAG_DEBUG, "Sending LE_ARP_REQUEST\n");
-
-        if (sizeoftlvs == 0) frame_size = sizeof(struct ctrl_frame) + lec_params.sizeoftlvs;
-        else frame_size = sizeof(struct ctrl_frame) + sizeoftlvs;
-        frame = (struct ctrl_frame *)buff;
-        memset(frame, 0, frame_size);
-
-        prefill_frame(frame, LE_ARP_REQ);
-        frame->header.lec_id = htons(lec_params.c14_lec_id);
-        frame->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
-        memcpy(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN);
-        memcpy(frame->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-        if (mac_addr != NULL) {
-                frame->target_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
-                memcpy(frame->target_lan_dst.mac, mac_addr, ETH_ALEN);
-        } else diag(COMPONENT, DIAG_DEBUG, "Sending targetless LE_ARP\n");
-
-        if (sizeoftlvs != 0) {
-                if (read(lec_params.kernel->fd, (frame + 1), sizeoftlvs) < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "reading TLVs from kernel failed: %s\n", strerror(errno));
-                        return;
-                }
-                frame->num_tlvs++;
-        } else if (lec_params.sizeoftlvs != 0) {
-                memcpy((frame + 1), lec_params.tlvs, lec_params.sizeoftlvs);
-                frame->num_tlvs += lec_params.num_tlvs;
-        }
-
-        send_frame(lec_params.ctrl_direct, frame, frame_size);
-
-        return;
-}
-
-/* Associate the set of TLVs available in kernel socket
- * with this LEC. The old TLVs, if any, are removed.
- * Also, send a LE_REGISTER_REQUEST to register the TLVs
- * we just got.
- */
-static void associate_tlvs(int sizeoftlvs)
-{
-
-        if (lec_params.tlvs != NULL) free (lec_params.tlvs);
-        lec_params.sizeoftlvs = 0;
-        lec_params.num_tlvs = 0;
-        lec_params.tlvs = malloc(sizeoftlvs);
-        if (lec_params.tlvs == NULL) {
-                diag(COMPONENT, DIAG_ERROR, "Could not associate TLVs, out of memory\n");
-                lec_params.sizeoftlvs = 0;
-                lec_params.num_tlvs = 0;
-                return;
-        }
-        if (read(lec_params.kernel->fd, lec_params.tlvs, sizeoftlvs) < 0) {
-                diag(COMPONENT, DIAG_ERROR, "reading TLVs from kernel failed: %s\n", strerror(errno));
-                return;
-        }
-
-        lec_params.sizeoftlvs = sizeoftlvs;
-        lec_params.num_tlvs = 1; /* FIXME, add TLV count in messages */
-
-        send_register_req();
-
-        return;
-}
-
-/* Send a LE_ARP_RESPONSE for a LAN destination (MAC address) when
- * the LAN destination is present in kernel bridging table and we
- * are acting as a proxy lane client
- */
-static void send_proxy_arp_rsp(unsigned char *target_mac, uint32_t tran_id,
-                               uint16_t lec_id, unsigned char *src_atm_addr)
-{
-        struct ctrl_frame *frame;
-        int frame_size;
-
-        frame_size = sizeof(struct ctrl_frame) + lec_params.sizeoftlvs;
-        frame = malloc(frame_size);
-        if (frame == NULL) return;
-        memset(frame, 0, frame_size);
-        prefill_frame(frame, LE_ARP_RSP);
-        frame->header.tran_id = tran_id;
-        frame->header.lec_id = lec_id;
-        frame->header.flags = htons(REMOTE_ADDRESS);
-        memcpy(frame->target_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
-        frame->target_lan_dst.tag = htons(LAN_DST_MAC_ADDR);
-        memcpy(frame->target_lan_dst.mac, target_mac, ETH_ALEN);
-        memcpy(frame->src_atm_addr, src_atm_addr, ATM_ESA_LEN);
-        frame->num_tlvs = lec_params.num_tlvs;
-        if (lec_params.num_tlvs > 0)
-                memcpy(frame + 1, lec_params.tlvs, lec_params.sizeoftlvs);
-
-        if (send_frame(lec_params.ctrl_direct, frame, frame_size) < 0)
-                diag(COMPONENT, DIAG_ERROR, "send_proxy_arp_rsp: send_frame() failed");
-	free(frame);
-
-        return;
-}
-
-/* 7.1.25 Send a LE_TOPOLOGY_REQUEST */
-static void send_topology_req(int flag)
-{
-        struct ctrl_frame frame;
-
-        prefill_frame(&frame, LE_TOPO_REQ);
-        if (flag) frame.header.flags = htons(TOPO_CHANGE);
-
-        send_frame(lec_params.ctrl_direct, &frame, sizeof(struct ctrl_frame));
-
-        return;
-}
-
-static const char *get_mesg_type_str(atmlec_msg_type type)
-{
-        switch(type) {
-        case l_set_mac_addr:
-                return "SET_MAC_ADDR";
-        case l_del_mac_addr:
-                return "DEL_MAC_ADDR";
-        case l_svc_setup:
-                return "SVC_SETUP";
-        case l_arp_xmt:
-                return "ARP_XMT";
-        case l_addr_delete:
-                return "ADDR_DELETE";
-        case l_topology_change:
-                return "TOPOLOGY_CHANGE";
-        case l_flush_tran_id:
-                return "FLUSH_TRANSACTION_ID";
-        case l_flush_complete:
-                return "FLUSH_COMPLETE";
-        case l_arp_update:
-                return "ARP_UPDATE";
-        case l_config:
-                return "CONFIG";
-        case l_associate_req:
-                return "LANE2_ASSOCIATE_REQ";
-        case l_set_lecid:
-                return "SET_LEC_ID";
-        case l_narp_req:
-                return "LE_NARP_REQUEST";
-        case l_should_bridge:
-                return "SHOULD_BRIDGE";
-        default:
-                return "<Unknown message type>";
-        }
-}
diff -ur --new-file old/atm/led.new/kernel.h new/atm/led.new/kernel.h
--- old/atm/led.new/kernel.h	Sat Feb  6 14:45:20 1999
+++ new/atm/led.new/kernel.h	Thu Jan  1 01:00:00 1970
@@ -1,36 +0,0 @@
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#ifndef KERNEL_H
-#define KERNEL_H
-#include <linux/atmlec.h>
-
-int kernel_init(unsigned char *mac_addr, int itf);
-int msg_to_kernel(struct atmlec_msg *msg, int msg_size);
-int msg_from_kernel(void);
-int read_from_kernel (char *buff, int size);
-
-#endif /* KERNEL_H */
diff -ur --new-file old/atm/led.new/lec.h new/atm/led.new/lec.h
--- old/atm/led.new/lec.h	Sat Feb  6 21:49:04 1999
+++ new/atm/led.new/lec.h	Thu Jan  1 01:00:00 1970
@@ -1,64 +0,0 @@
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-#ifndef LEC_H
-#define LEC_H
-
-#include "conn.h"
-
-/*
- * LANE client configuration and operation values.
- * These are in host byte order since there are
- * some values coming from network and some values
- * which are used by the host only
- */
-struct lec_params {
-        unsigned char c1n_my_atm_addr[ATM_ESA_LEN];
-        uint8_t  c2_lan_type;
-        uint8_t  c3_max_frame_size;
-        int      c4_proxy_flag;
-        char     c5_elan_name[32 + 1];
-        char     c6_mac_addr[ETH_ALEN];
-        int      c7_ctrl_timeout;
-        int      c7i_initial_ctrl_timeout;
-        int      c7x_timeout_multiplier;
-        int      c7c_current_timeout; /* sum of c7i and c7x, LANEv2 5.3.1.7 */
-        unsigned char c9_les_atm_addr[ATM_ESA_LEN];
-        int      c10_max_unknown_frames;
-        int      c11_max_unknown_frame_time;
-        int      c12_vcc_timeout;
-        int      c13_max_retry_count;
-        uint16_t c14_lec_id;
-        int      c17_aging_time;
-        int      c18_forward_delay_time;
-        int      c19_topology_change;
-        int      c20_le_arp_response_time;
-        int      c21_flush_timeout;
-        int      c22_path_switching_delay;
-        /* LANE2 variables follow */
-        int      c29_v2_capable;
-        uint32_t c31_elan_id;
-        unsigned char c35_preferred_les[ATM_ESA_LEN];
-        int      c35_contains_address;
-        int      c37_min_reconfig_delay; /* milliseconds */
-        int      c38_max_reconfig_delay; /* milliseconds */
-
-        /* other stuff */
-        int  itf_num;    /* 1 for lec1 and so forth */
-        int  sizeoftlvs; /* total size of TLVs associated with this LEC */
-        int  num_tlvs;   /* number of the TLVs */
-        unsigned char *tlvs; /* the TLVs */
-        char foreId[255];
-
-        /* connections to and from LES/BUS plus listen sockets */
-        Conn_t *kernel;
-        Conn_t *ctrl_direct;
-        Conn_t *ctrl_listen; /* Closed when join phase is over */
-        Conn_t *ctrl_dist;
-        Conn_t *mcast_send;  /* LANEv2 calls this Default Mcast Send VCC */
-        Conn_t *mcast_listen;
-        Conn_t *data_listen;
-};
-
-extern struct lec_params lec_params;
-
-#endif /* LEC_H */
diff -ur --new-file old/atm/led.new/main.c new/atm/led.new/main.c
--- old/atm/led.new/main.c	Sun Feb  7 12:07:52 1999
+++ new/atm/led.new/main.c	Thu Jan  1 01:00:00 1970
@@ -1,451 +0,0 @@
-/* main.c - Do what ever a LANE client does */
-
-/*
- * Marko Kiiskila carnil@cs.tut.fi 
- * 
- * Copyright (c) 1996
- * Tampere University of Technology - Telecommunications Laboratory
- * All rights reserved.
- *
- * 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.
- * 
- */
-
-/* Copyright (C) 1999 Heikki Vatiainen hessu@cs.tut.fi */
-
-/* Global includes */
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <getopt.h>
-#include <errno.h>
-
-#include <atm.h>
-#include <atmd.h>
-
-#include <linux/atmlec.h>
-
-/* Local incs */
-#include "join.h"
-#include "lec.h"
-#include "address.h"
-#include "display.h"
-#include "kernel.h"
-
-#define COMPONENT "main.c"
-
-static void main_loop(void);
-static int reset = 0;
-
-void sig_reset(int a)
-{
-        reset = 1;  
-
-        return;
-}
-
-static void usage(const char *progname)
-{
-  printf("Usage: %s [-c LECS_address | -s LES_address] [-e esi] [-n VLAN_name]"
-    " [-m mesg_mask] [-l listen_address] [-i interface_number]"
-    " [-t 1516|1580|4544|9234|18190] [-1] [-2] [-p] [-F logfile]"
-    " [-f Fore specific name]\n", progname);
-}
-
-/*
- * My First C function (TM), hessu@cs.tut.fi
- */
-static int esi_convert(char *parsestring, unsigned char *mac_addr)
-{
-        const char *hexchars = "abcdefABCDEF0123456789";
-        char hexnum [17+1], curr;
-        int i = 0, j = -1, hexindex = 0, tmp;
-        char *k, *string;
-        
-        if (strchr(parsestring,'.') ||     /* do we have separators like */
-            strchr(parsestring,':')) {     /* 00:20:22:23:04:05 */
-                k = parsestring;
-                for (i = 0; i < strlen(parsestring); i++) {
-                        curr = *k;
-                        if (curr == ':' || curr == '.') {   /* separator ? */
-                                if (i - j == 3) {  /* there were 2 hex characters */
-                                        ;
-                                }
-                                else if (i - j == 2) {  /* there was only 1 hex char */
-                                        hexnum [hexindex] = hexnum [hexindex-1];
-                                        hexnum [hexindex-1] = '0';
-                                        hexindex +=1;
-                                }
-                                else   /* too many hexchars in a byte */
-                                        return -1;
-                                j = i;  /* j is the location of the last separator */
-                        }
-                        else if (strchr(hexchars, curr) == NULL) /* not a hexchar ? */
-                                return -1;
-                        else {  /* we have a hex character */
-                                hexnum [hexindex] = curr;
-                                hexindex +=1;
-                        }
-                        k++;
-                }
-                hexnum [hexindex] = '\0';
-                string = hexnum;
-        } else {   /* no separators */
-                k = parsestring;
-                while (*k != '\0') {
-                        if (strchr(hexchars, *k) == NULL)
-                                return -1;
-                        k++;
-                }
-                
-                string = parsestring;
-        }
-        
-        /* the esi now looks like 002022230405 */
-        i = strlen(string);
-        if (i != 12)
-                return -1;
-        for(i=0; i<6; i++) {
-                sscanf(&string[i*2], "%2x", &tmp);
-                mac_addr[i] = (unsigned char)tmp;
-        }
-        return 0;
-}
-
-/* Tells kernel what our LEC_ID is.
- * Returns < 0 for serisous error
- */
-static int set_lec_id(uint16_t lec_id)
-{
-        struct atmlec_msg msg;
-
-        memset(&msg, 0, sizeof(struct atmlec_msg));
-        msg.type = l_set_lecid;
-        msg.content.normal.flag = lec_id;
-        if (msg_to_kernel(&msg, sizeof(struct atmlec_msg)) < 0) {
-                diag(COMPONENT, DIAG_ERROR, "Could not tell kernel LEC_ID\n");
-                return -1;
-        }
-
-        return 0;
-}
-
-/* Tell kernel the parameters this ELAN has.
- * Returns < 0 for serious error
- */
-static int config_kernel(void)
-{
-        struct atmlec_msg msg;
-
-        memset(&msg, 0, sizeof(struct atmlec_msg));
-        msg.type = l_config;
-        msg.content.config.maximum_unknown_frame_count = lec_params.c10_max_unknown_frames;
-        msg.content.config.max_unknown_frame_time = lec_params.c11_max_unknown_frame_time;
-        msg.content.config.max_retry_count = lec_params.c13_max_retry_count;
-        msg.content.config.aging_time = lec_params.c17_aging_time;
-        msg.content.config.forward_delay_time = lec_params.c18_forward_delay_time;
-        msg.content.config.arp_response_time = lec_params.c20_le_arp_response_time;
-        msg.content.config.flush_timeout = lec_params.c21_flush_timeout;
-        msg.content.config.path_switching_delay = lec_params.c22_path_switching_delay;
-        msg.content.config.lane_version = (lec_params.c29_v2_capable) ? 2 : 1;
-
-        if (msg_to_kernel(&msg, sizeof(struct atmlec_msg)) < 0) {
-                diag(COMPONENT, DIAG_ERROR, "Could not tell kernel ELAN parameters\n");
-                return -1;
-        }
-
-        return 0;
-}
-
-int main(int argc, char **argv)
-{
-        char mac_addr[ETH_ALEN];
-        char elan_name[32 + 1];
-        char preferred_les[ATM_ESA_LEN]; /* LANE2 */
-        char foreId[255]; /* Max size for a TLV */
-        char atm2textbuff[100];
-        char esibuff[20];
-        int esi_set = 0;
-        int atm_set=0;
-        int proxy_flag = 0;
-        int lane_version = 0;              /* LANE2 */
-        int max_frame_size = MTU_UNSPEC;
-        int lecs_method = LECS_WELLKNOWN;
-        int poll_ret = 0, itf = 0;
-        struct sockaddr_atmsvc manual_atm_addr;
-        struct sockaddr_atmsvc listen_addr;
-        
-        memset(elan_name, '\0', sizeof(elan_name));
-        memset(foreId, '\0', sizeof(foreId));
-        memset(preferred_les, 0, ATM_ESA_LEN);
-        memset(&manual_atm_addr, 0, sizeof(struct sockaddr_atmsvc));
-        memset(&listen_addr, 0, sizeof(struct sockaddr_atmsvc));
-
-        set_application("zeppelin"); /* for debug msgs */
-
-        if (get_listenaddr(listen_addr.sas_addr.prv) < 0) {
-                diag(COMPONENT, DIAG_FATAL, "Could not figure out my ATM address\n");
-                exit(-1);
-        }
-
-        while(poll_ret != -1) {
-                poll_ret = getopt(argc, argv, "c:e:n:s:m:l:i:q:12pf:t:F:");
-                switch(poll_ret) {
-                case 'c':
-                        if (atm_set) {
-                                usage(argv[0]);
-                                exit(-1);
-                        }
-                        if (text2atm(optarg, (struct sockaddr *)&manual_atm_addr,
-                                     sizeof(struct sockaddr_atmsvc), T2A_NAME) < 0) {
-                                diag(COMPONENT, DIAG_ERROR, "Invalid LECS address\n");
-                                usage(argv[0]);
-                                exit(-1);
-                        }
-                        atm2text(atm2textbuff, sizeof(atm2textbuff),
-                                 (struct sockaddr *)&manual_atm_addr, 0);
-                        diag(COMPONENT, DIAG_INFO, "LECS address: %s\n", atm2textbuff);
-                        lecs_method = LECS_MANUAL;
-                        atm_set=1;
-                        break;
-                case 'e':
-                        if(esi_convert(optarg, mac_addr)<0) {
-                                diag(COMPONENT, DIAG_ERROR, "Invalid ESI format\n");
-                                usage(argv[0]);
-                                exit(-1);
-                        }
-                        mac2text(esibuff, mac_addr);
-                        diag(COMPONENT, DIAG_DEBUG, "LEC ESI:%s\n", esibuff);
-                        esi_set=1;
-                        break;
-                case 'n':
-                        if (strlen(optarg) > 32) {
-                                diag(COMPONENT, DIAG_ERROR, "ELAN name too long\n");
-                                exit(-1);
-                        }
-                        strcpy(elan_name, optarg);
-                        diag(COMPONENT, DIAG_INFO, "Vlan name :'%s'\n", elan_name);
-                        break;
-                case 's':
-                        if (atm_set) {
-                                usage(argv[0]);
-                                exit(-1);
-                        }
-                        if (text2atm(optarg, (struct sockaddr *)&manual_atm_addr,
-                                     sizeof(struct sockaddr_atmsvc), T2A_NAME) < 0) {
-                                diag(COMPONENT, DIAG_ERROR, "Invalid LES address\n");
-                                usage(argv[0]);
-                                exit(-1);
-                        }
-                        atm2text(atm2textbuff, sizeof(atm2textbuff),
-                                 (struct sockaddr *)&manual_atm_addr, 0);
-                        diag(COMPONENT, DIAG_INFO, "LES address: %s\n", atm2textbuff);
-                        lecs_method = LECS_NONE;
-                        atm_set=1;
-                        break;
-                case 'm':
-                        set_verbosity(NULL, DIAG_DEBUG);
-                        break;
-                case 'l':
-                        if (text2atm(optarg, (struct sockaddr *)&listen_addr,
-                                     sizeof(struct sockaddr_atmsvc), T2A_NAME) < 0) {
-                                diag(COMPONENT, DIAG_ERROR, "Invalid ATM listen address\n");
-                                usage(argv[0]);
-                                exit(-1);
-                        }
-                        atm2text(atm2textbuff, sizeof(atm2textbuff),
-                                 (struct sockaddr *)&listen_addr, 0);
-                        diag(COMPONENT, DIAG_INFO, "Our ATM address: %s\n", atm2textbuff);
-                        break;
-                case 'i':
-                        if (sscanf(optarg, "%d", &itf) < 0 || itf >= MAX_LEC_ITF) {
-                                diag(COMPONENT, DIAG_ERROR, "Invalid interface number\n");
-                                usage(argv[0]);
-                                exit(-1);
-                        }
-                        diag(COMPONENT, DIAG_INFO, "Interface number set to %d\n", itf);
-                        break;
-                case 'q':
-#if 0
-                        if (text2qos(optarg,NULL,0) < 0) {
-                                diag(COMPONENT, DIAG_ERROR, "Invalid QOS specification\n");
-                                usage(argv[0]);
-                                exit(-1);
-                        }
-                        qos_spec = optarg;
-#endif
-                        diag(COMPONENT, DIAG_INFO, "-q is deprecated, ignoring it\n");
-                        break;
-                case '1':
-                        lane_version = 1;
-                        break;
-                case '2':
-                        lane_version = 2;
-                        break;
-                case 'p':
-                        proxy_flag = 1;
-                        break;
-                case 'f':
-                        if (strlen(optarg) > 255) {
-                                diag(COMPONENT, DIAG_ERROR, "foreId too long\n");
-                                exit(-1);
-                        }
-                        memcpy (foreId, optarg, strlen(optarg));
-                        foreId[strlen(optarg)] = '\0';
-                        diag(COMPONENT, DIAG_INFO, "foreId :'%s'\n", foreId);
-                        break;
-                case 't':	/* ERIC */
-                        if( !strncmp( optarg, "1516", 4 )) max_frame_size = MTU_1516;
-                        else if( !strncmp( optarg, "1580", 4 )) max_frame_size = MTU_1580;
-                        else if( !strncmp( optarg, "4544", 4 )) max_frame_size = MTU_4544;
-                        else if( !strncmp( optarg, "9234", 4 )) max_frame_size = MTU_9234;
-                        else if( !strncmp( optarg, "18190", 5 )) max_frame_size = MTU_18190;
-                        break;
-                case 'F':
-                        set_logfile(optarg);
-                        diag(COMPONENT, DIAG_DEBUG, "logfile set to %s\n", optarg);
-                        break;
-                case -1:
-                        break;
-                default:
-                        usage(argv[0]);
-                        exit(-1);
-                }
-        }
-        if (argc != optind) {
-                usage(argv[0]);
-                exit(1);
-        }
-        if (lane_version == 1 && max_frame_size == MTU_1580) {
-                diag(COMPONENT, DIAG_ERROR, "MTU 1580 not defined with LANEv1\n");
-                exit(-1);
-        }
-
-        /* Reserve signals */
-        signal(SIGHUP, sig_reset);
-
-        if (!esi_set) {
-                if(addr_getesi(mac_addr) < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "Can't get ESI from kernel!\n");
-                        return -1;
-                }
-                mac2text(esibuff, mac_addr);
-                diag(COMPONENT, DIAG_DEBUG, "LEC ESI:%s\n", esibuff);
-        }
-
-        /* Loop here until the Sun gets cold */
-        while (1) {
-                if ((itf = kernel_init(mac_addr, itf)) < 0 ) {
-                        diag(COMPONENT, DIAG_FATAL, "Kernel interface creation failed, exiting...\n");
-                        return -1;
-                } 
-
-                diag(COMPONENT, DIAG_DEBUG, "initializing lec parameters\n");
-                init_lec_params(mac_addr, elan_name, listen_addr.sas_addr.prv,
-                                itf, foreId, max_frame_size, proxy_flag, lane_version);
-
-                diag(COMPONENT, DIAG_DEBUG, "About to connect LECS\n");
-                if (lec_configure(lecs_method, &manual_atm_addr, &listen_addr) < 0) {
-                        close_connections();
-                        random_delay();
-                        continue;
-                }
-                diag(COMPONENT, DIAG_DEBUG, "About to connect LES\n");
-                if (les_connect(lecs_method, &manual_atm_addr, &listen_addr) < 0) {
-                        close_connections();
-                        random_delay();
-                        continue;
-                }
-                diag(COMPONENT, DIAG_DEBUG, "About to connect BUS\n");
-                if (bus_connect() < 0) {
-                        close_connections();
-                        random_delay();
-                        continue;
-                }
-                diag(COMPONENT, DIAG_DEBUG, "About to create data direct listen socket\n");
-                if (create_data_listen() < 0) {
-                        close_connections();
-                        random_delay();
-                        continue;
-                }
-                diag(COMPONENT, DIAG_DEBUG, "About to tell kernel our LEC_ID %d\n", lec_params.c14_lec_id);
-                if (set_lec_id(lec_params.c14_lec_id) < 0) {
-                        close_connections();
-                        continue;
-                }
-                diag(COMPONENT, DIAG_DEBUG, "About to tell kernel LEC parameters\n");
-                if (config_kernel() < 0) {
-                        close_connections();
-                        continue;
-                }
-
-                diag(COMPONENT, DIAG_DEBUG, "Joined ELAN '%s' successfully\n", lec_params.c5_elan_name);
-
-                main_loop();
-                diag(COMPONENT, DIAG_INFO, "Resetting...\n");
-                close_connections();
-                random_delay();
-
-                reset = 0;
-        }
-
-        return 0; /* not reached */
-}
-
-/* zeppelin loops here when it is in operational state.  The check
- * against reset variable is probably not needed since select() will
- * return < 0 when a signal interrupts it.
- */
-static void main_loop(void)
-{
-        fd_set rfds, cfds;
-        int retval, ret1, ret2, ret3;
-
-        while(!reset) {
-                retval = ret1 = ret2 = ret3 = 0;
-                FD_ZERO(&rfds);
-                conn_get_fds(&rfds);
-                FD_ZERO(&cfds);
-                conn_get_connecting_fds(&cfds);
-
-                retval = select(FD_SETSIZE, &rfds, &cfds, NULL, NULL);
-                diag(COMPONENT, DIAG_DEBUG, "main_loop: select returned %d\n", retval);
-                if (retval < 0) {
-                        diag(COMPONENT, DIAG_ERROR, "main_loop: select: %s\n", strerror(errno));
-                        break; /* leave main_loop */
-                }
-                if (retval == 0) {
-                        /* Timeout, funny, since we have no timers */
-                        continue;
-                }
-                if (FD_ISSET(lec_params.kernel->fd, &rfds)) {
-                        ret1 = msg_from_kernel();
-                        FD_CLR(lec_params.kernel->fd, &rfds);
-                }
-                ret2 = complete_connections(&cfds);
-                ret3 = check_connections(&rfds);
-                
-                if (ret1 < 0 || ret2 < 0 || ret3 < 0)
-                        break; /* leave main_loop */
-        }
-        
-        diag(COMPONENT, DIAG_DEBUG, "exiting main_loop\n");
-
-        return;
-}
diff -ur --new-file old/atm/led.new/zeppelin.new.8 new/atm/led.new/zeppelin.new.8
--- old/atm/led.new/zeppelin.new.8	Sat Feb  6 23:48:20 1999
+++ new/atm/led.new/zeppelin.new.8	Thu Jan  1 01:00:00 1970
@@ -1,91 +0,0 @@
-.TH zeppelin 8 "Feb 6, 1999" "Linux" "Maintenance Commands"
-.SH NAME
-zeppelin \- ATM LAN Emulation client demon (LED) Zeppelin
-.SH SYNOPSIS
-.B zeppelin
-.RB [ \-c\ \fILECS_address\fP\ |\ \-s\ \fILES_address\fP ]
-.RB [ \-e\ \fIesi\fP ]
-.RB [ \-n\ \fIVLAN_name\fP ]
-.RB [ \-m\ \fImesg_mask\fP ]
-.RB [ \-l\ \fIlisten_address\fP ]
-.RB [ \-i\ \fIinterface_number\fP ]
-.RB [ \-t\ \fI1516|1580|4544|9234|18190\fP ]
-.RB [ \-1\ ]
-.RB [ \-2\ ]
-.RB [ \-p\ ]
-.RB [ \-F\ \fIlogfile\fP ]
-.RB [ \-f\ \fIFore_specific_name\fP ]
-.SH DESCRIPTION
-A LAN Emulation Client is an entity in an ATM endstation that performs 
-data forwarding, address resolution and other control functions. It 
-uses the LUNI interface when communicating with other components in 
-emulated LANs. It provides upper protocol layers a MAC like 
-interface similar to IEEE 802.3/Ethernet or IEEE 802.5/Token Ring LAN.
-.PP
-LAN Emulation client code is divided into two parts: user space 
-application LAN Emulation Demon called (LED) \fBzeppelin(8)\fP, and the 
-kernel component. \fBZeppelin\fP is responsible for control operations needed 
-in LAN Emulation clienthood. It forms the necessary VCCs and receives 
-all the LE control frames and acts accordingly. It also controls the 
-operation of the LEC kernel component.
-.PP
-Linux LEC supports only Ethernet type of emulated LAN.
-.PP
-\fBSIGHUP\fP causes restart of the LEC. All resources are 
-released and \fBzeppelin\fP is started. 
-.SH OPTIONS
-.IP \fB\-c\ \fILECS_address\fP
-ATM address of \fBlecs(8)\fP (Lan Emulation Configuration Server), if not
-set, Well-Known server address is used.
-.IP \fB\-s\ \fILES_address\fP
-ATM address of \fBles(8)\fP (Lan Emulation Server), can be used in
-bypassing configuration phase in joining emulated Lan i.e \fBlecs\fP address
-is not used. 
-.IP \fB\-e\ \fIesi\fP
-Mac address to use when communicating in Emulated LAN. E.g. 00:20:22:23:04:05 .
-.IP \fB\-n\ \fIVLAN_name\fP
-Name of the virtual LAN to which joining is requested.
-This is used in LE_CONFIGURE_REQUEST to LECS or
-LE_JOIN_RESPONSE to LES, if configuration phase is bypassed.
-.IP \fB\-m\ \fImesg_mask\fP
-Sometimes one wants to know more what is happening in LE
-daemon e.g. when nothing works. This is a hexadecimal long value
-setting global message mask. 0 = No messages, ffff = All messages.
-.IP \fB\-l\ \fIlisten_address\fP
-Local ATM address that zeppelin uses as local binding point in
-signalling. Use this if you are running more than one client or
-a set of LE servers.
-.IP \fB\-i\ \fIinterface_number\fP
-Linux LEC supports up to 16 network interfaces. This number tells
-zeppelin to which of these to attach. Network interfaces are
-numbered from "lec0" to "lec15".
-.IP \fB\-t\ \fIMTU\fP
-The MTU of ELAN to join. You need to also use \fBifconfig(8)\fP to
-set the MTU of the LANE interface.
-.IP \fB\-1\fP
-Run as LANEv1 client. This is the default.
-.IP \fB\-2\fP
-Run as LANEv2 client. This is required by MPOA.
-.IP \fB\-p\fP
-Enable proxy. When started with this option, it is possible to bridge
-packets between ATM and Ethernet. That is, you can use LANE interfaces
-with normal bridging. See the Bridging mini-Howto for more info.
-.IP \fB\-F\ \fIlogfile\fP
-Instead of writing debug messages to \fBstderr\fP, write the messages
-to the file \fBlogfile\fP. Use \fBsyslog\fP as the file name to use
-the \fBsyslog(3)\fP facility.
-.IP \fB\-f\ \fIFore\ specific\ name\fP
-The LANE servers on Fore ATM switches can display a special
-name if a client can supply one. This name shows with command
-\'conf lane les show advanced\'.
-.SH BUGS
-Supports only IEEE 802.3 / Ethernet type of ELANs. Please report any
-new bugs to Heikki Vatiainen <hessu@cs.tut.fi>
-.PP
-John Bonham died 1980 and Led Zeppelin broke.
-.SH AUTHORS
-Marko Kiiskila, TUT <carnil@cs.tut.fi> and Heikki Vatiainen, TUT
-<hessu@cs.tut.fi>
-.SH "SEE ALSO"
-lecs(8), mpcd(8), atmsigd(8), les(8), qos(7)
-.\"{{{}}}
diff -ur --new-file old/atm/mkdist new/atm/mkdist
--- old/atm/mkdist	Tue May 18 00:39:37 1999
+++ new/atm/mkdist	Wed Jun  2 23:39:38 1999
@@ -82,25 +82,12 @@
     atm/lib/sap2text.c atm/lib/text2sap.c atm/lib/sapequal.c atm/lib/misc.c \
     atm/lib/atmres.h atm/lib/ans.c atm/lib/rtf2e164_cc.pl \
     atm/lib/stdint.h atm/lib/unix.c atm/lib/text2ip.c \
-  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/le_disp.h atm/led/g_event.h \
-    atm/led/addr_reg.h atm/led/af_lane.h atm/led/lane_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/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/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/lane2.h \
-    atm/led/Makefile atm/led/zeppelin.8 \
-  atm/led.new/COPYRIGHT.TUT atm/led.new/Makefile \
-    atm/led.new/address.c atm/led.new/address.h atm/led.new/conn.c \
-    atm/led.new/conn.h atm/led.new/display.c atm/led.new/display.h \
-    atm/led.new/frame_defs.h atm/led.new/frames.c atm/led.new/frames.h \
-    atm/led.new/join.c atm/led.new/join.h atm/led.new/kernel.c \
-    atm/led.new/kernel.h atm/led.new/lec.h atm/led.new/main.c \
-    atm/led.new/zeppelin.new.8 \
+  atm/led/COPYRIGHT.TUT atm/led/Makefile \
+    atm/led/address.c atm/led/address.h atm/led/conn.c atm/led/conn.h \
+    atm/led/display.c atm/led/display.h atm/led/frame_defs.h \
+    atm/led/frames.c atm/led/frames.h atm/led/join.c atm/led/join.h \
+    atm/led/kernel.c atm/led/kernel.h atm/led/lec.h atm/led/main.c \
+    atm/led/zeppelin.8 \
   atm/lane/COPYRIGHT.TUT atm/lane/Makefile atm/lane/USAGE \
     atm/lane/bus.8 atm/lane/lecs.8 atm/lane/les.8 \
     atm/lane/atm.c \
diff -ur --new-file old/atm/mkpatch new/atm/mkpatch
--- old/atm/mkpatch	Tue May 18 01:29:42 1999
+++ new/atm/mkpatch	Thu Jun  3 00:31:03 1999
@@ -12,6 +12,8 @@
 arch/i386/config.in
 #--- arch/alpha ---------------------------------------------------------------
 arch/alpha/config.in
+#--- arch/sparc ---------------------------------------------------------------
+arch/sparc/config.in
 #--- drivers ------------------------------------------------------------------
 drivers/Makefile
 #--- drivers/atm --------------------------------------------------------------
@@ -84,6 +86,8 @@
 net/sched/Makefile
 net/sched/sch_api.c
 net/sched/sch_atm.c
+#--- net/802 ------------------------------------------------------------------
+net/802/tr.c
 #--- net/atm ------------------------------------------------------------------
 net/atm/Makefile
 net/atm/addr.c