Fix copy_from/to_user in ISDN

Joerg Lehrke (Joerg.Lehrke@ecrc.de)
Tue, 17 Jun 1997 14:28:17 +0200


This is a multipart MIME message.

--==_Exmh_12446522240
Content-Type: text/plain; charset=us-ascii

Hi!

As suggested by Bill Hawes (thanks Bill!) I looked through the ISDN stuff
and tried to fix the problems with copy_from/to_user while interrupts
dissabled.
The result is the following patch, which fixes some (I hope most) of
these problems. My first patch to isdn_net.c is also included in this one.
The patch is against 2.1.42, but I think nothing is changed in
2.1.43 for the affected files. I only tested the net and
the tty stuff and it seems to work. But there are still problems :-(
Sorry, it's work in progress.

J"org

--==_Exmh_12446522240
Content-Type: application/x-patch ; name="21-isdn_userspace+net.patch"
Content-Description: 21-isdn_userspace+net.patch
Content-Disposition: attachment; filename="21-isdn_userspace+net.patch"

diff -u --recursive --new-file linux-2.1.42/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- linux-2.1.42/drivers/isdn/isdn_common.c Wed May 28 19:49:09 1997
+++ linux/drivers/isdn/isdn_common.c Tue Jun 17 12:30:06 1997
@@ -330,7 +330,7 @@
}
}
if (tf) {
- int flags;
+ unsigned long flags;

save_flags(flags);
cli();
@@ -344,7 +344,7 @@
void
isdn_timer_ctrl(int tf, int onoff)
{
- int flags;
+ unsigned long flags;

save_flags(flags);
cli();
@@ -410,13 +410,18 @@
isdn_status_callback(isdn_ctrl * c)
{
int di;
- ulong flags;
+ unsigned long flags;
int i;
int r;
int retval = 0;
isdn_ctrl cmd;

di = c->driver;
+ if (!dev->drv[di]) {
+ printk(KERN_WARNING
+ "Try to access unregistered isdn device %d\n", di);
+ return -1;
+ }
i = isdn_dc2minor(di, c->arg);
switch (c->command) {
case ISDN_STAT_BSENT:
@@ -662,28 +667,22 @@
* It MUST be called with interrupts off.
*/
int
-isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user)
+isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len)
{
- int left;
int count;
int count_pull;
int count_put;
int dflag;
struct sk_buff *skb;
- u_char *cp;

if (!dev->drv[di])
- return 0;
- if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
- if (user)
- interruptible_sleep_on(&dev->drv[di]->rcv_waitq[channel]);
- else
- return 0;
- }
- left = MIN(len, dev->drv[di]->rcvcount[channel]);
- cp = buf;
+ return -ENODEV;
+ if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
+ return -EAGAIN;
+
+ len = MIN(len, dev->drv[di]->rcvcount[channel]);
count = 0;
- while (left) {
+ while (len) {
if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
break;
#ifdef CONFIG_ISDN_AUDIO
@@ -696,18 +695,12 @@

dflag = 0;
count_pull = count_put = 0;
- while ((count_pull < skb->len) && (left-- > 0)) {
+ while ((count_pull < skb->len) && (len-- > 0)) {
if (dev->drv[di]->DLEflag & DLEmask) {
- if (user)
- put_user(DLE, cp++);
- else
- *cp++ = DLE;
+ *buf++ = DLE;
dev->drv[di]->DLEflag &= ~DLEmask;
} else {
- if (user)
- put_user(*p, cp++);
- else
- *cp++ = *p;
+ *buf++ = *p;
if (*p == DLE) {
dev->drv[di]->DLEflag |= DLEmask;
(ISDN_AUDIO_SKB_DLECOUNT(skb))--;
@@ -723,17 +716,14 @@
#endif
/* No DLE's in buff, so simply copy it */
dflag = 1;
- if ((count_pull = skb->len) > left) {
- count_pull = left;
+ if ((count_pull = skb->len) > len) {
+ count_pull = len;
dflag = 0;
}
count_put = count_pull;
- if (user)
- copy_to_user(cp, skb->data, count_put);
- else
- memcpy(cp, skb->data, count_put);
- cp += count_put;
- left -= count_put;
+ memcpy(buf, skb->data, count_put);
+ buf += count_put;
+ len -= count_put;
#ifdef CONFIG_ISDN_AUDIO
}
#endif
@@ -853,12 +843,12 @@
{
uint minor = MINOR(inode->i_rdev);
int len = 0;
- ulong flags;
+ unsigned long flags;
int drvidx;
int chidx;
+ char *p;

if (minor == ISDN_MINOR_STATUS) {
- char *p;
if (!file->private_data) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
@@ -880,14 +870,25 @@
drvidx = isdn_minor2drv(minor);
if (drvidx < 0)
return -ENODEV;
- if (!dev->drv[drvidx]->running)
+ if (!dev->drv[drvidx] || !dev->drv[drvidx]->running)
return -ENODEV;
chidx = isdn_minor2chan(minor);
- save_flags(flags);
- cli();
- len = isdn_readbchan(drvidx, chidx, buf, 0, count, 1);
- file->f_pos += len;
- restore_flags(flags);
+ if (!(p = (char *) kmalloc(count, GFP_BUFFER)))
+ return -ENOMEM;
+ do {
+ save_flags(flags);
+ cli();
+ len = isdn_readbchan(drvidx, chidx, p, 0, count);
+ restore_flags(flags);
+ if (len == -EAGAIN)
+ interruptible_sleep_on(&dev->drv[drvidx]->rcv_waitq[chidx]);
+ } while (len == -EAGAIN);
+ if (len > 0) {
+ if (copy_to_user(buf, p, len))
+ return -EFAULT;
+ file->f_pos += len;
+ }
+ kfree(p);
return len;
}
if (minor <= ISDN_MINOR_CTRLMAX) {
@@ -1049,7 +1050,7 @@
{
int ret;
int i;
- ulong flags;
+ unsigned long flags;
isdn_net_ioctl_cfg cfg;
isdn_net_ioctl_phone phone;

@@ -1057,32 +1058,33 @@
return ret;
if ((ret = copy_from_user((char *) &i, src, sizeof(int))))
return ret;
- save_flags(flags);
- cli();
src += sizeof(int);
while (i) {
int phone_len;
int out_flag;

- if ((ret = copy_from_user((char *) &cfg, src, sizeof(cfg)))) {
- restore_flags(flags);
+ if ((ret = copy_from_user((char *) &cfg, src, sizeof(cfg))))
return ret;
- }
+
src += sizeof(cfg);
- if (!isdn_net_new(cfg.name, NULL)) {
+ save_flags(flags);
+ cli();
+
+ if ((ret = isdn_net_new(cfg.name, NULL))) {
restore_flags(flags);
- return -EIO;
+ return ret;
}
if ((ret = isdn_net_setcfg(&cfg))) {
restore_flags(flags);
return ret;
}
+ restore_flags(flags);
+
phone_len = out_flag = 0;
while (out_flag < 2) {
- if ((ret = verify_area(VERIFY_READ, src, 1))) {
- restore_flags(flags);
+ if ((ret = verify_area(VERIFY_READ, src, 1)))
return ret;
- }
+
GET_USER(phone.phone[phone_len], src++);
if ((phone.phone[phone_len] == ' ') ||
(phone.phone[phone_len] == '\0')) {
@@ -1090,10 +1092,13 @@
phone.phone[phone_len] = '\0';
strcpy(phone.name, cfg.name);
phone.outgoing = out_flag;
+ save_flags(flags);
+ cli();
if ((ret = isdn_net_addphone(&phone))) {
restore_flags(flags);
return ret;
}
+ restore_flags(flags);
} else
out_flag++;
phone_len = 0;
@@ -1105,7 +1110,6 @@
}
i--;
}
- restore_flags(flags);
return 0;
}

@@ -1115,18 +1119,17 @@
isdn_net_ioctl_cfg cfg;
isdn_net_ioctl_phone phone;
isdn_net_dev *p;
- ulong flags;
+ unsigned long flags;
+ char name[10];
int ret;

/* Walk through netdev-chain */
- save_flags(flags);
- cli();
p = dev->netdev;
while (p) {
- if ((ret = verify_area(VERIFY_WRITE, (void *) dest, sizeof(cfg) + 200))) {
- restore_flags(flags);
+ if ((ret = verify_area(VERIFY_WRITE, (void *) dest, sizeof(cfg) + 200)))
return ret;
- }
+ save_flags(flags);
+ cli();
strcpy(cfg.eaz, p->local.msn);
cfg.exclusive = p->local.exclusive;
if (p->local.pre_device >= 0) {
@@ -1144,34 +1147,30 @@
cfg.chargehup = (p->local.hupflags & ISDN_CHARGEHUP) ? 1 : 0;
cfg.ihup = (p->local.hupflags & ISDN_INHUP) ? 1 : 0;
cfg.chargeint = p->local.chargeint;
- if (copy_to_user(dest, p->local.name, 10)) {
- restore_flags(flags);
+ memcpy(name, p->local.name, 10);
+ restore_flags(flags);
+ if (copy_to_user(dest, name, 10))
return -EFAULT;
- }
dest += 10;
- if (copy_to_user(dest, (char *) &cfg, sizeof(cfg))) {
- restore_flags(flags);
+ if (copy_to_user(dest, (char *) &cfg, sizeof(cfg)))
return -EFAULT;
- }
+
dest += sizeof(cfg);
- strcpy(phone.name, p->local.name);
+ strcpy(phone.name, name);
phone.outgoing = 0;
- if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
- restore_flags(flags);
+ if ((ret = isdn_net_getphones(&phone, dest)) < 0)
return ret;
- } else
+ else
dest += ret;
- strcpy(phone.name, p->local.name);
+ strcpy(phone.name, name);
phone.outgoing = 1;
- if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
- restore_flags(flags);
+ if ((ret = isdn_net_getphones(&phone, dest)) < 0)
return ret;
- } else
+ else
dest += ret;
put_user(0, dest);
p = p->next;
}
- restore_flags(flags);
return 0;
}

@@ -1247,12 +1246,11 @@
s = name;
} else
s = NULL;
- if ((s = isdn_net_new(s, NULL))) {
- if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1)))
- return ret;
- return 0;
- } else
- return -ENODEV;
+
+ if (!(ret = isdn_net_new(s, NULL)))
+ ret = copy_to_user((char *) arg, s, strlen(s) + 1);
+ return ret;
+
case IIOCNETASL:
/* Add a slave to a network-interface */
if (arg) {
@@ -1260,12 +1258,13 @@
return ret;
} else
return -EINVAL;
- if ((s = isdn_net_newslave(bname))) {
- if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1)))
- return ret;
- return 0;
- } else
- return -ENODEV;
+
+ s = bname;
+
+ if (!(ret = isdn_net_newslave(s)))
+ ret = copy_to_user((char *) arg, s, strlen(s) + 1);
+ return ret;
+
case IIOCNETDIF:
/* Delete a network-interface */
if (arg) {
@@ -1737,7 +1736,7 @@
,int pre_chan)
{
int i;
- ulong flags;
+ unsigned long flags;
ulong features;
isdn_ctrl cmd;

@@ -1790,7 +1789,7 @@
isdn_free_channel(int di, int ch, int usage)
{
int i;
- ulong flags;
+ unsigned long flags;
isdn_ctrl cmd;

save_flags(flags);
@@ -1822,7 +1821,7 @@
isdn_unexclusive_channel(int di, int ch)
{
int i;
- ulong flags;
+ unsigned long flags;

save_flags(flags);
cli();
@@ -1938,7 +1937,7 @@
int n,
j,
k;
- ulong flags;
+ unsigned long flags;
int drvidx;

if (dev->drivers >= ISDN_MAX_DRIVERS) {
@@ -2088,7 +2087,7 @@
sti();
if (!(dev = (isdn_dev *) kmalloc(sizeof(isdn_dev), GFP_KERNEL))) {
printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
- return -EIO;
+ return -ENOMEM;
}
memset((char *) dev, 0, sizeof(isdn_dev));
init_timer(&dev->timer);
@@ -2157,7 +2156,7 @@
void
cleanup_module(void)
{
- int flags;
+ unsigned long flags;
int i;

#ifdef CONFIG_ISDN_PPP
diff -u --recursive --new-file linux-2.1.42/drivers/isdn/isdn_common.h linux/drivers/isdn/isdn_common.h
--- linux-2.1.42/drivers/isdn/isdn_common.h Wed May 28 19:49:09 1997
+++ linux/drivers/isdn/isdn_common.h Sun Jun 15 16:02:11 1997
@@ -67,7 +67,7 @@
extern void isdn_timer_ctrl(int tf, int onoff);
extern void isdn_unexclusive_channel(int di, int ch);
extern int isdn_getnum(char **);
-extern int isdn_readbchan(int, int, u_char *, u_char *, int, int);
+extern int isdn_readbchan(int, int, u_char *, u_char *, int);
extern int isdn_get_free_channel(int, int, int, int, int);
extern int isdn_writebuf_skb_stub(int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
diff -u --recursive --new-file linux-2.1.42/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- linux-2.1.42/drivers/isdn/isdn_net.c Wed May 28 19:49:09 1997
+++ linux/drivers/isdn/isdn_net.c Tue Jun 17 10:18:04 1997
@@ -209,6 +209,7 @@
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 *);
+static int isdn_change_mtu(struct device *, int);
static void dev_purge_queues(struct device *dev); /* move this to net/core/dev.c */

char *isdn_net_revision = "$Revision: 1.44 $";
@@ -232,7 +233,7 @@
static void
isdn_net_reset(struct device *dev)
{
- ulong flags;
+ unsigned long flags;

save_flags(flags);
cli(); /* Avoid glitch on writes to CMD regs */
@@ -251,19 +252,18 @@
isdn_net_reset(dev);
dev->start = 1;
/* Fill in the MAC-level header. */
- for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
+ for (i = 0; i < ETH_ALEN - sizeof(dev->pa_addr); i++)
dev->dev_addr[i] = 0xfc;
- memcpy(&(dev->dev_addr[i]), &dev->pa_addr, sizeof(u32));
+ memcpy(&(dev->dev_addr[i]), &dev->pa_addr, sizeof(dev->pa_addr));

/* If this interface has slaves, start them also */
-
- if ((p = (((isdn_net_local *) dev->priv)->slave))) {
- while (p) {
- isdn_net_reset(p);
- p->start = 1;
- p = (((isdn_net_local *) p->priv)->slave);
- }
+ p = dev->slave;
+ while (p) {
+ isdn_net_reset(p);
+ p->start = 1;
+ p = p->slave;
}
+
isdn_MOD_INC_USE_COUNT();
return 0;
}
@@ -274,15 +274,10 @@
static void
isdn_net_bind_channel(isdn_net_local * lp, int idx)
{
- ulong flags;
-
- 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);
}

/*
@@ -291,10 +286,6 @@
static void
isdn_net_unbind_channel(isdn_net_local * lp)
{
- ulong flags;
-
- save_flags(flags);
- cli();
if (lp->first_skb) {
dev_kfree_skb(lp->first_skb, FREE_WRITE);
lp->first_skb = NULL;
@@ -312,8 +303,6 @@
lp->flags &= ~ISDN_NET_CONNECTED;
lp->isdn_device = -1;
lp->isdn_channel = -1;
-
- restore_flags(flags);
}

/*
@@ -399,7 +388,6 @@
/* 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) {
struct device *mdev;
if (lp->master)
@@ -552,7 +540,7 @@
isdn_net_dev *p = dev->netdev;
int anymore = 0;
int i;
- int flags;
+ unsigned long flags;
isdn_ctrl cmd;

while (p) {
@@ -778,6 +766,7 @@
void
isdn_net_hangup(struct device *d)
{
+ unsigned long flags;
isdn_net_local *lp = (isdn_net_local *) d->priv;
isdn_ctrl cmd;

@@ -794,7 +783,10 @@
printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
}
+ save_flags(flags);
+ cli();
isdn_net_unbind_channel(lp);
+ restore_flags(flags);
}

typedef struct {
@@ -889,7 +881,14 @@

ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, skb);
if (ret == len) {
- lp->transcount += len;
+ lp->stats.tx_packets++;
+ lp->stats.tx_bytes += len;
+ if (lp->master) {
+ /* Bundling: handle master's statistics */
+ isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;
+ mlp->stats.tx_packets++;
+ mlp->stats.tx_bytes += len;
+ }
clear_bit(0, (void *) &(ndev->tbusy));
return 0;
}
@@ -897,6 +896,11 @@
SET_SKB_FREE(skb);
dev_kfree_skb(skb, FREE_WRITE);
lp->stats.tx_errors++;
+ if (lp->master) {
+ /* Bundling: handle master's statistics */
+ isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;
+ mlp->stats.tx_errors++;
+ }
clear_bit(0, (void *) &(ndev->tbusy));
return 0;
}
@@ -945,13 +949,13 @@
ret = isdn_net_send_skb(ndev, lp, skb);
else
ret = ndev->tbusy = isdn_net_start_xmit(skb, lp->srobin);
- lp->srobin = (slp->slave) ? slp->slave : ndev;
+ lp->srobin = (slp->netdev->dev.slave) ? slp->netdev->dev.slave : ndev;
slp = (isdn_net_local *) (lp->srobin->priv);
if (!((slp->flags & ISDN_NET_CONNECTED) && (slp->dialstate == 0)))
lp->srobin = ndev;
}
/* Slave-startup using delay-variable */
- if (lp->slave) {
+ if (lp->netdev->dev.slave) {
if (!lp->sqfull) {
/* First time overload: set timestamp only */
lp->sqfull = 1;
@@ -959,7 +963,7 @@
} 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);
+ isdn_net_force_dial_lp((isdn_net_local *) lp->netdev->dev.slave->priv);
}
}
} else {
@@ -1006,7 +1010,7 @@
if (!(lp->flags & ISDN_NET_CONNECTED)) {
int chi;
if (lp->phone[1]) {
- ulong flags;
+ unsigned long flags;
save_flags(flags);
cli();
/* Grab a free ISDN-Channel */
@@ -1101,15 +1105,16 @@

dev->tbusy = 1;
dev->start = 0;
- if ((p = (((isdn_net_local *) dev->priv)->slave))) {
- /* If this interface has slaves, stop them also */
- while (p) {
- isdn_net_hangup(p);
- p->tbusy = 1;
- p->start = 0;
- p = (((isdn_net_local *) p->priv)->slave);
- }
+
+ /* If this interface has slaves, stop them also */
+ p = dev->slave;
+ while (p) {
+ isdn_net_hangup(p);
+ p->tbusy = 1;
+ p->start = 0;
+ p = p->slave;
}
+
isdn_net_hangup(dev);
isdn_MOD_DEC_USE_COUNT();
return 0;
@@ -1118,7 +1123,7 @@
/*
* Get statistics
*/
-static struct enet_statistics *
+static struct net_device_stats *
isdn_net_get_stats(struct device *dev)
{
isdn_net_local *lp = (isdn_net_local *) dev->priv;
@@ -1191,6 +1196,7 @@

lp->transcount += skb->len;
lp->stats.rx_packets++;
+ lp->stats.rx_bytes += skb->len;
#ifdef CONFIG_ISDN_PPP
/*
* If encapsulation is syncppp, don't reset
@@ -1208,6 +1214,7 @@
ndev = lp->master;
lp = (isdn_net_local *) ndev->priv;
lp->stats.rx_packets++;
+ lp->stats.rx_bytes += skb->len;
#ifdef CONFIG_ISDN_PPP
/*
* If encapsulation is syncppp, don't reset
@@ -1436,9 +1443,7 @@
isdn_net_init(struct device *ndev)
{
ushort max_hlhdr_len = 0;
- isdn_net_local *lp = (isdn_net_local *) ndev->priv;
- int drvidx,
- i;
+ int drvidx;

if (ndev == NULL) {
printk(KERN_WARNING "isdn_net_init: dev = NULL!\n");
@@ -1448,42 +1453,39 @@
printk(KERN_WARNING "isdn_net_init: dev->priv = NULL!\n");
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 */
+ dev_init_buffers(ndev);

- 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;
+ /* Setup the generic properties */
+ ndev->get_stats = isdn_net_get_stats;
+
+ ndev->type = ARPHRD_ETHER;
ndev->mtu = 1500;
+ ndev->addr_len = ETH_ALEN;
+ ndev->tx_queue_len = 100; /* ISDN wants good queues */
+
+ memset(ndev->broadcast,0xFF, ETH_ALEN);
+
+ /* New-style flags. */
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 < DEV_NUMBUFFS; 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->stop = isdn_net_close;
+ ndev->hard_start_xmit = isdn_net_start_xmit;
+ ndev->hard_header = NULL;
+ ndev->rebuild_header = isdn_net_rebuild_header;
+ ndev->set_multicast_list = NULL;
+ ndev->set_mac_address = NULL;
+#ifdef CONFIG_ISDN_PPP
+ ndev->do_ioctl = isdn_ppp_dev_ioctl;
+#endif
+ ndev->change_mtu = isdn_change_mtu;

/*
* up till binding we ask the protocol layer to reserve as much
@@ -1497,13 +1499,6 @@

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;
-
-#ifdef CONFIG_ISDN_PPP
- ndev->do_ioctl = isdn_ppp_dev_ioctl;
-#endif
return 0;
}

@@ -1640,12 +1635,10 @@
int sidx = 0;
isdn_net_dev *p;
isdn_net_phone *n;
- ulong flags;
+ unsigned long flags;
char nr[32];

/* Search name in netdev-chain */
- save_flags(flags);
- cli();
if (!setup.phone[0]) {
nr[0] = '0';
nr[1] = '\0';
@@ -1668,13 +1661,15 @@
return 0;
}
n = (isdn_net_phone *) 0;
- p = dev->netdev;
ematch = 0;
+ swapped = 0;
+ save_flags(flags);
+ cli();
+ p = dev->netdev;
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
dev->usage[idx]);
#endif
- swapped = 0;
while (p) {
/* If last check has triggered as binding-swap, revert it */
switch (swapped) {
@@ -1805,10 +1800,10 @@
if (mlp->flags & ISDN_NET_CONNECTED) {
printk(KERN_DEBUG "master online\n");
/* Master is online, find parent-slave (master if first slave) */
- while (mlp->slave) {
- if ((isdn_net_local *) mlp->slave->priv == lp)
+ while (mlp->netdev->dev.slave) {
+ if ((isdn_net_local *) mlp->netdev->dev.slave->priv == lp)
break;
- mlp = (isdn_net_local *) mlp->slave->priv;
+ mlp = (isdn_net_local *) mlp->netdev->dev.slave->priv;
}
} else
printk(KERN_DEBUG "master offline\n");
@@ -1931,7 +1926,7 @@
if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
int chi;
if (lp->phone[1]) {
- ulong flags;
+ unsigned long flags;
save_flags(flags);
cli();
/* Grab a free ISDN-Channel */
@@ -1982,19 +1977,20 @@
/*
* Allocate a new network-interface and initialize its data structures.
*/
-char *
+int
isdn_net_new(char *name, struct device *master)
{
isdn_net_dev *netdev;
+ int ret;

/* Avoid creating an existing interface */
if (isdn_net_findif(name)) {
printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
- return NULL;
+ return -EEXIST;
}
if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
- return NULL;
+ return -ENOMEM;
}
memset(netdev, 0, sizeof(isdn_net_dev));
if (name == NULL)
@@ -2004,29 +2000,48 @@
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 */
- struct device *p = (((isdn_net_local *) master->priv)->slave);
- struct device *q = master;
-
+ struct device *p = master;
+ isdn_net_local *mlp = (isdn_net_local *) master->priv;
netdev->local.master = master;
+ netdev->local.p_encap = mlp->p_encap;
+ netdev->local.l2_proto = mlp->l2_proto;
+ netdev->local.l3_proto = mlp->l3_proto;
+ netdev->local.hupflags = mlp->hupflags;
+ netdev->local.onhtime = mlp->onhtime;
+ netdev->local.dialmax = mlp->dialmax;
+ netdev->local.flags = mlp->flags;
+ netdev->local.cbdelay = mlp->cbdelay;
+
/* Put device at end of slave-chain */
- while (p) {
- q = p;
- p = (((isdn_net_local *) p->priv)->slave);
- }
- ((isdn_net_local *) q->priv)->slave = &(netdev->dev);
- q->interrupt = 0;
- q->tbusy = 0;
- q->start = master->start;
+ while (p->slave) {
+ p = p->slave;
+ }
+ p->slave = &netdev->dev;
+ p->interrupt = 0;
+ p->tbusy = 0;
+ p->start = master->start;
} else {
/* Device shall be a master */
- if (register_netdev(&netdev->dev) != 0) {
+ if ((ret = register_netdev(&netdev->dev)) != 0) {
printk(KERN_WARNING "isdn_net: Could not register net-device\n");
kfree(netdev);
- return NULL;
+ return ret;
}
+ netdev->local.p_encap = ISDN_NET_ENCAP_RAWIP;
+ netdev->local.l2_proto = ISDN_PROTO_L2_X75I;
+ netdev->local.l3_proto = ISDN_PROTO_L3_TRANS;
+ /* Do hangup even on incoming calls */
+ netdev->local.hupflags = ISDN_INHUP;
+ /* Default hangup-time for saving costs
+ of those who forget configuring this */
+ netdev->local.onhtime = 10;
+ netdev->local.dialmax = 1;
+ /* Hangup before Callback */
+ netdev->local.flags = ISDN_NET_CBHUP;
+ /* Wait 5 secs before Callback */
+ netdev->local.cbdelay = 25;
}
netdev->local.magic = ISDN_NET_MAGIC;

@@ -2049,23 +2064,16 @@
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
- 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 */
/* Put into to netdev-chain */
netdev->next = (void *) dev->netdev;
dev->netdev = netdev;
- return netdev->dev.name;
+ name = netdev->dev.name;
+ return 0;
}

-char *
+int
isdn_net_newslave(char *parm)
{
char *p = strchr(parm, ',');
@@ -2075,21 +2083,21 @@
if (p) {
/* Slave-Name MUST not be empty */
if (!strlen(p + 1))
- return NULL;
+ return -EINVAL;
strcpy(newname, p + 1);
*p = 0;
/* Master must already exist */
if (!(n = isdn_net_findif(parm)))
- return NULL;
+ return -ENODEV;
/* Master must be a real interface, not a slave */
if (n->local.master)
- return NULL;
+ return -EPERM;
/* Master must not be started yet */
if (n->dev.start)
- return NULL;
+ return -EBUSY;
return (isdn_net_new(newname, &(n->dev)));
}
- return NULL;
+ return -EINVAL;
}

/*
@@ -2166,10 +2174,11 @@
chidx = p->local.pre_channel;
}
if (cfg->exclusive > 0) {
- int flags;
+ unsigned long flags;

/* If binding is exclusive, try to grab the channel */
save_flags(flags);
+ cli();
if ((i = isdn_get_free_channel(ISDN_USAGE_NET, p->local.l2_proto,
p->local.l3_proto,
drvidx,
@@ -2239,37 +2248,29 @@
p->local.chargeint = cfg->chargeint * HZ;
}
if (cfg->p_encap != p->local.p_encap) {
- if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
+ if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP)
p->dev.hard_header = NULL;
+ 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 = NULL;
+ p->dev.header_cache_bind = eth_header_cache;
#else
- p->dev.hard_header_cache = NULL;
+ p->dev.hard_header_cache = eth_header_cache;
#endif
- p->dev.header_cache_update = NULL;
- p->dev.flags = IFF_NOARP;
+ p->dev.header_cache_update = eth_header_cache_update;
+ p->dev.flags = IFF_BROADCAST | IFF_MULTICAST;
} 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;
+ p->dev.header_cache_bind = NULL;
#else
- p->dev.hard_header_cache = NULL;
+ p->dev.hard_header_cache = NULL;
#endif
- p->dev.header_cache_update = NULL;
- p->dev.flags = IFF_NOARP;
- }
+ p->dev.header_cache_update = NULL;
+ p->dev.flags = IFF_NOARP;
}
+ p->local.p_encap = cfg->p_encap;
}
- p->local.p_encap = cfg->p_encap;
return 0;
}
return -ENODEV;
@@ -2311,12 +2312,12 @@
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);
+ if (p->dev.slave)
+ strcpy(cfg->slave, p->dev.slave->name);
else
cfg->slave[0] = '\0';
if (p->local.master)
- strcpy(cfg->master, ((isdn_net_local *) p->local.master->priv)->name);
+ strcpy(cfg->master, p->local.master->name);
else
cfg->master[0] = '\0';
return 0;
@@ -2354,33 +2355,38 @@
{
isdn_net_dev *p = isdn_net_findif(phone->name);
int inout = phone->outgoing & 1;
- int more = 0;
+ int i;
int count = 0;
+ char *buf;
+ char *q;
isdn_net_phone *n;
- int flags;
+ unsigned long flags;
int ret;

- if (!p)
+ if (!dev)
return -ENODEV;
save_flags(flags);
cli();
- inout &= 1;
+ for (n = p->local.phone[inout]; n; n = n->next)
+ count++;
+ if (!(buf = (char *) kmalloc((count * ISDN_MSNLEN), GFP_BUFFER))) {
+ restore_flags(flags);
+ return -ENOMEM;
+ }
+ q = buf;
for (n = p->local.phone[inout]; n; n = n->next) {
- if (more) {
- put_user(' ', phones++);
- count++;
- }
- if ((ret = copy_to_user(phones, n->num, strlen(n->num) + 1))) {
- restore_flags(flags);
- return ret;
- }
- phones += strlen(n->num);
- count += strlen(n->num);
- more = 1;
+ i = strlen(n->num);
+ memcpy(q, n->num, i);
+ q += i;
+ *q++ = ' ';
}
- put_user(0, phones);
- count++;
restore_flags(flags);
+ q--;
+ *q= '\0';
+ ret = copy_to_user(phones, buf, strlen(buf) + 1);
+ kfree(buf);
+ if (ret)
+ return ret;
return count;
}

@@ -2395,7 +2401,7 @@
int inout = phone->outgoing & 1;
isdn_net_phone *n;
isdn_net_phone *m;
- int flags;
+ unsigned long flags;

if (p) {
save_flags(flags);
@@ -2430,7 +2436,7 @@
{
isdn_net_phone *n;
isdn_net_phone *m;
- int flags;
+ unsigned long flags;
int i;

save_flags(flags);
@@ -2461,13 +2467,12 @@
if (p) {
if (p->local.isdn_device < 0)
return 1;
- q = p->local.slave;
+ q = &p->dev;
/* If this interface has slaves, do a hangup for them also. */
- while (q) {
+ do {
isdn_net_hangup(q);
- q = (((isdn_net_local *) q->priv)->slave);
- }
- isdn_net_hangup(&p->dev);
+ } while ((q = q->slave));
+
return 0;
}
return -ENODEV;
@@ -2477,9 +2482,9 @@
* Helper-function for isdn_net_rm: Do the real work.
*/
static int
-isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
+isdn_net_realrm(isdn_net_dev *p)
{
- int flags;
+ unsigned long flags;

save_flags(flags);
cli();
@@ -2500,30 +2505,29 @@
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;
+ /* It's a slave-device, so update master's pointer-list */
+ struct device *q = p->local.master;
+ while(q && (q->slave != &p->dev))
+ q = q->slave;
+ if (q)
+ q->slave = p->dev.slave;
} else
/* Unregister only if it's a master-device */
unregister_netdev(&p->dev);
/* Unlink device from chain */
- if (q)
- q->next = p->next;
- else
- dev->netdev = p->next;
- if (p->local.slave) {
- /* If this interface has a slave, remove it also */
- char *slavename = ((isdn_net_local *) (p->local.slave->priv))->name;
+ if (p == dev->netdev)
+ dev->netdev = (isdn_net_dev *) p->next;
+ else {
isdn_net_dev *n = dev->netdev;
- q = NULL;
- while (n) {
- if (!strcmp(n->local.name, slavename)) {
- isdn_net_realrm(n, q);
- break;
- }
- q = n;
+ while (n && ((isdn_net_dev *) n->next != p))
n = (isdn_net_dev *) n->next;
- }
+ if (n)
+ n->next = p->next;
+ }
+ if (!p->local.master && p->dev.slave) {
+ /* If this interface has slaves, remove them also */
+ while(p->dev.slave)
+ isdn_net_realrm(((isdn_net_local *) p->dev.slave->priv)->netdev);
}
/* If no more net-devices remain, disable auto-hangup timer */
if (dev->netdev == NULL)
@@ -2542,15 +2546,12 @@
isdn_net_rm(char *name)
{
isdn_net_dev *p;
- isdn_net_dev *q;

/* Search name in netdev-chain */
p = dev->netdev;
- q = NULL;
while (p) {
if (!strcmp(p->local.name, name))
- return (isdn_net_realrm(p, q));
- q = p;
+ return (isdn_net_realrm(p));
p = (isdn_net_dev *) p->next;
}
/* If no more net-devices remain, disable auto-hangup timer */
@@ -2565,7 +2566,7 @@
int
isdn_net_rmall(void)
{
- int flags;
+ unsigned long flags;
int ret;

/* Walk through netdev-chain */
@@ -2574,7 +2575,7 @@
while (dev->netdev) {
if (!dev->netdev->local.master) {
/* Remove master-devices only, slaves get removed with their master */
- if ((ret = isdn_net_realrm(dev->netdev, NULL))) {
+ if ((ret = isdn_net_realrm(dev->netdev))) {
restore_flags(flags);
return ret;
}
@@ -2599,4 +2600,12 @@
dev_kfree_skb(skb, FREE_WRITE);
}

+}
+
+static int isdn_change_mtu(struct device *dev, int new_mtu)
+{
+ if ((new_mtu < 68) || (new_mtu > 1500))
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
}
diff -u --recursive --new-file linux-2.1.42/drivers/isdn/isdn_net.h linux/drivers/isdn/isdn_net.h
--- linux-2.1.42/drivers/isdn/isdn_net.h Wed Feb 26 02:12:50 1997
+++ linux/drivers/isdn/isdn_net.h Wed Jun 11 09:47:55 1997
@@ -45,8 +45,8 @@
#define ISDN_INHUP 8 /* Even if incoming, close after huptimeout */
#define ISDN_MANCHARGE 16 /* Charge Interval manually set */

-extern char *isdn_net_new(char *, struct device *);
-extern char *isdn_net_newslave(char *);
+extern int isdn_net_new(char *, struct device *);
+extern int isdn_net_newslave(char *);
extern int isdn_net_rm(char *);
extern int isdn_net_rmall(void);
extern int isdn_net_stat_callback(int, int);
diff -u --recursive --new-file linux-2.1.42/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- linux-2.1.42/drivers/isdn/isdn_ppp.c Wed May 28 19:49:09 1997
+++ linux/drivers/isdn/isdn_ppp.c Tue Jun 17 10:19:19 1997
@@ -224,6 +224,8 @@
}
lp->next = lp->last = lp; /* (re)set own pointers */
#endif
+ if (!(master_lp->flags & ISDN_NET_CONNECTED))
+ is->state &= ~IPPP_CONNECT;

if ((is->state & IPPP_CONNECT))
isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */
@@ -253,15 +255,11 @@
{
int i;
int unit = 0;
- long flags;
struct ippp_struct *is;

if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
return -1;

- save_flags(flags);
- cli();
-
if (lp->pppbind < 0) { /* device bounded to ippp device ? */
isdn_net_dev *net_dev = dev->netdev;
char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */
@@ -287,7 +285,6 @@
}

if (i >= ISDN_MAX_CHANNELS) {
- restore_flags(flags);
printk(KERN_WARNING "isdn_ppp_bind: Can't find usable ippp device.\n");
return -1;
}
@@ -302,8 +299,6 @@
is->unit = unit;
is->state = IPPP_OPEN | IPPP_ASSIGNED; /* assigned to a netdevice but not connected */

- restore_flags(flags);
-
return lp->ppp_slot;
}

@@ -797,12 +792,13 @@
struct ippp_struct *is;
struct ippp_buf_queue *b;
int r;
+ char *p;
unsigned long flags;

is = file->private_data;

if (!(is->state & IPPP_OPEN))
- return 0;
+ return -EPERM;

save_flags(flags);
cli();
@@ -812,17 +808,20 @@
restore_flags(flags);
return -EAGAIN;
}
- if (b->len < count)
+ if (b->len <= count)
count = b->len;
- if ((r = copy_to_user(buf, b->buf, count))) {
+ else {
restore_flags(flags);
- return r;
+ return -EFAULT;
}
- kfree(b->buf);
+ p = b->buf;
b->buf = NULL;
is->first = b;
restore_flags(flags);

+ if ((r = copy_to_user(buf, p, count)))
+ return r;
+ kfree(p);
return count;
}

@@ -841,7 +840,7 @@
is = file->private_data;

if (!(is->state & IPPP_CONNECT))
- return 0;
+ return -EACCES;

lp = is->lp;

@@ -1435,7 +1434,7 @@
isdn_ppp_bundle(struct ippp_struct *is, int unit)
{
char ifn[IFNAMSIZ + 1];
- long flags;
+ unsigned long flags;
isdn_net_dev *p;
isdn_net_local *lp,
*nlp;
@@ -1495,8 +1494,8 @@
struct mpqueue *qe,
*q1,
*q;
- long cnt,
- flags;
+ long cnt;
+ unsigned long flags;
int pktlen,
sqno_end;
int sqno = *sqnop;
@@ -1857,12 +1856,12 @@
if (!(lp->flags & ISDN_NET_CONNECTED))
return 5;

- sdev = lp->slave;
+ sdev = lp->netdev->dev.slave;
while (sdev) {
isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
if (!(mlp->flags & ISDN_NET_CONNECTED))
break;
- sdev = mlp->slave;
+ sdev = mlp->netdev->dev.slave;
}
if (!sdev)
return 2;
@@ -1888,12 +1887,12 @@
if (!(lp->flags & ISDN_NET_CONNECTED))
return 5;

- sdev = lp->slave;
+ sdev = lp->netdev->dev.slave;
while (sdev) {
isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
if ((mlp->flags & ISDN_NET_CONNECTED))
break;
- sdev = mlp->slave;
+ sdev = mlp->netdev->dev.slave;
}
if (!sdev)
return 2;
diff -u --recursive --new-file linux-2.1.42/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- linux-2.1.42/drivers/isdn/isdn_tty.c Wed May 28 19:49:09 1997
+++ linux/drivers/isdn/isdn_tty.c Tue Jun 17 11:49:21 1997
@@ -201,8 +201,8 @@

/* Prototypes */

-static int isdn_tty_edit_at(const char *, int, modem_info *, int);
-static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int);
+static int isdn_tty_edit_at(const char *, int, modem_info *);
+static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *);
static void isdn_tty_modem_reset_regs(modem_info *, int);
static void isdn_tty_cmd_ATA(modem_info *);
static void isdn_tty_at_cout(char *, modem_info *);
@@ -297,7 +297,7 @@
int i;
int c;
int r;
- ulong flags;
+ unsigned long flags;
struct tty_struct *tty;
modem_info *info;

@@ -317,15 +317,16 @@
cli();
r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
tty->flip.char_buf_ptr,
- tty->flip.flag_buf_ptr, c, 0);
- /* CISCO AsyncPPP Hack */
- if (!(info->emu.mdmreg[12] & 128))
- memset(tty->flip.flag_buf_ptr, 0, r);
- tty->flip.count += r;
- tty->flip.flag_buf_ptr += r;
- tty->flip.char_buf_ptr += r;
- if (r)
- queue_task(&tty->flip.tqueue, &tq_timer);
+ tty->flip.flag_buf_ptr, c);
+ if (r > 0) {
+ /* CISCO AsyncPPP Hack */
+ if (!(info->emu.mdmreg[12] & 128))
+ memset(tty->flip.flag_buf_ptr, 0, r);
+ tty->flip.count += r;
+ tty->flip.flag_buf_ptr += r;
+ tty->flip.char_buf_ptr += r;
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ }
restore_flags(flags);
}
} else
@@ -347,7 +348,7 @@
int
isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
{
- ulong flags;
+ unsigned long flags;
int midx;
#ifdef CONFIG_ISDN_AUDIO
int ifmt;
@@ -584,15 +585,12 @@
* ^S or ^Q is sent.
*/
static int
-isdn_tty_end_vrx(const char *buf, int c, int from_user)
+isdn_tty_end_vrx(const char *buf, int c)
{
char ch;

while (c--) {
- if (from_user)
- GET_USER(ch, buf);
- else
- ch = *buf;
+ ch = *buf;
if ((ch != 0x11) && (ch != 0x13))
return 1;
buf++;
@@ -763,7 +761,7 @@
int si = 7;
int l2 = m->mdmreg[14];
isdn_ctrl cmd;
- ulong flags;
+ unsigned long flags;
int i;
int j;

@@ -972,7 +970,7 @@
static int
isdn_tty_startup(modem_info * info)
{
- ulong flags;
+ unsigned long flags;

if (info->flags & ISDN_ASYNC_INITIALIZED)
return 0;
@@ -1007,7 +1005,7 @@
static void
isdn_tty_shutdown(modem_info * info)
{
- ulong flags;
+ unsigned long flags;

if (!(info->flags & ISDN_ASYNC_INITIALIZED))
return;
@@ -1047,15 +1045,21 @@
static int
isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count)
{
- int c,
- total = 0;
- ulong flags;
+ int c, total = 0;
+ unsigned long flags;
+ u_char *p = NULL;
modem_info *info = (modem_info *) tty->driver_data;

if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write"))
- return 0;
+ return -ENOTTY;
if (!tty)
- return 0;
+ return -ENOTTY;
+ if (from_user) {
+ if (!(p = (u_char *) kmalloc(count, GFP_BUFFER)))
+ return -ENOMEM;
+ copy_from_user(p, buf, count);
+ buf = p;
+ }
save_flags(flags);
cli();
while (1) {
@@ -1076,12 +1080,8 @@
#endif
isdn_tty_check_esc(buf, m->mdmreg[2], c,
&(m->pluscount),
- &(m->lastplus),
- from_user);
- if (from_user)
- copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c);
- else
- memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
+ &(m->lastplus));
+ memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
#ifdef CONFIG_ISDN_AUDIO
if (info->vonline) {
int cc = isdn_tty_handleDLEdown(info, m, c);
@@ -1103,7 +1103,7 @@
/* Do NOT handle Ctrl-Q or Ctrl-S
* when in full-duplex audio mode.
*/
- if (isdn_tty_end_vrx(buf, c, from_user)) {
+ if (isdn_tty_end_vrx(buf, c)) {
info->vonline &= ~1;
#ifdef ISDN_DEBUG_MODEM_VOICE
printk(KERN_DEBUG
@@ -1131,7 +1131,7 @@
isdn_tty_modem_result(3, info);
isdn_tty_modem_hup(info, 1);
} else
- c = isdn_tty_edit_at(buf, c, info, from_user);
+ c = isdn_tty_edit_at(buf, c, info);
}
buf += c;
count -= c;
@@ -1140,6 +1140,8 @@
if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))
isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
restore_flags(flags);
+ if (from_user)
+ kfree(p);
return total;
}

@@ -1263,12 +1265,8 @@
{
u_char status;
uint result;
- ulong flags;

- save_flags(flags);
- cli();
status = info->lsr;
- restore_flags(flags);
result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
put_user(result, (ulong *) value);
return 0;
@@ -1281,13 +1279,9 @@
u_char control,
status;
uint result;
- ulong flags;

control = info->mcr;
- save_flags(flags);
- cli();
status = info->msr;
- restore_flags(flags);
result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
| ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
@@ -1667,7 +1661,7 @@
isdn_tty_close(struct tty_struct *tty, struct file *filp)
{
modem_info *info = (modem_info *) tty->driver_data;
- ulong flags;
+ unsigned long flags;
ulong timeout;

if (!info || isdn_tty_paranoia_check(info, tty->device, "isdn_tty_close"))
@@ -1716,6 +1710,8 @@
info->callout_termios = *tty->termios;

tty->closing = 1;
+ restore_flags(flags);
+
/*
* At this point we stop accepting input. To do this, we
* disable the receive line status interrupts, and tell the
@@ -1731,13 +1727,18 @@
*/
timeout = jiffies + HZ;
while (!(info->lsr & UART_LSR_TEMT)) {
+ save_flags(flags);
+ cli();
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + 20;
+ restore_flags(flags);
schedule();
if (jiffies > timeout)
break;
}
}
+ save_flags(flags);
+ cli();
dev->modempoll--;
isdn_tty_shutdown(info);
if (tty->driver.flush_buffer)
@@ -1747,16 +1748,19 @@
info->tty = 0;
info->ncarrier = 0;
tty->closing = 0;
+ restore_flags(flags);
if (info->blocked_open) {
+ save_flags(flags);
+ cli();
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + 50;
+ restore_flags(flags);
schedule();
wake_up_interruptible(&info->open_wait);
}
info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE |
ISDN_ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
- restore_flags(flags);
#ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "isdn_tty_close normal exit\n");
#endif
@@ -1952,10 +1956,8 @@
int si1;
int si2;
char nr[32];
- ulong flags;
+ unsigned long flags;

- save_flags(flags);
- cli();
if (!setup.phone[0]) {
nr[0] = '0';
nr[1] = '\0';
@@ -1972,6 +1974,8 @@
#ifdef ISDN_DEBUG_MODEM_ICALL
printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
#endif
+ save_flags(flags);
+ cli();
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
modem_info *info = &dev->mdm.info[i];
#ifdef ISDN_DEBUG_MODEM_ICALL
@@ -2172,7 +2176,7 @@
atemu *m = &info->emu;
char *p;
char c;
- ulong flags;
+ unsigned long flags;

if (!msg) {
printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
@@ -2243,10 +2247,8 @@
*/
static void
isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount,
- int *lastplus, int from_user)
+ int *lastplus)
{
- char cbuf[3];
-
if (plus > 127)
return;
if (count > 3) {
@@ -2254,10 +2256,6 @@
count = 3;
*pluscount = 0;
}
- if (from_user) {
- copy_from_user(cbuf, p, count);
- p = cbuf;
- }
while (count > 0) {
if (*(p++) == plus) {
if ((*pluscount)++) {
@@ -2294,7 +2292,7 @@
{"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
"CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
"RINGING", "NO MSN/EAZ", "VCON"};
- ulong flags;
+ unsigned long flags;
char s[10];

switch (code) {
@@ -3244,10 +3242,9 @@
* p inputbuffer
* count length of buffer
* channel index to line (minor-device)
- * user flag: buffer is in userspace
*/
static int
-isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
+isdn_tty_edit_at(const char *p, int count, modem_info * info)
{
atemu *m = &info->emu;
int total = 0;
@@ -3256,10 +3253,7 @@
int cnt;

for (cnt = count; cnt > 0; p++, cnt--) {
- if (user)
- GET_USER(c, p);
- else
- c = *p;
+ c = *p;
total++;
if (c == m->mdmreg[3] || c == m->mdmreg[4]) {
/* Separator (CR oder LF) */
diff -u --recursive --new-file linux-2.1.42/include/linux/isdn.h linux/include/linux/isdn.h
--- linux-2.1.42/include/linux/isdn.h Wed May 28 19:49:11 1997
+++ linux/include/linux/isdn.h Sun Jun 15 18:52:30 1997
@@ -366,7 +366,7 @@
typedef struct isdn_net_local_s {
ulong magic;
char name[10]; /* Name of device */
- struct enet_statistics stats; /* Ethernet Statistics */
+ struct net_device_stats stats; /* Device Statistics */
int isdn_device; /* Index to isdn-device */
int isdn_channel; /* Index to isdn-channel */
int ppp_slot; /* PPPD device slot number */
@@ -419,35 +419,11 @@
/* phone[1] = Outgoing Numbers */
isdn_net_phone *dial; /* Pointer to dialed number */
struct device *master; /* Ptr to Master device for slaves */
- struct device *slave; /* Ptr to Slave device for masters */
struct isdn_net_local_s *next; /* Ptr to next link in bundle */
struct isdn_net_local_s *last; /* Ptr to last link in bundle */
struct isdn_net_dev_s *netdev; /* Ptr to netdev */
struct sk_buff *first_skb; /* Ptr to skb that triggers dialing */
struct sk_buff *sav_skb; /* Ptr to skb, rejected by LL-driver*/
-#if (LINUX_VERSION_CODE < 0x02010F)
- /* Ptr to orig. header_cache_bind */
- void (*org_hcb)(struct hh_cache **,
- struct device *,
- unsigned short,
- __u32);
-#else
-#if (LINUX_VERSION_CODE < 0x2011E)
- /* Ptr to orig. hard_header_cache */
- int (*org_hhc)(struct dst_entry *dst,
- struct dst_entry *neigh,
- struct hh_cache *hh);
-#else
- /* Ptr to orig. hard_header_cache */
- int (*org_hhc)(struct dst_entry *dst,
- struct neighbour *neigh,
- struct hh_cache *hh);
-#endif
-#endif
- /* Ptr to orig. header_cache_update */
- void (*org_hcu)(struct hh_cache *,
- struct device *,
- unsigned char *);
int pppbind; /* ippp device for bindings */
} isdn_net_local;

diff -u --recursive --new-file linux-2.1.42/net/netsyms.c linux/net/netsyms.c
--- linux-2.1.42/net/netsyms.c Wed May 28 19:49:12 1997
+++ linux/net/netsyms.c Sun Jun 8 22:09:34 1997
@@ -294,6 +294,8 @@
EXPORT_SYMBOL(register_netdev);
EXPORT_SYMBOL(unregister_netdev);
EXPORT_SYMBOL(ether_setup);
+EXPORT_SYMBOL(eth_header_cache);
+EXPORT_SYMBOL(eth_header_cache_update);
EXPORT_SYMBOL(dev_new_index);
EXPORT_SYMBOL(dev_get_by_index);
EXPORT_SYMBOL(eth_type_trans);

--==_Exmh_12446522240--