diff -ur --new-file old/atm/BUGS new/atm/BUGS
--- old/atm/BUGS	Fri Feb 19 16:40:02 1999
+++ new/atm/BUGS	Thu Apr 22 17:37:54 1999
@@ -1,6 +1,7 @@
-Known bugs and restrictions in version 0.54
+Known bugs and restrictions in version 0.56
 ===========================================
 
+ - some recently discovered message sequences crash ilmid
  - ENI driver: closing an AAL0 socket while data is arriving at a high rate
    hangs in the close system call
  - mpcd: adds an MPOA Egress Cache Tag Extension in the MPOA Cache Imposition
@@ -9,7 +10,6 @@
  - ENI driver loses synchronization on some systems, leading to panics or hung
    VCs (these may be two distinct problems)
  - few if any drivers build properly as modules
- - CLIP interfaces must not be reconfigured while "up"
  - swc show  only displays manually configured VCs
  - invoking a queuing discipline that overwrites skb->cb from within sch_atm
    will yield unpredictable results if CONFIG_ATM_SKB is enabled
diff -ur --new-file old/atm/CHANGES new/atm/CHANGES
--- old/atm/CHANGES	Mon Mar  1 16:07:19 1999
+++ new/atm/CHANGES	Thu Apr 22 19:56:37 1999
@@ -1,3 +1,70 @@
+Version 0.55 to 0.56 (22-APR-1999)
+====================
+
+Bug fixes
+---------
+
+ - atm/doc/Makefile assumed . to be included in PATH when invoking rlatex
+   (fix by Heikki Vatiainen)
+ - usage.txt leaked Arequipa configuration examples (fix by Heikki Vatiainen)
+ - plugged a small memory leak in led.new which occurred when using the LANE
+   client as a proxy (Heikki Vatiainen)
+ - atmarpd crashed when printing ATMARP table entries with flag 0x8000 set
+   (reported by Vinay Kulkarni)
+ - CLIP interfaces now follow netmask changes
+ - Nicstar: 25.6 Mbps cell rate corrected (by Rui Prior)
+ - atm_equal could loop forever when comparing NSAP-encoded E.164 addresses
+   (reported by Valley Zhizhkun)
+ - [AP]F_ATM[PS]VC definitions in lib/atm.h conflicted with glibc 2.1
+   (reported by Heikki Vatiainen and Jens Vagelpohl)
+ - changed a few  non-int main  to  int main  (reported by Heikki Vatiainen)
+ - changed lib/diag.c work with glibc 2.1, where stderr is no longer a constant
+   (based on a patch by Heikki Vatiainen, also reported by Giuliano Procida)
+ - make clean didn't remove qgen/q.test.c, qgen/qd.out.h, qgen/qd.test.c,
+   sigd/q.out.h and sigd.old/q.out.h (reported by Giuliano Procida)
+ - optional headers were installed even with system headers present if
+   INSTROOT was different from / (reported by Giuliano Procida)
+ - lib/stdint.h was used even on systems that had a "real" stdlib.h (based on a
+   patch by Heikki Vatiainen, also reported by Giuliano Procida)
+ - renamed net/atm/misc.c to atm_misc.c to avoid name clash with
+   drivers/char/misc.c on include/linux/modules/misc.* (reported by Borek
+   Lupomesky)
+  
+New features
+------------
+
+ - new ioctl ATM_GETLINKRATE to query link rate of an interface (suggested by
+   Vitaly Lavrov)
+ - new atmsigd.conf option  io max_rate  to specify rate to signal if
+   application requests the "maximum"
+ - added decription of CONFIG_ATM_LANE and CONFIG_ATM_MPOA to the kernel
+   configuration help (Heikki Vatiainen)
+ - added description of LANE to usage.tex (Heikki Vatiainen)
+ - new function atm_force_charge to unconditionally add data to a receive
+   buffer
+
+Other changes
+-------------
+
+ - atmsigd now determines maximum link rate by querying interfaces (suggested
+   by Vitaly Lavrov)
+ - moved local address registry from a global table to VPCI structures
+ - changed unknown net device notification severity from KERN_ERR to
+   KERN_WARNING
+ - atmarpd now overwrites old atmarpd.table on startup (it used to keep it
+   until the first configuration change)
+ - shutdown(2) of native ATM VCs now returns 0 instead of -EOPNOTSUPP
+   (suggested by Mitchell Blank)
+ - Nicstar: IRQ sharing is now allowed (by Rui Prior)
+ - Nicstar: default maximum number of cards is now 4 (by Rui Prior)
+ - Nicstar: when compiled as a module, the driver may no longer be removed
+   while in use (by Rui Prior)
+ - Nicstar: loss of cells is no longer reported as a plain CRC error (by Rui
+   Prior)
+ - atmsigd now always clears the endpoint reference flag if in UNI 3.0 mode
+   (based on a patch by Heikki Vatiainen)
+
+
 Version 0.54 to 0.55 (1-MAR-1999)
 ====================
 
diff -ur --new-file old/atm/README new/atm/README
--- old/atm/README	Mon Mar  1 15:57:59 1999
+++ new/atm/README	Thu Apr 22 17:38:31 1999
@@ -1,4 +1,4 @@
-ATM on Linux, release 0.55 (alpha)        by Werner Almesberger, EPFL ICA
+ATM on Linux, release 0.56 (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/Rules.make new/atm/Rules.make
--- old/atm/Rules.make	Tue Jan  5 20:34:26 1999
+++ new/atm/Rules.make	Thu Apr 22 17:19:45 1999
@@ -128,7 +128,7 @@
 		@process() { if [ ! -z "$$3" ]; then mode=$$1; dir=$$2; \
 		  shift 2; echo "install -c -m $$mode $$* $$dir"; \
 		  install -c -m $$mode $$* $$dir || exit 1; fi; }; \
-		  optprocess() { [ -z "$$3" -o -r "$$2/$$3" ] || \
+		  optprocess() { [ -z "$$3" -o -r "/usr/include/$$3" ] || \
 		  process $$*; }; \
 		  $(PROCLIST)
 		@for n in "" $(SUBDIRS); do [ -z "$$n" ] || \
diff -ur --new-file old/atm/USAGE new/atm/USAGE
--- old/atm/USAGE	Mon Mar  1 16:09:07 1999
+++ new/atm/USAGE	Thu Apr 22 20:02:00 1999
@@ -1,4 +1,4 @@
-Usage instructions  -  ATM on Linux, release 0.55
+Usage instructions  -  ATM on Linux, release 0.56
 -------------------------------------------------
 
 For updates of ATM on Linux, please check the Web page at  
@@ -17,7 +17,7 @@
 In order to install this package, you need 
 
   - the package itself  
-    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.55.tar.gz  
+    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.56.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 
@@ -33,7 +33,7 @@
 all the files listed above there. Then extract the ATM on Linux 
 distribution:
 
-tar xfz atm-0.55.tar.gz
+tar xfz atm-0.56.tar.gz
 
 and the kernel source:
 
@@ -701,7 +701,8 @@
 ===========
 
 IP over ATM is supported with Classical IP over ATM (CLIP, defined in 
-RFC1577 [2]), and LAN Emulation.
+RFC1577 [2]), LAN Emulation (LANE, defined in [3] and [4]) and 
+Multi-Protocol Over ATM (MPOA, client only, defined in [5]).
 
 
 CLIP
@@ -777,18 +778,142 @@
 
 Besides Classical IP over ATM, LAN Emulation (LANE) can be used to carry IP 
 over ATM. LANE emulates the characteristics of legacy LAN technology, such 
-as support for broadcasts. LANE client support is described in the file 
-atm/led/USAGE, LANE server support is described in atm/lane/USAGE.
+as support for broadcasts. LANE server support is described in 
+atm/lane/USAGE.
 
 Man pages: bus.8, lecs.8, les.8, and zeppelin.8
 
-%# arequipad -b
-%# ttcp_atm -r -s -Q dummy
-%
-
-%# arequipad -b
-%# ttcp_atm -t -s -Q b-atm b
-%
+If you plan to run more than one LANE clients, LANE service or LANE clients 
+and LANE service, you need to specify different local ATM addresses for 
+each demon. Since all the LANE demons use similar service access points 
+(SAPs) they need different ATM addresses to differentiate between 
+connections.
+
+Just as with CLIP, the LANE client consists of two parts: a demon process 
+called zeppelin which takes care of the LANE protocol and kernel part which 
+contains LANE ARP cache.
+
+atmsigd and ilmid must already be running when zeppelin is started. When 
+zeppelin starts, the kernel creates a new interface which can then be 
+configured:
+
+  # zeppelin <possibly_more_options> &
+     # ifconfig lec0 <local_address> <possibly_more_options> up
+      
+
+In the example below, two LANE clients are started. The first client uses 
+default interface  lec0 , default listen address and tries to join the 
+default ELAN. The other LANE client gets interface  lec2  assigned to it, 
+binds to local address  mybox3 , tries to join ELAN called  myelan  and 
+will bridge packets between ELAN and Ethernet segments. Address  mybox3  is 
+defined in /etc/hosts.atm. Rest of the bridging can be configured by 
+reading the Bridging mini-HOWTO. [6]
+
+# zeppelin &
+# ifconfig lec0 10.1.1.42 netmask 255.255.255.0 \
+                          broadcast 10.1.1.255 up
+#
+# zeppelin -i 2 -l mybox3 -n myelan -p &
+# ifconfig lec2 10.1.2.42 netmask 255.255.255.0 \
+                          broadcast 10.1.2.255 up
+
+By default, zeppelin uses interface  lec0 , binds to local ATM address 
+using selector byte value 0, tries to contact LECS using Well-Known LECS 
+address, joins the default ELAN as defined by the LECS, accepts the MTU 
+size as defined by the LES and will not act as an proxy LEC. These 
+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.
+
+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 
+listed. If the entry has an active connection, the connection identifiers 
+are also listed.
+
+The LANE service (lecs.8, les.8 and bus.8) is configured using 
+configuration files. The configuration file syntax is listed on the 
+respective manual pages.
+
+A more detailed description of Linux LANE services is discussed in Marko 
+Kiiskilae's Master's Thesis. [7]
+
+
+MPOA
+----
+
+The Linux MPOA client continues the tradition of user space - kernel 
+divided ATM services. The demon process called mpcd processes MPOA control 
+packets while the kernel holds MPOA ingress and egress caches and does the 
+packet forwarding.
+
+Man page: mpcd.8
+
+atmsigd and ilmid must already be running when mpcd is started. Since MPOA 
+detects IP layer flows from LANE traffic, you need to have zeppelin running 
+before MPOA can function. However, the order in which zeppelin and mpcd is 
+started is not fixed. You can kill any of the demons at your will and 
+restart it later without need to restart the other demon. The easiest way 
+to disable MPOA is to kill the running mpcd.
+
+Below is the example from Section "LAN Emulation" which starts two LANE 
+clients. The configuration has been augmented with two MPOA clients which 
+the LANE clients will serve.
+
+# zeppelin &
+# ifconfig lec0 10.1.1.42 netmask 255.255.255.0 \
+                          broadcast 10.1.1.255 up
+# mpcd -s mybox1 -l mybox2 &
+#
+# zeppelin -i 2 -l mybox3 -n myelan -p &
+# ifconfig lec2 10.1.2.42 netmask 255.255.255.0 \
+                          broadcast 10.1.2.255 up
+# mpcd -i 2 -s mybox4 -l mybox5 &
+
+The MPOA demon needs two different local ATM addresses which it uses when 
+initiating and receiving data and control connections. The addresses can be 
+the same as with e.g. zeppelin but must be different among other mpcd 
+demons. By default, mpcd does not retrieve configuration information from 
+the LECS. The necessary command line options and an example of using LECS 
+are shown on the mpcd manual page. The manual page also lists the rest of 
+the available options.
+
+The contents of MPOA ingress and egress caches can be monitored through 
+/proc/atm/mpc file.
+
+The Linux MPOA client also supports CBR traffic class for shortcuts SVCs 
+instead of default UBR. The QoS specifications for future shortcuts can be 
+set and modified using /proc/atm/mpc.
+
+# echo add 130.230.54.146 tx=80000,1600 rx=tx > /proc/atm/mpc
+#             # generate enough traffic to trigger a shortcut
+# cat /proc/atm/mpc 
+QoS entries for shortcuts:
+IP address
+  TX:max_pcr pcr     min_pcr max_cdv max_sdu
+  RX:max_pcr pcr     min_pcr max_cdv max_sdu
+130.230.54.146  
+     80000   0       0       0       1600   
+     80000   0       0       0       1600   
+
+Interface 2:
+
+Ingress Entries:
+IP address      State     Holding time  Packets fwded  VPI VCI
+130.230.4.3     invalid   1160          0           
+130.230.54.146  resolved  542           151            0   109
+...
+
+The shortcut to IP address  130.230.54.146  was established with the 
+parameters shown above. There also exist patches which extend the flow 
+detection to fully support layer 4 flows. The layer 4 flows are expressed 
+as a 5 tuple (proto, local addr, local port, remote addr, remote port) and 
+they identify application to application flows. If you are interested, see  
+ftp://sunsite.tut.fi/pub/Local/linux-atm/mpoa/  for the latest patch.
 
 
 References
@@ -798,3 +923,11 @@
     ftp://lrcftp.epfl.ch/pub/linux/atm/api/ , July 1996. 
   [2]  Laubach, Mark.  Classical IP and ARP over ATM, RFC1577, January 
     1994. 
+  [6]  Cole, Christopher.  Bridging mini-Howto,  
+    http://metalab.unc.edu/LDP/HOWTO/mini/Bridge.html , September 1998. 
+  [7]  Kiiskilae, Marko.  Implementation of LAN Emulation Over ATM in 
+    Linux,  ftp://sunsite.tut.fi/pub/Local/linux-atm/misc/ , October 1996. 
+  [3]  ATM Forum.  LAN Emulation Over ATM - Version 1.0, February 1996. 
+  [4]  ATM Forum.  LAN Emulation Over ATM - Version 2 - LUNI Specification, 
+    July 1997. 
+  [5]  ATM Forum.  Multi-Protocol Over ATM - Version 1.0, July 1997. 
diff -ur --new-file old/atm/VERSION new/atm/VERSION
--- old/atm/VERSION	Mon Mar  1 16:42:59 1999
+++ new/atm/VERSION	Thu Apr 22 17:38:19 1999
@@ -1 +1 @@
-0.55
+0.56
diff -ur --new-file old/atm/arpd/atmarpd.c new/atm/arpd/atmarpd.c
--- old/atm/arpd/atmarpd.c	Thu Oct  1 19:43:13 1998
+++ new/atm/arpd/atmarpd.c	Wed Apr 21 16:47:24 1999
@@ -94,6 +94,7 @@
 	    exit(0);
 	}
     }
+    (void) table_update(); /* erase old table, if any */
     poll_loop();
     close_all();
     return 0;
diff -ur --new-file old/atm/arpd/table.c new/atm/arpd/table.c
--- old/atm/arpd/table.c	Tue Jul 28 16:19:02 1998
+++ new/atm/arpd/table.c	Mon Apr 12 14:53:32 1999
@@ -1,6 +1,6 @@
 /* table.c - ATMARP table */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */
  
 
 #include <stdio.h>
@@ -147,7 +147,7 @@
 	"???",	"com", "PERM", "PUBL",			/* 0x0001-0x0008 */
 	"trailers", "netmask", "dontpub", "magic",	/* 0x0010-0x0080 */
 	"???", "???", "???", "???",			/* 0x0100-0x0800 */
-	"NULL", "ARPSRV", "NOVC" };			/* 0x1000-0x8000 */
+	"NULL", "ARPSRV", "NOVC", "???" };		/* 0x1000-0x8000 */
     /* lower case flags are not used by ATMARP */
     ENTRY *entry;
     char addr_buf[MAX_ATM_ADDR_LEN+1];
diff -ur --new-file old/atm/atm.patch new/atm/atm.patch
--- old/atm/atm.patch	Mon Mar  1 16:08:09 1999
+++ new/atm/atm.patch	Thu Apr 22 20:01:48 1999
@@ -20,8 +20,8 @@
  	if [ -f FS_MODULES    ]; then inst_mod FS_MODULES    fs;    fi; \
  	if [ -f NLS_MODULES   ]; then inst_mod NLS_MODULES   fs;    fi; \
 --- ref/Documentation/Configure.help	Wed Jan 20 20:05:32 1999
-+++ work/Documentation/Configure.help	Tue Feb  9 15:49:57 1999
-@@ -3460,6 +3460,164 @@
++++ work/Documentation/Configure.help	Tue Mar 30 21:19:57 1999
+@@ -3460,6 +3460,179 @@
    This is a backward compatibility option, choose Y for now.
    This option will be removed soon.
  
@@ -64,6 +64,21 @@
 +  during revalidation. If this configuration option is set to "yes",
 +  packets to such neighbours are silently discarded instead.
 +
++LAN Emulation (LANE) support
++CONFIG_ATM_LANE
++  LAN Emulation emulates services of existing LANs across an ATM network.
++  Besides operating as a normal ATM end station client, Linux LANE client
++  can also act as an proxy client bridging packets between ELAN and
++  Ethernet segments. You need LANE if you want to try MPOA.
++
++Multi-Protocol Over ATM (MPOA) support
++CONFIG_ATM_MPOA
++  Multi-Protocol Over ATM allows ATM edge devices such as routers,
++  bridges and ATM attached hosts establish direct ATM VCs across
++  subnetwork boundaries. These shortcut connections bypass routers
++  enhancing overall network performance.
++
++
 +Application REQUested IP over ATM
 +CONFIG_AREQUIPA
 +  Arequipa is a mechanism to create ATM connections under application
@@ -731,8 +746,8 @@
 +#endif
 +    
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/eni.c	Tue Feb  9 16:53:05 1999
-@@ -0,0 +1,2258 @@
++++ work/drivers/atm/eni.c	Wed Apr 21 17:36:48 1999
+@@ -0,0 +1,2259 @@
 +/* drivers/atm/eni.c - Efficient Networks ENI155P device driver */
 + 
 +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
@@ -2392,6 +2407,7 @@
 +	DPRINTK(">eni_init\n");
 +	dev->ci_range.vpi_bits = 0;
 +	dev->ci_range.vci_bits = NR_VCI_LD;
++	dev->link_rate = ATM_OC3_PCR;
 +	eni_dev = ENI_DEV(dev);
 +	pci_dev = eni_dev->pci_dev;
 +	real_base = pci_dev->base_address[0] & MEM_VALID; /* strip flags */
@@ -2992,7 +3008,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/eni.h	Fri Feb 19 17:27:41 1999
++++ work/drivers/atm/eni.h	Thu Apr 22 19:46:09 1999
 @@ -0,0 +1,115 @@
 +/* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */
 + 
@@ -3378,7 +3394,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/nicstar.h	Tue Feb  9 15:49:57 1999
++++ work/drivers/atm/nicstar.h	Wed Apr 21 18:37:17 1999
 @@ -0,0 +1,746 @@
 +/******************************************************************************
 + *
@@ -3409,7 +3425,7 @@
 +
 +/* Options ********************************************************************/
 +
-+#define NS_MAX_CARDS 1		/* Maximum number of NICStAR based cards
++#define NS_MAX_CARDS 4		/* Maximum number of NICStAR based cards
 +				   controlled by the device driver. Must
 +                                   be <= 5 */
 +
@@ -3481,7 +3497,7 @@
 +
 +#define NS_IOREMAP_SIZE 4096
 +
-+#define IDT_25_PCR (25600000/270*260/8/53)
++#define IDT_25_PCR ((25600000 / 8 - 8000) / 54)
 +
 +#define BUF_SM 0x00000000	/* These two are used for push_rxbufs() */
 +#define BUF_LG 0x00000001       /* CMD, Write_FreeBufQ, LBUF bit */
@@ -4127,8 +4143,8 @@
 +
 +#endif /* _LINUX_NICSTAR_H_ */
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/nicstar.c	Tue Feb  9 15:49:57 1999
-@@ -0,0 +1,2945 @@
++++ work/drivers/atm/nicstar.c	Wed Apr 21 18:37:17 1999
+@@ -0,0 +1,2949 @@
 +/******************************************************************************
 + *
 + * nicstar.c
@@ -4725,7 +4741,7 @@
 +   if (mac[i] == NULL)
 +      nicstar_init_eprom(card->membase);
 +
-+   if (request_irq(pcidev->irq, &ns_irq_handler, SA_INTERRUPT, "nicstar", card) != 0)
++   if (request_irq(pcidev->irq, &ns_irq_handler, SA_INTERRUPT | SA_SHIRQ, "nicstar", card) != 0)
 +   {
 +      printk("nicstar%d: can't allocate IRQ.\n", i);
 +      error = 9;
@@ -5002,6 +5018,7 @@
 +   card->atmdev->dev_data = card;
 +   card->atmdev->ci_range.vpi_bits = card->vpibits;
 +   card->atmdev->ci_range.vci_bits = card->vcibits;
++   card->atmdev->link_rate = card->max_pcr;
 +
 +   num_cards++;
 +
@@ -5648,6 +5665,7 @@
 +   }
 +   
 +   vcc->flags |= ATM_VF_READY;
++   MOD_INC_USE_COUNT;
 +   return 0;
 +}
 +
@@ -5775,6 +5793,7 @@
 +
 +   vcc->dev_data = NULL;
 +   vcc->flags &= ~(ATM_VF_PARTIAL | ATM_VF_ADDR);
++   MOD_DEC_USE_COUNT;
 +
 +#ifdef RX_DEBUG
 +   {
@@ -6317,10 +6336,11 @@
 +      if (ns_rsqe_crcerr(rsqe) ||
 +          len + 8 > iovb->len || len + (47 + 8) < iovb->len)
 +      {
-+         if (ns_rsqe_crcerr(rsqe))
-+	    printk("nicstar%d: AAL5 CRC error.\n", card->index);
++         printk("nicstar%d: AAL5 CRC error", card->index);
++         if (len + 8 > iovb->len || len + (47 + 8) < iovb->len)
++            printk(" - PDU size mismatch.\n");
 +         else
-+            printk("nicstar%d: AAL5 PDU size mismatch.\n", card->index);
++            printk(".\n");
 +         vcc->stats->rx_err++;
 +         recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
 +	   ATM_SKB(iovb)->iovcnt);
@@ -10620,7 +10640,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/suni.h	Fri Feb 19 17:27:40 1999
++++ work/drivers/atm/suni.h	Thu Apr 22 19:46:07 1999
 @@ -0,0 +1,210 @@
 +/* drivers/atm/suni.h - PMC SUNI (PHY) declarations */
 + 
@@ -11488,11 +11508,11 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/zatm.c	Tue Feb  9 15:49:57 1999
-@@ -0,0 +1,1876 @@
++++ work/drivers/atm/zatm.c	Thu Mar 25 16:32:15 1999
+@@ -0,0 +1,1877 @@
 +/* drivers/atm/zatm.c - ZeitNet ZN122x device driver */
 + 
-+/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
++/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 +
 +
 +#include <linux/module.h>
@@ -12973,6 +12993,7 @@
 +	for (rx = 1; rx < vccs; rx <<= 1) ld++;
 +	dev->ci_range.vpi_bits = 0; /* @@@ no VPI for now */
 +	dev->ci_range.vci_bits = ld;
++	dev->link_rate = ATM_OC3_PCR;
 +	zatm_dev->chans = vccs; /* ??? */
 +	curr = rx*RX_SIZE/4;
 +	DPRINTK("RX pool 0x%08lx\n",curr);
@@ -13367,7 +13388,7 @@
 + 
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/drivers/atm/zatm.h	Fri Feb 19 17:27:45 1999
++++ work/drivers/atm/zatm.h	Thu Apr 22 19:46:13 1999
 @@ -0,0 +1,137 @@
 +/* drivers/atm/zatm.h - ZeitNet ZN122x device driver declarations */
 +
@@ -13564,7 +13585,7 @@
  #ifdef CONFIG_VT
  	console_map_init();
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/include/linux/arequipa.h	Tue Feb  9 18:09:24 1999
++++ work/include/linux/arequipa.h	Thu Apr 22 17:31:28 1999
 @@ -0,0 +1,63 @@
 +/* arequipa.h - Arequipa interface definitions */
 + 
@@ -14152,8 +14173,8 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/include/linux/atmdev.h	Thu Feb 18 17:40:29 1999
-@@ -0,0 +1,345 @@
++++ work/include/linux/atmdev.h	Thu Apr 22 19:33:51 1999
+@@ -0,0 +1,363 @@
 +/* atmdev.h - ATM device driver declarations and various related items */
 + 
 +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
@@ -14175,6 +14196,9 @@
 +			   bits per cell:  /8/53
 +			   max cell rate:  353207.547 cells/sec */
 +
++#define ATM_PDU_OVHD	0	/* number of bytes to charge against buffer
++				   quota per PDU */
++
 +#define ATM_SD(s)	((s)->sk->protinfo.af_atm)
 +
 +
@@ -14192,6 +14216,8 @@
 +};
 +
 +
++#define ATM_GETLINKRATE	_IOW('a',ATMIOC_ITF+1,struct atmif_sioc)
++					/* get link rate */
 +#define ATM_GETNAMES	_IOW('a',ATMIOC_ITF+3,struct atm_iobuf)
 +					/* get interface names (numbers) */
 +#define ATM_GETTYPE	_IOW('a',ATMIOC_ITF+4,struct atmif_sioc)
@@ -14407,6 +14433,7 @@
 +	struct atm_cirange ci_range;	/* VPI/VCI range */
 +	struct atm_dev_stats stats;	/* statistics */
 +	char		signal;		/* signal status (ATM_PHY_SIG_*) */
++	int		link_rate;	/* link rate (default: OC3) */
 +#ifdef CONFIG_PROC_FS
 +	struct proc_dir_entry *proc_entry; /* proc entry */
 +	char *proc_name;		/* proc entry name */
@@ -14489,6 +14516,18 @@
 +}
 +
 +
++static __inline__ void atm_force_charge(struct atm_vcc *vcc,int truesize)
++{
++	atomic_add(truesize+ATM_PDU_OVHD,&vcc->rx_inuse);
++}
++
++
++static __inline__ void atm_return(struct atm_vcc *vcc,int truesize)
++{
++	atomic_sub(truesize+ATM_PDU_OVHD,&vcc->rx_inuse);
++}
++
++
 +int atm_charge(struct atm_vcc *vcc,int truesize);
 +void atm_return(struct atm_vcc *vcc,int truesize);
 +int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci);
@@ -14988,7 +15027,7 @@
  #define CAP_NET_ADMIN        12
  
 --- ref/include/linux/if_arp.h	Thu Jan 28 21:43:16 1999
-+++ work/include/linux/if_arp.h	Tue Feb  9 18:03:14 1999
++++ work/include/linux/if_arp.h	Thu Apr 22 17:24:49 1999
 @@ -35,6 +35,7 @@
  #define	ARPHRD_ARCNET	7		/* ARCnet			*/
  #define	ARPHRD_APPLETLK	8		/* APPLEtalk			*/
@@ -15029,7 +15068,7 @@
 +
  #endif
 --- ref/include/linux/skbuff.h	Thu Jan 28 21:43:15 1999
-+++ work/include/linux/skbuff.h	Tue Feb  9 18:02:02 1999
++++ work/include/linux/skbuff.h	Thu Apr 22 17:23:33 1999
 @@ -112,6 +112,25 @@
  		__u32	ifield;
  	} private;
@@ -15112,7 +15151,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/include/net/atmclip.h	Fri Feb 19 17:30:52 1999
++++ work/include/net/atmclip.h	Thu Apr 22 19:46:35 1999
 @@ -0,0 +1,62 @@
 +/* net/atm/atmarp.h - RFC1577 ATM ARP */
 + 
@@ -15177,7 +15216,7 @@
 +
 +#endif
 --- ref/include/net/sock.h	Thu Jan 28 21:43:16 1999
-+++ work/include/net/sock.h	Tue Feb  9 18:03:17 1999
++++ work/include/net/sock.h	Thu Apr 22 17:24:52 1999
 @@ -81,6 +81,10 @@
  #include <net/dn.h>
  #endif
@@ -15994,7 +16033,7 @@
 +}
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/Makefile	Tue Feb  9 15:49:58 1999
++++ work/net/atm/Makefile	Thu Apr 22 19:19:28 1999
 @@ -0,0 +1,64 @@
 +#
 +# Makefile for the ATM Protocol Families.
@@ -16014,7 +16053,7 @@
 +ifeq ($(CONFIG_ATM),y)
 +
 +O_OBJS	= addr.o pvc.o raw.o signaling.o svc.o # party.o
-+OX_OBJS = common.o misc.o resources.o
++OX_OBJS = common.o atm_misc.o resources.o
 +
 +ifeq ($(CONFIG_MMU_HACKS),y)
 +O_OBJS += mmuio.o
@@ -16223,7 +16262,7 @@
 +	return total;
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/addr.h	Fri Feb 19 17:30:58 1999
++++ work/net/atm/addr.h	Thu Apr 22 19:46:47 1999
 @@ -0,0 +1,18 @@
 +/* net/atm/addr.h - Local ATM address registry */
 +
@@ -16244,11 +16283,11 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/clip.c	Tue Feb  9 15:49:58 1999
-@@ -0,0 +1,654 @@
++++ work/net/atm/clip.c	Thu Apr 22 19:29:21 1999
+@@ -0,0 +1,688 @@
 +/* net/atm/clip.c - RFC1577 Classical IP over ATM */
 +
-+/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
++/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 +
 +
 +#include <linux/config.h>
@@ -16311,7 +16350,7 @@
 +	ctrl->type = type;
 +	ctrl->itf_num = itf;
 +	ctrl->ip = ip;
-+	atomic_add(skb->truesize+ATM_PDU_OVHD,&atmarpd->rx_inuse);
++	atm_force_charge(atmarpd,skb->truesize);
 +	skb_queue_tail(&atmarpd->recvq,skb);
 +	wake_up(&atmarpd->sleep);
 +	return 0;
@@ -16792,7 +16831,9 @@
 +    void *dev)
 +{
 +	/* ignore non-CLIP devices */
-+	if (((struct device *) dev)->init != clip_init) return NOTIFY_DONE;
++	if (((struct device *) dev)->type != ARPHRD_ATM ||
++	    ((struct device *) dev)->init != clip_init)
++		return NOTIFY_DONE;
 +	switch (event) {
 +		case NETDEV_UP:
 +			DPRINTK("clip_device_event NETDEV_UP\n");
@@ -16803,7 +16844,8 @@
 +			(void) to_atmarpd(act_down,PRIV(dev)->number,0);
 +			break;
 +		case NETDEV_CHANGE:
-+			DPRINTK("clip_device_event NETDEV_CHANGE\n");
++		case NETDEV_CHANGEMTU:
++			DPRINTK("clip_device_event NETDEV_CHANGE*\n");
 +			(void) to_atmarpd(act_change,PRIV(dev)->number,0);
 +			break;
 +		case NETDEV_REBOOT:
@@ -16812,7 +16854,7 @@
 +			/* ignore */
 +			break;
 +		default:
-+			printk(KERN_ERR "clip_device_event: unknown event "
++			printk(KERN_WARNING "clip_device_event: unknown event "
 +			    "%ld\n",event);
 +			break;
 +	}
@@ -16820,6 +16862,25 @@
 +}
 +
 +
++static int clip_inet_event(struct notifier_block *this,unsigned long event,
++    void *ifa)
++{
++	struct in_device *in_dev;
++
++	in_dev = ((struct in_ifaddr *) ifa)->ifa_dev;
++	if (!in_dev || !in_dev->dev) {
++		printk(KERN_WARNING "clip_inet_event: no device\n");
++		return NOTIFY_DONE;
++	}
++	/*
++	 * Transitions are of the down-change-up type, so it's sufficient to
++	 * handle the change on up.
++	 */
++	if (event != NETDEV_UP) return NOTIFY_DONE;
++	return clip_device_event(this,NETDEV_CHANGE,in_dev->dev);
++}
++
++
 +static struct notifier_block clip_dev_notifier = {
 +	clip_device_event,
 +	NULL,
@@ -16828,6 +16889,14 @@
 +
 +
 +
++static struct notifier_block clip_inet_notifier = {
++	clip_inet_event,
++	NULL,
++	0
++};
++
++
++
 +static void atmarpd_close(struct atm_vcc *vcc)
 +{
 +	struct sk_buff *skb;
@@ -16835,6 +16904,7 @@
 +	DPRINTK("atmarpd_close\n");
 +	atmarpd = NULL; /* assumed to be atomic */
 +	barrier();
++	unregister_inetaddr_notifier(&clip_inet_notifier);
 +	unregister_netdevice_notifier(&clip_dev_notifier);
 +	wake_up(&atmarpd_sleep);
 +	if (skb_peek(&vcc->recvq))
@@ -16894,18 +16964,21 @@
 +	vcc->push = NULL;
 +	vcc->pop = NULL; /* crash */
 +	vcc->push_oam = NULL; /* crash */
-+	register_netdevice_notifier(&clip_dev_notifier);
++	if (register_netdevice_notifier(&clip_dev_notifier))
++		printk(KERN_ERR "register_netdevice_notifier failed\n");
++	if (register_inetaddr_notifier(&clip_inet_notifier))
++		printk(KERN_ERR "register_inetaddr_notifier failed\n");
 +	for (dev = clip_devs; dev; dev = PRIV(dev)->next)
 +		if (dev->flags & IFF_UP)
 +			(void) to_atmarpd(act_up,PRIV(dev)->number,0);
 +	return 0;
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/common.c	Tue Feb  9 15:49:58 1999
-@@ -0,0 +1,928 @@
++++ work/net/atm/common.c	Thu Mar 25 16:29:11 1999
+@@ -0,0 +1,933 @@
 +/* net/atm/common.c - ATM sockets (common part for PVC and SVC) */
 +
-+/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
++/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 +
 +
 +#include <linux/config.h>
@@ -17640,6 +17713,11 @@
 +			if (copy_to_user(buf,&dev->ci_range,size))
 +				return -EFAULT;
 +			break;
++		case ATM_GETLINKRATE:
++			size = sizeof(int);
++			if (copy_to_user(buf,&dev->link_rate,size))
++				return -EFAULT;
++			break;
 +		case ATM_RSTADDR:
 +			if (!capable(CAP_NET_ADMIN)) return -EPERM;
 +			reset_addr(dev);
@@ -17832,7 +17910,7 @@
 +	return atm_do_getsockopt(sock,level,optname,optval,len);
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/common.h	Tue Feb  9 18:09:24 1999
++++ work/net/atm/common.h	Thu Apr 22 17:31:28 1999
 @@ -0,0 +1,46 @@
 +/* net/atm/common.h - ATM sockets (common part for PVC and SVC) */
 + 
@@ -17936,7 +18014,7 @@
 +	skb_queue_head_init(from);
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/ipcommon.h	Fri Feb 19 17:31:03 1999
++++ work/net/atm/ipcommon.h	Thu Apr 22 19:48:26 1999
 @@ -0,0 +1,21 @@
 +/* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */
 +
@@ -17960,9 +18038,9 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/misc.c	Mon Mar  1 15:03:23 1999
-@@ -0,0 +1,184 @@
-+/* net/atm/misc.c - Various functions for use by ATM drivers */
++++ work/net/atm/atm_misc.c	Thu Apr 22 19:33:49 1999
+@@ -0,0 +1,124 @@
++/* net/atm/atm_misc.c - Various functions for use by ATM drivers */
 +
 +/* Written 1995-1999 by Werner Almesberger, EPFL ICA */
 +
@@ -17972,7 +18050,6 @@
 +#include <linux/atm.h>
 +#include <linux/atmdev.h>
 +#include <linux/skbuff.h>
-+#include <linux/module.h>
 +#include <asm/atomic.h>
 +#include <asm/errno.h>
 +
@@ -17981,20 +18058,14 @@
 +
 +int atm_charge(struct atm_vcc *vcc,int truesize)
 +{
-+	atomic_add(truesize+ATM_PDU_OVHD,&vcc->rx_inuse);
++	atm_force_charge(vcc,truesize);
 +	if (atomic_read(&vcc->rx_inuse) <= vcc->rx_quota) return 1;
-+	atomic_sub(truesize+ATM_PDU_OVHD,&vcc->rx_inuse);
++	atm_return(vcc,truesize);
 +	vcc->stats->rx_drop++;
 +	return 0;
 +}
 +
 +
-+void atm_return(struct atm_vcc *vcc,int truesize)
-+{
-+	atomic_sub(truesize+ATM_PDU_OVHD,&vcc->rx_inuse);
-+}
-+
-+
 +static int check_ci(struct atm_vcc *vcc,short vpi,int vci)
 +{
 +	struct atm_vcc *walk;
@@ -18093,59 +18164,6 @@
 +EXPORT_SYMBOL(atm_return);
 +EXPORT_SYMBOL(atm_find_ci);
 +EXPORT_SYMBOL(atm_pcr_goal);
-+
-+
-+#ifdef URGL_THIS_WOULD_HAVE_BEEN_FAR_TOO_MESSY
-+
-+int atm_get_trafprm(struct atm_vcc *vcc,const struct atm_trafprm *tp,
-+    int (*try_trafprm)(struct atm_vcc *vcc,struct atm_trafprm *up,
-+    int flags)
-+{
-+	struct atm_trafprm curr,backup;
-+
-+	curr = *tp;
-+	if (!curr.max_pcr && !curr.min_pcr && !curr.pcr) return -EINVAL;
-+	if (!curr.max_pcr) curr.max_pcr = ATM_MAX_PCR;
-+	if (curr.min_pcr == ATM_MAX_PCR) return -EINVAL;
-+	if (curr.min_pcr > curr.max_pcr && curr.max_pcr != ATM_MAX_PCR)
-+		return -EINVAL;
-+	if (curr.min_pcr > curr.pcr && curr.pcr != ATM_MAX_PCR) return -EINVAL;
-+	if (curr.pcr > curr.max_pcr && curr.max_pcr != ATM_MAX_PCR)
-+		return -EINVAL;
-+	if (curr.traffic_class == ATM_UBR && curr.min_pcr) {
-+		if (!curr.pcr) curr.pcr = curr.min_pcr;
-+		curr.min_pcr = 0;
-+	}
-+	if (curr.traffic_class == ATM_CBR && curr.pcr == ATM_MAX_PCR)
-+		curr.pcr = vcc->dev->available_bw;
-+	if (curr.pcr) {
-+		backup = curr;
-+		error = try_trafprm(vcc,&curr,ATM_TP_PCR_DOWN);
-+		if (!error && curr.pcr >= curr.min_pcr) return 0;
-+		curr = backup;
-+		error = try_trafprm(vcc,&curr,ATM_TP_PCR_UP);
-+		if (error) return error;
-+		if (curr.pcr > curr.max_pcr && curr.max_pcr != ATM_MAX_PCR)
-+			return -EAGAIN;
-+		return 0;
-+	}
-+	if (curr.min_pcr) {
-+		if (
-+		curr.pcr = curr.min_pcr;
-+		error = try_trafprm(vcc,&curr,ATM_TP_PCR_UP);
-+		if (error) return error;
-+		if (curr.pcr > curr.max_pcr && curr.max_pcr != ATM_MAX_PCR)
-+			return -EAGAIN;
-+		return 0;
-+	}
-+	curr.pcr = curr.max_pcr == ATM_MAX_PCR ||
-+	    curr.max_pcr > vcc->dev->available_bw ? curr.max_pcr;
-+	error = try_trafprm(vcc,&curr,ATM_TP_PCR_DOWN);
-+	if (error) return error;
-+	...
-+}
-+
-+#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
 +++ work/net/atm/lec.c	Thu Feb 18 16:36:00 1999
 @@ -0,0 +1,2080 @@
@@ -20230,7 +20248,7 @@
 +}
 +
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/lec.h	Fri Feb 19 17:30:58 1999
++++ work/net/atm/lec.h	Thu Apr 22 19:46:47 1999
 @@ -0,0 +1,149 @@
 +/*
 + *
@@ -20382,7 +20400,7 @@
 +#endif _LEC_H_
 +
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/lec_arpc.h	Fri Feb 19 17:30:58 1999
++++ work/net/atm/lec_arpc.h	Thu Apr 22 19:46:47 1999
 @@ -0,0 +1,114 @@
 +/*
 + * Lec arp cache
@@ -22017,7 +22035,7 @@
 +}
 +#endif /* MODULE */
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/mpc.h	Fri Feb 19 17:30:58 1999
++++ work/net/atm/mpc.h	Thu Apr 22 19:46:47 1999
 @@ -0,0 +1,65 @@
 +#ifndef _MPC_H_
 +#define _MPC_H_
@@ -22645,7 +22663,7 @@
 +        return;
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/mpoa_caches.h	Fri Feb 19 17:30:58 1999
++++ work/net/atm/mpoa_caches.h	Thu Apr 22 19:46:47 1999
 @@ -0,0 +1,90 @@
 +#ifndef MPOA_CACHES_H
 +#define MPOA_CACHES_H
@@ -23824,7 +23842,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/pvc.c	Tue Feb  9 15:49:58 1999
++++ work/net/atm/pvc.c	Wed Apr 21 18:32:11 1999
 @@ -0,0 +1,158 @@
 +/* net/atm/pvc.c - ATM PVC sockets */
 +
@@ -23862,7 +23880,7 @@
 +
 +static int pvc_shutdown(struct socket *sock,int how)
 +{
-+	return -EOPNOTSUPP;
++	return 0;
 +}
 +
 +
@@ -24068,11 +24086,11 @@
 +	return 0;
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/resources.c	Tue Feb  9 16:45:37 1999
-@@ -0,0 +1,201 @@
++++ work/net/atm/resources.c	Thu Mar 25 16:31:28 1999
+@@ -0,0 +1,202 @@
 +/* net/atm/resources.c - Staticly allocated resources */
 +
-+/* Written 1995-1999 by Werner Almesberger, EPFL LRC */
++/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 +
 +
 +#include <linux/config.h>
@@ -24108,6 +24126,7 @@
 +	dev->type = type;
 +	dev->prev = last_dev;
 +	dev->signal = ATM_PHY_SIG_UNKNOWN;
++	dev->link_rate = ATM_OC3_PCR;
 +	dev->next = NULL;
 +	if (atm_devs) last_dev->next = dev;
 +	else atm_devs = dev;
@@ -24272,7 +24291,7 @@
 +EXPORT_SYMBOL(shutdown_atm_dev);
 +EXPORT_SYMBOL(bind_vcc);
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/resources.h	Fri Feb 19 17:30:58 1999
++++ work/net/atm/resources.h	Thu Apr 22 19:46:47 1999
 @@ -0,0 +1,32 @@
 +/* net/atm/resources.h - ATM-related resources */
 +
@@ -24307,11 +24326,11 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/signaling.c	Tue Feb  9 15:49:58 1999
++++ work/net/atm/signaling.c	Thu Apr 22 19:35:29 1999
 @@ -0,0 +1,252 @@
 +/* net/atm/signaling.c - ATM signaling */
 +
-+/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
++/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 +
 +
 +#include <linux/errno.h>	/* error codes */
@@ -24365,7 +24384,7 @@
 +		return;
 +#endif
 +	}
-+	atomic_add(skb->truesize+ATM_PDU_OVHD,&sigd->rx_inuse);
++	atm_force_charge(sigd,skb->truesize);
 +	skb_queue_tail(&sigd->recvq,skb);
 +	wake_up(&sigd->sleep);
 +}
@@ -24562,7 +24581,7 @@
 +	return 0;
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/signaling.h	Mon Mar  1 15:19:20 1999
++++ work/net/atm/signaling.h	Thu Apr 22 19:46:47 1999
 @@ -0,0 +1,25 @@
 +/* net/atm/signaling.h - ATM signaling */
 + 
@@ -24590,7 +24609,7 @@
 +
 +#endif
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/svc.c	Mon Mar  1 15:03:13 1999
++++ work/net/atm/svc.c	Wed Apr 21 18:32:01 1999
 @@ -0,0 +1,389 @@
 +/* net/atm/svc.c - ATM SVC sockets */
 +
@@ -24650,7 +24669,7 @@
 +
 +static int svc_shutdown(struct socket *sock,int how)
 +{
-+	return -EOPNOTSUPP;
++	return 0;
 +}
 +
 +
@@ -24982,11 +25001,11 @@
 +	}
 +}
 --- /dev/null	Tue Jan  1 05:00:00 1980
-+++ work/net/atm/tunable.h	Tue Feb  9 15:49:58 1999
-@@ -0,0 +1,26 @@
++++ work/net/atm/tunable.h	Thu Apr 22 19:33:00 1999
+@@ -0,0 +1,23 @@
 +/* net/atm/tunable.h - Tunable parameters of ATM support */
 +
-+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */
++/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 +
 +
 +#ifndef NET_ATM_TUNABLE_H
@@ -25005,9 +25024,6 @@
 +#define ATM_TXBQ_MIN	(   1*1024)  /* TX buffer minimum, in bytes */
 +#define ATM_RXBQ_MAX	(1024*1024)  /* RX buffer quota limit, in bytes */
 +#define ATM_TXBQ_MAX	(1024*1024)  /* TX buffer quota limit, in bytes */
-+
-+#define ATM_PDU_OVHD	0	/* number of bytes to charge against buffer
-+				   quota per PDU */
 +
 +#endif
 --- ref/net/core/skbuff.c	Tue Sep 15 07:52:10 1998
diff -ur --new-file old/atm/debug/svctor.c new/atm/debug/svctor.c
--- old/atm/debug/svctor.c	Sat Jun  6 02:02:21 1998
+++ new/atm/debug/svctor.c	Thu Apr 22 15:56:03 1999
@@ -1,6 +1,6 @@
 /* svctor.c - SVC Torture */
 
-/* Written 1998 by Werner Almesberger, EPFL ICA */
+/* Written 1998,1999 by Werner Almesberger, EPFL ICA */
 
 /*
  * This program frantically tries to concurrently set up connections to
@@ -28,7 +28,7 @@
 #include <linux/atmdev.h>
 
 
-void main(void)
+int main(void)
 {
     static int fd[MAX_PAR]; /* to force initialization */
     struct sockaddr_atmsvc local[MAX_ADDR];
@@ -43,47 +43,47 @@
     FD_ZERO(&wset);
     if (text2sap(SAP,&sap,0) < 0) {
 	fprintf(stderr,"text2sap\n");
-	exit(1);
+	return 1;
     }
     if (text2qos(QOS,&qos,0) < 0) {
 	fprintf(stderr,"text2qos\n");
-	exit(1);
+	return 1;
     }
     listen_fd = socket(PF_ATMSVC,SOCK_DGRAM,0);
     if (listen_fd < 0) {
 	perror("socket");
-	exit(1);
+	return 1;
     }
     req.number = ITF;
     req.arg = local;
     req.length = sizeof(local);
     if (ioctl(listen_fd,ATM_GETADDR,&req) < 0) {
 	perror("ioctl");
-	exit(1);
+	return 1;
     }
     if (!req.length) {
 	fprintf(stderr,"No local address\n");
-	exit(1);
+	return 1;
     }
     if (setsockopt(listen_fd,SOL_ATM,SO_ATMSAP,&sap,sizeof(sap)) < 0) {
 	perror("setsockopt SO_ATMSAP");
-	exit(1);
+	return 1;
     }
     if (setsockopt(listen_fd,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) {
 	perror("setsockopt SO_ATMQOS");
-	exit(1);
+	return 1;
     }
     if (bind(listen_fd,(struct sockaddr *) local,sizeof(*local)) < 0) {
 	perror("bind");
-	exit(1);
+	return 1;
     }
     if (fcntl(listen_fd,F_SETFL,O_NONBLOCK) < 0) {
 	perror("fnctl");
-	exit(1);
+	return 1;
     }
     if (listen(listen_fd,5) < 0) {
 	perror("listen");
-	exit(1);
+	return 1;
     }
     FD_SET(listen_fd,&rset);
     fds = listen_fd+1;
@@ -99,7 +99,7 @@
 	ret = select(fds,&_rset,&_wset,NULL,&no_delay);
 	if (ret < 0) {
 	    perror("select");
-	    exit(1);
+	    return 1;
 	}
 	if (FD_ISSET(listen_fd,&_rset)) {
 	    pid_t pid;
@@ -107,12 +107,12 @@
 	    pid = fork();
 	    if (pid < 0) {
 		perror("fork");
-		exit(1);
+		return 1;
 	    }
 	    if (!pid) {
 		if (accept(listen_fd,NULL,NULL) >= 0) exit(0);
 		perror("accept");
-		exit(1);
+		return 1;
 	    }
 	    accepts++;
 	}
@@ -125,7 +125,7 @@
 		    if (connect(fd[i],(struct sockaddr *) &dummy,sizeof(dummy))
 		      < 0) {
 			perror("connect");
-			exit(1);
+			return 1;
 		    }
 		    FD_CLR(fd[i],&wset);
 		    fd[i] = 0;
@@ -133,35 +133,36 @@
 		    if (++completed == EXIT_LIM) {
 			printf("%d attempted, %d completed, %d accepts\n",
 			  connects,completed,accepts);
-			exit(0);
+			return 0;
 		    }
 		}
 	if (empty != -1) {
 	    fd[empty] = socket(PF_ATMSVC,SOCK_DGRAM,0);
 	    if (fd[empty] < 0) {
 		perror("socket");
-		exit(1);
+		return 1;
 	    }
 	    if (fcntl(fd[empty],F_SETFL,O_NONBLOCK) < 0) {
 		perror("fnctl");
-		exit(1);
+		return 1;
 	    }
 	    if (setsockopt(fd[empty],SOL_ATM,SO_ATMSAP,&sap,sizeof(sap)) < 0) {
 		perror("setsockopt SO_ATMSAP");
-		exit(1);
+		return 1;
 	    }
 	    if (setsockopt(fd[empty],SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) {
 		perror("setsockopt SO_ATMQOS");
-		exit(1);
+		return 1;
 	    }
 	    if (connect(fd[empty],(struct sockaddr *) local,sizeof(*local)) < 0
 	      && errno != EINPROGRESS) {
 		perror("connect");
-		exit(1);
+		return 1;
 	    }
 	    FD_SET(fd[empty],&wset);
 	    if (fds <= fd[empty]) fds = fd[empty]+1;
 	    connects++;
 	}
     }
+    return 0;
 }
diff -ur --new-file old/atm/doc/Makefile new/atm/doc/Makefile
--- old/atm/doc/Makefile	Wed Nov 19 03:58:27 1997
+++ new/atm/doc/Makefile	Tue Mar 30 20:50:56 1999
@@ -10,7 +10,7 @@
 		./t2a.pl <usage.tex >usage.txt
 
 usage.dvi:	usage.tex
-		rlatex usage
+		./rlatex usage
 
 usage.ps:	usage.dvi
 		dvips -o usage.ps usage
diff -ur --new-file old/atm/doc/usage.tex new/atm/doc/usage.tex
--- old/atm/doc/usage.tex	Mon Mar  1 15:58:15 1999
+++ new/atm/doc/usage.tex	Thu Apr 22 17:39:04 1999
@@ -1,7 +1,7 @@
 %%def%:=
 
 %:\begin{verbatim}
-%:Usage instructions  -  ATM on Linux, release 0.55
+%:Usage instructions  -  ATM on Linux, release 0.56
 %:-------------------------------------------------
 %:
 %:\end{verbatim}
@@ -38,7 +38,7 @@
 
 \title{ATM on Linux \\
   User's guide \\
-  Release 0.55 (alpha)}
+  Release 0.56 (alpha)}
 \author{Werner Almesberger \\
   {\tt Werner.Almesberger@epfl.ch} \\
   \\
@@ -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.55.tar.gz}
+    \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.56.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.55.tar.gz
+tar xfz atm-0.56.tar.gz
 \end{verbatim}
 
 and the kernel source:
@@ -859,7 +859,9 @@
 \label{ipoveratm}
 
 IP over ATM is supported with Classical IP over ATM (CLIP, defined in
-RFC1577 \cite{RFC1577}), and LAN Emulation.
+RFC1577 \cite{RFC1577}), LAN Emulation (LANE, defined in~\cite{lanev1}
+and~\cite{lanev2}) and Multi-Protocol Over ATM (MPOA, client only,
+defined in~\cite{mpoav1}).
 
 
 \subsection{CLIP}
@@ -945,16 +947,162 @@
 
 
 \subsection{LAN Emulation}
+\label{lane}
 
-Besides Classical IP over ATM, LAN Emulation (LANE) can be used to carry IP
-over ATM. LANE emulates the characteristics of legacy LAN technology,
-such as support for broadcasts. LANE client support is described in the
-file \path{atm/led/USAGE}, LANE server support is described in
-\path{atm/lane/USAGE}.
+Besides Classical IP over ATM, LAN Emulation (LANE) can be used to
+carry IP over ATM. LANE emulates the characteristics of legacy LAN
+technology, such as support for broadcasts. LANE server support is
+described in \path{atm/lane/USAGE}.
 
 Man pages: \name{bus.8}, \name{lecs.8}, \name{les.8}, and \name{zeppelin.8}
 
+If you plan to run more than one LANE clients, LANE service or LANE
+clients and LANE service, you need to specify different local ATM
+addresses for each demon. Since all the LANE demons use similar
+service access points (SAPs) they need different ATM addresses to
+differentiate between connections.
+
+Just as with CLIP, the LANE client consists of two parts: a demon
+process called \name{zeppelin} which takes care of the LANE protocol
+and kernel part which contains LANE ARP cache.
+
+\name{atmsigd} and \name{ilmid} must already be running when
+\name{zeppelin} is started. When \name{zeppelin} starts, the kernel
+creates a new interface which can then be configured:
 
+\begin{command}
+\# zeppelin \meta{possibly\_more\_options} \&\\
+\# ifconfig lec0 \meta{local\_address} \meta{possibly\_more\_options} up\\
+\end{command}
+
+In the example below, two LANE clients are started. The first client
+uses default interface \raw{lec0}, default listen address and tries to
+join the default ELAN. The other LANE client gets interface \raw{lec2}
+assigned to it, binds to local address \raw{mybox3}, tries to join
+ELAN called \raw{myelan} and will bridge packets between ELAN and
+Ethernet segments. Address \raw{mybox3} is defined in
+\path{/etc/hosts.atm}. Rest of the bridging can be configured
+by reading the Bridging mini-HOWTO.~\cite{bridge-howto}
+
+\begin{verbatim}
+# zeppelin &
+# ifconfig lec0 10.1.1.42 netmask 255.255.255.0 \
+                          broadcast 10.1.1.255 up
+#
+# zeppelin -i 2 -l mybox3 -n myelan -p &
+# ifconfig lec2 10.1.2.42 netmask 255.255.255.0 \
+                          broadcast 10.1.2.255 up
+\end{verbatim}
+
+By default, \name{zeppelin} uses interface \raw{lec0}, binds to local
+ATM address using selector byte value 0, tries to contact LECS using
+Well-Known LECS address, joins the default ELAN as defined by the
+LECS, accepts the MTU size as defined by the LES and will not act as
+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
+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
+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
+\path{/proc/atm/lec}. For each entry the MAC and ATM addresses and status 
+is listed. If the entry has an active connection, the connection
+identifiers are also listed.
+
+The LANE service (\name{lecs.8}, \name{les.8} and \name{bus.8}) is
+configured using configuration files. The configuration file syntax is
+listed on the respective manual pages.
+
+A more detailed description of Linux LANE services is discussed in
+Marko Kiiskil\"a's Master's Thesis.~\cite{kiis}
+
+
+\subsection{MPOA}
+\label{mpoa}
+
+The Linux MPOA client continues the tradition of user space -- kernel
+divided ATM services. The demon process called \name{mpcd} processes
+MPOA control packets while the kernel holds MPOA ingress and egress
+caches and does the packet forwarding.
+
+Man page: \name{mpcd.8}
+
+\name{atmsigd} and \name{ilmid} must already be running when
+\name{mpcd} is started. Since MPOA detects IP layer flows from LANE
+traffic, you need to have \name{zeppelin} running before MPOA can
+function. However, the order in which \name{zeppelin} and \name{mpcd}
+is started is not fixed. You can kill any of the demons at your will
+and restart it later without need to restart the other demon. The
+easiest way to disable MPOA is to kill the running \name{mpcd}.
+
+Below is the example from Section~\ref{lane} which starts two LANE
+clients. The configuration has been augmented with two MPOA clients
+which the LANE clients will serve.
+
+\begin{verbatim}
+# zeppelin &
+# ifconfig lec0 10.1.1.42 netmask 255.255.255.0 \
+                          broadcast 10.1.1.255 up
+# mpcd -s mybox1 -l mybox2 &
+#
+# zeppelin -i 2 -l mybox3 -n myelan -p &
+# ifconfig lec2 10.1.2.42 netmask 255.255.255.0 \
+                          broadcast 10.1.2.255 up
+# mpcd -i 2 -s mybox4 -l mybox5 &
+\end{verbatim}
+
+The MPOA demon needs two different local ATM addresses which it uses
+when initiating and receiving data and control connections. The
+addresses can be the same as with e.g. \name{zeppelin} but must be
+different among other \name{mpcd} demons. By default, \name{mpcd} does
+not retrieve configuration information from the LECS. The necessary
+command line options and an example of using LECS are shown on the
+\name{mpcd} manual page.  The manual page also lists the rest of the
+available options.
+
+
+The contents of MPOA ingress and egress caches can be monitored
+through \path{/proc/atm/mpc} file.
+
+The Linux MPOA client also supports CBR traffic class for shortcuts
+SVCs instead of default UBR. The QoS specifications for future
+shortcuts can be set and modified using \path{/proc/atm/mpc}.
+
+\begin{verbatim}
+# echo add 130.230.54.146 tx=80000,1600 rx=tx > /proc/atm/mpc
+#             # generate enough traffic to trigger a shortcut
+# cat /proc/atm/mpc 
+QoS entries for shortcuts:
+IP address
+  TX:max_pcr pcr     min_pcr max_cdv max_sdu
+  RX:max_pcr pcr     min_pcr max_cdv max_sdu
+130.230.54.146  
+     80000   0       0       0       1600   
+     80000   0       0       0       1600   
+
+Interface 2:
+
+Ingress Entries:
+IP address      State     Holding time  Packets fwded  VPI VCI
+130.230.4.3     invalid   1160          0           
+130.230.54.146  resolved  542           151            0   109
+...
+\end{verbatim}
+
+The shortcut to IP address \raw{130.230.54.146} was established with
+the parameters shown above. There also exist patches which extend the
+flow detection to fully support layer 4 flows. The layer 4 flows are
+expressed as a 5 tuple (proto, local addr, local port, remote addr,
+remote port) and they identify application to application flows. If
+you are interested, see
+\url{ftp://sunsite.tut.fi/pub/Local/linux-atm/mpoa/} for the latest
+patch.
+
+%%beginskip
 %\subsection{Arequipa}
 %
 %Arequipa (Application REQUested IP over ATM, \cite{Arequipa}) is an extension
@@ -986,6 +1134,7 @@
 %# ttcp_atm -t -s -Q b-atm b
 %\end{verbatim}
 %}
+%%endskip
 
 \begin{thebibliography}{8}
 %  \bibitem{I361}ITU-T Recommendation I.361.
@@ -1011,6 +1160,23 @@
 %    {\em Application REQuested IP over ATM (AREQUIPA)} (work in progress),
 %    Internet Draft \url{draft-almesberger-arequipa-01.txt},
 %    June 1996.
+   \bibitem{bridge-howto}Cole, Christopher.
+     {\em Bridging mini-Howto},
+     \url{http://metalab.unc.edu/LDP/HOWTO/mini/Bridge.html},
+     September 1998.
+   \bibitem{kiis} Kiiskil\"a, Marko.
+     {\em Implementation of LAN Emulation Over ATM in Linux},
+     \url{ftp://sunsite.tut.fi/pub/Local/linux-atm/misc/},
+     October 1996.
+   \bibitem{lanev1} ATM Forum.
+     {\em LAN Emulation Over ATM -- Version 1.0},
+     February 1996.
+   \bibitem{lanev2} ATM Forum.
+     {\em LAN Emulation Over ATM -- Version 2 -- LUNI Specification},
+     July 1997.
+   \bibitem{mpoav1} ATM Forum.
+     {\em Multi-Protocol Over ATM -- Version 1.0},
+     July 1997.
 \end{thebibliography}
 
 %%beginskip
diff -ur --new-file old/atm/doc/usage.txt new/atm/doc/usage.txt
--- old/atm/doc/usage.txt	Mon Mar  1 16:09:07 1999
+++ new/atm/doc/usage.txt	Thu Apr 22 20:02:00 1999
@@ -1,4 +1,4 @@
-Usage instructions  -  ATM on Linux, release 0.55
+Usage instructions  -  ATM on Linux, release 0.56
 -------------------------------------------------
 
 For updates of ATM on Linux, please check the Web page at  
@@ -17,7 +17,7 @@
 In order to install this package, you need 
 
   - the package itself  
-    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.55.tar.gz  
+    ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.56.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 
@@ -33,7 +33,7 @@
 all the files listed above there. Then extract the ATM on Linux 
 distribution:
 
-tar xfz atm-0.55.tar.gz
+tar xfz atm-0.56.tar.gz
 
 and the kernel source:
 
@@ -701,7 +701,8 @@
 ===========
 
 IP over ATM is supported with Classical IP over ATM (CLIP, defined in 
-RFC1577 [2]), and LAN Emulation.
+RFC1577 [2]), LAN Emulation (LANE, defined in [3] and [4]) and 
+Multi-Protocol Over ATM (MPOA, client only, defined in [5]).
 
 
 CLIP
@@ -777,18 +778,142 @@
 
 Besides Classical IP over ATM, LAN Emulation (LANE) can be used to carry IP 
 over ATM. LANE emulates the characteristics of legacy LAN technology, such 
-as support for broadcasts. LANE client support is described in the file 
-atm/led/USAGE, LANE server support is described in atm/lane/USAGE.
+as support for broadcasts. LANE server support is described in 
+atm/lane/USAGE.
 
 Man pages: bus.8, lecs.8, les.8, and zeppelin.8
 
-%# arequipad -b
-%# ttcp_atm -r -s -Q dummy
-%
-
-%# arequipad -b
-%# ttcp_atm -t -s -Q b-atm b
-%
+If you plan to run more than one LANE clients, LANE service or LANE clients 
+and LANE service, you need to specify different local ATM addresses for 
+each demon. Since all the LANE demons use similar service access points 
+(SAPs) they need different ATM addresses to differentiate between 
+connections.
+
+Just as with CLIP, the LANE client consists of two parts: a demon process 
+called zeppelin which takes care of the LANE protocol and kernel part which 
+contains LANE ARP cache.
+
+atmsigd and ilmid must already be running when zeppelin is started. When 
+zeppelin starts, the kernel creates a new interface which can then be 
+configured:
+
+  # zeppelin <possibly_more_options> &
+     # ifconfig lec0 <local_address> <possibly_more_options> up
+      
+
+In the example below, two LANE clients are started. The first client uses 
+default interface  lec0 , default listen address and tries to join the 
+default ELAN. The other LANE client gets interface  lec2  assigned to it, 
+binds to local address  mybox3 , tries to join ELAN called  myelan  and 
+will bridge packets between ELAN and Ethernet segments. Address  mybox3  is 
+defined in /etc/hosts.atm. Rest of the bridging can be configured by 
+reading the Bridging mini-HOWTO. [6]
+
+# zeppelin &
+# ifconfig lec0 10.1.1.42 netmask 255.255.255.0 \
+                          broadcast 10.1.1.255 up
+#
+# zeppelin -i 2 -l mybox3 -n myelan -p &
+# ifconfig lec2 10.1.2.42 netmask 255.255.255.0 \
+                          broadcast 10.1.2.255 up
+
+By default, zeppelin uses interface  lec0 , binds to local ATM address 
+using selector byte value 0, tries to contact LECS using Well-Known LECS 
+address, joins the default ELAN as defined by the LECS, accepts the MTU 
+size as defined by the LES and will not act as an proxy LEC. These 
+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.
+
+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 
+listed. If the entry has an active connection, the connection identifiers 
+are also listed.
+
+The LANE service (lecs.8, les.8 and bus.8) is configured using 
+configuration files. The configuration file syntax is listed on the 
+respective manual pages.
+
+A more detailed description of Linux LANE services is discussed in Marko 
+Kiiskilae's Master's Thesis. [7]
+
+
+MPOA
+----
+
+The Linux MPOA client continues the tradition of user space - kernel 
+divided ATM services. The demon process called mpcd processes MPOA control 
+packets while the kernel holds MPOA ingress and egress caches and does the 
+packet forwarding.
+
+Man page: mpcd.8
+
+atmsigd and ilmid must already be running when mpcd is started. Since MPOA 
+detects IP layer flows from LANE traffic, you need to have zeppelin running 
+before MPOA can function. However, the order in which zeppelin and mpcd is 
+started is not fixed. You can kill any of the demons at your will and 
+restart it later without need to restart the other demon. The easiest way 
+to disable MPOA is to kill the running mpcd.
+
+Below is the example from Section "LAN Emulation" which starts two LANE 
+clients. The configuration has been augmented with two MPOA clients which 
+the LANE clients will serve.
+
+# zeppelin &
+# ifconfig lec0 10.1.1.42 netmask 255.255.255.0 \
+                          broadcast 10.1.1.255 up
+# mpcd -s mybox1 -l mybox2 &
+#
+# zeppelin -i 2 -l mybox3 -n myelan -p &
+# ifconfig lec2 10.1.2.42 netmask 255.255.255.0 \
+                          broadcast 10.1.2.255 up
+# mpcd -i 2 -s mybox4 -l mybox5 &
+
+The MPOA demon needs two different local ATM addresses which it uses when 
+initiating and receiving data and control connections. The addresses can be 
+the same as with e.g. zeppelin but must be different among other mpcd 
+demons. By default, mpcd does not retrieve configuration information from 
+the LECS. The necessary command line options and an example of using LECS 
+are shown on the mpcd manual page. The manual page also lists the rest of 
+the available options.
+
+The contents of MPOA ingress and egress caches can be monitored through 
+/proc/atm/mpc file.
+
+The Linux MPOA client also supports CBR traffic class for shortcuts SVCs 
+instead of default UBR. The QoS specifications for future shortcuts can be 
+set and modified using /proc/atm/mpc.
+
+# echo add 130.230.54.146 tx=80000,1600 rx=tx > /proc/atm/mpc
+#             # generate enough traffic to trigger a shortcut
+# cat /proc/atm/mpc 
+QoS entries for shortcuts:
+IP address
+  TX:max_pcr pcr     min_pcr max_cdv max_sdu
+  RX:max_pcr pcr     min_pcr max_cdv max_sdu
+130.230.54.146  
+     80000   0       0       0       1600   
+     80000   0       0       0       1600   
+
+Interface 2:
+
+Ingress Entries:
+IP address      State     Holding time  Packets fwded  VPI VCI
+130.230.4.3     invalid   1160          0           
+130.230.54.146  resolved  542           151            0   109
+...
+
+The shortcut to IP address  130.230.54.146  was established with the 
+parameters shown above. There also exist patches which extend the flow 
+detection to fully support layer 4 flows. The layer 4 flows are expressed 
+as a 5 tuple (proto, local addr, local port, remote addr, remote port) and 
+they identify application to application flows. If you are interested, see  
+ftp://sunsite.tut.fi/pub/Local/linux-atm/mpoa/  for the latest patch.
 
 
 References
@@ -798,3 +923,11 @@
     ftp://lrcftp.epfl.ch/pub/linux/atm/api/ , July 1996. 
   [2]  Laubach, Mark.  Classical IP and ARP over ATM, RFC1577, January 
     1994. 
+  [6]  Cole, Christopher.  Bridging mini-Howto,  
+    http://metalab.unc.edu/LDP/HOWTO/mini/Bridge.html , September 1998. 
+  [7]  Kiiskilae, Marko.  Implementation of LAN Emulation Over ATM in 
+    Linux,  ftp://sunsite.tut.fi/pub/Local/linux-atm/misc/ , October 1996. 
+  [3]  ATM Forum.  LAN Emulation Over ATM - Version 1.0, February 1996. 
+  [4]  ATM Forum.  LAN Emulation Over ATM - Version 2 - LUNI Specification, 
+    July 1997. 
+  [5]  ATM Forum.  Multi-Protocol Over ATM - Version 1.0, July 1997. 
diff -ur --new-file old/atm/lane/lecs.c new/atm/lane/lecs.c
--- old/atm/lane/lecs.c	Thu Oct  1 19:51:04 1998
+++ new/atm/lane/lecs.c	Thu Apr 22 16:50:12 1999
@@ -105,8 +105,7 @@
   return write(fd, buffer, len);
 }
 
-void
-main(int argc, char **argv)
+int main(int argc, char **argv)
 {
   int i =0;
   char *config_file =NULL;
@@ -245,5 +244,5 @@
     no_fds=0;
     reset_db();
   }
-  exit(0);
+  return 0;
 }
diff -ur --new-file old/atm/led/main.c new/atm/led/main.c
--- old/atm/led/main.c	Tue Feb  9 17:12:04 1999
+++ new/atm/led/main.c	Thu Apr 22 17:13:23 1999
@@ -333,7 +333,7 @@
   return 0;
 }
 
-STATUS 
+int
 main(int argc, char **argv)
 {
   HANDLE line_up_handle = NULL;
diff -ur --new-file old/atm/led.new/kernel.c new/atm/led.new/kernel.c
--- old/atm/led.new/kernel.c	Sun Feb  7 12:11:57 1999
+++ new/atm/led.new/kernel.c	Thu Apr  8 06:06:40 1999
@@ -273,6 +273,7 @@
 
         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;
 }
diff -ur --new-file old/atm/lib/atm.h new/atm/lib/atm.h
--- old/atm/lib/atm.h	Sat Jun  6 01:01:26 1998
+++ new/atm/lib/atm.h	Thu Apr 22 15:33:08 1999
@@ -1,6 +1,6 @@
 /* atm.h - Functions useful for ATM applications */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */
  
 
 #ifndef _ATM_H
@@ -12,16 +12,32 @@
 
 
 /*
- * For glibc. gcc won't complain unless we define something else than what
- * is in sys/socket.h
+ * For versions of glibc < 2.1
  */
 
+#ifndef AF_ATMPVC
 #define AF_ATMPVC	8
+#endif
+
+#ifndef AF_ATMSVC
 #define AF_ATMSVC	20
+#endif
+
+#ifndef PF_ATMPVC
 #define PF_ATMPVC	AF_ATMPVC
+#endif
+
+#ifndef PF_ATMSVC
 #define PF_ATMSVC	AF_ATMSVC
+#endif
+
+#ifndef SOL_ATM
 #define SOL_ATM		264
+#endif
+
+#ifndef SOL_AAL
 #define SOL_AAL		265
+#endif
 
 
 #define HOSTS_ATM "/etc/hosts.atm"
@@ -88,6 +104,7 @@
 int sap2text(char *buffer,int length,const struct atm_sap *sap,int flags);
 int sap_equal(const struct atm_sap *a,const struct atm_sap *b,int flags,...);
 
+int __t2q_get_rate(const char **text,int up);
 int __atmlib_fetch(const char **pos,...); /* internal use only */
 
 #endif
diff -ur --new-file old/atm/lib/atmequal.c new/atm/lib/atmequal.c
--- old/atm/lib/atmequal.c	Thu Apr  9 14:47:50 1998
+++ new/atm/lib/atmequal.c	Wed Apr 21 19:14:39 1999
@@ -1,6 +1,6 @@
 /* atmequal.c - Compares ATM addresses for equality */
 
-/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */
 
 
 #include <string.h>
@@ -50,6 +50,8 @@
 		    b_val = (b_prv[b_pos/2] >> (((~b_pos) & 1)*4)) & 0xf;
 		    if (a_val == 15 || b_val == 15) break;
 		    if (a_val != b_val) return 0;
+		    a_pos++;
+		    b_pos++;
 		}
 		a_prv += 9;
 		b_prv += 9;
diff -ur --new-file old/atm/lib/diag.c new/atm/lib/diag.c
--- old/atm/lib/diag.c	Tue Oct 21 22:20:00 1997
+++ new/atm/lib/diag.c	Thu Apr 22 16:43:33 1999
@@ -1,6 +1,6 @@
 /* diag.c - Diagnostic messages */
 
-/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */
+/* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */
 
 
 #include <stdlib.h>
@@ -31,7 +31,8 @@
 static const char *app_name = NULL;
 static COMPONENT *components = NULL;
 static int default_verbosity = DIAG_INFO;
-static FILE *log_to = stderr;
+static FILE *log_to = NULL;
+static int log_to_initialized = 0;
 
 
 void set_application(const char *name)
@@ -96,6 +97,10 @@
 
 FILE *get_logfile(void)
 {
+    if (!log_to_initialized) {
+	log_to = stderr;
+	log_to_initialized = 1;
+    }
     return log_to;
 }
 
@@ -115,6 +120,7 @@
 void vdiag(const char *component,int severity,const char *fmt,va_list ap)
 {
     COMPONENT *walk;
+    FILE *to;
     char buffer[MAX_DIAG_MSG+1];
     int i;
 
@@ -122,17 +128,18 @@
 	if (!strcmp(walk->name,component)) break;
     if (severity > (walk ? walk->verbosity : default_verbosity)) return;
     fflush(stdout);
-    if (!log_to) {
+    to = get_logfile();
+    if (!to) {
 	for (i = 0; sev2prio[i] == severity || sev2prio[i] == -1; i += 2);
 	vsprintf(buffer,fmt,ap);
 	syslog(sev2prio[i+1],"%s: %s",component,buffer);
     }
     else {
-	if (app_name) fprintf(log_to,"%s:%s: ",app_name,component);
-	else fprintf(log_to,"%s: ",component);
-	vfprintf(log_to,fmt,ap);
-	fputc('\n',log_to);
-	fflush(log_to);
+	if (app_name) fprintf(to,"%s:%s: ",app_name,component);
+	else fprintf(to,"%s: ",component);
+	vfprintf(to,fmt,ap);
+	fputc('\n',to);
+	fflush(to);
     }
     if (severity == DIAG_FATAL) {
 	diag_fatal_debug_hook();
diff -ur --new-file old/atm/lib/qosequal.c new/atm/lib/qosequal.c
--- old/atm/lib/qosequal.c	Mon Mar  1 15:55:53 1999
+++ new/atm/lib/qosequal.c	Mon Mar  1 19:34:59 1999
@@ -1,6 +1,6 @@
 /* qosequal.c - Compares QOS specifications for equality */
 
-/* Written 1996,1999 by Werner Almesberger, EPFL-LRC */
+/* Written 1996,1999 by Werner Almesberger, EPFL-LRC/ICA */
 
 
 #include "atm.h"
diff -ur --new-file old/atm/lib/stdint.h new/atm/lib/stdint.h
--- old/atm/lib/stdint.h	Sat Jun  6 02:52:31 1998
+++ new/atm/lib/stdint.h	Thu Apr 22 18:17:42 1999
@@ -4,7 +4,11 @@
 
 #include <features.h>
 
-#if __GLIBC__ >= 2
+#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
+
+#include "/usr/include/stdint.h"
+
+#elif __GLIBC__ >= 2
 
 /* Works for i386 and Alpha */
 
@@ -20,5 +24,8 @@
 
 #endif
 
+#ifndef _STDINT_H
 #define _STDINT_H
+#endif
+
 #endif
diff -ur --new-file old/atm/lib/text2qos.c new/atm/lib/text2qos.c
--- old/atm/lib/text2qos.c	Wed Mar 18 21:39:55 1998
+++ new/atm/lib/text2qos.c	Wed Mar 24 15:16:19 1999
@@ -1,7 +1,7 @@
 /* text2qos.c - Converts textual representation of QOS parameters to binary
 		encoding */
 
-/* Written 1996-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1996-1999 by Werner Almesberger, EPFL-LRC/ICA */
 
 
 #include <stdlib.h>
@@ -19,7 +19,7 @@
 #define RATE_ERROR -2
 
 
-static int get_rate(const char **text,int up)
+int __t2q_get_rate(const char **text,int up)
 {
     const char mult[] = "kKmMgGg";
     const char *multiplier;
@@ -86,17 +86,17 @@
 	switch (fetch(text,"max_pcr=","pcr=","min_pcr=","max_sdu=","sdu=",
 	  NULL)) {
 	    case 0:
-		if ((value = get_rate(text,0)) == RATE_ERROR) return -1;
+		if ((value = __t2q_get_rate(text,0)) == RATE_ERROR) return -1;
 		if (a) a->max_pcr = value;
 		if (b) b->max_pcr = value;
 		break;
 	    case 1:
-		if ((value = get_rate(text,0)) == RATE_ERROR) return -1;
+		if ((value = __t2q_get_rate(text,0)) == RATE_ERROR) return -1;
 		if (a) a->pcr = value;
 		if (b) b->pcr = value;
 		break;
 	    case 2:
-		if ((value = get_rate(text,1)) == RATE_ERROR) return -1;
+		if ((value = __t2q_get_rate(text,1)) == RATE_ERROR) return -1;
 		if (value == ATM_MAX_PCR) return -1;
 		if (a) a->min_pcr = value;
 		if (b) b->min_pcr = value;
diff -ur --new-file old/atm/qgen/Makefile new/atm/qgen/Makefile
--- old/atm/qgen/Makefile	Fri Oct 30 19:41:21 1998
+++ new/atm/qgen/Makefile	Thu Apr 22 17:26:57 1999
@@ -1,6 +1,6 @@
 LIBS=-lfl # lex may want  -ll  here
 OBJS=common.o file.o first.o lex.yy.o qgen.o second.o third.o y.tab.o
-TRASH=q.out.h q.out.c qd.out.c qd.dump.c default.nl
+TRASH=q.out.h q.out.c q.test.c qd.out.h qd.out.c qd.test.c qd.dump.c default.nl
 # q40.out.h q40.out.c q40.test.c
 PGMS=qgen q.out.o qd.dump.o q.dump #qtest
 # q40.out.o
diff -ur --new-file old/atm/sigd/Makefile new/atm/sigd/Makefile
--- old/atm/sigd/Makefile	Sun Nov  1 17:36:36 1998
+++ new/atm/sigd/Makefile	Thu Apr 22 17:29:12 1999
@@ -5,7 +5,7 @@
   policy.o lex.yy.o y.tab.o
 EXTOBJS=../qgen/q.out.o ../qgen/qd.dump.o
 BOOTPGMS=atmsigd
-TRASH=mess.c
+TRASH=mess.c q.out.h
 MAN4=atmsigd.conf.4
 MAN8=atmsigd.8
 
diff -ur --new-file old/atm/sigd/atmsigd.c new/atm/sigd/atmsigd.c
--- old/atm/sigd/atmsigd.c	Tue Feb 23 13:51:03 1999
+++ new/atm/sigd/atmsigd.c	Wed Apr 21 17:33:54 1999
@@ -11,6 +11,7 @@
 #include <signal.h>
 #include <limits.h>
 #include <sys/types.h>
+#include <linux/atmdev.h>
 
 #include "atm.h"
 #include "atmd.h"
@@ -41,7 +42,8 @@
 	0,		/* unspecified UNI version */
 	sm_user,	/* mode */
 	-1,		/* sig_pcr; obsolete @@@ */
-	NULL		/* sig_qos */
+	NULL,		/* sig_qos */
+	-1		/* max_rate */
 };
 
 
@@ -466,6 +468,8 @@
     init_current_time();
     q_start();
     for (sig = entities; sig; sig = sig->next) {
+	set_vpi_0(sig);
+	if (sig->max_rate < 0) sig->max_rate = get_max_rate(sig);
 	if (sig->mode != sm_switch) init_addr(sig);
 	start_saal(&sig->saal,&ops,sig,
 	  sig->uni == S_UNI30 ? sscop_qsaal1 : sscop_q2110);
diff -ur --new-file old/atm/sigd/atmsigd.conf.4 new/atm/sigd/atmsigd.conf.4
--- old/atm/sigd/atmsigd.conf.4	Sun Nov  1 17:32:18 1998
+++ new/atm/sigd/atmsigd.conf.4	Thu Mar 25 15:44:20 1999
@@ -1,4 +1,4 @@
-.TH ATMSIGD.CONF 4 "November 1, 1998" "Linux" "File Formats"
+.TH ATMSIGD.CONF 4 "March 25, 1999" "Linux" "File Formats"
 .SH NAME
 atmsigd.conf \- configuration file for the ATM signaling demon
 .SH SYNOPSIS
@@ -42,6 +42,11 @@
 omitted.
 .IP \fBio\ level\ \fIlevel\fP
 Sets the debug level for IO-related messages to \fIlevel\fP.
+.IP \fBio\ max_rate\ \fIrate\fP
+Sets the rate to signal if an application requests the "maximum". See qos(7)
+for the syntax to use for expressing the rate. The default maximum rate is
+353207 cells/second (OC3). (Note that the value of \fBmax_rate\fP does not
+constrain the rates an application can explicitly request.)
 .IP \fBio\ qos\ \fIqos\fP
 Configures the signaling VC to use the specified QOS (see qos(7) for the
 syntax). By default, UBR at link speed is used on the signaling VC.
diff -ur --new-file old/atm/sigd/cfg.l new/atm/sigd/cfg.l
--- old/atm/sigd/cfg.l	Thu Aug 20 23:02:30 1998
+++ new/atm/sigd/cfg.l	Thu Mar 25 16:57:33 1999
@@ -1,7 +1,7 @@
 %{
 /* cfg.l - configuration language */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */
 
 
 #include <stdlib.h>
@@ -25,6 +25,7 @@
 
 %s N
 %s P
+%s R
 
 %%
 			BEGIN(N);
@@ -67,6 +68,8 @@
 			  token = TOK_TO; }
 <N>route		{ BEGIN(P); /* syntacticly close to a path */
 			  token = TOK_ROUTE; }
+<N>max_rate		{ BEGIN(R); /* rate */
+			  token = TOK_MAX_RATE; }
 <N>trace		return TOK_TRACE;
 <N>[0-9]+		{ char *end;
 			  yylval.num = strtoul(yytext,&end,10);
@@ -84,6 +87,12 @@
 				perror("strdup");
 				exit(1);
 			  }
+			  return token; }
+<R>[0-9]+\.?[0-9]*[\t ]*([kKmMgG]?[bBcC][pP][sS])? { const char *text;
+			  BEGIN(N);
+			  text = yytext;
+			  yylval.num = __t2q_get_rate(&text,1);
+			  if (yylval.num < 0) yyerror("invalid rate");
 			  return token; }
 \n?[\t ]*		lineno += *yytext == '\n';
 #[^\n]*\n		lineno++;
diff -ur --new-file old/atm/sigd/cfg.y new/atm/sigd/cfg.y
--- old/atm/sigd/cfg.y	Mon Nov  2 08:37:12 1998
+++ new/atm/sigd/cfg.y	Thu Mar 25 15:45:19 1999
@@ -1,7 +1,7 @@
 %{
 /* cfg.y - configuration language */
 
-/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */
 
 
 #include <string.h>
@@ -59,7 +59,7 @@
 %token		TOK_VC TOK_IO TOK_MODE TOK_USER TOK_NET TOK_SWITCH TOK_VPCI
 %token		TOK_ITF TOK_PCR TOK_TRACE TOK_POLICY TOK_ALLOW TOK_REJECT
 %token		TOK_ENTITY TOK_DEFAULT
-%token <num>	TOK_NUMBER
+%token <num>	TOK_NUMBER TOK_MAX_RATE
 %token <str>	TOK_DUMP_DIR TOK_LOGFILE TOK_QOS TOK_FROM TOK_TO TOK_ROUTE
 %token <pvc>	TOK_PVC
 
@@ -152,6 +152,10 @@
 	{
 	    curr_sig->sig_qos = $1;
 	}
+    | TOK_MAX_RATE
+	{
+	    curr_sig->max_rate = $1;
+	}
     | TOK_ROUTE
 	{
 	     struct sockaddr_atmsvc addr;
@@ -297,6 +301,10 @@
     | TOK_QOS
 	{
 	    curr_sig->sig_qos = $1;
+	}
+    | TOK_MAX_RATE
+	{
+	    curr_sig->max_rate = $1;
 	}
     ;
 
diff -ur --new-file old/atm/sigd/io.c new/atm/sigd/io.c
--- old/atm/sigd/io.c	Wed Sep 23 19:45:35 1998
+++ new/atm/sigd/io.c	Fri Mar 26 01:02:00 1999
@@ -1,6 +1,6 @@
 /* io.c - I/O operations */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */
  
 
 #include <stdlib.h>
@@ -203,21 +203,7 @@
 /* ----- addresses --------------------------------------------------------- */
 
 
-LOCAL_ADDR local_addr[MAX_LOCAL_ADDRS+1];
-
-
-struct sockaddr_atmsvc *get_local(int itf)
-{
-    LOCAL_ADDR *local;
-
-    for (local = local_addr; local->state != ls_unused; local++)
-	if (local->state == ls_same && atmsvc_addr_in_use(local->addr) &&
-	  (local->itf == itf || itf == ATM_ITF_ANY)) return &local->addr;
-    return NULL;
-}
-
-
-int get_addr(int itf)
+int get_addr(int itf,LOCAL_ADDR *local_addr)
 {
     struct atmif_sioc req;
     struct sockaddr_atmsvc buffer[MAX_LOCAL_ADDRS];
@@ -226,7 +212,7 @@
 
     for (from = to = local_addr; from->state != ls_unused; from++)
 	if (from->state != ls_removed) {
-	    from->state = itf == from->itf ? ls_removed : ls_same;
+	    from->state = ls_removed;
 	    *to++ = *from;
 	}
     req.number = itf;
@@ -238,14 +224,13 @@
     addrs = req.length/sizeof(struct sockaddr_atmsvc);
     for (i = 0; i < addrs; i++) {
 	for (from = local_addr; from->state != ls_unused; from++)
-	    if (from->itf == itf && atm_equal((struct sockaddr *) (buffer+i),
+	    if (atm_equal((struct sockaddr *) (buffer+i),
 	      (struct sockaddr *) &from->addr,0,0)) break;
 	if (from->state != ls_unused) from->state = ls_same;
 	else if (to == local_addr+MAX_LOCAL_ADDRS-1)
 		diag(COMPONENT,DIAG_WARN,"local address table overflow");
 	    else {
 		to->state = ls_added;
-		to->itf = itf;
 		to->addr = buffer[i];
 		to++;
 	    }
@@ -273,7 +258,6 @@
 	    return -1;
 	}
     }
-    local_addr[0].state = ls_unused;
     return 0;
 }
 
@@ -376,4 +360,19 @@
     }
     (void) close(s);
     return -error;
+}
+
+
+int get_link_rate(int itf)
+{
+    struct atmif_sioc req;
+    int rate;
+
+    req.number = itf;
+    req.arg = &rate;
+    req.length = sizeof(rate);
+    if (ioctl(entities->signaling,ATM_GETLINKRATE,&req) < 0)
+	diag(COMPONENT,DIAG_FATAL,"ioctl ATM_GETLINERATE yields \"%s\"",
+	  strerror(errno));
+    return rate;
 }
diff -ur --new-file old/atm/sigd/io.h new/atm/sigd/io.h
--- old/atm/sigd/io.h	Thu Aug 20 19:50:44 1998
+++ new/atm/sigd/io.h	Fri Mar 26 01:01:56 1999
@@ -1,6 +1,6 @@
 /* io.h - I/O operations */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */
  
 
 #ifndef IO_H
@@ -13,19 +13,6 @@
 #include "proto.h"
 
 
-#define MAX_LOCAL_ADDRS 128
-
-
-typedef struct {
-    enum { ls_unused,ls_added,ls_removed,ls_same } state;
-    int itf;
-    struct sockaddr_atmsvc addr;
-} LOCAL_ADDR;
-
-
-extern LOCAL_ADDR local_addr[];
-
-
 int open_all(void);
 void open_unix(const char *name);
 void init_current_time(void);
@@ -35,9 +22,10 @@
 void to_kernel(struct atmsvc_msg *msg);
 void to_net(SIG_ENTITY *sig,void *msg,int size);
 
-struct sockaddr_atmsvc *get_local(int itf);
-int get_addr(int itf);
+int get_addr(int itf,LOCAL_ADDR *local_addr);
 
 int get_pvc(int itf,int *vci);
+
+int get_link_rate(int itf);
 
 #endif
diff -ur --new-file old/atm/sigd/kernel.c new/atm/sigd/kernel.c
--- old/atm/sigd/kernel.c	Fri Nov  6 16:34:21 1998
+++ new/atm/sigd/kernel.c	Thu Mar 25 19:34:24 1999
@@ -1,6 +1,6 @@
 /* kernel.c - Processing of incoming kernel messages */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */
  
 
 #include <stdlib.h>
@@ -57,8 +57,8 @@
 	sock->sig = route_remote(&sock->remote);
 	if (!sock->sig) error = -EHOSTUNREACH;
 	else {
-	    local = get_local(sock->sig->signaling_pvc.sap_addr.itf);
-	    if (!local) local = get_local(ATM_ITF_ANY);
+	    local = get_local(sock->sig);
+	    if (!local) local = get_local(NULL);
 	    if (local) sock->local = *local;
 	    else {
 		error = -EADDRNOTAVAIL;
@@ -89,7 +89,7 @@
     q_assign(&dsc,QF_sscs_type,0); /* unspecified - LANE wants this */
     if (!error)
 	error = sap_encode(&dsc,&sock->remote,&sock->sap,&sock->qos,
-	  sock->sig->uni);
+	  sock->sig->uni,sock->sig->max_rate);
     q_assign(&dsc,QF_bearer_class,16); /* BCOB-X */
     q_assign(&dsc,QF_upcc,0); /* p2p */
 #if !defined(UNI30) || defined(DYNAMIC_UNI)
@@ -198,12 +198,11 @@
 	    }
 	    if (!atmsvc_addr_in_use(msg->svc))
 #ifdef BE_PICKY_ABOUT_BINDING_LOCAL_WILDCARD_ADDRESSES
-		if (local_addr[0].state != ls_same)
-		    SEND_ERROR(msg->vcc,-EADDRNOTAVAIL);
+		if (!get_local(NULL)) SEND_ERROR(msg->vcc,-EADDRNOTAVAIL);
 		else
 #endif
-		send_kernel(msg->vcc,0,as_okay,0,NULL,NULL,
-		      &local_addr[0].addr,NULL,NULL);
+		send_kernel(msg->vcc,0,as_okay,0,NULL,NULL,get_local(NULL),
+		  NULL,NULL);
 	    else {
 		if (!route_local(&msg->svc)) {
 		    SEND_ERROR(msg->vcc,-EADDRNOTAVAIL);
@@ -500,36 +499,36 @@
 }
 
 
-void itf_load(int itf)
+void sync_addr(VPCI *vpci)
 {
     char buf[MAX_ATM_ADDR_LEN+1];
     LOCAL_ADDR *walk;
 
-    (void) get_addr(itf);
-    for (walk = local_addr; walk->state != ls_unused; walk++)
-	if (walk->itf == itf) {
-	    if (atm2text(buf,MAX_ATM_ADDR_LEN+1,(struct sockaddr *)
-	      &walk->addr,pretty) < 0) strcpy(buf,"<invalid>");
-	    switch (walk->state) {
-		case ls_added:
-		    diag(COMPONENT,DIAG_INFO,"Added local ATM address %s at "
-		      "itf %d",buf,itf);
-		    walk->state = ls_same;
-		    break;
-		case ls_removed:
-		    diag(COMPONENT,DIAG_INFO,"Removed local ATM address %s at "
-		      "itf %d",buf,itf);
-		    walk->state = ls_unused;
+    (void) get_addr(vpci->itf,vpci->local_addr);
+    for (walk = vpci->local_addr; walk->state != ls_unused; walk++) {
+	if (atm2text(buf,MAX_ATM_ADDR_LEN+1,(struct sockaddr *)
+	  &walk->addr,pretty) < 0) strcpy(buf,"<invalid>");
+	switch (walk->state) {
+	    case ls_added:
+		diag(COMPONENT,DIAG_INFO,"Added local ATM address %s at "
+		  "itf %d",buf,vpci->itf);
+		walk->state = ls_same;
+		break;
+	    case ls_removed:
+		diag(COMPONENT,DIAG_INFO,"Removed local ATM address %s at "
+		  "itf %d",buf,vpci->itf);
 /*
+ *		walk->state = ls_unused;
+ *
  * This is probably wrong. What if we delete an entry from the middle of
  * the list ? @@@
  */
-		    /* @@@ delete SVCs using that address ? */
-		    break;
-		default:
-		    break;
-	    }
+		/* @@@ delete SVCs using that address ? */
+		break;
+	    default:
+		break;
 	}
+    }
 }
 
 
@@ -539,7 +538,7 @@
     SOCKET *curr;
 
     if (msg->type == as_itf_notify) {
-	itf_load(msg->pvc.sap_addr.itf);
+	itf_reload(msg->pvc.sap_addr.itf);
 	return;
     }
     if (msg->type == as_terminate) {
diff -ur --new-file old/atm/sigd/proto.c new/atm/sigd/proto.c
--- old/atm/sigd/proto.c	Tue Nov  3 17:16:43 1998
+++ new/atm/sigd/proto.c	Wed Apr 21 17:11:50 1999
@@ -1,6 +1,6 @@
 /* proto.c - Common protocol functions and structures */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL-LRC */
+/* Written 1995-1999 by Werner Almesberger, EPFL-LRC */
  
 
 #include <stdarg.h>
@@ -355,11 +355,22 @@
     entry = alloc_t(VPCI);
     entry->vpci = vpci;
     entry->itf = itf;
+    entry->local_addr[0].state = ls_unused;
     entry->next = sig->vpcis;
     sig->vpcis = entry;
 }
 
 
+void set_vpi_0(SIG_ENTITY *sig)
+{
+    VPCI *vpci;
+
+    for (vpci = sig->vpcis; vpci; vpci = vpci->next)
+	if (!vpci->vpci) return;
+    enter_vpci(sig,0,sig->signaling_pvc.sap_addr.itf);
+}
+
+
 int get_itf(SIG_ENTITY *sig,int *vpci)
 {
     VPCI *best,*walk;
@@ -376,10 +387,48 @@
 
 void init_addr(SIG_ENTITY *sig)
 {
-    VPCI *walk;
+    VPCI *vpci;
 
-    itf_load(sig->signaling_pvc.sap_addr.itf);
-    for (walk = sig->vpcis; walk; walk = walk->next) itf_load(walk->itf);
+    for (vpci = sig->vpcis; vpci; vpci = vpci->next) sync_addr(vpci);
+}
+
+
+void itf_reload(int itf)
+{
+    SIG_ENTITY *sig;
+    VPCI *vpci;
+
+    for (sig = entities; sig; sig = sig->next)
+	for (vpci = sig->vpcis; vpci; vpci = vpci->next)
+	    if (vpci->itf == itf) sync_addr(vpci);
+}
+
+
+static struct sockaddr_atmsvc *do_get_local(SIG_ENTITY *sig)
+{
+    VPCI *vpci;
+    LOCAL_ADDR *local;
+
+    for (vpci = sig->vpcis; vpci; vpci = vpci->next)
+	for (local = vpci->local_addr; local->state != ls_unused; local++)
+	    if (local->state == ls_same && atmsvc_addr_in_use(local->addr))
+		return &local->addr;
+    return NULL;
+
+}
+
+
+struct sockaddr_atmsvc *get_local(SIG_ENTITY *sig)
+{
+    SIG_ENTITY *entity;
+    struct sockaddr_atmsvc *local;
+
+    if (sig) return do_get_local(sig);
+    for (entity = entities; entity; entity = entity->next) {
+	local = do_get_local(entity);
+	if (local) return local;
+    }
+    return NULL;
 }
 
 
@@ -442,25 +491,42 @@
 }
 
 
-SIG_ENTITY *get_sig_entity(int itf)
+SIG_ENTITY *route_local(struct sockaddr_atmsvc *addr)
 {
     SIG_ENTITY *sig;
+    VPCI *vpci;
+    LOCAL_ADDR *walk;
 
+    /*
+     * @@@ This is quite close to the truth but still not entirely correct:
+     * the actual result should be the VPCI to use. While this is irrelevant
+     * when the connection identifier is assigned by the peer, the VPI
+     * selection should be based on the VPCI we find here if it's atmsigd who
+     * assigns the connection identifier. The bottom line is that VPI > 0 plus
+     * connection identifier assignment by atmsigd doesn't work yet.
+     */
     for (sig = entities; sig; sig = sig->next)
-	if (sig->signaling_pvc.sap_addr.itf == itf) return sig;
-    /* should also check for vpcis @@@ */
+	for (vpci = sig->vpcis; vpci; vpci = vpci->next)
+	    for (walk = vpci->local_addr; walk->state != ls_unused; walk++)
+		if (walk->state == ls_same && atm_equal((struct sockaddr *)
+		  &walk->addr,(struct sockaddr *) addr,(ATM_ESA_LEN-1)*8,
+		  AXE_WILDCARD))
+		    return sig;
     return NULL;
 }
 
 
-SIG_ENTITY *route_local(struct sockaddr_atmsvc *addr)
+int get_max_rate(SIG_ENTITY *sig)
 {
-    LOCAL_ADDR *walk;
+    VPCI *vpci;
+    int max;
 
-    for (walk = local_addr; walk->state != ls_unused; walk++)
-	if (walk->state == ls_same && atm_equal((struct sockaddr *) &walk->addr,
-	  (struct sockaddr *) addr,(ATM_ESA_LEN-1)*8,AXE_WILDCARD))
-	    break;
-    if (walk->state == ls_unused) return NULL;
-    return get_sig_entity(walk->itf);
+    max = 0;
+    for (vpci = sig->vpcis; vpci; vpci = vpci->next) {
+	int curr;
+
+	curr = get_link_rate(vpci->itf);
+	if (curr > max) max = curr;
+    }
+    return max;
 }
diff -ur --new-file old/atm/sigd/proto.h new/atm/sigd/proto.h
--- old/atm/sigd/proto.h	Thu Feb 18 21:01:10 1999
+++ new/atm/sigd/proto.h	Fri Mar 26 00:59:48 1999
@@ -42,9 +42,18 @@
 
 typedef enum { sm_unknown,sm_user,sm_net,sm_switch } SIGNALING_MODE;
 
+typedef struct {
+    enum { ls_unused,ls_added,ls_removed,ls_same } state;
+    struct sockaddr_atmsvc addr;
+} LOCAL_ADDR;
+
+#define MAX_LOCAL_ADDRS 32
+
 typedef struct _vpci {
     int vpci;
     int itf;
+//    struct _sig_entity *sig; /* back pointer */
+    LOCAL_ADDR local_addr[MAX_LOCAL_ADDRS+1];
     struct _vpci *next;
 } VPCI;
 
@@ -54,6 +63,7 @@
     SIGNALING_MODE mode;
     int sig_pcr; /* @@@ remove soon */
     const char *sig_qos;
+    int max_rate;
     struct sockaddr_atmpvc signaling_pvc;
     SAAL_DSC saal;
     VPCI *vpcis;
@@ -124,7 +134,7 @@
 void poll_signals(void);
 
 void from_kernel(struct atmsvc_msg *msg,int size);
-void itf_load(int itf);
+void sync_addr(VPCI *vpci);
 
 void to_uni(SIG_ENTITY *sig,void *msg,int size);
 void send_kernel(unsigned long vcc,unsigned long listen_vcc,
@@ -160,13 +170,16 @@
 int get_vci(int itf);
 
 void enter_vpci(SIG_ENTITY *sig,int vpci,int itf);
+void set_vpi_0(SIG_ENTITY *sig);
 int get_itf(SIG_ENTITY *sig,int *vpci);
 void init_addr(SIG_ENTITY *sig);
+void itf_reload(int itf);
+struct sockaddr_atmsvc *get_local(SIG_ENTITY *sig);
 
 void add_route(SIG_ENTITY *sig,struct sockaddr_atmsvc *addr,int len);
 SIG_ENTITY *route_remote(struct sockaddr_atmsvc *addr);
 SIG_ENTITY *route_local(struct sockaddr_atmsvc *addr);
 
-SIG_ENTITY *get_sig_entity(int itf);
+int get_max_rate(SIG_ENTITY *sig);
 
 #endif
diff -ur --new-file old/atm/sigd/sap.c new/atm/sigd/sap.c
--- old/atm/sigd/sap.c	Fri Nov  6 16:34:09 1998
+++ new/atm/sigd/sap.c	Thu Mar 25 15:47:50 1999
@@ -1,6 +1,6 @@
 /* sap.c - SAP manipulations */
  
-/* Written 1996-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1996-1999 by Werner Almesberger, EPFL-LRC/ICA */
  
 
 #include <stdlib.h>
@@ -130,7 +130,7 @@
 
 
 int sap_encode(Q_DSC *dsc,const struct sockaddr_atmsvc *addr,
-  const struct atm_sap *sap,const struct atm_qos *qos,int uni)
+  const struct atm_sap *sap,const struct atm_qos *qos,int uni,int max_rate)
 {
     int error,pcr;
 
@@ -163,7 +163,7 @@
 	    pcr = SELECT_TOP_PCR(qos->txtp);
 	    diag(COMPONENT,DIAG_DEBUG,"fwd %d (%d..%d)",pcr,
 	      qos->txtp.min_pcr,qos->txtp.max_pcr);
-	    if (pcr == ATM_MAX_PCR) pcr = ATM_OC3_PCR;
+	    if (pcr == ATM_MAX_PCR) pcr = max_rate;
 	    q_assign(dsc,QF_fw_pcr_01,pcr);
 	    break;
         default:
@@ -181,7 +181,7 @@
 	    pcr = SELECT_TOP_PCR(qos->rxtp);
 	    diag(COMPONENT,DIAG_DEBUG,"bwd %d (%d..%d)",pcr,
 	      qos->rxtp.min_pcr,qos->rxtp.max_pcr);
-	    if (pcr == ATM_MAX_PCR) pcr = ATM_OC3_PCR;
+	    if (pcr == ATM_MAX_PCR) pcr = max_rate;
 	    q_assign(dsc,QF_bw_pcr_01,pcr);
 	    break;
         default:
diff -ur --new-file old/atm/sigd/sap.h new/atm/sigd/sap.h
--- old/atm/sigd/sap.h	Sun Nov  1 16:40:00 1998
+++ new/atm/sigd/sap.h	Thu Mar 25 16:56:25 1999
@@ -1,6 +1,6 @@
 /* sap.h - SAP manipulations */
 
-/* Written 1996-1998 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1996-1999 by Werner Almesberger, EPFL-LRC/ICA */
 
 
 #ifndef SAP_H
@@ -22,7 +22,7 @@
   struct atm_sap *res_sap,const struct atm_qos *old_qos,
   const struct atm_qos *new_qos,struct atm_qos *res_qos);
 int sap_encode(Q_DSC *dsc,const struct sockaddr_atmsvc *addr,
-  const struct atm_sap *sap,const struct atm_qos *qos,int uni);
+  const struct atm_sap *sap,const struct atm_qos *qos,int uni,int max_rate);
 
 /*
  * sap_encode returns zero on success, -errno on error.
diff -ur --new-file old/atm/sigd/uni.c new/atm/sigd/uni.c
--- old/atm/sigd/uni.c	Tue Jan  5 20:01:23 1999
+++ new/atm/sigd/uni.c	Thu Apr 22 15:21:09 1999
@@ -35,6 +35,12 @@
 static TIMER *t309 = NULL;
 
 
+static unsigned short cvt_ep_ref(SIG_ENTITY *sig,unsigned short ep_ref)
+{
+    return sig->uni == S_UNI30 ? ep_ref & 0x7fff : ep_ref ^ 0x8000;
+}
+
+
 int send_call_proceeding(SOCKET *sock)
 {
     Q_DSC dsc;
@@ -103,7 +109,7 @@
     this->call_state = cs_in_proc;
     this->call_ref = call_ref;
     if (q_present(&in_dsc,QF_ep_ref))
-	this->ep_ref = q_fetch(&in_dsc,QF_ep_ref) ^ 0x8000;
+	this->ep_ref = cvt_ep_ref(sig,q_fetch(&in_dsc,QF_ep_ref));
 #ifdef CISCO
     else
 #endif
@@ -256,7 +262,7 @@
 
 
 static void send_drop_party_ack(SIG_ENTITY *sig,unsigned long call_ref,
-  short ep_ref,unsigned char cause)
+  unsigned short ep_ref,unsigned char cause)
 {
     Q_DSC dsc;
     int size;
@@ -753,12 +759,15 @@
 	return;
     }
     if (curr && q_present(&in_dsc,QF_ep_ref) && mid != ATM_MSG_ADD_PARTY &&
-      mid != ATM_MSG_DROP_PARTY_ACK)
-	if (curr->ep_ref != (q_fetch(&in_dsc,QF_ep_ref) ^ 0x8000)) {
-	    send_drop_party_ack(sig,call_ref,
-	      q_fetch(&in_dsc,QF_ep_ref) ^ 0x8000,ATM_CV_INV_EPR);
+      mid != ATM_MSG_DROP_PARTY_ACK) {
+	unsigned short ep_ref;
+
+	ep_ref = cvt_ep_ref(sig,q_fetch(&in_dsc,QF_ep_ref));
+	if (curr->ep_ref != ep_ref) {
+	    send_drop_party_ack(sig,call_ref,ep_ref,ATM_CV_INV_EPR);
 	    return;
 	}
+    }
     if (!curr || curr->call_state == cs_null) {
 	if (mid != ATM_MSG_REL_COMP)
 	    if (mid != ATM_MSG_STATUS)
diff -ur --new-file old/atm/sigd.old/Makefile new/atm/sigd.old/Makefile
--- old/atm/sigd.old/Makefile	Sun Nov  1 17:36:34 1998
+++ new/atm/sigd.old/Makefile	Thu Apr 22 17:29:40 1999
@@ -6,7 +6,7 @@
 EXTOBJS=../qgen/q.out.o ../qgen/qd.dump.o
 #BOOTPGMS=atmsigd # don't install anymore
 PGMS=atmsigd.old
-TRASH=mess.c
+TRASH=mess.c q.out.h
 #MAN4=atmsigd.conf.4 # don't install anymore
 #MAN8=atmsigd.8 # don't install anymore
 
diff -ur --new-file old/atm/sigd.old/atmsigd.c new/atm/sigd.old/atmsigd.c
--- old/atm/sigd.old/atmsigd.c	Mon Oct  5 17:52:08 1998
+++ new/atm/sigd.old/atmsigd.c	Thu Apr 22 16:47:13 1999
@@ -182,7 +182,7 @@
 
 void poll_signals(void)
 {
-    static status_num = 0,trace_num = 0;
+    static int status_num = 0,trace_num = 0;
     char path[PATH_MAX+1];
     FILE *file;
 
diff -ur --new-file old/atm/test/window.c new/atm/test/window.c
--- old/atm/test/window.c	Sat Jun  6 01:59:32 1998
+++ new/atm/test/window.c	Thu Apr 22 15:53:27 1999
@@ -59,7 +59,7 @@
   return (double)t.tv_sec+((double)t.tv_usec/(double)1e6);
 }
 
-void main(int argc, char **argv) {
+int main(int argc, char **argv) {
    struct sockaddr_atmpvc addr1, addr2;
    struct atm_qos qos1, qos2;
    char *buffer;
@@ -266,5 +266,5 @@
      }
    }
    
-   exit(0);
+   return 0;
 }