patch-2.0.31 linux/drivers/isdn/isdn_net.c

Next file: linux/drivers/isdn/isdn_net.h
Previous file: linux/drivers/isdn/isdn_common.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.30/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
@@ -1,11 +1,11 @@
-/* $Id: isdn_net.c,v 1.29 1996/11/13 02:31:38 fritz Exp $
- *
+/* $Id: isdn_net.c,v 1.47 1997/06/21 10:52:05 fritz Exp $
+
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
  * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
  * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -18,9 +18,73 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_net.c,v $
+ * Revision 1.47  1997/06/21 10:52:05  fritz
+ * Removed wrong SET_SKB_FREE in isdn_net_send_skb()
+ *
+ * Revision 1.46  1997/06/17 13:05:24  hipp
+ * Applied Eric's underflow-patches (slightly modified)
+ *
+ * Revision 1.45  1997/06/10 16:24:22  hipp
+ * hard_header changes for syncPPP (now behaves like RAWIP)
+ *
+ * Revision 1.44  1997/05/27 15:17:26  fritz
+ * Added changes for recent 2.1.x kernels:
+ *   changed return type of isdn_close
+ *   queue_task_* -> queue_task
+ *   clear/set_bit -> test_and_... where apropriate.
+ *   changed type of hard_header_cache parameter.
+ *
+ * Revision 1.43  1997/03/30 16:51:13  calle
+ * changed calls to copy_from_user/copy_to_user and removed verify_area
+ * were possible.
+ *
+ * Revision 1.42  1997/03/11 08:43:51  fritz
+ * Perform a hangup if number is deleted while dialing.
+ *
+ * Revision 1.41  1997/03/08 08:16:31  fritz
+ * Bugfix: Deleting a phone number during dial gave unpredictable results.
+ *
+ * Revision 1.40  1997/03/05 21:16:08  fritz
+ * Fix: did not compile with 2.1.27
+ *
+ * Revision 1.39  1997/03/04 21:36:52  fritz
+ * Added sending ICMP messages when no connetion is possible.
+ *
+ * Revision 1.38  1997/02/23 23:41:14  fritz
+ * Bugfix: Slave interfaces have to be hung up before master.
+ *
+ * Revision 1.37  1997/02/11 18:32:51  fritz
+ * Bugfix in isdn_ppp_free_mpqueue().
+ *
+ * Revision 1.36  1997/02/10 21:31:11  fritz
+ * Changed setup-interface (incoming and outgoing).
+ *
+ * Revision 1.35  1997/02/10 20:12:45  fritz
+ * Changed interface for reporting incoming calls.
+ *
+ * Revision 1.34  1997/02/03 23:15:07  fritz
+ * Reformatted according CodingStyle.
+ * replaced arp_find prototype by proper include.
+ * made dev_purge_queues static.
+ * Bugfix in bogocps calculation.
+ * removed isdn_net_receive_callback - was never used ;-)
+ * Misc. fixes for Kernel 2.1.X comaptibility.
+ *
+ * Revision 1.33  1997/01/17 01:19:25  fritz
+ * Applied chargeint patch.
+ *
+ * Revision 1.32  1997/01/14 01:29:31  fritz
+ * Bugfix: isdn_net_hangup() did not reset ISDN_NET_CONNECTED.
+ *
+ * Revision 1.31  1997/01/11 23:30:42  fritz
+ * Speed up dial statemachine.
+ *
+ * Revision 1.30  1996/11/25 17:20:50  hipp
+ * fixed pppbind bug in isdn_net_find_icall()
+ *
  * Revision 1.29  1996/11/13 02:31:38  fritz
  * Minor cleanup.
  *
@@ -140,38 +204,47 @@
 #include <linux/module.h>
 #include <linux/isdn.h>
 #include <linux/if_arp.h>
+#include <net/arp.h>
+#include <net/icmp.h>
 #include "isdn_common.h"
 #include "isdn_net.h"
 #ifdef CONFIG_ISDN_PPP
 #include "isdn_ppp.h"
 #endif
 
-/* In ksyms.c, but why not in some .h ??? */
-extern int arp_find(unsigned char *, u32, struct device *, u32,
-                    struct sk_buff *);
-
 /* Prototypes */
 
 int isdn_net_force_dial_lp(isdn_net_local *);
 static int isdn_net_wildmat(char *s, char *p);
 static int isdn_net_start_xmit(struct sk_buff *, struct device *);
 static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
- 
-extern void dev_purge_queues(struct device *dev);	/* move this to net/core/dev.c */
+static void dev_purge_queues(struct device *dev);	/* move this to net/core/dev.c */
 
-char *isdn_net_revision = "$Revision: 1.29 $";
+char *isdn_net_revision = "$Revision: 1.47 $";
 
  /*
   * Code for raw-networking over ISDN
   */
 
 static void
+isdn_net_unreachable(struct device *dev, struct sk_buff *skb, char *reason)
+{
+	printk(KERN_DEBUG "isdn_net: %s: %s, send ICMP\n",
+	       dev->name, reason);
+	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0
+#if (LINUX_VERSION_CODE < 0x02010f)	/* 2.1.15 */
+		  ,dev
+#endif
+	    );
+}
+
+static void
 isdn_net_reset(struct device *dev)
 {
 	ulong flags;
 
 	save_flags(flags);
-	cli();			/* Avoid glitch on writes to CMD regs */
+	cli();                  /* Avoid glitch on writes to CMD regs */
 	dev->interrupt = 0;
 	dev->tbusy = 0;
 	restore_flags(flags);
@@ -191,7 +264,7 @@
 		dev->dev_addr[i] = 0xfc;
 	memcpy(&(dev->dev_addr[i]), &dev->pa_addr, sizeof(u32));
 
-        /* If this interface has slaves, start them also */
+	/* If this interface has slaves, start them also */
 
 	if ((p = (((isdn_net_local *) dev->priv)->slave))) {
 		while (p) {
@@ -200,7 +273,6 @@
 			p = (((isdn_net_local *) p->priv)->slave);
 		}
 	}
-
 	isdn_MOD_INC_USE_COUNT();
 	return 0;
 }
@@ -211,15 +283,15 @@
 static void
 isdn_net_bind_channel(isdn_net_local * lp, int idx)
 {
-        ulong flags;
+	ulong flags;
 
-        save_flags(flags);
-        cli();
+	save_flags(flags);
+	cli();
 	lp->isdn_device = dev->drvmap[idx];
 	lp->isdn_channel = dev->chanmap[idx];
-        dev->rx_netdev[idx] = lp->netdev;
-        dev->st_netdev[idx] = lp->netdev;
-        restore_flags(flags);
+	dev->rx_netdev[idx] = lp->netdev;
+	dev->st_netdev[idx] = lp->netdev;
+	restore_flags(flags);
 }
 
 /*
@@ -232,25 +304,25 @@
 
 	save_flags(flags);
 	cli();
-        if (lp->first_skb) {
-                dev_kfree_skb(lp->first_skb,FREE_WRITE);
-                lp->first_skb = NULL;
-        }
-	if(lp->sav_skb) {
-                dev_kfree_skb(lp->sav_skb,FREE_WRITE);
+	if (lp->first_skb) {
+		dev_kfree_skb(lp->first_skb, FREE_WRITE);
+		lp->first_skb = NULL;
+	}
+	if (lp->sav_skb) {
+		dev_kfree_skb(lp->sav_skb, FREE_WRITE);
 		lp->sav_skb = NULL;
 	}
-	if(!lp->master) /* purge only for master device */
+	if (!lp->master)        /* purge only for master device */
 		dev_purge_queues(&lp->netdev->dev);
 	lp->dialstate = 0;
-	dev->rx_netdev[isdn_dc2minor(lp->isdn_device,lp->isdn_channel)] = NULL;
-	dev->st_netdev[isdn_dc2minor(lp->isdn_device,lp->isdn_channel)] = NULL;
+	dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
+	dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
 	isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET);
 	lp->flags &= ~ISDN_NET_CONNECTED;
 	lp->isdn_device = -1;
 	lp->isdn_channel = -1;
 
-        restore_flags(flags);
+	restore_flags(flags);
 }
 
 /*
@@ -272,37 +344,50 @@
 isdn_net_autohup()
 {
 	isdn_net_dev *p = dev->netdev;
-        int anymore;
+	int anymore;
 
-        anymore = 0;
+	anymore = 0;
 	while (p) {
 		isdn_net_local *l = (isdn_net_local *) & (p->local);
 		if ((jiffies - last_jiffies) == 0)
-			l->cps = 0;
+			l->cps = l->transcount;
 		else
-			l->cps = l->transcount / (jiffies - last_jiffies);
+			l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
 		l->transcount = 0;
 		if (dev->net_verbose > 3)
 			printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps);
 		if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
-                        anymore = 1;
+			anymore = 1;
 			l->huptimer++;
 			if ((l->onhtime) && (l->huptimer > l->onhtime))
-				if (l->outgoing) {
-					if (l->hupflags & 4) {
-						if (l->hupflags & 1)
+				if (l->hupflags & ISDN_MANCHARGE &&
+				    l->hupflags & ISDN_CHARGEHUP) {
+					while (jiffies - l->chargetime > l->chargeint)
+						l->chargetime += l->chargeint;
+					if (jiffies - l->chargetime >= l->chargeint - 2 * HZ)
+						if (l->outgoing || l->hupflags & ISDN_INHUP)
 							isdn_net_hangup(&p->dev);
-						else if (jiffies - l->chargetime > l->chargeint)
+				} else if (l->outgoing) {
+					if (l->hupflags & ISDN_CHARGEHUP) {
+						if (l->hupflags & ISDN_WAITCHARGE) {
+							printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
+							       l->name, l->hupflags);
 							isdn_net_hangup(&p->dev);
+						} else if (jiffies - l->chargetime > l->chargeint) {
+							printk(KERN_DEBUG
+							       "isdn_net: %s: chtime = %d, chint = %d\n",
+							       l->name, l->chargetime, l->chargeint);
+							isdn_net_hangup(&p->dev);
+						}
 					} else
 						isdn_net_hangup(&p->dev);
-				} else if (l->hupflags & 8)
+				} else if (l->hupflags & ISDN_INHUP)
 					isdn_net_hangup(&p->dev);
 		}
 		p = (isdn_net_dev *) p->next;
 	}
 	last_jiffies = jiffies;
-        isdn_timer_ctrl(ISDN_TIMER_NETHANGUP,anymore);
+	isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore);
 }
 
 /*
@@ -318,57 +403,56 @@
 
 	if (p) {
 		isdn_net_local *lp = &(p->local);
-                switch (cmd) {
+		switch (cmd) {
 			case ISDN_STAT_BSENT:
 				/* A packet has successfully been sent out */
 				if ((lp->flags & ISDN_NET_CONNECTED) &&
 				    (!lp->dialstate)) {
 					lp->stats.tx_packets++;
-					if(lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && lp->sav_skb) {
+					if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && lp->sav_skb) {
 						struct device *mdev;
-						if(lp->master)
+						if (lp->master)
 							mdev = lp->master;
 						else
 							mdev = &lp->netdev->dev;
-						if(!isdn_net_send_skb(mdev,lp,lp->sav_skb)) {
+						if (!isdn_net_send_skb(mdev, lp, lp->sav_skb)) {
 							lp->sav_skb = NULL;
 							mark_bh(NET_BH);
-						}
-						else {
+						} else {
 							return 1;
 						}
 					}
-                                        if (clear_bit(0,(void*)&(p->dev.tbusy)))
-                                                mark_bh(NET_BH);
+					if (test_and_clear_bit(0, (void *) &(p->dev.tbusy)))
+						mark_bh(NET_BH);
 				}
 				return 1;
 			case ISDN_STAT_DCONN:
 				/* D-Channel is up */
-                                switch (lp->dialstate) {
-                                        case 4:
-                                        case 7:
-                                        case 8:
-                                                lp->dialstate++;
-                                                return 1;
-                                        case 12:
-                                                lp->dialstate = 5;
-                                                return 1;
-                                }
+				switch (lp->dialstate) {
+					case 4:
+					case 7:
+					case 8:
+						lp->dialstate++;
+						return 1;
+					case 12:
+						lp->dialstate = 5;
+						return 1;
+				}
 				break;
 			case ISDN_STAT_DHUP:
 				/* Either D-Channel-hangup or error during dialout */
 				if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
 					lp->flags &= ~ISDN_NET_CONNECTED;
-					if(lp->first_skb) {
-						dev_kfree_skb(lp->first_skb,FREE_WRITE);
+					if (lp->first_skb) {
+						dev_kfree_skb(lp->first_skb, FREE_WRITE);
 						lp->first_skb = NULL;
 					}
-					if(lp->sav_skb) {
-						dev_kfree_skb(lp->sav_skb,FREE_WRITE);
+					if (lp->sav_skb) {
+						dev_kfree_skb(lp->sav_skb, FREE_WRITE);
 						lp->sav_skb = NULL;
 					}
 					isdn_free_channel(lp->isdn_device, lp->isdn_channel,
-                                                          ISDN_USAGE_NET);
+							  ISDN_USAGE_NET);
 #ifdef CONFIG_ISDN_PPP
 					isdn_ppp_free(lp);
 #endif
@@ -380,49 +464,51 @@
 					lp->isdn_channel = -1;
 					dev->st_netdev[idx] = NULL;
 					dev->rx_netdev[idx] = NULL;
-                                        return 1;
+					return 1;
 				}
-                                break;
+				break;
 			case ISDN_STAT_BCONN:
 				/* B-Channel is up */
-                                switch (lp->dialstate) {
-                                        case 5:
-                                        case 6:
-                                        case 7:
-                                        case 8:
-                                        case 9:
-                                        case 10:
-                                        case 12:
-                                                if (lp->dialstate <= 6) {
-                                                        dev->usage[idx] |= ISDN_USAGE_OUTGOING;
-                                                        isdn_info_update();
-                                                } else
-                                                        dev->rx_netdev[idx] = p;
-                                                lp->dialstate = 0;
-                                                isdn_timer_ctrl(ISDN_TIMER_NETHANGUP,1);
-                                                printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
-                                                /* If first Chargeinfo comes before B-Channel connect,
-                                                 * we correct the timestamp here.
-                                                 */
-                                                lp->chargetime = jiffies;
-                                                /* Immediately send first skb to speed up arp */
+				switch (lp->dialstate) {
+					case 5:
+					case 6:
+					case 7:
+					case 8:
+					case 9:
+					case 10:
+					case 12:
+						if (lp->dialstate <= 6) {
+							dev->usage[idx] |= ISDN_USAGE_OUTGOING;
+							isdn_info_update();
+						} else
+							dev->rx_netdev[idx] = p;
+						lp->dialstate = 0;
+						isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
+						printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
+						/* If first Chargeinfo comes before B-Channel connect,
+						 * we correct the timestamp here.
+						 */
+						lp->chargetime = jiffies;
+						printk(KERN_DEBUG "isdn_net: chargetime of %s now %d\n",
+						lp->name, lp->chargetime);
+						/* Immediately send first skb to speed up arp */
 #ifdef CONFIG_ISDN_PPP
-						if(lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
 							isdn_ppp_wakeup_daemon(lp);
 #endif
-                                                if (lp->first_skb) {
-                                                        if (!(isdn_net_xmit(&p->dev,lp,lp->first_skb)))
-                                                                lp->first_skb = NULL;
-                                                }
-                                                return 1;
+						if (lp->first_skb) {
+							if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
+								lp->first_skb = NULL;
+						}
+						return 1;
 				}
 				break;
 			case ISDN_STAT_NODCH:
 				/* No D-Channel avail. */
 				if (lp->dialstate == 4) {
 					lp->dialstate--;
-                                        return 1;
-                                }
+					return 1;
+				}
 				break;
 			case ISDN_STAT_CINF:
 				/* Charge-info from TelCo. Calculate interval between
@@ -430,17 +516,19 @@
 				 * usage by isdn_net_autohup()
 				 */
 				lp->charge++;
-				if (lp->hupflags & 2) {
-					lp->hupflags &= ~1;
+				if (lp->hupflags & ISDN_HAVECHARGE) {
+					lp->hupflags &= ~ISDN_WAITCHARGE;
 					lp->chargeint = jiffies - lp->chargetime - (2 * HZ);
 				}
-				if (lp->hupflags & 1)
-					lp->hupflags |= 2;
+				if (lp->hupflags & ISDN_WAITCHARGE)
+					lp->hupflags |= ISDN_HAVECHARGE;
 				lp->chargetime = jiffies;
+				printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %d\n",
+				       lp->name, lp->chargetime);
 				return 1;
-                }
+		}
 	}
-        return 0;
+	return 0;
 }
 
 /*
@@ -473,191 +561,220 @@
 	isdn_net_dev *p = dev->netdev;
 	int anymore = 0;
 	int i;
+	int flags;
 	isdn_ctrl cmd;
 
 	while (p) {
 #ifdef ISDN_DEBUG_NET_DIAL
-                if (p->local.dialstate)
-                        printk(KERN_DEBUG "%s: dialstate=%d\n", p->local.name,p->local.dialstate);
+		if (p->local.dialstate)
+			printk(KERN_DEBUG "%s: dialstate=%d\n", p->local.name, p->local.dialstate);
 #endif
 		switch (p->local.dialstate) {
-		case 0:
-			/* Nothing to do for this interface */
-			break;
-		case 1:
-			/* Initiate dialout. Set phone-number-pointer to first number
-			 * of interface.
-			 */
-			p->local.dial = p->local.phone[1];
-			anymore = 1;
-			p->local.dialstate++;
-			break;
-			/* Prepare dialing. Clear EAZ, then set EAZ. */
-		case 2:
-			cmd.driver = p->local.isdn_device;
-			cmd.arg = p->local.isdn_channel;
-			cmd.command = ISDN_CMD_CLREAZ;
-			dev->drv[p->local.isdn_device]->interface->command(&cmd);
-			sprintf(cmd.num, "%s", isdn_map_eaz2msn(p->local.msn, cmd.driver));
-			cmd.command = ISDN_CMD_SETEAZ;
-			dev->drv[p->local.isdn_device]->interface->command(&cmd);
-			p->local.dialretry = 0;
-			anymore = 1;
-			p->local.dialstate++;
-			break;
-		case 3:
-			/* Setup interface, dial current phone-number, switch to next number.
-			 * If list of phone-numbers is exhausted, increment
-			 * retry-counter.
-			 */
-			cmd.driver = p->local.isdn_device;
-			cmd.command = ISDN_CMD_SETL2;
-			cmd.arg = p->local.isdn_channel + (p->local.l2_proto << 8);
-			dev->drv[p->local.isdn_device]->interface->command(&cmd);
-			cmd.driver = p->local.isdn_device;
-			cmd.command = ISDN_CMD_SETL3;
-			cmd.arg = p->local.isdn_channel + (p->local.l3_proto << 8);
-			dev->drv[p->local.isdn_device]->interface->command(&cmd);
-			cmd.driver = p->local.isdn_device;
-			cmd.arg = p->local.isdn_channel;
-			p->local.huptimer = 0;
-			p->local.outgoing = 1;
-			p->local.hupflags |= 1;
-                        p->local.hupflags &= ~2;
-			if (!strcmp(p->local.dial->num, "LEASED")) {
-				p->local.dialstate = 4;
-				printk(KERN_INFO "%s: Open leased line ...\n", p->local.name);
-			} else {
-				cmd.command = ISDN_CMD_DIAL;
-				sprintf(cmd.num, "%s,%s,7,0", p->local.dial->num,
-				  isdn_map_eaz2msn(p->local.msn, cmd.driver));
-				i = isdn_dc2minor(p->local.isdn_device, p->local.isdn_channel);
-				if (i >= 0) {
-					strcpy(dev->num[i], p->local.dial->num);
-					isdn_info_update();
+			case 0:
+				/* Nothing to do for this interface */
+				break;
+			case 1:
+				/* Initiate dialout. Set phone-number-pointer to first number
+				 * of interface.
+				 */
+				save_flags(flags);
+				cli();
+				p->local.dial = p->local.phone[1];
+				restore_flags(flags);
+				if (!p->local.dial) {
+					printk(KERN_WARNING "%s: phone number deleted?\n",
+					       p->local.name);
+					isdn_net_hangup(&p->dev);
+					break;
 				}
-				printk(KERN_INFO "%s: dialing %d %s...\n", p->local.name,
-				 p->local.dialretry, p->local.dial->num);
-				/*
-				 * Switch to next number or back to start if at end of list.
+				anymore = 1;
+				p->local.dialstate++;
+				/* Fall through */
+			case 2:
+				/* Prepare dialing. Clear EAZ, then set EAZ. */
+				cmd.driver = p->local.isdn_device;
+				cmd.arg = p->local.isdn_channel;
+				cmd.command = ISDN_CMD_CLREAZ;
+				dev->drv[p->local.isdn_device]->interface->command(&cmd);
+				sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(p->local.msn, cmd.driver));
+				cmd.command = ISDN_CMD_SETEAZ;
+				dev->drv[p->local.isdn_device]->interface->command(&cmd);
+				p->local.dialretry = 0;
+				anymore = 1;
+				p->local.dialstate++;
+				/* Falls through */
+			case 3:
+				/* Setup interface, dial current phone-number, switch to next number.
+				 * If list of phone-numbers is exhausted, increment
+				 * retry-counter.
 				 */
-				if (!(p->local.dial = (isdn_net_phone *) p->local.dial->next)) {
-					p->local.dial = p->local.phone[1];
-					p->local.dialretry++;
+				cmd.driver = p->local.isdn_device;
+				cmd.command = ISDN_CMD_SETL2;
+				cmd.arg = p->local.isdn_channel + (p->local.l2_proto << 8);
+				dev->drv[p->local.isdn_device]->interface->command(&cmd);
+				cmd.driver = p->local.isdn_device;
+				cmd.command = ISDN_CMD_SETL3;
+				cmd.arg = p->local.isdn_channel + (p->local.l3_proto << 8);
+				dev->drv[p->local.isdn_device]->interface->command(&cmd);
+				cmd.driver = p->local.isdn_device;
+				cmd.arg = p->local.isdn_channel;
+				save_flags(flags);
+				cli();
+				if (!p->local.dial) {
+					restore_flags(flags);
+					printk(KERN_WARNING "%s: phone number deleted?\n",
+					       p->local.name);
+					isdn_net_hangup(&p->dev);
+					break;
 				}
-				p->local.dtimer = 0;
+				if (!strcmp(p->local.dial->num, "LEASED")) {
+					restore_flags(flags);
+					p->local.dialstate = 4;
+					printk(KERN_INFO "%s: Open leased line ...\n", p->local.name);
+				} else {
+					sprintf(cmd.parm.setup.phone, "%s", p->local.dial->num);
+					/*
+					 * Switch to next number or back to start if at end of list.
+					 */
+					if (!(p->local.dial = (isdn_net_phone *) p->local.dial->next)) {
+						p->local.dial = p->local.phone[1];
+						p->local.dialretry++;
+					}
+					restore_flags(flags);
+					cmd.command = ISDN_CMD_DIAL;
+					cmd.parm.setup.si1 = 7;
+					cmd.parm.setup.si2 = 0;
+					sprintf(cmd.parm.setup.eazmsn, "%s",
+						isdn_map_eaz2msn(p->local.msn, cmd.driver));
+					i = isdn_dc2minor(p->local.isdn_device, p->local.isdn_channel);
+					if (i >= 0) {
+						strcpy(dev->num[i], cmd.parm.setup.phone);
+						isdn_info_update();
+					}
+					printk(KERN_INFO "%s: dialing %d %s...\n", p->local.name,
+					       p->local.dialretry - 1, cmd.parm.setup.phone);
+					p->local.dtimer = 0;
 #ifdef ISDN_DEBUG_NET_DIAL
-				printk(KERN_DEBUG "dial: d=%d c=%d\n", p->local.isdn_device,
-				       p->local.isdn_channel);
+					printk(KERN_DEBUG "dial: d=%d c=%d\n", p->local.isdn_device,
+					       p->local.isdn_channel);
 #endif
+					dev->drv[p->local.isdn_device]->interface->command(&cmd);
+				}
+				p->local.huptimer = 0;
+				p->local.outgoing = 1;
+				if (p->local.chargeint) {
+					p->local.hupflags |= ISDN_HAVECHARGE;
+					p->local.hupflags &= ~ISDN_WAITCHARGE;
+				} else {
+					p->local.hupflags |= ISDN_WAITCHARGE;
+					p->local.hupflags &= ~ISDN_HAVECHARGE;
+				}
+				anymore = 1;
+				p->local.dialstate =
+				    (p->local.cbdelay &&
+				     (p->local.flags & ISDN_NET_CBOUT)) ? 12 : 4;
+				break;
+			case 4:
+				/* Wait for D-Channel-connect.
+				 * If timeout and max retries not
+				 * reached, switch back to state 3.
+				 */
+				if (p->local.dtimer++ > ISDN_TIMER_DTIMEOUT10)
+					if (p->local.dialretry < p->local.dialmax) {
+						p->local.dialstate = 3;
+					} else
+						isdn_net_hangup(&p->dev);
+				anymore = 1;
+				break;
+			case 5:
+				/* Got D-Channel-Connect, send B-Channel-request */
+				cmd.driver = p->local.isdn_device;
+				cmd.arg = p->local.isdn_channel;
+				cmd.command = ISDN_CMD_ACCEPTB;
+				anymore = 1;
+				p->local.dtimer = 0;
+				p->local.dialstate++;
 				dev->drv[p->local.isdn_device]->interface->command(&cmd);
-			}
-			anymore = 1;
-			p->local.dialstate =
-                                (p->local.cbdelay &&
-                                 (p->local.flags & ISDN_NET_CBOUT))?12:4;
-			break;
-		case 4:
-			/* Wait for D-Channel-connect.
-                         * If timeout and max retries not
-			 * reached, switch back to state 3.
-			 */
-			if (p->local.dtimer++ > ISDN_TIMER_DTIMEOUT10)
-				if (p->local.dialretry < p->local.dialmax) {
-					p->local.dialstate = 3;
-				} else
-                                        isdn_net_hangup(&p->dev);
-			anymore = 1;
-			break;
-		case 5:
-			/* Got D-Channel-Connect, send B-Channel-request */
-			cmd.driver = p->local.isdn_device;
-			cmd.arg = p->local.isdn_channel;
-			cmd.command = ISDN_CMD_ACCEPTB;
-			anymore = 1;
-			p->local.dtimer = 0;
-			p->local.dialstate++;
-			dev->drv[p->local.isdn_device]->interface->command(&cmd);
-			break;
-		case 6:
-			/* Wait for B- or D-Channel-connect. If timeout,
-                         * switch back to state 3.
-			 */
+				break;
+			case 6:
+				/* Wait for B- or D-Channel-connect. If timeout,
+				 * switch back to state 3.
+				 */
 #ifdef ISDN_DEBUG_NET_DIAL
-			printk(KERN_DEBUG "dialtimer2: %d\n", p->local.dtimer);
+				printk(KERN_DEBUG "dialtimer2: %d\n", p->local.dtimer);
 #endif
-			if (p->local.dtimer++ > ISDN_TIMER_DTIMEOUT10)
-				p->local.dialstate = 3;
-			anymore = 1;
-			break;
-		case 7:
-			/* Got incoming Call, setup L2 and L3 protocols,
-                         * then wait for D-Channel-connect
-                         */
+				if (p->local.dtimer++ > ISDN_TIMER_DTIMEOUT10)
+					p->local.dialstate = 3;
+				anymore = 1;
+				break;
+			case 7:
+				/* Got incoming Call, setup L2 and L3 protocols,
+				 * then wait for D-Channel-connect
+				 */
 #ifdef ISDN_DEBUG_NET_DIAL
-			printk(KERN_DEBUG "dialtimer4: %d\n", p->local.dtimer);
+				printk(KERN_DEBUG "dialtimer4: %d\n", p->local.dtimer);
 #endif
-			cmd.driver = p->local.isdn_device;
-			cmd.command = ISDN_CMD_SETL2;
-			cmd.arg = p->local.isdn_channel + (p->local.l2_proto << 8);
-			dev->drv[p->local.isdn_device]->interface->command(&cmd);
-			cmd.driver = p->local.isdn_device;
-			cmd.command = ISDN_CMD_SETL3;
-			cmd.arg = p->local.isdn_channel + (p->local.l3_proto << 8);
-			dev->drv[p->local.isdn_device]->interface->command(&cmd);
-			if (p->local.dtimer++ > ISDN_TIMER_DTIMEOUT15)
-				isdn_net_hangup(&p->dev);
-			else {
+				cmd.driver = p->local.isdn_device;
+				cmd.command = ISDN_CMD_SETL2;
+				cmd.arg = p->local.isdn_channel + (p->local.l2_proto << 8);
+				dev->drv[p->local.isdn_device]->interface->command(&cmd);
+				cmd.driver = p->local.isdn_device;
+				cmd.command = ISDN_CMD_SETL3;
+				cmd.arg = p->local.isdn_channel + (p->local.l3_proto << 8);
+				dev->drv[p->local.isdn_device]->interface->command(&cmd);
+				if (p->local.dtimer++ > ISDN_TIMER_DTIMEOUT15)
+					isdn_net_hangup(&p->dev);
+				else {
+					anymore = 1;
+					p->local.dialstate++;
+				}
+				break;
+			case 9:
+				/* Got incoming D-Channel-Connect, send B-Channel-request */
+				cmd.driver = p->local.isdn_device;
+				cmd.arg = p->local.isdn_channel;
+				cmd.command = ISDN_CMD_ACCEPTB;
+				dev->drv[p->local.isdn_device]->interface->command(&cmd);
 				anymore = 1;
-                                p->local.dialstate++;
-                        }
-			break;
-		case 9:
-			/* Got incoming D-Channel-Connect, send B-Channel-request */
-			cmd.driver = p->local.isdn_device;
-			cmd.arg = p->local.isdn_channel;
-			cmd.command = ISDN_CMD_ACCEPTB;
-			dev->drv[p->local.isdn_device]->interface->command(&cmd);
-			anymore = 1;
-			p->local.dtimer = 0;
-			p->local.dialstate++;
-			break;
-		case 8:
-                case 10:
-			/*  Wait for B- or D-channel-connect */
+				p->local.dtimer = 0;
+				p->local.dialstate++;
+				break;
+			case 8:
+			case 10:
+				/*  Wait for B- or D-channel-connect */
 #ifdef ISDN_DEBUG_NET_DIAL
-			printk(KERN_DEBUG "dialtimer4: %d\n", p->local.dtimer);
+				printk(KERN_DEBUG "dialtimer4: %d\n", p->local.dtimer);
 #endif
-			if (p->local.dtimer++ > ISDN_TIMER_DTIMEOUT10)
-				isdn_net_hangup(&p->dev);
-			else
+				if (p->local.dtimer++ > ISDN_TIMER_DTIMEOUT10)
+					isdn_net_hangup(&p->dev);
+				else
+					anymore = 1;
+				break;
+			case 11:
+				/* Callback Delay */
+				if (p->local.dtimer++ > p->local.cbdelay)
+					p->local.dialstate = 1;
 				anymore = 1;
-			break;
-                case 11:
-                        /* Callback Delay */
-                        if (p->local.dtimer++ > p->local.cbdelay)
-                                p->local.dialstate = 1;
-                        anymore = 1;
-                        break;
-		case 12:
-			/* Remote does callback. Hangup after cbdelay, then wait for incoming
-                         * call (in state 4).
-			 */
-                        if (p->local.dtimer++ > p->local.cbdelay) {
-                                printk(KERN_INFO "%s: hangup waiting for callback ...\n", p->local.name);
-                                p->local.dtimer = 0;
-                                p->local.dialstate = 4;
-                                cmd.driver = p->local.isdn_device;
-                                cmd.command = ISDN_CMD_HANGUP;
-                                cmd.arg = p->local.isdn_channel;
-                                (void) dev->drv[cmd.driver]->interface->command(&cmd);
-                                isdn_all_eaz(p->local.isdn_device, p->local.isdn_channel);
-                        }
-                        anymore = 1;
-			break;
-		default:
-			printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
-			       p->local.dialstate, p->local.name);
+				break;
+			case 12:
+				/* Remote does callback. Hangup after cbdelay, then wait for incoming
+				 * call (in state 4).
+				 */
+				if (p->local.dtimer++ > p->local.cbdelay) {
+					printk(KERN_INFO "%s: hangup waiting for callback ...\n", p->local.name);
+					p->local.dtimer = 0;
+					p->local.dialstate = 4;
+					cmd.driver = p->local.isdn_device;
+					cmd.command = ISDN_CMD_HANGUP;
+					cmd.arg = p->local.isdn_channel;
+					(void) dev->drv[cmd.driver]->interface->command(&cmd);
+					isdn_all_eaz(p->local.isdn_device, p->local.isdn_channel);
+				}
+				anymore = 1;
+				break;
+			default:
+				printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
+				       p->local.dialstate, p->local.name);
 		}
 		p = (isdn_net_dev *) p->next;
 	}
@@ -674,6 +791,7 @@
 	isdn_ctrl cmd;
 
 	if (lp->flags & ISDN_NET_CONNECTED) {
+		lp->flags &= ~ISDN_NET_CONNECTED;
 		printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
 #ifdef CONFIG_ISDN_PPP
 		isdn_ppp_free(lp);
@@ -685,7 +803,7 @@
 		printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
 		isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
 	}
-        isdn_net_unbind_channel(lp);
+	isdn_net_unbind_channel(lp);
 }
 
 typedef struct {
@@ -696,59 +814,59 @@
 static void
 isdn_net_log_packet(u_char * buf, isdn_net_local * lp)
 {
-        u_char *p = buf;
+	u_char *p = buf;
 	unsigned short proto = ETH_P_IP;
-        int data_ofs;
+	int data_ofs;
 	ip_ports *ipp;
 	char addinfo[100];
 
-        addinfo[0] = '\0';
-        switch (lp->p_encap) {
-                case ISDN_NET_ENCAP_IPTYP:
-                        proto = ntohs(*(unsigned short *)&buf[0]);
-                        p = &buf[2];
-                        break;
-                case ISDN_NET_ENCAP_ETHER:
-                        proto = ntohs(*(unsigned short *)&buf[12]);
-                        p = &buf[14];
-                        break;
-                case ISDN_NET_ENCAP_CISCOHDLC:
-                        proto = ntohs(*(unsigned short *)&buf[2]);
-                        p = &buf[4];
-                        break;
-        }
+	addinfo[0] = '\0';
+	switch (lp->p_encap) {
+		case ISDN_NET_ENCAP_IPTYP:
+			proto = ntohs(*(unsigned short *) &buf[0]);
+			p = &buf[2];
+			break;
+		case ISDN_NET_ENCAP_ETHER:
+			proto = ntohs(*(unsigned short *) &buf[12]);
+			p = &buf[14];
+			break;
+		case ISDN_NET_ENCAP_CISCOHDLC:
+			proto = ntohs(*(unsigned short *) &buf[2]);
+			p = &buf[4];
+			break;
+	}
 	data_ofs = ((p[0] & 15) * 4);
-        switch (proto) {
+	switch (proto) {
 		case ETH_P_IP:
 			switch (p[9]) {
-                                case 1:
-                                        strcpy(addinfo, " ICMP");
-                                        break;
-                                case 2:
-                                        strcpy(addinfo, " IGMP");
-                                        break;
-                                case 4:
-                                        strcpy(addinfo, " IPIP");
-                                        break;
-                                case 6:
-                                        ipp = (ip_ports *) (&p[data_ofs]);
-                                        sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source),
-                                                ntohs(ipp->dest));
-                                        break;
-                                case 8:
-                                        strcpy(addinfo, " EGP");
-                                        break;
-                                case 12:
-                                        strcpy(addinfo, " PUP");
-                                        break;
-                                case 17:
-                                        ipp = (ip_ports *) (&p[data_ofs]);
-                                        sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source),
-                                                ntohs(ipp->dest));
-                                        break;
-                                case 22:
-                                        strcpy(addinfo, " IDP");
-                                        break;
+				case 1:
+					strcpy(addinfo, " ICMP");
+					break;
+				case 2:
+					strcpy(addinfo, " IGMP");
+					break;
+				case 4:
+					strcpy(addinfo, " IPIP");
+					break;
+				case 6:
+					ipp = (ip_ports *) (&p[data_ofs]);
+					sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source),
+						ntohs(ipp->dest));
+					break;
+				case 8:
+					strcpy(addinfo, " EGP");
+					break;
+				case 12:
+					strcpy(addinfo, " PUP");
+					break;
+				case 17:
+					ipp = (ip_ports *) (&p[data_ofs]);
+					sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source),
+						ntohs(ipp->dest));
+					break;
+				case 22:
+					strcpy(addinfo, " IDP");
+					break;
 			}
 			printk(KERN_INFO "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
 			       p[12], p[13], p[14], p[15],
@@ -760,7 +878,7 @@
 			       p[14], p[15], p[16], p[17],
 			       p[24], p[25], p[26], p[27]);
 			break;
-        }
+	}
 }
 
 /*
@@ -772,28 +890,27 @@
  * Side-effects: ndev->tbusy is cleared on success.
  */
 int
-isdn_net_send_skb(struct device *ndev, isdn_net_local *lp,
-                  struct sk_buff *skb)
+isdn_net_send_skb(struct device *ndev, isdn_net_local * lp,
+		  struct sk_buff *skb)
 {
 	int ret;
-	int len = skb->len;	/* save len */
-	
-        ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, skb);
+	int len = skb->len;     /* save len */
+
+	ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, skb);
 	if (ret == len) {
 		lp->transcount += len;
-		clear_bit(0, (void *)&(ndev->tbusy));
+		clear_bit(0, (void *) &(ndev->tbusy));
+		return 0;
+	}
+	if (ret < 0) {
+		dev_kfree_skb(skb, FREE_WRITE);
+		lp->stats.tx_errors++;
+		clear_bit(0, (void *) &(ndev->tbusy));
 		return 0;
 	}
-        if (ret < 0) {
-                skb->free = 1;
-                dev_kfree_skb(skb, FREE_WRITE);
-                lp->stats.tx_errors++;
-                clear_bit(0, (void *)&(ndev->tbusy));
-                return 0;
-        }
 	return 1;
-}                                      
-	
+}
+
 
 /*
  *  Helper function for isdn_net_start_xmit.
@@ -807,23 +924,23 @@
  */
 
 static int
-isdn_net_xmit(struct device *ndev, isdn_net_local *lp, struct sk_buff *skb) 
+isdn_net_xmit(struct device *ndev, isdn_net_local * lp, struct sk_buff *skb)
 {
-        int ret;
+	int ret;
 
 	/* For the other encaps the header has already been built */
 #ifdef CONFIG_ISDN_PPP
 	if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
 		return isdn_ppp_xmit(skb, ndev);
 	}
-#endif		
+#endif
 	/* Reset hangup-timeout */
 	lp->huptimer = 0;
-	if (lp->cps > 7000) {
+	if (lp->cps > lp->triggercps) {
 		/* Device overloaded */
 
-		/* 
-		 * Packet-delivery via round-robin over master 
+		/*
+		 * Packet-delivery via round-robin over master
 		 * and all connected slaves.
 		 */
 		if (lp->master)
@@ -847,18 +964,16 @@
 				/* First time overload: set timestamp only */
 				lp->sqfull = 1;
 				lp->sqfull_stamp = jiffies;
-			} 
-			else {
+			} else {
 				/* subsequent overload: if slavedelay exceeded, start dialing */
 				if ((jiffies - lp->sqfull_stamp) > lp->slavedelay)
 					isdn_net_force_dial_lp((isdn_net_local *) lp->slave->priv);
 			}
 		}
-	} 
-	else {
+	} else {
 		/* Not overloaded, deliver locally */
 		ret = isdn_net_send_skb(ndev, lp, skb);
-		if (lp->sqfull && ((jiffies - lp->sqfull_stamp) > (lp->slavedelay + (10*HZ) )))
+		if (lp->sqfull && ((jiffies - lp->sqfull_stamp) > (lp->slavedelay + (10 * HZ))))
 			lp->sqfull = 0;
 	}
 	return ret;
@@ -877,8 +992,8 @@
 	if (ndev->tbusy) {
 		if (jiffies - ndev->trans_start < (2 * HZ))
 			return 1;
-                if (!lp->dialstate)
-                        lp->stats.tx_errors++;
+		if (!lp->dialstate)
+			lp->stats.tx_errors++;
 		ndev->tbusy = 0;
 		ndev->trans_start = jiffies;
 	}
@@ -887,10 +1002,10 @@
 		return 0;
 	}
 	/* Avoid timer-based retransmission conflicts. */
-	if (set_bit(0, (void *) &ndev->tbusy) != 0)
+	if (test_and_set_bit(0, (void *) &ndev->tbusy) != 0)
 		printk(KERN_WARNING
-                       "%s: Transmitter access conflict.\n",
-                       ndev->name);
+		       "%s: Transmitter access conflict.\n",
+		       ndev->name);
 	else {
 		u_char *buf = skb->data;
 #ifdef ISDN_DEBUG_NET_DUMP
@@ -903,23 +1018,31 @@
 				save_flags(flags);
 				cli();
 				/* Grab a free ISDN-Channel */
-				if ((chi = 
-                                     isdn_get_free_channel(ISDN_USAGE_NET,
-                                                           lp->l2_proto,
-                                                           lp->l3_proto,
-                                                           lp->pre_device,
-                                                           lp->pre_channel)) < 0) {
-                                        printk(KERN_WARNING
-                                               "isdn_net_start_xmit: No channel for %s\n",
-                                               ndev->name);
+				if ((chi =
+				     isdn_get_free_channel(ISDN_USAGE_NET,
+							   lp->l2_proto,
+							   lp->l3_proto,
+							   lp->pre_device,
+						 lp->pre_channel)) < 0) {
 					restore_flags(flags);
-		/* we probably should drop the skb here and return 0 to omit
-		   'socket destroy delayed' messages */
+#if 0
+					printk(KERN_WARNING
+					       "isdn_net_start_xmit: No channel for %s\n",
+					       ndev->name);
+					/* we probably should drop the skb here and return 0 to omit
+					   'socket destroy delayed' messages */
 					return 1;
+#else
+					isdn_net_unreachable(ndev, skb,
+							   "No channel");
+					dev_kfree_skb(skb, FREE_WRITE);
+					ndev->tbusy = 0;
+					return 0;
+#endif
 				}
-                                /* Log packet, which triggered dialing */
+				/* Log packet, which triggered dialing */
 				if (dev->net_verbose)
-                                        isdn_net_log_packet(buf, lp);
+					isdn_net_log_packet(buf, lp);
 				lp->dialstate = 1;
 				lp->flags |= ISDN_NET_CONNECTED;
 				/* Connect interface with channel */
@@ -928,59 +1051,47 @@
 				if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
 					/* no 'first_skb' handling for syncPPP */
 					if (isdn_ppp_bind(lp) < 0) {
-                                        	dev_kfree_skb(skb,FREE_WRITE);
+						dev_kfree_skb(skb, FREE_WRITE);
 						isdn_net_unbind_channel(lp);
-                                                restore_flags(flags);
+						restore_flags(flags);
 						return 0;	/* STN (skb to nirvana) ;) */
 					}
 					restore_flags(flags);
-	                                isdn_net_dial();	/* Initiate dialing */
+					isdn_net_dial();	/* Initiate dialing */
 					return 1;	/* let upper layer requeue skb packet */
 				}
 #endif
-                                /* remember first skb to speed up arp
-                                 * when using encap ETHER
-                                 */
-                                if (lp->first_skb) {
-                                        printk(KERN_WARNING "isdn_net_start_xmit: First skb already set!\n");
-                                        dev_kfree_skb(lp->first_skb,FREE_WRITE);
-                                        lp->first_skb = NULL;
-                                }
-                                lp->first_skb = skb;
+				/* remember first skb to speed up arp
+				 * when using encap ETHER
+				 */
+				if (lp->first_skb) {
+					printk(KERN_WARNING "isdn_net_start_xmit: First skb already set!\n");
+					dev_kfree_skb(lp->first_skb, FREE_WRITE);
+					lp->first_skb = NULL;
+				}
+				lp->first_skb = skb;
 				/* Initiate dialing */
-                                ndev->tbusy = 0;
+				ndev->tbusy = 0;
 				restore_flags(flags);
 				isdn_net_dial();
-                                return 0;
+				return 0;
 			} else {
-                                /*
-                                 * Having no phone-number is a permanent
-                                 * failure or misconfiguration.
-                                 * Instead of just dropping, we should also
-                                 * have the upper layers to respond
-                                 * with an ICMP No route to host in the
-                                 * future, however at the moment, i don't
-                                 * know a simple way to do that.
-                                 * The same applies, when the telecom replies
-                                 * "no destination" to our dialing-attempt.
-                                 */
-                                printk(KERN_WARNING
-                                       "isdn_net: No phone number for %s, packet dropped\n",
-                                       ndev->name);
+				isdn_net_unreachable(ndev, skb,
+						     "No phone number");
 				dev_kfree_skb(skb, FREE_WRITE);
 				ndev->tbusy = 0;
-                                return 0;
+				return 0;
 			}
 		} else {
-                        /* Connection is established, try sending */
+			/* Connection is established, try sending */
 			ndev->trans_start = jiffies;
 			if (!lp->dialstate) {
-                                if (lp->first_skb) {
-                                        if (isdn_net_xmit(ndev,lp,lp->first_skb))
-                                                return 1;
-                                        lp->first_skb = NULL;
-                                }
-				return(isdn_net_xmit(ndev, lp, skb));
+				if (lp->first_skb) {
+					if (isdn_net_xmit(ndev, lp, lp->first_skb))
+						return 1;
+					lp->first_skb = NULL;
+				}
+				return (isdn_net_xmit(ndev, lp, skb));
 			} else
 				ndev->tbusy = 1;
 		}
@@ -998,7 +1109,6 @@
 
 	dev->tbusy = 1;
 	dev->start = 0;
-	isdn_net_hangup(dev);
 	if ((p = (((isdn_net_local *) dev->priv)->slave))) {
 		/* If this interface has slaves, stop them also */
 		while (p) {
@@ -1008,6 +1118,7 @@
 			p = (((isdn_net_local *) p->priv)->slave);
 		}
 	}
+	isdn_net_hangup(dev);
 	isdn_MOD_DEC_USE_COUNT();
 	return 0;
 }
@@ -1016,7 +1127,7 @@
  * Get statistics
  */
 static struct enet_statistics *
- isdn_net_get_stats(struct device *dev)
+isdn_net_get_stats(struct device *dev)
 {
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
 	return &lp->stats;
@@ -1031,51 +1142,50 @@
  *      This is normal practice and works for any 'now in use' protocol.
  */
 
-unsigned short isdn_net_type_trans(struct sk_buff *skb, struct device *dev)
+static unsigned short
+isdn_net_type_trans(struct sk_buff *skb, struct device *dev)
 {
-        struct ethhdr *eth;
-        unsigned char *rawp;
-        
-        skb_pull(skb,ETH_HLEN);
-        eth= skb->mac.ethernet;
-        
-        if(*eth->h_dest&1) {
-                if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
-                        skb->pkt_type=PACKET_BROADCAST;
-                else
-                        skb->pkt_type=PACKET_MULTICAST;
-        }
-        
-        /*
-         *      This ALLMULTI check should be redundant by 1.4
-         *      so don't forget to remove it.
-         */
-        
-        else if (dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) {
-                if (memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
-                        skb->pkt_type=PACKET_OTHERHOST;
-        }
-
-        if (ntohs(eth->h_proto) >= 1536)
-                return eth->h_proto;
-
-        rawp = skb->data;
-
-        /*
-         *      This is a magic hack to spot IPX packets. Older Novell breaks
-         *      the protocol design and runs IPX over 802.3 without an 802.2 LLC
-         *      layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
-         *      won't work for fault tolerant netware but does for the rest.
-         */
-        if (*(unsigned short *)rawp == 0xFFFF)
-                return htons(ETH_P_802_3);
-        /*
-         *      Real 802.2 LLC
-         */
-        return htons(ETH_P_802_2);
+	struct ethhdr *eth;
+	unsigned char *rawp;
+
+	skb_pull(skb, ETH_HLEN);
+	eth = skb->mac.ethernet;
+
+	if (*eth->h_dest & 1) {
+		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+			skb->pkt_type = PACKET_BROADCAST;
+		else
+			skb->pkt_type = PACKET_MULTICAST;
+	}
+	/*
+	 *      This ALLMULTI check should be redundant by 1.4
+	 *      so don't forget to remove it.
+	 */
+
+	else if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
+		if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+			skb->pkt_type = PACKET_OTHERHOST;
+	}
+	if (ntohs(eth->h_proto) >= 1536)
+		return eth->h_proto;
+
+	rawp = skb->data;
+
+	/*
+	 *      This is a magic hack to spot IPX packets. Older Novell breaks
+	 *      the protocol design and runs IPX over 802.3 without an 802.2 LLC
+	 *      layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
+	 *      won't work for fault tolerant netware but does for the rest.
+	 */
+	if (*(unsigned short *) rawp == 0xFFFF)
+		return htons(ETH_P_802_3);
+	/*
+	 *      Real 802.2 LLC
+	 */
+	return htons(ETH_P_802_2);
 }
 
-/* 
+/*
  * Got a packet from ISDN-Channel.
  */
 static void
@@ -1083,21 +1193,21 @@
 {
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 #ifdef CONFIG_ISDN_PPP
-        isdn_net_local *olp = lp;  /* original 'lp' */
-        int proto = PPP_PROTOCOL(skb->data);
+	isdn_net_local *olp = lp;	/* original 'lp' */
+	int proto = PPP_PROTOCOL(skb->data);
 #endif
 
 	lp->transcount += skb->len;
 	lp->stats.rx_packets++;
 #ifdef CONFIG_ISDN_PPP
-        /*
-         * If encapsulation is syncppp, don't reset
-         * huptimer on LCP packets.
-         */
-        if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP ||
-            (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && proto != PPP_LCP))
+	/*
+	 * If encapsulation is syncppp, don't reset
+	 * huptimer on LCP packets.
+	 */
+	if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP ||
+	    (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && proto != PPP_LCP))
 #endif
-	        lp->huptimer = 0;
+		lp->huptimer = 0;
 
 	if (lp->master) {
 		/* Bundling: If device is a slave-device, deliver to master, also
@@ -1107,56 +1217,55 @@
 		lp = (isdn_net_local *) ndev->priv;
 		lp->stats.rx_packets++;
 #ifdef CONFIG_ISDN_PPP
-                /*
-                 * If encapsulation is syncppp, don't reset
-                 * huptimer on LCP packets.
-                 */
-                if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP ||
-                    (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && proto != PPP_LCP))
+		/*
+		 * If encapsulation is syncppp, don't reset
+		 * huptimer on LCP packets.
+		 */
+		if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP ||
+		    (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && proto != PPP_LCP))
 #endif
-                        lp->huptimer = 0;
+			lp->huptimer = 0;
 	}
-
 	skb->dev = ndev;
 	skb->pkt_type = PACKET_HOST;
-        skb->mac.raw = skb->data;
+	skb->mac.raw = skb->data;
 #ifdef ISDN_DEBUG_NET_DUMP
-        isdn_dumppkt("R:", skb->data, skb->len, 40);
+	isdn_dumppkt("R:", skb->data, skb->len, 40);
 #endif
 	switch (lp->p_encap) {
-                case ISDN_NET_ENCAP_ETHER:
-                        /* Ethernet over ISDN */
-                        skb->protocol = isdn_net_type_trans(skb,ndev);
-                        break;
-                case ISDN_NET_ENCAP_UIHDLC:
-                        /* HDLC with UI-frame (for ispa with -h1 option) */
-                        skb_pull(skb,2);
-                        /* Fall through */
-                case ISDN_NET_ENCAP_RAWIP:
-                        /* RAW-IP without MAC-Header */
-                        skb->protocol = htons(ETH_P_IP);
-                        break;
-                case ISDN_NET_ENCAP_CISCOHDLC:
-                        /* CISCO-HDLC IP with type field and  fake I-frame-header */
-                        skb_pull(skb, 2);
-                        /* Fall through */
-                case ISDN_NET_ENCAP_IPTYP:
-                        /* IP with type field */
-                        skb->protocol = *(unsigned short *)&(skb->data[0]);
-                        skb_pull(skb, 2);
-                        if (*(unsigned short *)skb->data == 0xFFFF)
-                                skb->protocol = htons(ETH_P_802_3);
-                        break;
+		case ISDN_NET_ENCAP_ETHER:
+			/* Ethernet over ISDN */
+			skb->protocol = isdn_net_type_trans(skb, ndev);
+			break;
+		case ISDN_NET_ENCAP_UIHDLC:
+			/* HDLC with UI-frame (for ispa with -h1 option) */
+			skb_pull(skb, 2);
+			/* Fall through */
+		case ISDN_NET_ENCAP_RAWIP:
+			/* RAW-IP without MAC-Header */
+			skb->protocol = htons(ETH_P_IP);
+			break;
+		case ISDN_NET_ENCAP_CISCOHDLC:
+			/* CISCO-HDLC IP with type field and  fake I-frame-header */
+			skb_pull(skb, 2);
+			/* Fall through */
+		case ISDN_NET_ENCAP_IPTYP:
+			/* IP with type field */
+			skb->protocol = *(unsigned short *) &(skb->data[0]);
+			skb_pull(skb, 2);
+			if (*(unsigned short *) skb->data == 0xFFFF)
+				skb->protocol = htons(ETH_P_802_3);
+			break;
 #ifdef CONFIG_ISDN_PPP
-                case ISDN_NET_ENCAP_SYNCPPP:
-                        isdn_ppp_receive(lp->netdev, olp, skb);
-                        return;
-#endif
-                default:
-                        printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
-                               lp->name);
-                        kfree_skb(skb,FREE_READ);
-                        return;
+		case ISDN_NET_ENCAP_SYNCPPP:
+			isdn_ppp_receive(lp->netdev, olp, skb);
+			return;
+#endif
+		default:
+			printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
+			       lp->name);
+			kfree_skb(skb, FREE_READ);
+			return;
 	}
 	netif_rx(skb);
 	return;
@@ -1168,34 +1277,7 @@
  * else return 0.
  */
 int
-isdn_net_receive_callback(int idx, u_char * buf, int len)
-{
-	isdn_net_dev *p = dev->rx_netdev[idx];
-	struct sk_buff *skb;
-
-	if (p) {
-		isdn_net_local *lp = &p->local;
-		if ((lp->flags & ISDN_NET_CONNECTED) &&
-		    (!lp->dialstate)) {
-			skb = dev_alloc_skb(len);
-			if (skb == NULL) {
-				printk(KERN_WARNING "out of memory\n");
-				return 0;
-			}
-			memcpy(skb_put(skb, len), buf, len);
-			isdn_net_receive(&p->dev, skb);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- *  receive callback for lowlevel drivers, which support skb's
- */
-
-int
-isdn_net_rcv_skb(int idx, struct sk_buff *skb) 
+isdn_net_rcv_skb(int idx, struct sk_buff *skb)
 {
 	isdn_net_dev *p = dev->rx_netdev[idx];
 
@@ -1212,43 +1294,41 @@
 
 static int
 my_eth_header(struct sk_buff *skb, struct device *dev, unsigned short type,
-              void *daddr, void *saddr, unsigned len)
+	      void *daddr, void *saddr, unsigned len)
 {
-	struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
+	struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
 
-	/* 
+	/*
 	 * Set the protocol type. For a packet of type ETH_P_802_3 we
-         * put the length here instead. It is up to the 802.2 layer to
-         * carry protocol information.
+	 * put the length here instead. It is up to the 802.2 layer to
+	 * carry protocol information.
 	 */
-	
-	if(type!=ETH_P_802_3) 
+
+	if (type != ETH_P_802_3)
 		eth->h_proto = htons(type);
 	else
 		eth->h_proto = htons(len);
 
 	/*
-	 *	Set the source hardware address. 
+	 * Set the source hardware address.
 	 */
-	if(saddr)
-		memcpy(eth->h_source,saddr,dev->addr_len);
+	if (saddr)
+		memcpy(eth->h_source, saddr, dev->addr_len);
 	else
-		memcpy(eth->h_source,dev->dev_addr,dev->addr_len);
+		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
 
 	/*
-	 *	Anyway, the loopback-device should never use this function... 
+	 * Anyway, the loopback-device should never use this function...
 	 */
 
 	if (dev->flags & IFF_LOOPBACK) {
 		memset(eth->h_dest, 0, dev->addr_len);
-		return(dev->hard_header_len);
+		return (dev->hard_header_len);
 	}
-	
-	if(daddr) {
-		memcpy(eth->h_dest,daddr,dev->addr_len);
+	if (daddr) {
+		memcpy(eth->h_dest, daddr, dev->addr_len);
 		return dev->hard_header_len;
 	}
-	
 	return -dev->hard_header_len;
 }
 
@@ -1256,76 +1336,114 @@
  *  build an header
  *  depends on encaps that is being used.
  */
- 
+
 static int
 isdn_net_header(struct sk_buff *skb, struct device *dev, unsigned short type,
-                void *daddr, void *saddr, unsigned plen)
+		void *daddr, void *saddr, unsigned plen)
 {
 	isdn_net_local *lp = dev->priv;
 	ushort len = 0;
-	
+
 	switch (lp->p_encap) {
-                case ISDN_NET_ENCAP_ETHER:
-                        len = my_eth_header(skb, dev, type, daddr, saddr, plen);
-                        break;
-                case ISDN_NET_ENCAP_RAWIP:
-                        printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n");
+		case ISDN_NET_ENCAP_ETHER:
+			len = my_eth_header(skb, dev, type, daddr, saddr, plen);
+			break;
+#ifdef CONFIG_ISDN_PPP
+		case ISDN_NET_ENCAP_SYNCPPP:
+			/* stick on a fake header to keep fragmentation code happy. */
+			len = IPPP_MAX_HEADER;
+			skb_push(skb,len);
+			break;
+#endif
+		case ISDN_NET_ENCAP_RAWIP:
+			printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n");
 			len = 0;
-                        break;
-                case ISDN_NET_ENCAP_IPTYP:
-                        /* ethernet type field */
-                        *((ushort*) skb_push(skb, 2)) = htons(type);
-                        len = 2;
-                        break;
-                case ISDN_NET_ENCAP_UIHDLC:
-                        /* HDLC with UI-Frames (for ispa with -h1 option) */
-                        *((ushort*) skb_push(skb, 2)) = htons(0x0103);
-                        len = 2;
-                        break;
-                case ISDN_NET_ENCAP_CISCOHDLC:
+			break;
+		case ISDN_NET_ENCAP_IPTYP:
+			/* ethernet type field */
+			*((ushort *) skb_push(skb, 2)) = htons(type);
+			len = 2;
+			break;
+		case ISDN_NET_ENCAP_UIHDLC:
+			/* HDLC with UI-Frames (for ispa with -h1 option) */
+			*((ushort *) skb_push(skb, 2)) = htons(0x0103);
+			len = 2;
+			break;
+		case ISDN_NET_ENCAP_CISCOHDLC:
 			skb_push(skb, 4);
-                        skb->data[0] = 0x0f;
-                        skb->data[1] = 0x00;
-                        *((ushort*)&skb->data[2]) = htons(type);
-                        len = 4;
-                        break;
+			skb->data[0] = 0x0f;
+			skb->data[1] = 0x00;
+			*((ushort *) & skb->data[2]) = htons(type);
+			len = 4;
+			break;
 	}
 	return len;
 }
 
 /* We don't need to send arp, because we have point-to-point connections. */
-
+#if (LINUX_VERSION_CODE < 0x02010F)
 static int
 isdn_net_rebuild_header(void *buff, struct device *dev, unsigned long dst,
-                        struct sk_buff *skb)
+			struct sk_buff *skb)
 {
 	isdn_net_local *lp = dev->priv;
-        int ret = 0;
+	int ret = 0;
+
+	if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
+		struct ethhdr *eth = (struct ethhdr *) buff;
+
+		/*
+		 *      Only ARP/IP is currently supported
+		 */
 
-        if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
-                struct ethhdr *eth = (struct ethhdr *)buff;
-                
-                /*
-                 *      Only ARP/IP is currently supported
-                 */
-                
-                if(eth->h_proto != htons(ETH_P_IP)) {
-                        printk(KERN_WARNING
-                               "isdn_net: %s don't know how to resolve type %d addresses?\n",
-                               dev->name, (int)eth->h_proto);
-                        memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-                        return 0;
-                }
-                /*
-                 *      Try to get ARP to resolve the header.
-                 */
-#ifdef CONFIG_INET       
-                ret = arp_find(eth->h_dest, dst, dev, dev->pa_addr, skb)? 1 : 0;
-#endif  
-        }
+		if (eth->h_proto != htons(ETH_P_IP)) {
+			printk(KERN_WARNING
+			       "isdn_net: %s don't know how to resolve type %d addresses?\n",
+			       dev->name, (int) eth->h_proto);
+			memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+			return 0;
+		}
+		/*
+		 *      Try to get ARP to resolve the header.
+		 */
+#ifdef CONFIG_INET
+		ret = arp_find(eth->h_dest, dst, dev, dev->pa_addr, skb) ? 1 : 0;
+#endif
+	}
 	return ret;
 }
+#else
+static int
+isdn_net_rebuild_header(struct sk_buff *skb)
+{
+	struct device *dev = skb->dev;
+	isdn_net_local *lp = dev->priv;
+	int ret = 0;
+
+	if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
+		struct ethhdr *eth = (struct ethhdr *) skb->data;
 
+		/*
+		 *      Only ARP/IP is currently supported
+		 */
+
+		if (eth->h_proto != htons(ETH_P_IP)) {
+			printk(KERN_WARNING
+			       "isdn_net: %s don't know how to resolve type %d addresses?\n",
+			       dev->name, (int) eth->h_proto);
+			memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+			return 0;
+		}
+		/*
+		 *      Try to get ARP to resolve the header.
+		 */
+#ifdef CONFIG_INET
+		ret = arp_find(eth->h_dest, skb) ? 1 : 0;
+#endif
+	}
+	return ret;
+}
+#endif
 /*
  * Interface-setup. (called just after registering a new interface)
  */
@@ -1333,8 +1451,9 @@
 isdn_net_init(struct device *ndev)
 {
 	ushort max_hlhdr_len = 0;
-        isdn_net_local *lp = (isdn_net_local *)ndev->priv;
-	int drvidx, i;
+	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+	int drvidx,
+	 i;
 
 	if (ndev == NULL) {
 		printk(KERN_WARNING "isdn_net_init: dev = NULL!\n");
@@ -1344,54 +1463,61 @@
 		printk(KERN_WARNING "isdn_net_init: dev->priv = NULL!\n");
 		return -ENODEV;
 	}
-
-        ether_setup(ndev);
-        lp->org_hcb               = ndev->header_cache_bind;
-        lp->org_hcu               = ndev->header_cache_update;
+	ether_setup(ndev);
+#if (LINUX_VERSION_CODE < 0x02010F)
+	lp->org_hcb = ndev->header_cache_bind;
+#else
+	lp->org_hhc = ndev->hard_header_cache;
+#endif
+	lp->org_hcu = ndev->header_cache_update;
 
 	/* Setup the generic properties */
 
-        ndev->hard_header         = NULL;
-        ndev->header_cache_bind   = NULL;
-        ndev->header_cache_update = NULL;
-        ndev->mtu                 = 1500;
-        ndev->flags               = IFF_NOARP;
-        ndev->family              = AF_INET;
-        ndev->type                = ARPHRD_ETHER;  
-        ndev->addr_len            = ETH_ALEN;
-        ndev->pa_addr             = 0;
-        ndev->pa_brdaddr          = 0;
-        ndev->pa_mask             = 0;
-        ndev->pa_alen             = 4;
+	ndev->hard_header = NULL;
+#if (LINUX_VERSION_CODE < 0x02010F)
+	ndev->header_cache_bind = NULL;
+#else
+	ndev->hard_header_cache = NULL;
+#endif
+	ndev->header_cache_update = NULL;
+	ndev->mtu = 1500;
+	ndev->flags = IFF_NOARP;
+	ndev->family = AF_INET;
+	ndev->type = ARPHRD_ETHER;
+	ndev->addr_len = ETH_ALEN;
+	ndev->pa_addr = 0;
+	ndev->pa_brdaddr = 0;
+	ndev->pa_mask = 0;
+	ndev->pa_alen = 4;
 
-        for (i = 0; i < ETH_ALEN; i++)
-                ndev->broadcast[i]=0xff;
+	for (i = 0; i < ETH_ALEN; i++)
+		ndev->broadcast[i] = 0xff;
 
 	for (i = 0; i < DEV_NUMBUFFS; i++)
-                skb_queue_head_init(&ndev->buffs[i]);
-	
+		skb_queue_head_init(&ndev->buffs[i]);
+
 	/* The ISDN-specific entries in the device structure. */
-	ndev->open                = &isdn_net_open;
-	ndev->hard_start_xmit     = &isdn_net_start_xmit;
+	ndev->open = &isdn_net_open;
+	ndev->hard_start_xmit = &isdn_net_start_xmit;
 
-	/* 
+	/*
 	 *  up till binding we ask the protocol layer to reserve as much
 	 *  as we might need for HL layer
-         */
-	
+	 */
+
 	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
 		if (dev->drv[drvidx])
 			if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen)
 				max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
 
-	ndev->hard_header_len     = ETH_HLEN + max_hlhdr_len;
+	ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
 
-	ndev->stop                = &isdn_net_close;
-	ndev->get_stats           = &isdn_net_get_stats;
-	ndev->rebuild_header      = &isdn_net_rebuild_header;
+	ndev->stop = &isdn_net_close;
+	ndev->get_stats = &isdn_net_get_stats;
+	ndev->rebuild_header = &isdn_net_rebuild_header;
 
 #ifdef CONFIG_ISDN_PPP
-	ndev->do_ioctl            = isdn_ppp_dev_ioctl;
+	ndev->do_ioctl = isdn_ppp_dev_ioctl;
 #endif
 	return 0;
 }
@@ -1432,35 +1558,35 @@
 
 	for (; *p; s++, p++)
 		switch (*p) {
-                        case '\\':
-                                /*
-                                 * Literal match with following character,
-                                 * fall through.
-                                 */
-                                p++;
-                        default:
-                                if (*s != *p)
-                                        return (0);
-                                continue;
-                        case '?':
-                                /* Match anything. */
-                                if (*s == '\0')
-                                        return (0);
-                                continue;
-                        case '*':
-                                /* Trailing star matches everything. */
-                                return (*++p ? isdn_net_Star(s, p) : 1);
-                        case '[':
-                                /* [^....] means inverse character class. */
-                                if ((reverse = (p[1] == '^')))
-                                        p++;
-                                for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
-                                        /* This next line requires a good C compiler. */
-                                        if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
-                                                matched = 1;
-                                if (matched == reverse)
-                                        return (0);
-                                continue;
+			case '\\':
+				/*
+				 * Literal match with following character,
+				 * fall through.
+				 */
+				p++;
+			default:
+				if (*s != *p)
+					return (0);
+				continue;
+			case '?':
+				/* Match anything. */
+				if (*s == '\0')
+					return (0);
+				continue;
+			case '*':
+				/* Trailing star matches everything. */
+				return (*++p ? isdn_net_Star(s, p) : 1);
+			case '[':
+				/* [^....] means inverse character class. */
+				if ((reverse = (p[1] == '^')))
+					p++;
+				for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
+					/* This next line requires a good C compiler. */
+					if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
+						matched = 1;
+				if (matched == reverse)
+					return (0);
+				continue;
 		}
 	return (*s == '\0');
 }
@@ -1477,12 +1603,12 @@
 	while (p) {
 		if (p->local.pre_device == drvidx)
 			switch (p->local.pre_channel) {
-			case 0:
-				p->local.pre_channel = 1;
-				break;
-			case 1:
-				p->local.pre_channel = 0;
-				break;
+				case 0:
+					p->local.pre_channel = 1;
+					break;
+				case 1:
+					p->local.pre_channel = 0;
+					break;
 			}
 		p = (isdn_net_dev *) p->next;
 	}
@@ -1519,7 +1645,7 @@
  *               4 = Wait cbdelay, then call back
  */
 int
-isdn_net_find_icall(int di, int ch, int idx, char *num)
+isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
 {
 	char *eaz;
 	int si1;
@@ -1530,40 +1656,24 @@
 	isdn_net_dev *p;
 	isdn_net_phone *n;
 	ulong flags;
-	char nr[31];
-	char *s;
+	char nr[32];
 
 	/* Search name in netdev-chain */
 	save_flags(flags);
 	cli();
-	if (num[0] == ',') {
+	if (!setup.phone[0]) {
 		nr[0] = '0';
-		strncpy(&nr[1], num, 30);
+		nr[1] = '\0';
 		printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");
 	} else
-		strncpy(nr, num, 30);
-	s = strtok(nr, ",");
-	s = strtok(NULL, ",");
-	if (!s) {
-		printk(KERN_WARNING "isdn_net: Incoming callinfo garbled, ignored: %s\n",
-		       num);
-		restore_flags(flags);
-		return 0;
-	}
-	si1 = (int)simple_strtoul(s,NULL,10);
-	s = strtok(NULL, ",");
-	if (!s) {
-		printk(KERN_WARNING "isdn_net: Incoming callinfo garbled, ignored: %s\n",
-		       num);
-		restore_flags(flags);
-		return 0;
-	}
-	si2 = (int)simple_strtoul(s,NULL,10);
-	eaz = strtok(NULL, ",");
-	if (!eaz) {
+		strcpy(nr, setup.phone);
+	si1 = (int) setup.si1;
+	si2 = (int) setup.si2;
+	if (!setup.eazmsn[0]) {
 		printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n");
 		eaz = "0";
-	}
+	} else
+		eaz = setup.eazmsn;
 	if (dev->net_verbose > 1)
 		printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
 	/* Accept only calls with Si1 = 7 (Data-Transmission) */
@@ -1583,12 +1693,12 @@
 	while (p) {
 		/* If last check has triggered as binding-swap, revert it */
 		switch (swapped) {
-		case 2:
-			isdn_net_swap_usage(idx, sidx);
-			/* fall through */
-		case 1:
-			isdn_net_swapbind(di);
-			break;
+			case 2:
+				isdn_net_swap_usage(idx, sidx);
+				/* fall through */
+			case 1:
+				isdn_net_swapbind(di);
+				break;
 		}
 		swapped = 0;
 		if (!strcmp(isdn_map_eaz2msn(p->local.msn, di), eaz))
@@ -1597,11 +1707,11 @@
 		printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
 		       p->local.name, p->local.msn, p->local.flags, p->local.dialstate);
 #endif
-		if ((!strcmp(isdn_map_eaz2msn(p->local.msn, di), eaz)) &&	    /* EAZ is matching   */
-		    (((!(p->local.flags & ISDN_NET_CONNECTED)) &&	            /* but not connected */
-		      (USG_NONE(dev->usage[idx]))) ||	                            /* and ch. unused or */
-		     ((((p->local.dialstate == 4) || (p->local.dialstate == 12)) && /* if dialing        */
-		       (!(p->local.flags & ISDN_NET_CALLBACK)))		            /* but no callback   */
+		if ((!strcmp(isdn_map_eaz2msn(p->local.msn, di), eaz)) &&	/* EAZ is matching   */
+		    (((!(p->local.flags & ISDN_NET_CONNECTED)) &&	/* but not connected */
+		      (USG_NONE(dev->usage[idx]))) ||	/* and ch. unused or */
+		     ((((p->local.dialstate == 4) || (p->local.dialstate == 12)) &&	/* if dialing        */
+		       (!(p->local.flags & ISDN_NET_CALLBACK)))	/* but no callback   */
 		     ))) {
 #ifdef ISDN_DEBUG_NET_ICALL
 			printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
@@ -1611,13 +1721,13 @@
 				if ((p->local.pre_channel != ch) ||
 				    (p->local.pre_device != di)) {
 					/* Here we got a problem:
-					   If using an ICN-Card, an incoming call is always signaled on
-					   on the first channel of the card, if both channels are
-					   down. However this channel may be bound exclusive. If the
-					   second channel is free, this call should be accepted.
-					   The solution is horribly but it runs, so what:
-					   We exchange the exclusive bindings of the two channels, the
-					   corresponding variables in the interface-structs.
+					 * If using an ICN-Card, an incoming call is always signaled on
+					 * on the first channel of the card, if both channels are
+					 * down. However this channel may be bound exclusive. If the
+					 * second channel is free, this call should be accepted.
+					 * The solution is horribly but it runs, so what:
+					 * We exchange the exclusive bindings of the two channels, the
+					 * corresponding variables in the interface-structs.
 					 */
 					if (ch == 0) {
 						sidx = isdn_dc2minor(di, 1);
@@ -1626,13 +1736,13 @@
 #endif
 						if (USG_NONE(dev->usage[sidx])) {
 							/* Second Channel is free, now see if it is bound
-							   exclusive too. */
+							 * exclusive too. */
 							if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) {
 #ifdef ISDN_DEBUG_NET_ICALL
 								printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n");
 #endif
 								/* Yes, swap bindings only, if the original
-								   binding is bound to channel 1 of this driver */
+								 * binding is bound to channel 1 of this driver */
 								if ((p->local.pre_device == di) &&
 								    (p->local.pre_channel == 1)) {
 									isdn_net_swapbind(di);
@@ -1674,7 +1784,7 @@
 						continue;
 					}
 				}
-			} /* if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) */
+			}
 #ifdef ISDN_DEBUG_NET_ICALL
 			printk(KERN_DEBUG "n_fi: match2\n");
 #endif
@@ -1739,7 +1849,7 @@
 							return 0;
 						}
 						/* Setup dialstate. */
-                                                lp->dtimer = 0;
+						lp->dtimer = 0;
 						lp->dialstate = 11;
 						lp->flags |= ISDN_NET_CONNECTED;
 						/* Connect interface with channel */
@@ -1754,7 +1864,7 @@
 #endif
 						/* Initiate dialing by returning 2 or 4 */
 						restore_flags(flags);
-						return (lp->flags & ISDN_NET_CBHUP)?2:4;
+						return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
 					} else
 						printk(KERN_WARNING "isdn_net: %s: No phone number\n", lp->name);
 					restore_flags(flags);
@@ -1766,28 +1876,27 @@
 					   device, so free this device */
 					if ((p->local.dialstate == 4) || (p->local.dialstate == 12)) {
 #ifdef CONFIG_ISDN_PPP
-                                                if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
-                                                        isdn_ppp_free(lp);
+						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+							isdn_ppp_free(lp);
 #endif
 						isdn_free_channel(p->local.isdn_device, p->local.isdn_channel,
 							 ISDN_USAGE_NET);
-                                        }
+					}
 					dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
 					dev->usage[idx] |= ISDN_USAGE_NET;
 					strcpy(dev->num[idx], nr);
 					isdn_info_update();
-                                        dev->st_netdev[idx] = lp->netdev;
+					dev->st_netdev[idx] = lp->netdev;
 					p->local.isdn_device = di;
 					p->local.isdn_channel = ch;
 					p->local.ppp_slot = -1;
-					p->local.pppbind = -1;
 					p->local.flags |= ISDN_NET_CONNECTED;
 					p->local.dialstate = 7;
 					p->local.dtimer = 0;
 					p->local.outgoing = 0;
 					p->local.huptimer = 0;
-					p->local.hupflags |= 1;
-                                        p->local.hupflags &= ~2;
+					p->local.hupflags |= ISDN_WAITCHARGE;
+					p->local.hupflags &= ~ISDN_HAVECHARGE;
 #ifdef CONFIG_ISDN_PPP
 					if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
 						if (isdn_ppp_bind(lp) < 0) {
@@ -1814,7 +1923,7 @@
  * Search list of net-interfaces for an interface with given name.
  */
 isdn_net_dev *
- isdn_net_findif(char *name)
+isdn_net_findif(char *name)
 {
 	isdn_net_dev *p = dev->netdev;
 
@@ -1831,7 +1940,8 @@
  * This is called from the userlevel-routine below or
  * from isdn_net_start_xmit().
  */
-int isdn_net_force_dial_lp(isdn_net_local * lp)
+int
+isdn_net_force_dial_lp(isdn_net_local * lp)
 {
 	if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
 		int chi;
@@ -1841,8 +1951,8 @@
 			cli();
 			/* Grab a free ISDN-Channel */
 			if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
-						    lp->l3_proto,
-						    lp->pre_device,
+							 lp->l3_proto,
+							 lp->pre_device,
 						 lp->pre_channel)) < 0) {
 				printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
 				restore_flags(flags);
@@ -1874,7 +1984,7 @@
  * Force a net-interface to dial out.
  * This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
  */
-int 
+int
 isdn_net_force_dial(char *name)
 {
 	isdn_net_dev *p = isdn_net_findif(name);
@@ -1906,9 +2016,9 @@
 		strcpy(netdev->local.name, "         ");
 	else
 		strcpy(netdev->local.name, name);
-	netdev->dev.name      = netdev->local.name;
-	netdev->dev.priv      = &netdev->local;
-	netdev->dev.init      = isdn_net_init;
+	netdev->dev.name = netdev->local.name;
+	netdev->dev.priv = &netdev->local;
+	netdev->dev.init = isdn_net_init;
 	netdev->local.p_encap = ISDN_NET_ENCAP_RAWIP;
 	if (master) {
 		/* Device shall be a slave */
@@ -1936,7 +2046,7 @@
 	netdev->local.magic = ISDN_NET_MAGIC;
 
 #ifdef CONFIG_ISDN_PPP
-	netdev->mp_last = NULL;	/* mpqueue is empty */
+	netdev->mp_last = NULL; /* mpqueue is empty */
 	netdev->ib.next_num = 0;
 	netdev->ib.last = NULL;
 #endif
@@ -1952,18 +2062,19 @@
 	netdev->local.exclusive = -1;
 	netdev->local.ppp_slot = -1;
 	netdev->local.pppbind = -1;
-        netdev->local.sav_skb = NULL;
-        netdev->local.first_skb = NULL;
+	netdev->local.sav_skb = NULL;
+	netdev->local.first_skb = NULL;
 	netdev->local.l2_proto = ISDN_PROTO_L2_X75I;
 	netdev->local.l3_proto = ISDN_PROTO_L3_TRANS;
+	netdev->local.triggercps = 6000;
 	netdev->local.slavedelay = 10 * HZ;
 	netdev->local.srobin = &netdev->dev;
-	netdev->local.hupflags = 8;	/* Do hangup even on incoming calls */
+	netdev->local.hupflags = ISDN_INHUP;	/* Do hangup even on incoming calls */
 	netdev->local.onhtime = 10;	/* Default hangup-time for saving costs
-					   of those who forget configuring this */
+	   of those who forget configuring this */
 	netdev->local.dialmax = 1;
-        netdev->local.flags = ISDN_NET_CBHUP; /* Hangup before Callback */
-        netdev->local.cbdelay = 25;      /* Wait 5 secs before Callback */
+	netdev->local.flags = ISDN_NET_CBHUP;	/* Hangup before Callback */
+	netdev->local.cbdelay = 25;	/* Wait 5 secs before Callback */
 	/* Put into to netdev-chain */
 	netdev->next = (void *) dev->netdev;
 	dev->netdev = netdev;
@@ -1989,6 +2100,9 @@
 		/* Master must be a real interface, not a slave */
 		if (n->local.master)
 			return NULL;
+		/* Master must not be started yet */
+		if (n->dev.start)
+			return NULL;
 		return (isdn_net_new(newname, &(n->dev)));
 	}
 	return NULL;
@@ -2000,7 +2114,8 @@
  * for not overwriting existing setups. It has to get the current
  * setup first, if only selected parameters are to be changed.
  */
-int isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
+int
+isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
 {
 	isdn_net_dev *p = isdn_net_findif(cfg->name);
 	ulong features;
@@ -2020,33 +2135,34 @@
 			printk(KERN_WARNING "isdn_net: No driver with selected features\n");
 			return -ENODEV;
 		}
-                if (p->local.p_encap != cfg->p_encap)
-                        if (p->dev.start) {
-                                printk(KERN_WARNING
-                                       "%s: cannot change encap when if is up\n",
-                                       p->local.name);
-                                return -EBUSY;
-                        }
-                if (cfg->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
+		if (p->local.p_encap != cfg->p_encap)
+			if (p->dev.start) {
+				printk(KERN_WARNING
+				"%s: cannot change encap when if is up\n",
+				       p->local.name);
+				return -EBUSY;
+			}
+		if (cfg->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
 #ifndef CONFIG_ISDN_PPP
-                        printk(KERN_WARNING "%s: SyncPPP support not configured\n",
-                               p->local.name);
-                        return -EINVAL;
+			printk(KERN_WARNING "%s: SyncPPP support not configured\n",
+			       p->local.name);
+			return -EINVAL;
 #else
-                        p->dev.type = ARPHRD_PPP; /* change ARP type */
-                        p->dev.addr_len = 0;
+			p->dev.type = ARPHRD_PPP;	/* change ARP type */
+			p->dev.addr_len = 0;
 #endif
-                }
+		}
 		if (strlen(cfg->drvid)) {
 			/* A bind has been requested ... */
-			char *c,*e;
+			char *c,
+			*e;
 
 			drvidx = -1;
 			chidx = -1;
 			strcpy(drvid, cfg->drvid);
 			if ((c = strchr(drvid, ','))) {
 				/* The channel-number is appended to the driver-Id with a comma */
-				chidx = (int)simple_strtoul(c + 1,&e,10);
+				chidx = (int) simple_strtoul(c + 1, &e, 10);
 				if (e == c)
 					chidx = -1;
 				*c = '\0';
@@ -2071,9 +2187,9 @@
 			/* If binding is exclusive, try to grab the channel */
 			save_flags(flags);
 			if ((i = isdn_get_free_channel(ISDN_USAGE_NET, p->local.l2_proto,
-						  p->local.l3_proto,
-						  drvidx,
-						  chidx)) < 0) {
+						       p->local.l3_proto,
+						       drvidx,
+						       chidx)) < 0) {
 				/* Grab failed, because desired channel is in use */
 				p->local.exclusive = -1;
 				restore_flags(flags);
@@ -2089,22 +2205,23 @@
 			p->local.exclusive = -1;
 			if ((p->local.pre_device != -1) && (cfg->exclusive == -1)) {
 				isdn_unexclusive_channel(p->local.pre_device, p->local.pre_channel);
-                                isdn_free_channel(p->local.pre_device, p->local.pre_channel,ISDN_USAGE_NET);
+				isdn_free_channel(p->local.pre_device, p->local.pre_channel, ISDN_USAGE_NET);
 				drvidx = -1;
 				chidx = -1;
 			}
 		}
 		strcpy(p->local.msn, cfg->eaz);
-		p->local.pre_device  = drvidx;
+		p->local.pre_device = drvidx;
 		p->local.pre_channel = chidx;
-		p->local.onhtime     = cfg->onhtime;
-		p->local.charge      = cfg->charge;
-		p->local.l2_proto    = cfg->l2_proto;
-		p->local.l3_proto    = cfg->l3_proto;
-                p->local.cbdelay     = cfg->cbdelay;
-                p->local.dialmax     = cfg->dialmax;
-		p->local.slavedelay  = cfg->slavedelay * HZ;
-		p->local.pppbind     = cfg->pppbind;
+		p->local.onhtime = cfg->onhtime;
+		p->local.charge = cfg->charge;
+		p->local.l2_proto = cfg->l2_proto;
+		p->local.l3_proto = cfg->l3_proto;
+		p->local.cbdelay = cfg->cbdelay;
+		p->local.dialmax = cfg->dialmax;
+		p->local.triggercps = cfg->triggercps;
+		p->local.slavedelay = cfg->slavedelay * HZ;
+		p->local.pppbind = cfg->pppbind;
 		if (cfg->secure)
 			p->local.flags |= ISDN_NET_SECURE;
 		else
@@ -2114,47 +2231,63 @@
 		else
 			p->local.flags &= ~ISDN_NET_CBHUP;
 		switch (cfg->callback) {
-                        case 0:
-                                p->local.flags &= ~(ISDN_NET_CALLBACK|ISDN_NET_CBOUT);
-                                break;
-                        case 1:
-                                p->local.flags |= ISDN_NET_CALLBACK;
-                                p->local.flags &= ~ISDN_NET_CBOUT;
-                                break;
-                        case 2:
-                                p->local.flags |= ISDN_NET_CBOUT;
-                                p->local.flags &= ~ISDN_NET_CALLBACK;
-                                break;
-                }
+			case 0:
+				p->local.flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
+				break;
+			case 1:
+				p->local.flags |= ISDN_NET_CALLBACK;
+				p->local.flags &= ~ISDN_NET_CBOUT;
+				break;
+			case 2:
+				p->local.flags |= ISDN_NET_CBOUT;
+				p->local.flags &= ~ISDN_NET_CALLBACK;
+				break;
+		}
 		if (cfg->chargehup)
-			p->local.hupflags |= 4;
+			p->local.hupflags |= ISDN_CHARGEHUP;
 		else
-			p->local.hupflags &= ~4;
+			p->local.hupflags &= ~ISDN_CHARGEHUP;
 		if (cfg->ihup)
-			p->local.hupflags |= 8;
+			p->local.hupflags |= ISDN_INHUP;
 		else
-			p->local.hupflags &= ~8;
+			p->local.hupflags &= ~ISDN_INHUP;
+		if (cfg->chargeint > 10) {
+			p->local.hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
+			p->local.chargeint = cfg->chargeint * HZ;
+		}
 		if (cfg->p_encap != p->local.p_encap) {
-                        if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
-                                p->dev.hard_header         = NULL;
-                                p->dev.header_cache_bind   = NULL;
-                                p->dev.header_cache_update = NULL;
-                                p->dev.flags               = IFF_NOARP;
-                        } else {
-                                p->dev.hard_header = isdn_net_header;
-                                if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) {
-                                        p->dev.header_cache_bind   = p->local.org_hcb;
-                                        p->dev.header_cache_update = p->local.org_hcu;
-                                        p->dev.flags = IFF_BROADCAST | IFF_MULTICAST;
-                                } else {
-                                        p->dev.header_cache_bind   = NULL;
-                                        p->dev.header_cache_update = NULL;
-                                        p->dev.flags               = IFF_NOARP;
-                                }
-                        }
-                }
-		p->local.p_encap     = cfg->p_encap;
-                return 0;
+			if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
+				p->dev.hard_header = NULL;
+#if (LINUX_VERSION_CODE < 0x02010F)
+				p->dev.header_cache_bind = NULL;
+#else
+				p->dev.hard_header_cache = NULL;
+#endif
+				p->dev.header_cache_update = NULL;
+				p->dev.flags = IFF_NOARP;
+			} else {
+				p->dev.hard_header = isdn_net_header;
+				if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) {
+#if (LINUX_VERSION_CODE < 0x02010F)
+					p->dev.header_cache_bind = p->local.org_hcb;
+#else
+					p->dev.hard_header_cache = p->local.org_hhc;
+#endif
+					p->dev.header_cache_update = p->local.org_hcu;
+					p->dev.flags = IFF_BROADCAST | IFF_MULTICAST;
+				} else {
+#if (LINUX_VERSION_CODE < 0x02010F)
+					p->dev.header_cache_bind = NULL;
+#else
+					p->dev.hard_header_cache = NULL;
+#endif
+					p->dev.header_cache_update = NULL;
+					p->dev.flags = IFF_NOARP;
+				}
+			}
+		}
+		p->local.p_encap = cfg->p_encap;
+		return 0;
 	}
 	return -ENODEV;
 }
@@ -2162,7 +2295,8 @@
 /*
  * Perform get-interface-parameters.ioctl
  */
-int isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
+int
+isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
 {
 	isdn_net_dev *p = isdn_net_findif(cfg->name);
 
@@ -2181,16 +2315,19 @@
 		cfg->p_encap = p->local.p_encap;
 		cfg->secure = (p->local.flags & ISDN_NET_SECURE) ? 1 : 0;
 		cfg->callback = 0;
-                if (p->local.flags & ISDN_NET_CALLBACK)
-                        cfg->callback = 1;
-                if (p->local.flags & ISDN_NET_CBOUT)
-                        cfg->callback = 2;
+		if (p->local.flags & ISDN_NET_CALLBACK)
+			cfg->callback = 1;
+		if (p->local.flags & ISDN_NET_CBOUT)
+			cfg->callback = 2;
 		cfg->cbhup = (p->local.flags & ISDN_NET_CBHUP) ? 1 : 0;
 		cfg->chargehup = (p->local.hupflags & 4) ? 1 : 0;
 		cfg->ihup = (p->local.hupflags & 8) ? 1 : 0;
-                cfg->cbdelay = p->local.cbdelay;
-                cfg->dialmax = p->local.dialmax;
+		cfg->cbdelay = p->local.cbdelay;
+		cfg->dialmax = p->local.dialmax;
+		cfg->triggercps = p->local.triggercps;
 		cfg->slavedelay = p->local.slavedelay / HZ;
+		cfg->chargeint = (p->local.hupflags & ISDN_CHARGEHUP) ?
+		    (p->local.chargeint / HZ) : 0;
 		cfg->pppbind = p->local.pppbind;
 		if (p->local.slave)
 			strcpy(cfg->slave, ((isdn_net_local *) p->local.slave->priv)->name);
@@ -2208,7 +2345,8 @@
 /*
  * Add a phone-number to an interface.
  */
-int isdn_net_addphone(isdn_net_ioctl_phone * phone)
+int
+isdn_net_addphone(isdn_net_ioctl_phone * phone)
 {
 	isdn_net_dev *p = isdn_net_findif(phone->name);
 	isdn_net_phone *n;
@@ -2229,7 +2367,8 @@
 /*
  * Return a string of all phone-numbers of an interface.
  */
-int isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
+int
+isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
 {
 	isdn_net_dev *p = isdn_net_findif(phone->name);
 	int inout = phone->outgoing & 1;
@@ -2244,22 +2383,21 @@
 	save_flags(flags);
 	cli();
 	inout &= 1;
-        for (n = p->local.phone[inout]; n; n = n->next) {
+	for (n = p->local.phone[inout]; n; n = n->next) {
 		if (more) {
 			put_user(' ', phones++);
 			count++;
 		}
-		if ((ret = verify_area(VERIFY_WRITE, (void *) phones, strlen(n->num) + 1))) {
+		if ((ret = copy_to_user(phones, n->num, strlen(n->num) + 1))) {
 			restore_flags(flags);
 			return ret;
 		}
-		copy_to_user(phones, n->num, strlen(n->num) + 1);
 		phones += strlen(n->num);
 		count += strlen(n->num);
 		more = 1;
 	}
-        put_user(0,phones);
-        count++;
+	put_user(0, phones);
+	count++;
 	restore_flags(flags);
 	return count;
 }
@@ -2268,18 +2406,24 @@
  * Delete a phone-number from an interface.
  */
 
-int isdn_net_delphone(isdn_net_ioctl_phone * phone)
+int
+isdn_net_delphone(isdn_net_ioctl_phone * phone)
 {
 	isdn_net_dev *p = isdn_net_findif(phone->name);
 	int inout = phone->outgoing & 1;
 	isdn_net_phone *n;
 	isdn_net_phone *m;
+	int flags;
 
 	if (p) {
+		save_flags(flags);
+		cli();
 		n = p->local.phone[inout];
 		m = NULL;
 		while (n) {
 			if (!strcmp(n->num, phone->phone)) {
+				if (p->local.dial == n)
+					p->local.dial = n->next;
 				if (m)
 					m->next = n->next;
 				else
@@ -2290,6 +2434,7 @@
 			m = n;
 			n = (isdn_net_phone *) n->next;
 		}
+		restore_flags(flags);
 		return -EINVAL;
 	}
 	return -ENODEV;
@@ -2298,7 +2443,8 @@
 /*
  * Delete all phone-numbers of an interface.
  */
-static int isdn_net_rmallphone(isdn_net_dev * p)
+static int
+isdn_net_rmallphone(isdn_net_dev * p)
 {
 	isdn_net_phone *n;
 	isdn_net_phone *m;
@@ -2316,6 +2462,7 @@
 		}
 		p->local.phone[i] = NULL;
 	}
+	p->local.dial = NULL;
 	restore_flags(flags);
 	return 0;
 }
@@ -2323,7 +2470,8 @@
 /*
  * Force a hangup of a network-interface.
  */
-int isdn_net_force_hangup(char *name)
+int
+isdn_net_force_hangup(char *name)
 {
 	isdn_net_dev *p = isdn_net_findif(name);
 	struct device *q;
@@ -2331,13 +2479,13 @@
 	if (p) {
 		if (p->local.isdn_device < 0)
 			return 1;
-		isdn_net_hangup(&p->dev);
 		q = p->local.slave;
 		/* If this interface has slaves, do a hangup for them also. */
 		while (q) {
 			isdn_net_hangup(q);
 			q = (((isdn_net_local *) q->priv)->slave);
 		}
+		isdn_net_hangup(&p->dev);
 		return 0;
 	}
 	return -ENODEV;
@@ -2346,7 +2494,8 @@
 /*
  * Helper-function for isdn_net_rm: Do the real work.
  */
-static int isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
+static int
+isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
 {
 	int flags;
 
@@ -2399,9 +2548,6 @@
 		isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
 	restore_flags(flags);
 
-#ifdef CONFIG_ISDN_MPP
-	isdn_ppp_free_mpqueue(p);	/* still necessary? */
-#endif
 	kfree(p);
 
 	return 0;
@@ -2410,7 +2556,8 @@
 /*
  * Remove a single network-interface.
  */
-int isdn_net_rm(char *name)
+int
+isdn_net_rm(char *name)
 {
 	isdn_net_dev *p;
 	isdn_net_dev *q;
@@ -2433,7 +2580,8 @@
 /*
  * Remove all network-interfaces
  */
-int isdn_net_rmall(void)
+int
+isdn_net_rmall(void)
 {
 	int flags;
 	int ret;
@@ -2446,7 +2594,7 @@
 			/* Remove master-devices only, slaves get removed with their master */
 			if ((ret = isdn_net_realrm(dev->netdev, NULL))) {
 				restore_flags(flags);
-			        return ret;
+				return ret;
 			}
 		}
 	}
@@ -2455,17 +2603,18 @@
 	return 0;
 }
 
-/* 
+/*
  * helper function to flush device queues
  * the better place would be net/core/dev.c
  */
-void dev_purge_queues(struct device *dev)
+static void
+dev_purge_queues(struct device *dev)
 {
 	int i;
-	for(i=0;i<DEV_NUMBUFFS;i++) {
+	for (i = 0; i < DEV_NUMBUFFS; i++) {
 		struct sk_buff *skb;
-		while((skb=skb_dequeue(&dev->buffs[i])))
-				dev_kfree_skb(skb,FREE_WRITE);
-        }
-	
+		while ((skb = skb_dequeue(&dev->buffs[i])))
+			dev_kfree_skb(skb, FREE_WRITE);
+	}
+
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov