diff options
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/Config.in | 2 | ||||
-rw-r--r-- | drivers/isdn/avmb1/b1lli.c | 6 | ||||
-rw-r--r-- | drivers/isdn/hisax/callc.c | 9 | ||||
-rw-r--r-- | drivers/isdn/hisax/config.c | 2 | ||||
-rw-r--r-- | drivers/isdn/icn/icn.h | 4 | ||||
-rw-r--r-- | drivers/isdn/isdn_common.c | 208 | ||||
-rw-r--r-- | drivers/isdn/isdn_common.h | 6 | ||||
-rw-r--r-- | drivers/isdn/isdn_net.c | 42 | ||||
-rw-r--r-- | drivers/isdn/isdn_ppp.c | 25 | ||||
-rw-r--r-- | drivers/isdn/isdn_x25iface.c | 2 |
10 files changed, 193 insertions, 113 deletions
diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in index 3787c735f..08e3b78b8 100644 --- a/drivers/isdn/Config.in +++ b/drivers/isdn/Config.in @@ -38,7 +38,9 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then + if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930 + fi fi fi if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then diff --git a/drivers/isdn/avmb1/b1lli.c b/drivers/isdn/avmb1/b1lli.c index 1c4c0b806..db6fe1453 100644 --- a/drivers/isdn/avmb1/b1lli.c +++ b/drivers/isdn/avmb1/b1lli.c @@ -173,7 +173,7 @@ static inline int B1_rx_full(unsigned short base) static inline unsigned char B1_get_byte(unsigned short base) { unsigned long i = jiffies + 5 * HZ; /* maximum wait time 5 sec */ - while (!B1_rx_full(base) && i > jiffies); + while (!B1_rx_full(base) && time_before(jiffies, i)); if (B1_rx_full(base)) return inb(base + B1_READ); printk(KERN_CRIT "b1lli: rx not full after 5 second\n"); @@ -477,7 +477,7 @@ int B1_loaded(unsigned short base) if (loaddebug) printk(KERN_DEBUG "b1capi: loaded: wait 1 ..\n"); - for (i = jiffies + 10 * HZ; i > jiffies;) { + for (i = jiffies + 10 * HZ; time_before(jiffies, i);) { if (B1_tx_empty(base)) break; } @@ -487,7 +487,7 @@ int B1_loaded(unsigned short base) } B1_put_byte(base, SEND_POLL); printk(KERN_DEBUG "b1capi: loaded: wait 2 ..\n"); - for (i = jiffies + 10 * HZ; i > jiffies;) { + for (i = jiffies + 10 * HZ; time_before(jiffies, i);) { if (B1_rx_full(base)) { if ((ans = B1_get_byte(base)) == RECEIVE_POLL) { if (loaddebug) diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index 6924e3f9e..bcd305058 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -62,7 +62,7 @@ #include "hisax.h" #ifdef MODULE -#define MOD_USE_COUNT ((&__this_module)->usecount) +#define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module)) #endif /* MODULE */ const char *lli_revision = "$Revision: 2.13 $"; @@ -2055,7 +2055,7 @@ HiSax_command(isdn_ctrl * ic) if (csta->channel[0].debug & 0x400) { jiftime(tmp, jiffies); i = strlen(tmp); - sprintf(tmp + i, " LOCK modcnt %lx\n", MOD_USE_COUNT); + sprintf(tmp + i, " LOCK modcnt %d\n", MOD_USE_COUNT); HiSax_putstatus(csta, tmp); } #endif /* MODULE */ @@ -2066,7 +2066,7 @@ HiSax_command(isdn_ctrl * ic) if (csta->channel[0].debug & 0x400) { jiftime(tmp, jiffies); i = strlen(tmp); - sprintf(tmp + i, " UNLOCK modcnt %lx\n", MOD_USE_COUNT); + sprintf(tmp + i, " UNLOCK modcnt %d\n", MOD_USE_COUNT); HiSax_putstatus(csta, tmp); } #endif /* MODULE */ @@ -2128,7 +2128,8 @@ HiSax_command(isdn_ctrl * ic) break; #ifdef MODULE case (55): - MOD_USE_COUNT = 0; + while ( MOD_USE_COUNT > 0) + MOD_DEC_USE_COUNT; HiSax_mod_inc_use_count(); break; #endif /* MODULE */ diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 67e308e43..e6b3a9a52 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -97,9 +97,11 @@ #ifdef CONFIG_HISAX_ELSA #define DEFAULT_CARD ISDN_CTYPE_ELSA #define DEFAULT_CFG {0,0,0,0} +#ifdef MODULE int elsa_init_pcmcia(void*, int, int*, int); EXPORT_SYMBOL(elsa_init_pcmcia); #endif +#endif #ifdef CONFIG_HISAX_AVM_A1 #undef DEFAULT_CARD #undef DEFAULT_CFG diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h index 3bd2819ce..4aba68b38 100644 --- a/drivers/isdn/icn/icn.h +++ b/drivers/isdn/icn/icn.h @@ -318,9 +318,9 @@ static char *icn_id2 = "\0"; #ifdef MODULE MODULE_AUTHOR("Fritz Elfert"); MODULE_PARM(portbase, "i"); -MODULE_PARM_DESC(portbase, "Port adress of first card"); +MODULE_PARM_DESC(portbase, "Port address of first card"); MODULE_PARM(membase, "i"); -MODULE_PARM_DESC(membase, "Shared memory adress of all cards"); +MODULE_PARM_DESC(membase, "Shared memory address of all cards"); MODULE_PARM(icn_id, "s"); MODULE_PARM_DESC(icn_id, "ID-String of first card"); MODULE_PARM(icn_id2, "s"); diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c index 331842fab..92e2ee544 100644 --- a/drivers/isdn/isdn_common.c +++ b/drivers/isdn/isdn_common.c @@ -20,6 +20,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * Note: This file differs from the corresponding revision as present in the + * isdn4linux CVS repository because some later bug fixes have been extracted + * from the repository and merged into this file. -- Henner Eisen + * * $Log: isdn_common.c,v $ * Revision 1.55 1998/02/23 23:35:32 fritz * Eliminated some compiler warnings. @@ -770,9 +774,18 @@ isdn_getnum(char **p) /* * isdn_readbchan() tries to get data from the read-queue. * It MUST be called with interrupts off. + * + * Be aware that this is not an atomic operation when sleep != 0, even though + * interrupts are turned off! Well, like that we are currently only called + * on behalf of a read system call on raw device files (which are documented + * to be dangerous and for for debugging purpose only). The inode semaphore + * takes care that this is not called for the same minor device number while + * we are sleeping, but access is not serialized against simultaneous read() + * from the corresponding ttyI device. Can other ugly events, like changes + * of the mapping (di,ch)<->minor, happen during the sleep? --he */ 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, struct wait_queue **sleep) { int left; int count; @@ -785,8 +798,8 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user 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]); + if (sleep) + interruptible_sleep_on(sleep); else return 0; } @@ -808,16 +821,10 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user count_pull = count_put = 0; while ((count_pull < skb->len) && (left-- > 0)) { if (dev->drv[di]->DLEflag & DLEmask) { - if (user) - put_user(DLE, cp++); - else - *cp++ = DLE; + *cp++ = DLE; dev->drv[di]->DLEflag &= ~DLEmask; } else { - if (user) - put_user(*p, cp++); - else - *cp++ = *p; + *cp++ = *p; if (*p == DLE) { dev->drv[di]->DLEflag |= DLEmask; (ISDN_AUDIO_SKB_DLECOUNT(skb))--; @@ -838,10 +845,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user dflag = 0; } count_put = count_pull; - if (user) - copy_to_user(cp, skb->data, count_put); - else - memcpy(cp, skb->data, count_put); + memcpy(cp, skb->data, count_put); cp += count_put; left -= count_put; #ifdef CONFIG_ISDN_AUDIO @@ -966,12 +970,12 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off) ulong flags; int drvidx; int chidx; + char *p; if (off != &file->f_pos) return -ESPIPE; if (minor == ISDN_MINOR_STATUS) { - char *p; if (!file->private_data) { if (file->f_flags & O_NONBLOCK) return -EAGAIN; @@ -996,11 +1000,15 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off) if (!dev->drv[drvidx]->running) return -ENODEV; chidx = isdn_minor2chan(minor); + if( ! (p = kmalloc(count,GFP_KERNEL)) ) return -ENOMEM; save_flags(flags); cli(); - len = isdn_readbchan(drvidx, chidx, buf, 0, count, 1); + len = isdn_readbchan(drvidx, chidx, p, 0, count, + &dev->drv[drvidx]->rcv_waitq[chidx]); *off += len; restore_flags(flags); + if( copy_to_user(buf,p,len) ) len = -EFAULT; + kfree(p); return len; } if (minor <= ISDN_MINOR_CTRLMAX) { @@ -1124,6 +1132,11 @@ isdn_poll(struct file *file, poll_table * wait) return POLLERR; } +/* + * This accesses user space with interrupts off, but is not needed by + * any of the isdn4k-util programs anyway. Thus, in contrast to your + * first impression after looking at the code, fixing is trival!*/ +#if 0 static int isdn_set_allcfg(char *src) { @@ -1135,8 +1148,7 @@ isdn_set_allcfg(char *src) if ((ret = isdn_net_rmall())) return ret; - if ((ret = copy_from_user((char *) &i, src, sizeof(int)))) - return ret; + if (copy_from_user((char *) &i, src, sizeof(int))) return -EFAULT; save_flags(flags); cli(); src += sizeof(int); @@ -1144,9 +1156,9 @@ isdn_set_allcfg(char *src) int phone_len; int out_flag; - if ((ret = copy_from_user((char *) &cfg, src, sizeof(cfg)))) { + if (copy_from_user((char *) &cfg, src, sizeof(cfg))) { restore_flags(flags); - return ret; + return -EFAULT; } src += sizeof(cfg); if (!isdn_net_new(cfg.name, NULL)) { @@ -1256,6 +1268,7 @@ isdn_get_allcfg(char *dest) restore_flags(flags); return 0; } +#endif static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) @@ -1319,59 +1332,83 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) return 0; } if (minor <= ISDN_MINOR_CTRLMAX) { +/* + * isdn net devices manage lots of configuration variables as linked lists. + * Those lists must only be manipulated from user space. Some of the ioctl's + * service routines access user space and are not atomic. Therefor, ioctl's + * manipulating the lists and ioctl's sleeping while accessing the lists + * are serialized by means of a semaphore. + */ switch (cmd) { #ifdef CONFIG_NETDEVICES case IIOCNETAIF: /* Add a network-interface */ if (arg) { - if ((ret = copy_from_user(name, (char *) arg, sizeof(name)))) - return ret; + if (copy_from_user(name, (char *) arg, sizeof(name))) + return -EFAULT; s = name; - } else + } else { s = NULL; + } + ret = down_interruptible(&dev->sem); + if( ret ) return ret; if ((s = isdn_net_new(s, NULL))) { - if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1))) - return ret; - return 0; + if (copy_to_user((char *) arg, s, strlen(s) + 1)){ + ret = -EFAULT; + } else { + ret = 0; + } } else - return -ENODEV; + ret = -ENODEV; + up(&dev->sem); + return ret; case IIOCNETASL: /* Add a slave to a network-interface */ if (arg) { - if ((ret = copy_from_user(bname, (char *) arg, sizeof(bname) - 1))) - return ret; + if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1)) + return -EFAULT; } else return -EINVAL; + ret = down_interruptible(&dev->sem); + if( ret ) return ret; if ((s = isdn_net_newslave(bname))) { - if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1))) - return ret; - return 0; + if (copy_to_user((char *) arg, s, strlen(s) + 1)){ + ret = -EFAULT; + } else { + ret = 0; + } } else - return -ENODEV; + ret = -ENODEV; + up(&dev->sem); + return ret; case IIOCNETDIF: /* Delete a network-interface */ if (arg) { - if ((ret = copy_from_user(name, (char *) arg, sizeof(name)))) - return ret; - return isdn_net_rm(name); + if (copy_from_user(name, (char *) arg, sizeof(name))) + return -EFAULT; + ret = down_interruptible(&dev->sem); + if( ret ) return ret; + ret = isdn_net_rm(name); + up(&dev->sem); + return ret; } else return -EINVAL; case IIOCNETSCF: /* Set configurable parameters of a network-interface */ if (arg) { - if ((ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))) - return ret; + if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))) + return -EFAULT; return isdn_net_setcfg(&cfg); } else return -EINVAL; case IIOCNETGCF: /* Get configurable parameters of a network-interface */ if (arg) { - if ((ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))) - return ret; + if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))) + return -EFAULT; if (!(ret = isdn_net_getcfg(&cfg))) { - if ((ret = copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))) - return ret; + if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg))) + return -EFAULT; } return ret; } else @@ -1379,32 +1416,44 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) case IIOCNETANM: /* Add a phone-number to a network-interface */ if (arg) { - if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))) - return ret; - return isdn_net_addphone(&phone); + if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) + return -EFAULT; + ret = down_interruptible(&dev->sem); + if( ret ) return ret; + ret = isdn_net_addphone(&phone); + up(&dev->sem); + return ret; } else return -EINVAL; case IIOCNETGNM: /* Get list of phone-numbers of a network-interface */ if (arg) { - if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))) - return ret; - return isdn_net_getphones(&phone, (char *) arg); + if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) + return -EFAULT; + ret = down_interruptible(&dev->sem); + if( ret ) return ret; + ret = isdn_net_getphones(&phone, (char *) arg); + up(&dev->sem); + return ret; } else return -EINVAL; case IIOCNETDNM: /* Delete a phone-number of a network-interface */ if (arg) { - if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))) - return ret; - return isdn_net_delphone(&phone); + if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) + return -EFAULT; + ret = down_interruptible(&dev->sem); + if( ret ) return ret; + ret = isdn_net_delphone(&phone); + up(&dev->sem); + return ret; } else return -EINVAL; case IIOCNETDIL: /* Force dialing of a network-interface */ if (arg) { - if ((ret = copy_from_user(name, (char *) arg, sizeof(name)))) - return ret; + if (copy_from_user(name, (char *) arg, sizeof(name))) + return -EFAULT; return isdn_net_force_dial(name); } else return -EINVAL; @@ -1412,22 +1461,22 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) case IIOCNETALN: if (!arg) return -EINVAL; - if ((ret = copy_from_user(name, (char *) arg, sizeof(name)))) - return ret; + if (copy_from_user(name, (char *) arg, sizeof(name))) + return -EFAULT; return isdn_ppp_dial_slave(name); case IIOCNETDLN: if (!arg) return -EINVAL; - if ((ret = copy_from_user(name, (char *) arg, sizeof(name)))) - return ret; + if (copy_from_user(name, (char *) arg, sizeof(name))) + return -EFAULT; return isdn_ppp_hangup_slave(name); #endif case IIOCNETHUP: /* Force hangup of a network-interface */ if (!arg) return -EINVAL; - if ((ret = copy_from_user(name, (char *) arg, sizeof(name)))) - return ret; + if (copy_from_user(name, (char *) arg, sizeof(name))) + return -EFAULT; return isdn_net_force_hangup(name); break; #endif /* CONFIG_NETDEVICES */ @@ -1448,9 +1497,9 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) if (arg) { int i; char *p; - if ((ret = copy_from_user((char *) &iocts, (char *) arg, - sizeof(isdn_ioctl_struct)))) - return ret; + if (copy_from_user((char *) &iocts, (char *) arg, + sizeof(isdn_ioctl_struct))) + return -EFAULT; if (strlen(iocts.drvid)) { if ((p = strchr(iocts.drvid, ','))) *p = 0; @@ -1466,6 +1515,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) return -ENODEV; dev->drv[drvidx]->reject_bus = iocts.arg; return 0; +#if 0 case IIOCGETSET: /* Get complete setup (all network-interfaces and profile- settings of all tty-devices */ @@ -1482,6 +1532,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) else return -EINVAL; break; +#endif case IIOCSIGPRF: dev->profd = current; return 0; @@ -1522,12 +1573,12 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) return ret; for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if ((ret = copy_from_user(dev->mdm.info[i].emu.profile, p, - ISDN_MODEM_ANZREG))) - return ret; + if (copy_from_user(dev->mdm.info[i].emu.profile, p, + ISDN_MODEM_ANZREG)) + return -EFAULT; p += ISDN_MODEM_ANZREG; - if ((ret = copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))) - return ret; + if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN)) + return -EFAULT; p += ISDN_MSNLEN; } return 0; @@ -1539,10 +1590,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) /* Set/Get MSN->EAZ-Mapping for a driver */ if (arg) { - if ((ret = copy_from_user((char *) &iocts, + if (copy_from_user((char *) &iocts, (char *) arg, - sizeof(isdn_ioctl_struct)))) - return ret; + sizeof(isdn_ioctl_struct))) + return -EFAULT; if (strlen(iocts.drvid)) { drvidx = -1; for (i = 0; i < ISDN_MAX_DRIVERS; i++) @@ -1591,8 +1642,8 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) strlen(dev->drv[drvidx]->msn2eaz[i]) ? dev->drv[drvidx]->msn2eaz[i] : "-", (i < 9) ? "," : "\0"); - if ((ret = copy_to_user(p, bname, strlen(bname) + 1))) - return ret; + if (copy_to_user(p, bname, strlen(bname) + 1)) + return -EFAULT; p += strlen(bname); } } @@ -1601,8 +1652,8 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) return -EINVAL; case IIOCDBGVAR: if (arg) { - if ((ret = copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)))) - return ret; + if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong))) + return -EFAULT; return 0; } else return -EINVAL; @@ -1615,8 +1666,8 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) if (arg) { int i; char *p; - if ((ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)))) - return ret; + if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct))) + return -EFAULT; if (strlen(iocts.drvid)) { if ((p = strchr(iocts.drvid, ','))) *p = 0; @@ -1639,7 +1690,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong)); ret = isdn_command(&c); memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong)); - if ((copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)))) + if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct))) return -EFAULT; return ret; } else @@ -2164,6 +2215,7 @@ isdn_init(void) memset((char *) dev, 0, sizeof(isdn_dev)); init_timer(&dev->timer); dev->timer.function = isdn_timer_funct; + dev->sem = MUTEX; for (i = 0; i < ISDN_MAX_CHANNELS; i++) { dev->drvmap[i] = -1; dev->chanmap[i] = -1; diff --git a/drivers/isdn/isdn_common.h b/drivers/isdn/isdn_common.h index b9d5df715..6cb503b9f 100644 --- a/drivers/isdn/isdn_common.h +++ b/drivers/isdn/isdn_common.h @@ -20,6 +20,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * Note: This file differs from the corresponding revision as present in the + * isdn4linux CVS repository because some later bug fixes have been extracted + * from the repository and merged into this file. -- Henner Eisen + * * $Log: isdn_common.h,v $ * Revision 1.9 1998/02/20 17:19:01 fritz * Added common stub for sending commands to lowlevel. @@ -86,7 +90,7 @@ extern char *isdn_map_eaz2msn(char *msn, int di); 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, struct wait_queue**); extern int isdn_get_free_channel(int, int, int, int, int); extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *); extern int register_isdn(isdn_if * i); diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c index 33b122c96..daafceb1a 100644 --- a/drivers/isdn/isdn_net.c +++ b/drivers/isdn/isdn_net.c @@ -20,6 +20,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * Note: This file differs from the corresponding revision as present in the + * isdn4linux CVS repository because some later bug fixes have been extracted + * from the repository and merged into this file. -- Henner Eisen + * * $Log: isdn_net.c,v $ * Revision 1.55 1998/02/23 19:38:22 fritz * Corrected check for modified feature-flags. @@ -243,7 +247,7 @@ #include <linux/module.h> #include <linux/isdn.h> #include <net/arp.h> -#include <net/icmp.h> +#include <net/dst.h> #ifndef DEV_NUMBUFFS #include <net/pkt_sched.h> #endif @@ -277,9 +281,18 @@ char *isdn_net_revision = "$Revision: 1.55 $"; static void isdn_net_unreachable(struct device *dev, struct sk_buff *skb, char *reason) { - printk(KERN_DEBUG "isdn_net: %s: %s, send ICMP\n", - dev->name, reason); - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); + + if(skb) { + + u_short proto = ntohs(skb->protocol); + + printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n", + dev->name, + (reason != NULL) ? reason : "unknown", + (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : ""); + + dst_link_failure(skb); + } } static void @@ -610,6 +623,13 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb))) lp->first_skb = NULL; + } else { + /* + * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb). + * With an empty lp->first_skb, we need to do this ourselves + */ + lp->netdev->dev.tbusy = 0; + mark_bh(NET_BH); } return 1; } @@ -2696,7 +2716,8 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone) } /* - * Return a string of all phone-numbers of an interface. + * Copy a string of all phone-numbers of an interface to user space. + * This might sleep and must be called with the isdn semaphore down. */ int isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones) @@ -2706,22 +2727,17 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones) int more = 0; int count = 0; isdn_net_phone *n; - int flags; - int ret; if (!p) return -ENODEV; - save_flags(flags); - cli(); inout &= 1; 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; + if (copy_to_user(phones, n->num, strlen(n->num) + 1)) { + return -EFAULT; } phones += strlen(n->num); count += strlen(n->num); @@ -2729,7 +2745,6 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones) } put_user(0, phones); count++; - restore_flags(flags); return count; } @@ -2760,6 +2775,7 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone) else p->local->phone[inout] = n->next; kfree(n); + restore_flags(flags); return 0; } m = n; diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c index a4a45d9ea..5da3a49f0 100644 --- a/drivers/isdn/isdn_ppp.c +++ b/drivers/isdn/isdn_ppp.c @@ -18,6 +18,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * Note: This file differs from the corresponding revision as present in the + * isdn4linux CVS repository because some later bug fixes have been extracted + * from the repository and merged into this file. -- Henner Eisen + * * $Log: isdn_ppp.c,v $ * Revision 1.33 1998/02/20 17:11:54 fritz * Changes for recent kernels. @@ -500,11 +504,10 @@ isdn_ppp_release(int min, struct file *file) static int get_arg(void *b, void *val, int len) { - int r; if (len <= 0) len = sizeof(unsigned long); - if ((r = copy_from_user((void *) val, b, len))) - return r; + if (copy_from_user((void *) val, b, len)) + return -EFAULT; return 0; } @@ -514,13 +517,12 @@ get_arg(void *b, void *val, int len) static int set_arg(void *b, unsigned long val, void *str) { - int r; if (!str) { - if ((r = copy_to_user(b, (void *) &val, 4))) - return r; + if (copy_to_user(b, (void *) &val, 4)) + return -EFAULT; } else { - if ((r = copy_to_user(b, str, val))) - return r; + if (copy_to_user(b, str, val)) + return -EFAULT; } return 0; } @@ -1851,13 +1853,14 @@ isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct device *dev) } #endif } - return copy_to_user(res, &t, sizeof(struct ppp_stats)); + if( copy_to_user(res, &t, sizeof(struct ppp_stats))) return -EFAULT; + return 0; } int isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd) { - int error; + int error=0; char *r; int len; isdn_net_local *lp = (isdn_net_local *) dev->priv; @@ -1873,7 +1876,7 @@ isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd) case SIOCGPPPVER: r = (char *) ifr->ifr_ifru.ifru_data; len = strlen(PPP_VERSION) + 1; - error = copy_to_user(r, PPP_VERSION, len); + if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT; break; case SIOCGPPPSTATS: error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev); diff --git a/drivers/isdn/isdn_x25iface.c b/drivers/isdn/isdn_x25iface.c index c7471d361..2ae21fcf3 100644 --- a/drivers/isdn/isdn_x25iface.c +++ b/drivers/isdn/isdn_x25iface.c @@ -65,7 +65,7 @@ static struct concap_proto_ops ix25_pops = { &isdn_x25iface_disconn_ind }; -/* error message helper fuction */ +/* error message helper function */ static void illegal_state_warn( unsigned state, unsigned char firstbyte) { printk( KERN_WARNING "isdn_x25iface: firstbyte %x illegal in" |