summaryrefslogtreecommitdiffstats
path: root/drivers/isdn/isdn_net.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-06-03 09:23:20 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-06-03 09:23:20 +0000
commitac5ff8f4a72f7b4e66f73c3c6cb9fe7758cf6f12 (patch)
tree9fc7f8ce32e0d9a4aa055b2a58a05a5d727b333c /drivers/isdn/isdn_net.c
parent52662ff3e66770fd7e4fc508c91056d29c08bff0 (diff)
Sync with Linux 2.1.42.
Diffstat (limited to 'drivers/isdn/isdn_net.c')
-rw-r--r--drivers/isdn/isdn_net.c140
1 files changed, 101 insertions, 39 deletions
diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c
index 7d7bdad8d..a1866f07f 100644
--- a/drivers/isdn/isdn_net.c
+++ b/drivers/isdn/isdn_net.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.37 1997/02/11 18:32:51 fritz Exp $
+/* $Id: isdn_net.c,v 1.44 1997/05/27 15:17:26 fritz Exp $
* Linux ISDN subsystem, network interfaces and related functions (linklevel).
*
@@ -21,6 +21,32 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_net.c,v $
+ * 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().
*
@@ -170,6 +196,7 @@
#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
@@ -184,13 +211,25 @@ static int isdn_net_start_xmit(struct sk_buff *, struct device *);
static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
static void dev_purge_queues(struct device *dev); /* move this to net/core/dev.c */
-char *isdn_net_revision = "$Revision: 1.37 $";
+char *isdn_net_revision = "$Revision: 1.44 $";
/*
* 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;
@@ -513,6 +552,7 @@ isdn_net_dial(void)
isdn_net_dev *p = dev->netdev;
int anymore = 0;
int i;
+ int flags;
isdn_ctrl cmd;
while (p) {
@@ -528,7 +568,16 @@ isdn_net_dial(void)
/* 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;
+ }
anymore = 1;
p->local.dialstate++;
/* Fall through */
@@ -560,39 +609,41 @@ isdn_net_dial(void)
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;
- 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;
+ 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;
}
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.phone, "%s", p->local.dial->num);
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], p->local.dial->num);
+ 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, 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++;
- }
+ 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,
@@ -600,6 +651,15 @@ isdn_net_dial(void)
#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 &&
@@ -956,13 +1016,21 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
lp->l3_proto,
lp->pre_device,
lp->pre_channel)) < 0) {
+ restore_flags(flags);
+#if 0
printk(KERN_WARNING
"isdn_net_start_xmit: No channel for %s\n",
ndev->name);
- restore_flags(flags);
/* 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 */
if (dev->net_verbose)
@@ -1000,20 +1068,8 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
isdn_net_dial();
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;
@@ -1045,7 +1101,6 @@ isdn_net_close(struct device *dev)
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) {
@@ -1055,6 +1110,7 @@ isdn_net_close(struct device *dev)
p = (((isdn_net_local *) p->priv)->slave);
}
}
+ isdn_net_hangup(dev);
isdn_MOD_DEC_USE_COUNT();
return 0;
}
@@ -2314,11 +2370,10 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
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;
@@ -2340,12 +2395,17 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
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
@@ -2356,6 +2416,7 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
m = n;
n = (isdn_net_phone *) n->next;
}
+ restore_flags(flags);
return -EINVAL;
}
return -ENODEV;
@@ -2383,6 +2444,7 @@ isdn_net_rmallphone(isdn_net_dev * p)
}
p->local.phone[i] = NULL;
}
+ p->local.dial = NULL;
restore_flags(flags);
return 0;
}
@@ -2399,13 +2461,13 @@ isdn_net_force_hangup(char *name)
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;