diff -ur --new-file old/linux/include/linux/atmsvc.h new/linux/include/linux/atmsvc.h
--- old/linux/include/linux/atmsvc.h	Mon Sep  9 19:42:00 1996
+++ new/linux/include/linux/atmsvc.h	Mon Sep  9 19:42:31 1996
@@ -13,8 +13,8 @@
 #define ATMSIGD_CTRL _IO('a',ATMIOC_SPECIAL)
 				/* become ATM signaling demon control socket */
 
-enum atmsvc_msg_type { as_catch_null,as_bind,as_connect,as_accept,as_listen,
-  as_okay,as_error,as_indicate,as_close,as_itf_notify };
+enum atmsvc_msg_type { as_catch_null,as_bind,as_connect,as_accept,as_reject,
+  as_listen,as_okay,as_error,as_indicate,as_close,as_itf_notify };
 
 struct atmsvc_msg {
 	enum atmsvc_msg_type type;
@@ -35,31 +35,7 @@
 };
 
 /*
- * Message contents:
- *
- * Message   Dir  vcc listen_vcc reply aal    pvc       --svc--    local
- *                                         addr *xtp addr sap *xtp addr
- * bind	     K->D  X      -        -    -   -    -    X    X   -    -
- * - okay    D->K  X      -        -    -   -    -    X    X   -    -
- * connect   K->D  X      -        -    X   -    -    X    X   X    X
- * - okay    D->K  X      -        -    -   X    X    -    -   -    X
- * listen    K->D  X      -        -    X   -    -    X    X   X    -
- * - okay    D->K  X      -        -    -   -    -    -    -   -    -
- * indicate  D->K  -      X        -    -   X    1    X    X   X    -
- * accept    K->D  X      X        -    -   -    -    -    -   -    -
- * - okay    D->K  X      -        -    -   -    -    -    -   -    X
- * close     K->D  X      -        -    -   -    -    -    -   -    -
- * close     D->K  X      -        X    -   -    -    -    -   -    -
- *
- *  1  same value as in svc.*xtp
- *
- * Note: we may have to get rid of the PVC part in indicate messages later,
- *       so it's a good idea not to depend on it too heavily.
- */
-
-/*
- * In an as_itf_update message, only the fields type and pvc.sas_addr.itf are
- * valid.
+ * Message contents: see ftp://lrcftp.epfl.ch/pub/linux/atm/docs/isp-*.tar.gz
  */
 
 /*
diff -ur --new-file old/linux/net/atm/atmarp.c new/linux/net/atm/atmarp.c
--- old/linux/net/atm/atmarp.c	Mon Sep  9 19:42:00 1996
+++ new/linux/net/atm/atmarp.c	Mon Sep  9 19:42:31 1996
@@ -480,18 +480,10 @@
 
 int clip_create(int number) /* remove by downing */
 {
-	struct device *dev,*walk;
+	struct device *dev;
 
-	if (number != -1) {
-		for (walk = clip_devs; walk; walk = PRIV(walk)->next)
-			if (PRIV(walk)->number == number) return -EEXIST;
-	}
-	else {
-		number = 0;
-		for (walk = clip_devs; walk; walk = PRIV(walk)->next)
-			if (PRIV(walk)->number >= number)
-				number = PRIV(walk)->number+1;
-	}
+	number = ipcom_pick_number(number);
+	if (number < 0) return number;
 	dev = kmalloc(sizeof(struct device)+sizeof(struct atmarp_priv),
 	    GFP_KERNEL);
 	if (!dev) return -ENOMEM;
diff -ur --new-file old/linux/net/atm/atmarp.h new/linux/net/atm/atmarp.h
--- old/linux/net/atm/atmarp.h	Mon Sep  9 19:42:00 1996
+++ new/linux/net/atm/atmarp.h	Mon Sep  9 19:42:31 1996
@@ -42,7 +42,6 @@
 };
 
 
-extern struct device *clip_devs;
 extern struct atm_vcc *atmarpd; /* ugly */
 
 
diff -ur --new-file old/linux/net/atm/clip.c new/linux/net/atm/clip.c
--- old/linux/net/atm/clip.c	Mon Sep  9 19:42:00 1996
+++ new/linux/net/atm/clip.c	Mon Sep  9 19:42:31 1996
@@ -31,8 +31,7 @@
 #endif
 
 
-
-static int pvc_num = 0;
+struct clip_priv *old_clip_devs;
 
 
 /*static*/ void atm_push_clip(struct atm_vcc *vcc,struct sk_buff *skb)
@@ -91,7 +90,6 @@
 int atm_init_clip(struct atm_vcc *vcc)
 {
 	struct device *dev;
-	int number;
 
 	DPRINTK("atm_init_clip\n");
 	if (!suser()) return -EPERM;
@@ -105,11 +103,14 @@
 	if (!dev) return -ENOMEM;
 	memset(dev,0,sizeof(struct device)+sizeof(struct clip_priv));
 	dev->name = CLIP(dev)->name;
-	number = pvc_num++;
-	sprintf(dev->name,"atm%d",number);
+	CLIP(dev)->number = ipcom_pick_number(-1);
+	sprintf(dev->name,"atm%d",CLIP(dev)->number);
 	dev->init = clip_init;
 	CLIP(dev)->vcc = vcc;
 	if (register_netdev(dev)) return -EIO;
+		/* if register_netdev can sleep, we race on ->number */
+	CLIP(dev)->next = old_clip_devs;
+	old_clip_devs = CLIP(dev);
 	DPRINTK("registered %s,0x%lx\n",dev->name,(unsigned long) vcc);
-	return number;
+	return CLIP(dev)->number;
 }
diff -ur --new-file old/linux/net/atm/ipcommon.c new/linux/net/atm/ipcommon.c
--- old/linux/net/atm/ipcommon.c	Mon Sep  9 19:42:00 1996
+++ new/linux/net/atm/ipcommon.c	Mon Sep  9 19:42:31 1996
@@ -13,6 +13,7 @@
 
 #include "common.h"
 #include "ipcommon.h"
+#include "atmarp.h"
 
 
 #if 0
@@ -178,4 +179,36 @@
 	dev->mtu = RFC1626_MTU;
 	memset(&CLIP(dev)->stats,0,sizeof(struct enet_statistics));
 
+}
+
+
+int ipcom_pick_number(int number)
+{
+#ifdef CONFIG_ATM_ATMARP
+	struct device *atmarp;
+#endif
+#ifdef CONFIG_ATM_CLIP
+	struct clip_priv *clip;
+#endif
+
+	if (number != -1) {
+#ifdef CONFIG_ATM_ATMARP
+		for (atmarp = clip_devs; atmarp; atmarp = PRIV(atmarp)->next)
+			if (PRIV(atmarp)->number == number) return -EEXIST;
+#endif
+	}
+        else {
+                number = 0;
+
+#ifdef CONFIG_ATM_ATMARP
+                for (atmarp = clip_devs; atmarp; atmarp = PRIV(atmarp)->next)
+                        if (PRIV(atmarp)->number >= number)
+                                number = PRIV(atmarp)->number+1;
+#endif
+#ifdef CONFIG_ATM_CLIP
+                for (clip = old_clip_devs; clip; clip = clip->next)
+                        if (clip->number >= number) number = clip->number+1;
+#endif
+        }
+	return number;
 }
diff -ur --new-file old/linux/net/atm/ipcommon.h new/linux/net/atm/ipcommon.h
--- old/linux/net/atm/ipcommon.h	Mon Sep  9 19:42:00 1996
+++ new/linux/net/atm/ipcommon.h	Mon Sep  9 19:42:31 1996
@@ -15,18 +15,24 @@
 
 
 extern const unsigned char llc_oui[6];
+extern struct device *clip_devs;
 
 
 #define CLIP(dev) ((struct clip_priv *) ((struct device *) (dev)+1))
 
 
 struct clip_priv {
-	char name[8];
+	char name[8];			/* interface name */
+	int number;			/* for convenience ... */
 	struct atm_vcc *vcc;
 	struct enet_statistics stats;
+	struct clip_priv *next;		/* next CLIP interface */
 };
 
 
+extern struct clip_priv *old_clip_devs;
+
+
 static inline void ipcom_push(struct sk_buff *skb)
 {
 	skb->mac.raw = skb->data;
@@ -62,5 +68,6 @@
 void ipcom_init(struct device *dev,
     int (*hard_start_xmit)(struct sk_buff *skb,struct device *dev),
     unsigned short extra_flags);
+int ipcom_pick_number(int number);
 
 #endif
diff -ur --new-file old/linux/net/atm/proc.c new/linux/net/atm/proc.c
--- old/linux/net/atm/proc.c	Mon Sep  9 19:42:01 1996
+++ new/linux/net/atm/proc.c	Mon Sep  9 19:42:31 1996
@@ -22,6 +22,7 @@
 
 #include "static.h" /* ugly */
 #include "signaling.h" /* to get sigd - ugly too */
+#include "ipcommon.h"
 #include "atmarp.h"
 
 #ifdef CONFIG_ATM_LANE
diff -ur --new-file old/linux/net/atm/svc.c new/linux/net/atm/svc.c
--- old/linux/net/atm/svc.c	Mon Sep  9 19:42:00 1996
+++ new/linux/net/atm/svc.c	Mon Sep  9 19:42:31 1996
@@ -78,9 +78,8 @@
 	while ((skb = skb_dequeue(&vcc->listenq))) {
 		vcc->flags &= ~ATM_VF_RELEASED;
 		DPRINTK("LISTEN REL\n");
-		sigd_enq(NULL,as_close,vcc,NULL,NULL); /* reject */
-		while (!(vcc->flags & ATM_VF_RELEASED) && sigd)
-		    sleep_on(&vcc->sleep);
+		sigd_enq(NULL,as_reject,vcc,NULL,NULL); /* @@@ should include
+							       the reason */
 		dev_kfree_skb(skb,FREE_WRITE);
 	}
 	vcc->flags &= ~(ATM_VF_REGIS | ATM_VF_RELEASED); /* may retry later */
@@ -283,31 +282,35 @@
 		}
 		/* should try to atm_connect now and possibly send a close on
 		   error */
+		msg = (struct atmsvc_msg *) skb->data;
+		new_vcc->qos = msg->qos;
+		new_vcc->flags |= ATM_VF_HASQOS;
+		new_vcc->remote = msg->svc;
+		/* copy BLLI @@@ */
+		new_vcc->remote.sas_addr.blli = NULL;
+		error = atm_connect(newsock,msg->pvc.sap_addr.itf,
+		    msg->pvc.sap_addr.vpi,msg->pvc.sap_addr.vci);
+		dev_kfree_skb(skb,FREE_WRITE);
+		if (error) {
+			sigd_enq(NULL,as_reject,old_vcc,NULL,NULL);
+				/* @@@ should include the reason */
+			return error == -EAGAIN ? -EBUSY : error;
+		}
 		/* wait should be short, so we ignore the non-blocking flag */
 		new_vcc->reply = WAITING;
 		sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL);
 		while (new_vcc->reply == WAITING && sigd)
 			sleep_on(&new_vcc->sleep);
-		if (!sigd) return -EUNATCH;
+		if (!sigd) {
+			atm_release_vcc(new_vcc,1);
+			return -EUNATCH;
+		}
 		old_vcc->backlog_quota++;
 		if (!new_vcc->reply) break;
-		dev_kfree_skb(skb,FREE_WRITE);
-		if (new_vcc->reply != -ERESTARTSYS) return new_vcc->reply;
-	}
-	if (!sigd) return -EUNATCH;
-	msg = (struct atmsvc_msg *) skb->data;
-	new_vcc->qos = msg->qos;
-	new_vcc->remote = msg->svc;
-	/* copy BLLI @@@ */
-	new_vcc->remote.sas_addr.blli = NULL;
-	error = atm_connect(newsock,msg->pvc.sap_addr.itf,msg->pvc.sap_addr.vpi,
-	    msg->pvc.sap_addr.vci);
-	dev_kfree_skb(skb,FREE_WRITE);
-	if (error) {
-		(void) svc_disconnect(ATM_SD(newsock));
-		/* @@@ or should we try additional connections just until
-		   we'd block ? (then we MUST return) */
-		return error == -EAGAIN ? -EBUSY : error;
+		if (new_vcc->reply != -ERESTARTSYS) {
+			atm_release_vcc(new_vcc,1);
+			return new_vcc->reply;
+		}
 	}
 	newsock->state = SS_CONNECTED;
 	return 0;
diff -ur --new-file old/linux/net/ipv4/ip_forward.c new/linux/net/ipv4/ip_forward.c
--- old/linux/net/ipv4/ip_forward.c	Wed Aug  7 12:59:29 1996
+++ new/linux/net/ipv4/ip_forward.c	Mon Sep  9 19:42:31 1996
@@ -39,6 +39,9 @@
 #include <net/checksum.h>
 #include <linux/route.h>
 #include <net/route.h>
+#ifdef CONFIG_AREQUIPA
+#include <linux/arequipa.h>
+#endif
 
 #ifdef CONFIG_IP_FORWARD
 #ifdef CONFIG_IP_MROUTE
@@ -150,7 +153,11 @@
 		iph->check = checksum;
 	}
 
+#ifndef CONFIG_AREQUIPA
 	if (iph->ttl <= 0)
+#else
+	if (iph->ttl <= 0 || dev == arequipa_dev)
+#endif
 	{
 		/* Tell the sender its packet died... */
 		icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev);