patch-2.1.92 linux/drivers/isdn/isdn_net.c
Next file: linux/drivers/isdn/isdn_net.h
Previous file: linux/drivers/isdn/isdn_concap.h
Back to the patch index
Back to the overall index
- Lines: 1959
- Date:
Wed Apr 1 16:21:03 1998
- Orig file:
v2.1.91/linux/drivers/isdn/isdn_net.c
- Orig date:
Thu Feb 12 20:56:06 1998
diff -u --recursive --new-file v2.1.91/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.44 1997/05/27 15:17:26 fritz Exp $
+/* $Id: isdn_net.c,v 1.55 1998/02/23 19:38:22 fritz Exp $
* Linux ISDN subsystem, network interfaces and related functions (linklevel).
*
@@ -21,6 +21,54 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_net.c,v $
+ * Revision 1.55 1998/02/23 19:38:22 fritz
+ * Corrected check for modified feature-flags.
+ *
+ * Revision 1.54 1998/02/20 17:15:07 fritz
+ * Changes for recent kernels.
+ * Ugly workaround for adjusting Ethernet frames with recent kernels.
+ * replaced direct calls to lowlevel-driver command by common hook.
+ *
+ * Revision 1.53 1998/01/31 22:05:54 keil
+ * Lots of changes for X.25 support:
+ * Added generic support for connection-controlling encapsulation protocols
+ * Added support of BHUP status message
+ * Added support for additional p_encap X25IFACE
+ * Added support for kernels >= 2.1.72
+ *
+ * Revision 1.52 1998/01/31 19:29:51 calle
+ * Merged changes from and for 2.1.82, not tested only compiled ...
+ *
+ * Revision 1.51 1997/10/09 21:28:50 fritz
+ * New HL<->LL interface:
+ * New BSENT callback with nr. of bytes included.
+ * Sending without ACK.
+ * New L1 error status (not yet in use).
+ * Cleaned up obsolete structures.
+ * Implemented Cisco-SLARP.
+ * Changed local net-interface data to be dynamically allocated.
+ * Removed old 2.0 compatibility stuff.
+ *
+ * Revision 1.50 1997/10/01 09:20:32 fritz
+ * Removed old compatibility stuff for 2.0.X kernels.
+ * From now on, this code is for 2.1.X ONLY!
+ * Old stuff is still in the separate branch.
+ *
+ * Revision 1.49 1997/08/21 14:38:13 fritz
+ * Bugfix: Did not compile without SyncPPP.
+ *
+ * Revision 1.48 1997/06/22 11:57:15 fritz
+ * Added ability to adjust slave triggerlevel.
+ *
+ * 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
@@ -196,16 +244,18 @@
#include <linux/isdn.h>
#include <net/arp.h>
#include <net/icmp.h>
-#if (LINUX_VERSION_CODE >= 0x020117)
-#include <linux/poll.h>
+#ifndef DEV_NUMBUFFS
+#include <net/pkt_sched.h>
#endif
+#include <linux/inetdevice.h>
#include "isdn_common.h"
#include "isdn_net.h"
#ifdef CONFIG_ISDN_PPP
#include "isdn_ppp.h"
#endif
-#ifndef DEV_NUMBUFFS
-#include <net/pkt_sched.h>
+#ifdef CONFIG_ISDN_X25
+#include <linux/concap.h>
+#include "isdn_concap.h"
#endif
/* Prototypes */
@@ -218,7 +268,7 @@
static void dev_purge_queues(struct device *dev); /* move this to net/core/dev.c */
#endif
-char *isdn_net_revision = "$Revision: 1.44 $";
+char *isdn_net_revision = "$Revision: 1.55 $";
/*
* Code for raw-networking over ISDN
@@ -229,22 +279,28 @@
{
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
- );
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
}
static void
isdn_net_reset(struct device *dev)
{
+#ifdef CONFIG_ISDN_X25
+ struct concap_device_ops * dops =
+ ( (isdn_net_local *) dev->priv ) -> dops;
+ struct concap_proto * cprot =
+ ( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
+#endif
ulong flags;
save_flags(flags);
cli(); /* Avoid glitch on writes to CMD regs */
dev->interrupt = 0;
dev->tbusy = 0;
+#ifdef CONFIG_ISDN_X25
+ if( cprot && cprot -> pops && dops )
+ cprot -> pops -> restart ( cprot, dev, dops );
+#endif
restore_flags(flags);
}
@@ -254,14 +310,22 @@
{
int i;
struct device *p;
+ struct in_device *in_dev;
isdn_net_reset(dev);
dev->start = 1;
- /* Fill in the MAC-level header. */
+ /* Fill in the MAC-level header (not needed, but for compatibility... */
for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
dev->dev_addr[i] = 0xfc;
- memset(&(dev->dev_addr[i]), 0, sizeof(u32));
-
+ if ((in_dev = dev->ip_ptr) != NULL) {
+ /*
+ * Any address will do - we take the first
+ */
+ struct in_ifaddr *ifa = in_dev->ifa_list;
+ if (ifa != NULL)
+ memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
+ }
+
/* If this interface has slaves, start them also */
if ((p = (((isdn_net_local *) dev->priv)->slave))) {
@@ -356,7 +420,7 @@
anymore = 0;
while (p) {
- isdn_net_local *l = (isdn_net_local *) & (p->local);
+ isdn_net_local *l = p->local;
if ((jiffies - last_jiffies) == 0)
l->cps = l->transcount;
else
@@ -405,18 +469,24 @@
* Return: 1 = Event handled, 0 = not for us or unknown Event.
*/
int
-isdn_net_stat_callback(int idx, int cmd)
+isdn_net_stat_callback(int idx, isdn_ctrl *c)
{
isdn_net_dev *p = dev->st_netdev[idx];
-
+ int cmd = c->command;
+
if (p) {
- isdn_net_local *lp = &(p->local);
+ isdn_net_local *lp = p->local;
+#ifdef CONFIG_ISDN_X25
+ struct concap_proto *cprot = lp -> netdev -> cprot;
+ struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
+#endif
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++;
+ lp->stats.tx_bytes += c->parm.length;
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && lp->sav_skb) {
struct device *mdev;
if (lp->master)
@@ -449,6 +519,16 @@
break;
case ISDN_STAT_DHUP:
/* Either D-Channel-hangup or error during dialout */
+#ifdef CONFIG_ISDN_X25
+ /* If we are not connencted then dialing had
+ failed. If there are generic encap protocol
+ receiver routines signal the closure of
+ the link*/
+
+ if( !(lp->flags & ISDN_NET_CONNECTED)
+ && pops && pops -> disconn_ind )
+ pops -> disconn_ind(cprot);
+#endif /* CONFIG_ISDN_X25 */
if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
lp->flags &= ~ISDN_NET_CONNECTED;
if (lp->first_skb) {
@@ -475,6 +555,18 @@
return 1;
}
break;
+#ifdef CONFIG_ISDN_X25
+ case ISDN_STAT_BHUP:
+ /* B-Channel-hangup */
+ /* try if there are generic encap protocol
+ receiver routines and signal the closure of
+ the link */
+ if( pops && pops -> disconn_ind ){
+ pops -> disconn_ind(cprot);
+ return 1;
+ }
+ break;
+#endif /* CONFIG_ISDN_X25 */
case ISDN_STAT_BCONN:
/* B-Channel is up */
switch (lp->dialstate) {
@@ -492,6 +584,8 @@
dev->rx_netdev[idx] = p;
lp->dialstate = 0;
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
+ if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
+ isdn_timer_ctrl(ISDN_TIMER_KEEPALIVE, 1);
printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
/* If first Chargeinfo comes before B-Channel connect,
* we correct the timestamp here.
@@ -504,7 +598,15 @@
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
isdn_ppp_wakeup_daemon(lp);
#endif
+#ifdef CONFIG_ISDN_X25
+ /* try if there are generic concap receiver routines */
+ if( pops )
+ if( pops->connect_ind)
+ pops->connect_ind(cprot);
+
+#endif /* CONFIG_ISDN_X25 */
if (lp->first_skb) {
+
if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
lp->first_skb = NULL;
}
@@ -573,11 +675,13 @@
isdn_ctrl cmd;
while (p) {
+ isdn_net_local *lp = p->local;
+
#ifdef ISDN_DEBUG_NET_DIAL
- if (p->local.dialstate)
- printk(KERN_DEBUG "%s: dialstate=%d\n", p->local.name, p->local.dialstate);
+ if (lp->dialstate)
+ printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate);
#endif
- switch (p->local.dialstate) {
+ switch (lp->dialstate) {
case 0:
/* Nothing to do for this interface */
break;
@@ -587,132 +691,133 @@
*/
save_flags(flags);
cli();
- p->local.dial = p->local.phone[1];
+ lp->dial = lp->phone[1];
restore_flags(flags);
- if (!p->local.dial) {
+ if (!lp->dial) {
printk(KERN_WARNING "%s: phone number deleted?\n",
- p->local.name);
+ lp->name);
isdn_net_hangup(&p->dev);
break;
}
anymore = 1;
- p->local.dialstate++;
+ lp->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.driver = lp->isdn_device;
+ cmd.arg = lp->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));
+ isdn_command(&cmd);
+ sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver));
cmd.command = ISDN_CMD_SETEAZ;
- dev->drv[p->local.isdn_device]->interface->command(&cmd);
- p->local.dialretry = 0;
+ isdn_command(&cmd);
+ lp->dialretry = 0;
anymore = 1;
- p->local.dialstate++;
+ lp->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.
*/
- cmd.driver = p->local.isdn_device;
+ cmd.driver = lp->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.arg = lp->isdn_channel + (lp->l2_proto << 8);
+ isdn_command(&cmd);
+ cmd.driver = lp->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;
+ cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
+ isdn_command(&cmd);
+ cmd.driver = lp->isdn_device;
+ cmd.arg = lp->isdn_channel;
save_flags(flags);
cli();
- if (!p->local.dial) {
+ if (!lp->dial) {
restore_flags(flags);
printk(KERN_WARNING "%s: phone number deleted?\n",
- p->local.name);
+ lp->name);
isdn_net_hangup(&p->dev);
break;
}
- if (!strcmp(p->local.dial->num, "LEASED")) {
+ if (!strcmp(lp->dial->num, "LEASED")) {
restore_flags(flags);
- p->local.dialstate = 4;
- printk(KERN_INFO "%s: Open leased line ...\n", p->local.name);
+ lp->dialstate = 4;
+ printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
} else {
- sprintf(cmd.parm.setup.phone, "%s", p->local.dial->num);
+ sprintf(cmd.parm.setup.phone, "%s", lp->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++;
+ if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
+ lp->dial = lp->phone[1];
+ lp->dialretry++;
}
restore_flags(flags);
+ cmd.driver = lp->isdn_device;
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);
+ isdn_map_eaz2msn(lp->msn, cmd.driver));
+ i = isdn_dc2minor(lp->isdn_device, lp->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;
+ printk(KERN_INFO "%s: dialing %d %s...\n", lp->name,
+ lp->dialretry - 1, cmd.parm.setup.phone);
+ lp->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", lp->isdn_device,
+ lp->isdn_channel);
#endif
- dev->drv[p->local.isdn_device]->interface->command(&cmd);
+ isdn_command(&cmd);
}
- p->local.huptimer = 0;
- p->local.outgoing = 1;
- if (p->local.chargeint) {
- p->local.hupflags |= ISDN_HAVECHARGE;
- p->local.hupflags &= ~ISDN_WAITCHARGE;
+ lp->huptimer = 0;
+ lp->outgoing = 1;
+ if (lp->chargeint) {
+ lp->hupflags |= ISDN_HAVECHARGE;
+ lp->hupflags &= ~ISDN_WAITCHARGE;
} else {
- p->local.hupflags |= ISDN_WAITCHARGE;
- p->local.hupflags &= ~ISDN_HAVECHARGE;
+ lp->hupflags |= ISDN_WAITCHARGE;
+ lp->hupflags &= ~ISDN_HAVECHARGE;
}
anymore = 1;
- p->local.dialstate =
- (p->local.cbdelay &&
- (p->local.flags & ISDN_NET_CBOUT)) ? 12 : 4;
+ lp->dialstate =
+ (lp->cbdelay &&
+ (lp->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;
+ if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
+ if (lp->dialretry < lp->dialmax) {
+ lp->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.driver = lp->isdn_device;
+ cmd.arg = lp->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);
+ lp->dtimer = 0;
+ lp->dialstate++;
+ isdn_command(&cmd);
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", lp->dtimer);
#endif
- if (p->local.dtimer++ > ISDN_TIMER_DTIMEOUT10)
- p->local.dialstate = 3;
+ if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
+ lp->dialstate = 3;
anymore = 1;
break;
case 7:
@@ -720,69 +825,69 @@
* 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", lp->dtimer);
#endif
- cmd.driver = p->local.isdn_device;
+ cmd.driver = lp->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.arg = lp->isdn_channel + (lp->l2_proto << 8);
+ isdn_command(&cmd);
+ cmd.driver = lp->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)
+ cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
+ isdn_command(&cmd);
+ if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15)
isdn_net_hangup(&p->dev);
else {
anymore = 1;
- p->local.dialstate++;
+ lp->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.driver = lp->isdn_device;
+ cmd.arg = lp->isdn_channel;
cmd.command = ISDN_CMD_ACCEPTB;
- dev->drv[p->local.isdn_device]->interface->command(&cmd);
+ isdn_command(&cmd);
anymore = 1;
- p->local.dtimer = 0;
- p->local.dialstate++;
+ lp->dtimer = 0;
+ lp->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", lp->dtimer);
#endif
- if (p->local.dtimer++ > ISDN_TIMER_DTIMEOUT10)
+ if (lp->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;
+ if (lp->dtimer++ > lp->cbdelay)
+ lp->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;
+ if (lp->dtimer++ > lp->cbdelay) {
+ printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
+ lp->dtimer = 0;
+ lp->dialstate = 4;
+ cmd.driver = lp->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);
+ cmd.arg = lp->isdn_channel;
+ isdn_command(&cmd);
+ isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
}
anymore = 1;
break;
default:
printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
- p->local.dialstate, p->local.name);
+ lp->dialstate, lp->name);
}
p = (isdn_net_dev *) p->next;
}
@@ -797,6 +902,10 @@
{
isdn_net_local *lp = (isdn_net_local *) d->priv;
isdn_ctrl cmd;
+#ifdef CONFIG_ISDN_X25
+ struct concap_proto *cprot = lp -> netdev -> cprot;
+ struct concap_proto_ops *pops = cprot ? cprot -> pops : 0;
+#endif
if (lp->flags & ISDN_NET_CONNECTED) {
lp->flags &= ~ISDN_NET_CONNECTED;
@@ -804,10 +913,18 @@
#ifdef CONFIG_ISDN_PPP
isdn_ppp_free(lp);
#endif
+#ifdef CONFIG_ISDN_X25
+ /* try if there are generic encap protocol
+ receiver routines and signal the closure of
+ the link */
+ if( pops && pops -> disconn_ind )
+ pops -> disconn_ind(cprot);
+#endif /* CONFIG_ISDN_X25 */
+
cmd.driver = lp->isdn_device;
cmd.command = ISDN_CMD_HANGUP;
cmd.arg = lp->isdn_channel;
- (void) dev->drv[cmd.driver]->interface->command(&cmd);
+ isdn_command(&cmd);
printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
}
@@ -820,28 +937,43 @@
} ip_ports;
static void
-isdn_net_log_packet(u_char * buf, isdn_net_local * lp)
+isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
{
- u_char *p = buf;
- unsigned short proto = ETH_P_IP;
+ u_char *p = skb->nh.raw; /* hopefully, this was set correctly */
+ unsigned short proto = ntohs(skb->protocol);
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;
+ /* This check stolen from 2.1.72 dev_queue_xmit_nit() */
+ if (skb->nh.raw < skb->data || skb->nh.raw >= skb->tail) {
+ /* fall back to old isdn_net_log_packet method() */
+ char * buf = skb->data;
+
+ printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->name);
+ p = buf;
+ proto = ETH_P_IP;
+ 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;
+#ifdef CONFIG_ISDN_PPP
+ case ISDN_NET_ENCAP_SYNCPPP:
+ proto = ntohs(skb->protocol);
+ p = &buf[IPPP_MAX_HEADER];
+ break;
+#endif
+ }
}
data_ofs = ((p[0] & 15) * 4);
switch (proto) {
@@ -891,7 +1023,7 @@
/*
* Generic routine to send out an skbuf.
- * If lowlevel-device does not support supports skbufs, use
+ * If lowlevel-device does not support support skbufs, use
* standard send-routine, else send directly.
*
* Return: 0 on success, !0 on failure.
@@ -904,14 +1036,13 @@
int ret;
int len = skb->len; /* save len */
- ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, skb);
+ ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
if (ret == len) {
lp->transcount += len;
clear_bit(0, (void *) &(ndev->tbusy));
return 0;
}
if (ret < 0) {
- SET_SKB_FREE(skb);
dev_kfree_skb(skb);
lp->stats.tx_errors++;
clear_bit(0, (void *) &(ndev->tbusy));
@@ -945,7 +1076,7 @@
#endif
/* Reset hangup-timeout */
lp->huptimer = 0;
- if (lp->cps > 7000) {
+ if (lp->cps > lp->triggercps) {
/* Device overloaded */
/*
@@ -988,35 +1119,64 @@
return ret;
}
+static void
+isdn_net_adjust_hdr(struct sk_buff *skb, struct device *dev)
+{
+ isdn_net_local *lp = (isdn_net_local *) dev->priv;
+ if (!skb)
+ return;
+ if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
+ ulong pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN;
+ if (pullsize)
+ skb_pull(skb, pullsize);
+ }
+}
+
/*
* Try sending a packet.
* If this interface isn't connected to a ISDN-Channel, find a free channel,
* and start dialing.
*/
-int
+static int
isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
{
isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+#ifdef CONFIG_ISDN_X25
+ struct concap_proto * cprot = lp -> netdev -> cprot;
+#endif
if (ndev->tbusy) {
if (jiffies - ndev->trans_start < (2 * HZ))
return 1;
if (!lp->dialstate)
lp->stats.tx_errors++;
- ndev->tbusy = 0;
ndev->trans_start = jiffies;
}
- if (skb == NULL) {
- return 0;
- }
- /* Avoid timer-based retransmission conflicts. */
- if (test_and_set_bit(0, (void *) &ndev->tbusy) != 0)
- printk(KERN_WARNING
- "%s: Transmitter access conflict.\n",
- ndev->name);
- else {
- u_char *buf = skb->data;
+ ndev->tbusy = 1; /* left instead of obsolete test_and_set_bit() */
+#ifdef CONFIG_ISDN_X25
+/* At this point hard_start_xmit() passes control to the encapsulation
+ protocol (if present).
+ For X.25 auto-dialing is completly bypassed because:
+ - It does not conform with the semantics of a reliable datalink
+ service as needed by X.25 PLP.
+ - I don't want that the interface starts dialing when the network layer
+ sends a message which requests to disconnect the lapb link (or if it
+ sends any other message not resulting in data transmission).
+ Instead, dialing will be initiated by the encapsulation protocol entity
+ when a dl_establish request is received from the upper layer.
+*/
+ if( cprot ) {
+ return cprot -> pops -> encap_and_xmit ( cprot , skb);
+ } else
+#endif
+ /* auto-dialing xmit function */
+ {
#ifdef ISDN_DEBUG_NET_DUMP
+ u_char *buf;
+#endif
+ isdn_net_adjust_hdr(skb, ndev);
+#ifdef ISDN_DEBUG_NET_DUMP
+ buf = skb->data;
isdn_dumppkt("S:", buf, skb->len, 40);
#endif
if (!(lp->flags & ISDN_NET_CONNECTED)) {
@@ -1033,24 +1193,15 @@
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);
- /* 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);
ndev->tbusy = 0;
return 0;
-#endif
}
/* Log packet, which triggered dialing */
if (dev->net_verbose)
- isdn_net_log_packet(buf, lp);
+ isdn_net_log_skb(skb, lp);
lp->dialstate = 1;
lp->flags |= ISDN_NET_CONNECTED;
/* Connect interface with channel */
@@ -1114,12 +1265,26 @@
isdn_net_close(struct device *dev)
{
struct device *p;
+#ifdef CONFIG_ISDN_X25
+ struct concap_proto * cprot =
+ ( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
+ /* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */
+#endif
+#ifdef CONFIG_ISDN_X25
+ if( cprot && cprot -> pops ) cprot -> pops -> close( cprot );
+#endif
dev->tbusy = 1;
dev->start = 0;
if ((p = (((isdn_net_local *) dev->priv)->slave))) {
/* If this interface has slaves, stop them also */
while (p) {
+#ifdef CONFIG_ISDN_X25
+ cprot = ( (isdn_net_local *) p->priv )
+ -> netdev -> cprot;
+ if( cprot && cprot -> pops )
+ cprot -> pops -> close( cprot );
+#endif
isdn_net_hangup(p);
p->tbusy = 1;
p->start = 0;
@@ -1156,6 +1321,7 @@
struct ethhdr *eth;
unsigned char *rawp;
+ skb->mac.raw = skb->data;
skb_pull(skb, ETH_HLEN);
eth = skb->mac.ethernet;
@@ -1170,7 +1336,7 @@
* so don't forget to remove it.
*/
- else if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
+ else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
skb->pkt_type = PACKET_OTHERHOST;
}
@@ -1193,6 +1359,97 @@
return htons(ETH_P_802_2);
}
+static void
+isdn_net_slarp_send(isdn_net_local *lp, int is_reply)
+{
+ unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
+ struct sk_buff *skb = dev_alloc_skb(hl + sizeof(cisco_hdr) + sizeof(cisco_slarp));
+ unsigned long t = (jiffies / HZ * 1000000);
+ int len;
+ cisco_hdr *ch;
+ cisco_slarp *s;
+
+ if (!skb) {
+ printk(KERN_WARNING
+ "%s: Could not allocate SLARP reply\n", lp->name);
+ return;
+ }
+ skb_reserve(skb, hl);
+ ch = (cisco_hdr *)skb_put(skb, sizeof(cisco_hdr));
+ ch->addr = CISCO_ADDR_UNICAST;
+ ch->ctrl = 0;
+ ch->type = htons(CISCO_TYPE_SLARP);
+ s = (cisco_slarp *)skb_put(skb, sizeof(cisco_slarp));
+ if (is_reply) {
+ s->code = htonl(CISCO_SLARP_REPLY);
+ memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32));
+ memset(&s->slarp.reply.netmask, 0, sizeof(__u32));
+ } else {
+ lp->cisco_myseq++;
+ s->code = htonl(CISCO_SLARP_KEEPALIVE);
+ s->slarp.keepalive.my_seq = htonl(lp->cisco_myseq);
+ s->slarp.keepalive.your_seq = htonl(lp->cisco_yourseq);
+ }
+ s->rel = 0xffff;
+ s->t1 = t >> 16;
+ s->t0 = t & 0xffff;
+ len = skb->len;
+ if (isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 0, skb) != len)
+ dev_kfree_skb(skb);
+}
+
+static void
+isdn_net_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
+{
+ cisco_slarp *s = (cisco_slarp *)skb->data;
+
+ switch (ntohl(s->code)) {
+ case CISCO_SLARP_REQUEST:
+ isdn_net_slarp_send(lp, 1);
+ break;
+ case CISCO_SLARP_REPLY:
+ /* Ignore replies */
+ break;
+ case CISCO_SLARP_KEEPALIVE:
+ lp->cisco_yourseq = s->slarp.keepalive.my_seq;
+ if (ntohl(s->slarp.keepalive.my_seq == lp->cisco_myseq)) {
+ if (lp->cisco_loop++ == 2) {
+ printk(KERN_WARNING "%s: Keepalive Loop\n",
+ lp->name);
+ lp->cisco_myseq ^= jiffies;
+ }
+ } else
+ lp->cisco_loop = 0;
+ break;
+ }
+ kfree_skb(skb);
+}
+
+/*
+ * Called every 10 sec. via timer-interrupt if
+ * any network-interface has Cisco-Keepalive-Encapsulation
+ * and is online.
+ * Send Keepalive-Packet and re-schedule.
+ */
+void
+isdn_net_slarp_out(void)
+{
+ isdn_net_dev *p = dev->netdev;
+ int anymore = 0;
+
+ while (p) {
+ isdn_net_local *l = p->local;
+ if ((l->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) &&
+ (l->flags & ISDN_NET_CONNECTED) &&
+ (!l->dialstate) ) {
+ anymore = 1;
+ isdn_net_slarp_send(l, 0);
+ }
+ p = (isdn_net_dev *) p->next;
+ }
+ isdn_timer_ctrl(ISDN_TIMER_KEEPALIVE, anymore);
+}
+
/*
* Got a packet from ISDN-Channel.
*/
@@ -1200,23 +1457,19 @@
isdn_net_receive(struct device *ndev, struct sk_buff *skb)
{
isdn_net_local *lp = (isdn_net_local *) ndev->priv;
-#ifdef CONFIG_ISDN_PPP
isdn_net_local *olp = lp; /* original 'lp' */
+#ifdef CONFIG_ISDN_PPP
int proto = PPP_PROTOCOL(skb->data);
#endif
+#ifdef CONFIG_ISDN_X25
+ struct concap_proto *cprot = lp -> netdev -> cprot;
+#endif
+ cisco_hdr *ch;
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))
-#endif
- lp->huptimer = 0;
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes += skb->len;
if (lp->master) {
/* Bundling: If device is a slave-device, deliver to master, also
* handle master's statistics and hangup-timeout
@@ -1224,16 +1477,9 @@
ndev = lp->master;
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))
-#endif
- lp->huptimer = 0;
+ lp->stats.rx_bytes += skb->len;
}
+
skb->dev = ndev;
skb->pkt_type = PACKET_HOST;
skb->mac.raw = skb->data;
@@ -1243,22 +1489,61 @@
switch (lp->p_encap) {
case ISDN_NET_ENCAP_ETHER:
/* Ethernet over ISDN */
+ olp->huptimer = 0;
+ lp->huptimer = 0;
skb->protocol = isdn_net_type_trans(skb, ndev);
break;
case ISDN_NET_ENCAP_UIHDLC:
/* HDLC with UI-frame (for ispa with -h1 option) */
+ olp->huptimer = 0;
+ lp->huptimer = 0;
skb_pull(skb, 2);
/* Fall through */
case ISDN_NET_ENCAP_RAWIP:
/* RAW-IP without MAC-Header */
+ olp->huptimer = 0;
+ lp->huptimer = 0;
skb->protocol = htons(ETH_P_IP);
break;
+ case ISDN_NET_ENCAP_CISCOHDLCK:
+ ch = (cisco_hdr *)skb->data;
+ if ((ch->addr != CISCO_ADDR_UNICAST) &&
+ (ch->addr != CISCO_ADDR_BROADCAST) ) {
+ printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",
+ lp->name, ch->addr);
+ kfree_skb(skb);
+ return;
+ }
+ if (ch->ctrl != 0) {
+ printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",
+ lp->name, ch->ctrl);
+ kfree_skb(skb);
+ return;
+ }
+ switch (ntohs(ch->type)) {
+ case CISCO_TYPE_INET:
+ skb_pull(skb, 4);
+ skb->protocol = htons(ETH_P_IP);
+ break;
+ case CISCO_TYPE_SLARP:
+ skb_pull(skb, 4);
+ isdn_net_slarp_in(olp, skb);
+ return;
+ default:
+ printk(KERN_WARNING "%s: Unknown Cisco type 0x%04x\n",
+ lp->name, ch->type);
+ kfree_skb(skb);
+ return;
+ }
+ 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 */
+ olp->huptimer = 0;
+ lp->huptimer = 0;
skb->protocol = *(unsigned short *) &(skb->data[0]);
skb_pull(skb, 2);
if (*(unsigned short *) skb->data == 0xFFFF)
@@ -1266,10 +1551,26 @@
break;
#ifdef CONFIG_ISDN_PPP
case ISDN_NET_ENCAP_SYNCPPP:
+ /*
+ * If encapsulation is syncppp, don't reset
+ * huptimer on LCP packets.
+ */
+ if (proto != PPP_LCP) {
+ olp->huptimer = 0;
+ lp->huptimer = 0;
+ }
isdn_ppp_receive(lp->netdev, olp, skb);
return;
#endif
default:
+#ifdef CONFIG_ISDN_X25
+ /* try if there are generic sync_device receiver routines */
+ if(cprot) if(cprot -> pops)
+ if( cprot -> pops -> data_ind){
+ cprot -> pops -> data_ind(cprot,skb);
+ return;
+ };
+#endif /* CONFIG_ISDN_X25 */
printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
lp->name);
kfree_skb(skb);
@@ -1290,7 +1591,7 @@
isdn_net_dev *p = dev->rx_netdev[idx];
if (p) {
- isdn_net_local *lp = &p->local;
+ isdn_net_local *lp = p->local;
if ((lp->flags & ISDN_NET_CONNECTED) &&
(!lp->dialstate)) {
isdn_net_receive(&p->dev, skb);
@@ -1329,15 +1630,15 @@
* Anyway, the loopback-device should never use this function...
*/
- if (dev->flags & IFF_LOOPBACK) {
+ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
memset(eth->h_dest, 0, dev->addr_len);
- return (dev->hard_header_len);
+ return ETH_HLEN /*(dev->hard_header_len)*/;
}
if (daddr) {
memcpy(eth->h_dest, daddr, dev->addr_len);
- return dev->hard_header_len;
+ return ETH_HLEN /*dev->hard_header_len*/;
}
- return -dev->hard_header_len;
+ return -ETH_HLEN /*dev->hard_header_len*/;
}
/*
@@ -1356,6 +1657,13 @@
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;
@@ -1377,43 +1685,21 @@
*((ushort *) & skb->data[2]) = htons(type);
len = 4;
break;
+#ifdef CONFIG_ISDN_X25
+ default:
+ /* try if there are generic concap protocol routines */
+ if( lp-> netdev -> cprot ){
+ printk(KERN_WARNING "isdn_net_header called with concap_proto!\n");
+ len = 0;
+ break;
+ }
+ break;
+#endif /* CONFIG_ISDN_X25 */
}
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)
-{
- isdn_net_local *lp = dev->priv;
- int ret = 0;
-
- 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
- }
- return ret;
-}
-#else
static int
isdn_net_rebuild_header(struct sk_buff *skb)
{
@@ -1439,12 +1725,12 @@
* Try to get ARP to resolve the header.
*/
#ifdef CONFIG_INET
- ret = arp_find(eth->h_dest, skb) ? 1 : 0;
+ ret = arp_find(eth->h_dest, skb);
#endif
}
return ret;
}
-#endif
+
/*
* Interface-setup. (called just after registering a new interface)
*/
@@ -1465,21 +1751,13 @@
return -ENODEV;
}
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;
-#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|IFF_POINTOPOINT;
@@ -1599,13 +1877,13 @@
#endif
p = dev->netdev;
while (p) {
- if (p->local.pre_device == drvidx)
- switch (p->local.pre_channel) {
+ if (p->local->pre_device == drvidx)
+ switch (p->local->pre_channel) {
case 0:
- p->local.pre_channel = 1;
+ p->local->pre_channel = 1;
break;
case 1:
- p->local.pre_channel = 0;
+ p->local->pre_channel = 0;
break;
}
p = (isdn_net_dev *) p->next;
@@ -1676,6 +1954,7 @@
printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
/* Accept only calls with Si1 = 7 (Data-Transmission) */
if (si1 != 7) {
+ restore_flags(flags);
if (dev->net_verbose > 1)
printk(KERN_INFO "isdn_net: Service-Indicator not 7, ignored\n");
return 0;
@@ -1689,6 +1968,8 @@
#endif
swapped = 0;
while (p) {
+ isdn_net_local *lp = p->local;
+
/* If last check has triggered as binding-swap, revert it */
switch (swapped) {
case 2:
@@ -1699,25 +1980,25 @@
break;
}
swapped = 0;
- if (!strcmp(isdn_map_eaz2msn(p->local.msn, di), eaz))
+ if (!strcmp(isdn_map_eaz2msn(lp->msn, di), eaz))
ematch = 1;
#ifdef ISDN_DEBUG_NET_ICALL
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);
+ lp->name, lp->msn, lp->flags, lp->dialstate);
#endif
- if ((!strcmp(isdn_map_eaz2msn(p->local.msn, di), eaz)) && /* EAZ is matching */
- (((!(p->local.flags & ISDN_NET_CONNECTED)) && /* but not connected */
+ if ((!strcmp(isdn_map_eaz2msn(lp->msn, di), eaz)) && /* EAZ is matching */
+ (((!(lp->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 */
+ ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */
+ (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */
))) {
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
- p->local.pre_device, p->local.pre_channel);
+ lp->pre_device, lp->pre_channel);
#endif
if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
- if ((p->local.pre_channel != ch) ||
- (p->local.pre_device != di)) {
+ if ((lp->pre_channel != ch) ||
+ (lp->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
@@ -1741,8 +2022,8 @@
#endif
/* Yes, swap bindings only, if the original
* binding is bound to channel 1 of this driver */
- if ((p->local.pre_device == di) &&
- (p->local.pre_channel == 1)) {
+ if ((lp->pre_device == di) &&
+ (lp->pre_channel == 1)) {
isdn_net_swapbind(di);
swapped = 1;
} else {
@@ -1764,8 +2045,8 @@
printk(KERN_DEBUG "n_fi: final check\n");
#endif
if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) &&
- ((p->local.pre_channel != ch) ||
- (p->local.pre_device != di))) {
+ ((lp->pre_channel != ch) ||
+ (lp->pre_device != di))) {
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: final check failed\n");
#endif
@@ -1786,16 +2067,15 @@
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: match2\n");
#endif
- n = p->local.phone[0];
- if (p->local.flags & ISDN_NET_SECURE) {
+ n = lp->phone[0];
+ if (lp->flags & ISDN_NET_SECURE) {
while (n) {
if (isdn_net_wildmat(nr, n->num))
break;
n = (isdn_net_phone *) n->next;
}
}
- if (n || (!(p->local.flags & ISDN_NET_SECURE))) {
- isdn_net_local *lp = &(p->local);
+ if (n || (!(lp->flags & ISDN_NET_SECURE))) {
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: match3\n");
#endif
@@ -1804,7 +2084,7 @@
*/
if (!p->dev.start) {
restore_flags(flags);
- printk(KERN_INFO "%s: incoming call, if down -> rejected\n",
+ printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
lp->name);
return 3;
}
@@ -1872,12 +2152,12 @@
eaz);
/* if this interface is dialing, it does it probably on a different
device, so free this device */
- if ((p->local.dialstate == 4) || (p->local.dialstate == 12)) {
+ if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
#ifdef CONFIG_ISDN_PPP
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_free_channel(lp->isdn_device, lp->isdn_channel,
ISDN_USAGE_NET);
}
dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
@@ -1885,16 +2165,16 @@
strcpy(dev->num[idx], nr);
isdn_info_update();
dev->st_netdev[idx] = lp->netdev;
- p->local.isdn_device = di;
- p->local.isdn_channel = ch;
- p->local.ppp_slot = -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 |= ISDN_WAITCHARGE;
- p->local.hupflags &= ~ISDN_HAVECHARGE;
+ lp->isdn_device = di;
+ lp->isdn_channel = ch;
+ lp->ppp_slot = -1;
+ lp->flags |= ISDN_NET_CONNECTED;
+ lp->dialstate = 7;
+ lp->dtimer = 0;
+ lp->outgoing = 0;
+ lp->huptimer = 0;
+ lp->hupflags |= ISDN_WAITCHARGE;
+ lp->hupflags &= ~ISDN_HAVECHARGE;
#ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
if (isdn_ppp_bind(lp) < 0) {
@@ -1926,7 +2206,7 @@
isdn_net_dev *p = dev->netdev;
while (p) {
- if (!strcmp(p->local.name, name))
+ if (!strcmp(p->local->name, name))
return p;
p = (isdn_net_dev *) p->next;
}
@@ -1989,7 +2269,7 @@
if (!p)
return -ENODEV;
- return (isdn_net_force_dial_lp(&p->local));
+ return (isdn_net_force_dial_lp(p->local));
}
/*
@@ -2010,20 +2290,25 @@
return NULL;
}
memset(netdev, 0, sizeof(isdn_net_dev));
+ if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) {
+ printk(KERN_WARNING "isdn_net: Could not allocate device locals\n");
+ return NULL;
+ }
+ memset(netdev->local, 0, sizeof(isdn_net_local));
if (name == NULL)
- strcpy(netdev->local.name, " ");
+ strcpy(netdev->local->name, " ");
else
- strcpy(netdev->local.name, name);
- netdev->dev.name = netdev->local.name;
- netdev->dev.priv = &netdev->local;
+ strcpy(netdev->local->name, name);
+ 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;
+ netdev->local->p_encap = ISDN_NET_ENCAP_RAWIP;
if (master) {
/* Device shall be a slave */
struct device *p = (((isdn_net_local *) master->priv)->slave);
struct device *q = master;
- netdev->local.master = master;
+ netdev->local->master = master;
/* Put device at end of slave-chain */
while (p) {
q = p;
@@ -2037,41 +2322,43 @@
/* Device shall be a master */
if (register_netdev(&netdev->dev) != 0) {
printk(KERN_WARNING "isdn_net: Could not register net-device\n");
+ kfree(netdev->local);
kfree(netdev);
return NULL;
}
}
- netdev->local.magic = ISDN_NET_MAGIC;
+ netdev->local->magic = ISDN_NET_MAGIC;
#ifdef CONFIG_ISDN_PPP
netdev->mp_last = NULL; /* mpqueue is empty */
netdev->ib.next_num = 0;
netdev->ib.last = NULL;
#endif
- netdev->queue = &netdev->local;
- netdev->local.last = &netdev->local;
- netdev->local.netdev = netdev;
- netdev->local.next = &netdev->local;
-
- netdev->local.isdn_device = -1;
- netdev->local.isdn_channel = -1;
- netdev->local.pre_device = -1;
- netdev->local.pre_channel = -1;
- 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.l2_proto = ISDN_PROTO_L2_X75I;
- netdev->local.l3_proto = ISDN_PROTO_L3_TRANS;
- netdev->local.slavedelay = 10 * HZ;
- netdev->local.srobin = &netdev->dev;
- netdev->local.hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */
- netdev->local.onhtime = 10; /* Default hangup-time for saving costs
+ netdev->queue = netdev->local;
+ netdev->local->last = netdev->local;
+ netdev->local->netdev = netdev;
+ netdev->local->next = netdev->local;
+
+ netdev->local->isdn_device = -1;
+ netdev->local->isdn_channel = -1;
+ netdev->local->pre_device = -1;
+ netdev->local->pre_channel = -1;
+ 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->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 = ISDN_INHUP; /* Do hangup even on incoming calls */
+ netdev->local->onhtime = 10; /* Default hangup-time for saving costs
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->dialmax = 1;
+ 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;
@@ -2095,7 +2382,7 @@
if (!(n = isdn_net_findif(parm)))
return NULL;
/* Master must be a real interface, not a slave */
- if (n->local.master)
+ if (n->local->master)
return NULL;
/* Master must not be started yet */
if (n->dev.start)
@@ -2120,10 +2407,15 @@
int drvidx;
int chidx;
char drvid[25];
-
+#ifdef CONFIG_ISDN_X25
+ ulong flags;
+#endif
if (p) {
+ isdn_net_local *lp = p->local;
+
/* See if any registered driver supports the features we want */
- features = (1 << cfg->l2_proto) | (256 << cfg->l3_proto);
+ features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) |
+ ((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT);
for (i = 0; i < ISDN_MAX_DRIVERS; i++)
if (dev->drv[i])
if ((dev->drv[i]->interface->features & features) == features)
@@ -2132,22 +2424,68 @@
printk(KERN_WARNING "isdn_net: No driver with selected features\n");
return -ENODEV;
}
- if (p->local.p_encap != cfg->p_encap)
+ if (lp->p_encap != cfg->p_encap){
+#ifdef CONFIG_ISDN_X25
+ struct concap_proto * cprot = p -> cprot;
+#endif
if (p->dev.start) {
printk(KERN_WARNING
"%s: cannot change encap when if is up\n",
- p->local.name);
+ lp->name);
return -EBUSY;
}
- if (cfg->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
+#ifdef CONFIG_ISDN_X25
+ /* delete old encapsulation protocol if present ... */
+ save_flags(flags);
+ cli(); /* avoid races with incoming events trying to
+ call cprot->pops methods */
+ if( cprot && cprot -> pops )
+ cprot -> pops -> proto_del ( cprot );
+ p -> cprot = NULL;
+ lp -> dops = NULL;
+ restore_flags(flags);
+ /* ... , prepare for configuration of new one ... */
+ switch ( cfg -> p_encap ){
+ case ISDN_NET_ENCAP_X25IFACE:
+ lp -> dops = &isdn_concap_reliable_dl_dops;
+ }
+ /* ... and allocate new one ... */
+ p -> cprot = isdn_concap_new( cfg -> p_encap );
+ /* p -> cprot == NULL now if p_encap is not supported
+ by means of the concap_proto mechanism */
+ /* the protocol is not configured yet; this will
+ happen later when isdn_net_reset() is called */
+#endif
+ }
+ switch ( cfg->p_encap ) {
+ case ISDN_NET_ENCAP_SYNCPPP:
#ifndef CONFIG_ISDN_PPP
printk(KERN_WARNING "%s: SyncPPP support not configured\n",
- p->local.name);
+ lp->name);
return -EINVAL;
#else
p->dev.type = ARPHRD_PPP; /* change ARP type */
p->dev.addr_len = 0;
#endif
+ break;
+ case ISDN_NET_ENCAP_X25IFACE:
+#ifndef CONFIG_ISDN_X25
+ printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
+ p->local->name);
+ return -EINVAL;
+#else
+ p->dev.type = ARPHRD_X25; /* change ARP type */
+ p->dev.addr_len = 0;
+#endif
+ break;
+ default:
+ if( cfg->p_encap >= 0 &&
+ cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP )
+ break;
+ printk(KERN_WARNING
+ "%s: encapsulation protocol %d not supported\n",
+ p->local->name, cfg->p_encap);
+ return -EINVAL;
}
if (strlen(cfg->drvid)) {
/* A bind has been requested ... */
@@ -2175,20 +2513,20 @@
return -ENODEV;
} else {
/* Parameters are valid, so get them */
- drvidx = p->local.pre_device;
- chidx = p->local.pre_channel;
+ drvidx = lp->pre_device;
+ chidx = lp->pre_channel;
}
if (cfg->exclusive > 0) {
int flags;
/* 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,
+ if ((i = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
+ lp->l3_proto,
drvidx,
chidx)) < 0) {
/* Grab failed, because desired channel is in use */
- p->local.exclusive = -1;
+ lp->exclusive = -1;
restore_flags(flags);
return -EBUSY;
}
@@ -2196,93 +2534,82 @@
dev->usage[i] = ISDN_USAGE_EXCLUSIVE;
isdn_info_update();
restore_flags(flags);
- p->local.exclusive = i;
+ lp->exclusive = i;
} else {
/* Non-exclusive binding or unbind. */
- 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);
+ lp->exclusive = -1;
+ if ((lp->pre_device != -1) && (cfg->exclusive == -1)) {
+ isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
+ isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
drvidx = -1;
chidx = -1;
}
}
- strcpy(p->local.msn, cfg->eaz);
- 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;
+ strcpy(lp->msn, cfg->eaz);
+ lp->pre_device = drvidx;
+ lp->pre_channel = chidx;
+ lp->onhtime = cfg->onhtime;
+ lp->charge = cfg->charge;
+ lp->l2_proto = cfg->l2_proto;
+ lp->l3_proto = cfg->l3_proto;
+ lp->cbdelay = cfg->cbdelay;
+ lp->dialmax = cfg->dialmax;
+ lp->triggercps = cfg->triggercps;
+ lp->slavedelay = cfg->slavedelay * HZ;
+ lp->pppbind = cfg->pppbind;
if (cfg->secure)
- p->local.flags |= ISDN_NET_SECURE;
+ lp->flags |= ISDN_NET_SECURE;
else
- p->local.flags &= ~ISDN_NET_SECURE;
+ lp->flags &= ~ISDN_NET_SECURE;
if (cfg->cbhup)
- p->local.flags |= ISDN_NET_CBHUP;
+ lp->flags |= ISDN_NET_CBHUP;
else
- p->local.flags &= ~ISDN_NET_CBHUP;
+ lp->flags &= ~ISDN_NET_CBHUP;
switch (cfg->callback) {
case 0:
- p->local.flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
+ lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
break;
case 1:
- p->local.flags |= ISDN_NET_CALLBACK;
- p->local.flags &= ~ISDN_NET_CBOUT;
+ lp->flags |= ISDN_NET_CALLBACK;
+ lp->flags &= ~ISDN_NET_CBOUT;
break;
case 2:
- p->local.flags |= ISDN_NET_CBOUT;
- p->local.flags &= ~ISDN_NET_CALLBACK;
+ lp->flags |= ISDN_NET_CBOUT;
+ lp->flags &= ~ISDN_NET_CALLBACK;
break;
}
if (cfg->chargehup)
- p->local.hupflags |= ISDN_CHARGEHUP;
+ lp->hupflags |= ISDN_CHARGEHUP;
else
- p->local.hupflags &= ~ISDN_CHARGEHUP;
+ lp->hupflags &= ~ISDN_CHARGEHUP;
if (cfg->ihup)
- p->local.hupflags |= ISDN_INHUP;
+ lp->hupflags |= ISDN_INHUP;
else
- p->local.hupflags &= ~ISDN_INHUP;
+ lp->hupflags &= ~ISDN_INHUP;
if (cfg->chargeint > 10) {
- p->local.hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
- p->local.chargeint = cfg->chargeint * HZ;
+ lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
+ lp->chargeint = cfg->chargeint * HZ;
}
- if (cfg->p_encap != p->local.p_encap) {
+ if (cfg->p_encap != lp->p_encap) {
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|IFF_POINTOPOINT;
} 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.hard_header_cache = lp->org_hhc;
+ p->dev.header_cache_update = lp->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|IFF_POINTOPOINT;
}
}
}
- p->local.p_encap = cfg->p_encap;
+ lp->p_encap = cfg->p_encap;
return 0;
}
return -ENODEV;
@@ -2297,39 +2624,42 @@
isdn_net_dev *p = isdn_net_findif(cfg->name);
if (p) {
- strcpy(cfg->eaz, p->local.msn);
- cfg->exclusive = p->local.exclusive;
- if (p->local.pre_device >= 0) {
- sprintf(cfg->drvid, "%s,%d", dev->drvid[p->local.pre_device],
- p->local.pre_channel);
+ isdn_net_local *lp = p->local;
+
+ strcpy(cfg->eaz, lp->msn);
+ cfg->exclusive = lp->exclusive;
+ if (lp->pre_device >= 0) {
+ sprintf(cfg->drvid, "%s,%d", dev->drvid[lp->pre_device],
+ lp->pre_channel);
} else
cfg->drvid[0] = '\0';
- cfg->onhtime = p->local.onhtime;
- cfg->charge = p->local.charge;
- cfg->l2_proto = p->local.l2_proto;
- cfg->l3_proto = p->local.l3_proto;
- cfg->p_encap = p->local.p_encap;
- cfg->secure = (p->local.flags & ISDN_NET_SECURE) ? 1 : 0;
+ cfg->onhtime = lp->onhtime;
+ cfg->charge = lp->charge;
+ cfg->l2_proto = lp->l2_proto;
+ cfg->l3_proto = lp->l3_proto;
+ cfg->p_encap = lp->p_encap;
+ cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
cfg->callback = 0;
- if (p->local.flags & ISDN_NET_CALLBACK)
+ if (lp->flags & ISDN_NET_CALLBACK)
cfg->callback = 1;
- if (p->local.flags & ISDN_NET_CBOUT)
+ if (lp->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->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);
+ cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
+ cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
+ cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
+ cfg->cbdelay = lp->cbdelay;
+ cfg->dialmax = lp->dialmax;
+ cfg->triggercps = lp->triggercps;
+ cfg->slavedelay = lp->slavedelay / HZ;
+ cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
+ (lp->chargeint / HZ) : 0;
+ cfg->pppbind = lp->pppbind;
+ if (lp->slave)
+ strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name);
else
cfg->slave[0] = '\0';
- if (p->local.master)
- strcpy(cfg->master, ((isdn_net_local *) p->local.master->priv)->name);
+ if (lp->master)
+ strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name);
else
cfg->master[0] = '\0';
return 0;
@@ -2352,8 +2682,8 @@
if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
return -ENOMEM;
strcpy(n->num, phone->phone);
- n->next = p->local.phone[phone->outgoing & 1];
- p->local.phone[phone->outgoing & 1] = n;
+ n->next = p->local->phone[phone->outgoing & 1];
+ p->local->phone[phone->outgoing & 1] = n;
return 0;
}
return -ENODEV;
@@ -2378,7 +2708,7 @@
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++;
@@ -2413,16 +2743,16 @@
if (p) {
save_flags(flags);
cli();
- n = p->local.phone[inout];
+ 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 (p->local->dial == n)
+ p->local->dial = n->next;
if (m)
m->next = n->next;
else
- p->local.phone[inout] = n->next;
+ p->local->phone[inout] = n->next;
kfree(n);
return 0;
}
@@ -2449,15 +2779,15 @@
save_flags(flags);
cli();
for (i = 0; i < 2; i++) {
- n = p->local.phone[i];
+ n = p->local->phone[i];
while (n) {
m = n->next;
kfree(n);
n = m;
}
- p->local.phone[i] = NULL;
+ p->local->phone[i] = NULL;
}
- p->local.dial = NULL;
+ p->local->dial = NULL;
restore_flags(flags);
return 0;
}
@@ -2472,9 +2802,9 @@
struct device *q;
if (p) {
- if (p->local.isdn_device < 0)
+ if (p->local->isdn_device < 0)
return 1;
- q = p->local.slave;
+ q = p->local->slave;
/* If this interface has slaves, do a hangup for them also. */
while (q) {
isdn_net_hangup(q);
@@ -2496,7 +2826,7 @@
save_flags(flags);
cli();
- if (p->local.master) {
+ if (p->local->master) {
/* If it's a slave, it may be removed even if it is busy. However
* it has to be hung up first.
*/
@@ -2507,30 +2837,37 @@
restore_flags(flags);
return -EBUSY;
}
+#ifdef CONFIG_ISDN_X25
+ if( p -> cprot && p -> cprot -> pops )
+ p -> cprot -> pops -> proto_del ( p -> cprot );
+#endif
/* Free all phone-entries */
isdn_net_rmallphone(p);
/* If interface is bound exclusive, free channel-usage */
- if (p->local.exclusive != -1)
- isdn_unexclusive_channel(p->local.pre_device, p->local.pre_channel);
- if (p->local.master) {
+ if (p->local->exclusive != -1)
+ isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel);
+ if (p->local->master) {
/* It's a slave-device, so update master's slave-pointer if necessary */
- if (((isdn_net_local *) (p->local.master->priv))->slave == &p->dev)
- ((isdn_net_local *) (p->local.master->priv))->slave = p->local.slave;
- } else
+ if (((isdn_net_local *) (p->local->master->priv))->slave == &p->dev)
+ ((isdn_net_local *) (p->local->master->priv))->slave = p->local->slave;
+ } else {
/* Unregister only if it's a master-device */
+ p->dev.hard_header_cache = p->local->org_hhc;
+ p->dev.header_cache_update = p->local->org_hcu;
unregister_netdev(&p->dev);
+ }
/* Unlink device from chain */
if (q)
q->next = p->next;
else
dev->netdev = p->next;
- if (p->local.slave) {
+ if (p->local->slave) {
/* If this interface has a slave, remove it also */
- char *slavename = ((isdn_net_local *) (p->local.slave->priv))->name;
+ char *slavename = ((isdn_net_local *) (p->local->slave->priv))->name;
isdn_net_dev *n = dev->netdev;
q = NULL;
while (n) {
- if (!strcmp(n->local.name, slavename)) {
+ if (!strcmp(n->local->name, slavename)) {
isdn_net_realrm(n, q);
break;
}
@@ -2543,6 +2880,7 @@
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
restore_flags(flags);
+ kfree(p->local);
kfree(p);
return 0;
@@ -2561,7 +2899,7 @@
p = dev->netdev;
q = NULL;
while (p) {
- if (!strcmp(p->local.name, name))
+ if (!strcmp(p->local->name, name))
return (isdn_net_realrm(p, q));
q = p;
p = (isdn_net_dev *) p->next;
@@ -2585,7 +2923,7 @@
save_flags(flags);
cli();
while (dev->netdev) {
- if (!dev->netdev->local.master) {
+ if (!dev->netdev->local->master) {
/* Remove master-devices only, slaves get removed with their master */
if ((ret = isdn_net_realrm(dev->netdev, NULL))) {
restore_flags(flags);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov