X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=linux%2Fppp.c;h=aa7af25d8d6187a67e1abfa8bc4732076f8c09a2;hb=463cf57abda4845c8fbc01fd7c804aed1f30e758;hp=06f39c642149f5411883685c92fb0bdb5f4d0178;hpb=6df1318f7c7c2afa76293e90671aac884488a19d;p=ppp.git diff --git a/linux/ppp.c b/linux/ppp.c index 06f39c6..aa7af25 100644 --- a/linux/ppp.c +++ b/linux/ppp.c @@ -7,7 +7,7 @@ * Dynamic PPP devices by Jim Freeman . * ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid * - * ==FILEVERSION 971016== + * ==FILEVERSION 980319== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the number above to the @@ -48,9 +48,10 @@ #define CHECK_CHARACTERS 1 #define PPP_COMPRESS 1 -/* $Id: ppp.c,v 1.14 1997/11/27 06:04:45 paulus Exp $ */ +/* $Id: ppp.c,v 1.17 1998/03/24 23:54:59 paulus Exp $ */ #include +#include /* for CONFIG_KERNELD */ #include #include #include @@ -84,6 +85,11 @@ #include #include #include + +#if LINUX_VERSION_CODE >= VERSION(2,1,68) +#include +#endif + #include #include @@ -103,6 +109,10 @@ typedef struct sk_buff sk_buff; #include #include +#ifdef CONFIG_KERNELD +#include +#endif + #ifndef PPP_IPX #define PPP_IPX 0x2b /* IPX protocol over PPP */ #endif @@ -158,6 +168,22 @@ do { \ #define test_and_set_bit(nr, addr) set_bit(nr, addr) #endif +#if LINUX_VERSION_CODE < VERSION(2,1,57) +#define signal_pending(p) ((p)->signal & ~(p)->blocked) +#endif + +#if LINUX_VERSION_CODE < VERSION(2,1,25) +#define net_device_stats enet_statistics +#endif + +#if LINUX_VERSION_CODE < VERSION(2,1,60) +typedef int rw_ret_t; +typedef unsigned int rw_count_t; +#else +typedef ssize_t rw_ret_t; +typedef size_t rw_count_t; +#endif + static int ppp_register_compressor (struct compressor *cp); static void ppp_unregister_compressor (struct compressor *cp); @@ -220,7 +246,7 @@ static int ppp_dev_open (struct device *); static int ppp_dev_ioctl (struct device *dev, struct ifreq *ifr, int cmd); static int ppp_dev_close (struct device *); static int ppp_dev_xmit (sk_buff *, struct device *); -static struct enet_statistics *ppp_dev_stats (struct device *); +static struct net_device_stats *ppp_dev_stats (struct device *); #if LINUX_VERSION_CODE < VERSION(2,1,15) static int ppp_dev_header (sk_buff *, struct device *, __u16, @@ -233,17 +259,18 @@ static int ppp_dev_rebuild (void *eth, struct device *dev, * TTY callbacks */ -static int ppp_tty_read (struct tty_struct *, struct file *, __u8 *, - unsigned int); -static int ppp_tty_write (struct tty_struct *, struct file *, const __u8 *, - unsigned int); +static rw_ret_t ppp_tty_read(struct tty_struct *, struct file *, __u8 *, + rw_count_t); +static rw_ret_t ppp_tty_write(struct tty_struct *, struct file *, const __u8 *, + rw_count_t); static int ppp_tty_ioctl (struct tty_struct *, struct file *, unsigned int, unsigned long); #if LINUX_VERSION_CODE < VERSION(2,1,23) static int ppp_tty_select (struct tty_struct *tty, struct inode *inode, struct file *filp, int sel_type, select_table * wait); #else -static unsigned int ppp_tty_poll (struct tty_struct *tty, struct file *filp, poll_table * wait); +static unsigned int ppp_tty_poll (struct tty_struct *tty, struct file *filp, + poll_table * wait); #endif static int ppp_tty_open (struct tty_struct *); static void ppp_tty_close (struct tty_struct *); @@ -403,6 +430,9 @@ ppp_first_time (void) */ (void) memset (&ppp_ldisc, 0, sizeof (ppp_ldisc)); ppp_ldisc.magic = TTY_LDISC_MAGIC; +#if LINUX_VERSION_CODE >= VERSION(2,1,28) + ppp_ldisc.name = "ppp"; +#endif ppp_ldisc.open = ppp_tty_open; ppp_ldisc.close = ppp_tty_close; ppp_ldisc.read = ppp_tty_read; @@ -466,11 +496,13 @@ ppp_init_dev (struct device *dev) /* New-style flags */ dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; +#if LINUX_VERSION_CODE < VERSION(2,1,67) dev->family = AF_INET; dev->pa_addr = 0; dev->pa_brdaddr = 0; dev->pa_mask = 0; dev->pa_alen = 4; /* sizeof (__u32) */ +#endif return 0; } @@ -671,9 +703,7 @@ ppp_changedmtu (struct ppp *ppp, int new_mtu, int new_mru) */ if (new_wbuf == NULL || new_tbuf == NULL || new_rbuf == NULL || new_cbuf == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR - "ppp: failed to allocate new buffers\n"); + printk (KERN_ERR "ppp: failed to allocate new buffers\n"); ppp_free_buf (new_wbuf); ppp_free_buf (new_tbuf); @@ -788,11 +818,6 @@ ppp_release (struct ppp *ppp) if (tty != NULL && tty->disc_data == ppp) tty->disc_data = NULL; /* Break the tty->ppp link */ - if (dev && dev->flags & IFF_UP) { - dev->flags &= ~IFF_UP; /* prevent recursion */ - dev_close (dev); /* close the device properly */ - } - ppp_free_buf (ppp->rbuf); ppp_free_buf (ppp->wbuf); ppp_free_buf (ppp->cbuf); @@ -871,8 +896,7 @@ ppp_tty_open (struct tty_struct *tty) * There should not be an existing table for this slot. */ if (ppp) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR + printk (KERN_ERR "ppp_tty_open: gack! tty already associated to %s!\n", ppp->magic == PPP_MAGIC ? ppp2dev(ppp)->name : "unknown"); @@ -894,8 +918,7 @@ ppp_tty_open (struct tty_struct *tty) } else { ppp = ppp_alloc(); if (ppp == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR "ppp_alloc failed\n"); + printk (KERN_ERR "ppp_alloc failed\n"); return -ENFILE; } /* @@ -909,9 +932,8 @@ ppp_tty_open (struct tty_struct *tty) */ ppp->slcomp = slhc_init (16, 16); if (ppp->slcomp == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR "ppp_tty_open: " - "no space for compression buffers!\n"); + printk (KERN_ERR "ppp_tty_open: " + "no space for compression buffers!\n"); ppp_release (ppp); return -ENOMEM; } @@ -927,9 +949,8 @@ ppp_tty_open (struct tty_struct *tty) */ ppp->ubuf = ppp_alloc_buf (RBUFSIZE, BUFFER_TYPE_TTY_RD); if (ppp->ubuf == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR "ppp_tty_open: " - "no space for user receive buffer\n"); + printk (KERN_ERR "ppp_tty_open: " + "no space for user receive buffer\n"); ppp_release (ppp); return -ENOMEM; } @@ -1401,9 +1422,7 @@ ppp_doframe (struct ppp *ppp) */ new_data = kmalloc (ppp->mru + PPP_HDRLEN, GFP_ATOMIC); if (new_data == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR - "ppp_doframe: no memory\n"); + printk (KERN_ERR "ppp_doframe: no memory\n"); new_count = DECOMP_ERROR; } else { new_count = (*ppp->sc_rcomp->decompress) @@ -1422,8 +1441,7 @@ ppp_doframe (struct ppp *ppp) case DECOMP_FATALERROR: ppp->flags |= SC_DC_FERROR; - if (ppp->flags & SC_DEBUG) - printk(KERN_ERR "ppp: fatal decomp error\n"); + printk(KERN_ERR "ppp: fatal decomp error\n"); break; } /* @@ -1441,6 +1459,10 @@ ppp_doframe (struct ppp *ppp) (*ppp->sc_rcomp->incomp) (ppp->sc_rc_state, data, count); } + } else if (proto == PPP_COMP && (ppp->flags & SC_DEBUG)) { + printk(KERN_DEBUG "ppp: frame not decompressed: " + "flags=%x, count=%d, sc_rc_state=%p\n", + ppp->flags, count, ppp->sc_rc_state); } /* * Process the uncompressed frame. @@ -1778,6 +1800,9 @@ static void ppp_proto_ccp (struct ppp *ppp, __u8 *dp, int len, int rcvd) } break; } + if (ppp->flags & SC_DEBUG) + printk(KERN_DEBUG "ppp_proto_ccp: %s code %d, flags=%x\n", + (rcvd? "rcvd": "sent"), CCP_CODE(dp), ppp->flags); restore_flags(flags); } @@ -1811,14 +1836,14 @@ rcv_proto_lqr (struct ppp *ppp, __u16 proto, __u8 * data, int len) waiting if necessary */ -static int +static rw_ret_t ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, - unsigned int nr) + rw_count_t nr) { struct ppp *ppp = tty2ppp (tty); __u8 c; - int len, ret; int error; + rw_ret_t len, ret; #define GETC(c) \ { \ @@ -1864,7 +1889,7 @@ ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, current->state = TASK_INTERRUPTIBLE; schedule (); - if (current->signal & ~current->blocked) + if (signal_pending(current)) return -EINTR; continue; } @@ -1897,7 +1922,7 @@ ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, "ppp_tty_read: sleeping(read_wait)\n"); #endif interruptible_sleep_on (&ppp->read_wait); - if (current->signal & ~current->blocked) + if (signal_pending(current)) return -EINTR; } @@ -1910,8 +1935,8 @@ ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, if (ppp->flags & SC_DEBUG) printk (KERN_DEBUG - "ppp: read of %u bytes too small for %d " - "frame\n", nr, len + 2); + "ppp: read of %lu bytes too small for %ld " + "frame\n", (unsigned long) nr, (long) len + 2); ppp->stats.ppp_ierrors++; error = -EOVERFLOW; goto out; @@ -1943,10 +1968,6 @@ ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, } clear_bit (0, &ppp->ubuf->locked); -#if 0 - if (ppp->flags & SC_DEBUG) - printk (KERN_DEBUG "ppp_tty_read: passing %d bytes up\n", ret); -#endif return ret; out: @@ -2101,16 +2122,15 @@ ppp_dev_xmit_frame (struct ppp *ppp, struct ppp_buffer *buf, (control == PPP_UI) && (proto != PPP_LCP) && (proto != PPP_CCP)) { - new_data = kmalloc (ppp->mtu, GFP_ATOMIC); + new_data = kmalloc (ppp->mtu + PPP_HDRLEN, GFP_ATOMIC); if (new_data == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR - "ppp_dev_xmit_frame: no memory\n"); + printk (KERN_ERR "ppp_dev_xmit_frame: no memory\n"); return 1; } new_count = (*ppp->sc_xcomp->compress) - (ppp->sc_xc_state, data, new_data, count, ppp->mtu); + (ppp->sc_xc_state, data, new_data, count, + ppp->mtu + PPP_HDRLEN); if (new_count > 0 && (ppp->flags & SC_CCP_UP)) { ppp_dev_xmit_lower (ppp, buf, new_data, new_count, 0); @@ -2172,13 +2192,14 @@ send_revise_frame (register struct ppp *ppp, __u8 *data, int len) * we have to put the FCS field on ourselves */ -static int +static rw_ret_t ppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data, - unsigned int count) + rw_count_t count) { struct ppp *ppp = tty2ppp (tty); __u8 *new_data; int error; + struct wait_queue wait = {current, NULL}; /* * Verify the pointers. @@ -2197,7 +2218,7 @@ ppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data, if (ppp->flags & SC_DEBUG) printk (KERN_WARNING "ppp_tty_write: truncating user packet " - "from %u to mtu %d\n", count, + "from %lu to mtu %d\n", (unsigned long) count, PPP_MTU + PPP_HDRLEN); count = PPP_MTU + PPP_HDRLEN; } @@ -2206,43 +2227,48 @@ ppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data, */ new_data = kmalloc (count, GFP_KERNEL); if (new_data == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR - "ppp_tty_write: no memory\n"); + printk (KERN_ERR "ppp_tty_write: no memory\n"); return 0; } /* * Retrieve the user's buffer */ COPY_FROM_USER (error, new_data, data, count); - if (error) { - kfree (new_data); - return error; - } + if (error) + goto out_free; /* - * lock this PPP unit so we will be the only writer; - * sleep if necessary + * Lock this PPP unit so we will be the only writer, + * sleeping if necessary. + * + * Note that we add our task to the wait queue before + * attempting to lock, as the lock flag may be cleared + * from an interrupt. */ - while (lock_buffer (ppp->tbuf) != 0) { + add_wait_queue(&ppp->write_wait, &wait); + while (1) { + error = 0; current->timeout = 0; -#if 0 - if (ppp->flags & SC_DEBUG) - printk (KERN_DEBUG "ppp_tty_write: sleeping\n"); -#endif - interruptible_sleep_on (&ppp->write_wait); + current->state = TASK_INTERRUPTIBLE; + if (lock_buffer(ppp->tbuf) == 0) + break; + schedule(); + error = -EIO; ppp = tty2ppp (tty); - if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse - || tty != ppp->tty) { - kfree (new_data); - return 0; - } - - if (current->signal & ~current->blocked) { - kfree (new_data); - return -EINTR; + if (!ppp || ppp->magic != PPP_MAGIC || + !ppp->inuse || tty != ppp->tty) { + printk("ppp_tty_write: %p invalid after wait!\n", ppp); + break; } + error = -EINTR; + if (signal_pending(current)) + break; } + current->state = TASK_RUNNING; + remove_wait_queue(&ppp->write_wait, &wait); + if (error) + goto out_free; + /* * Change the LQR frame */ @@ -2262,34 +2288,31 @@ ppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data, } else { ppp_dev_xmit_frame (ppp, ppp->tbuf, new_data, count); } + error = count; +out_free: kfree (new_data); - return (int) count; + return error; } /* - * Process the BSD compression IOCTL event for the tty device. + * Process the set-compression ioctl. */ static int ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp) { struct compressor *cp; - struct ppp_option_data data; - int error; - int nb; + int error, nb; + unsigned long flags; __u8 *ptr; __u8 ccp_option[CCP_MAX_OPTION_LENGTH]; - unsigned long flags; + struct ppp_option_data data; /* * Fetch the compression parameters */ - COPY_FROM_USER (error, - &data, - odp, - sizeof (data)); - + COPY_FROM_USER (error, &data, odp, sizeof (data)); if (error != 0) return error; @@ -2298,11 +2321,7 @@ ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp) if ((__u32) nb >= (__u32)CCP_MAX_OPTION_LENGTH) nb = CCP_MAX_OPTION_LENGTH; - COPY_FROM_USER (error, - ccp_option, - ptr, - nb); - + COPY_FROM_USER (error, ccp_option, ptr, nb); if (error != 0) return error; @@ -2311,52 +2330,58 @@ ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp) save_flags(flags); cli(); - ppp->flags &= ~(SC_COMP_RUN | SC_DECOMP_RUN); + ppp->flags &= ~(data.transmit? SC_COMP_RUN: SC_DECOMP_RUN); restore_flags(flags); cp = find_compressor (ccp_option[0]); - if (cp != (struct compressor *) 0) { - /* - * Found a handler for the protocol - try to allocate - * a compressor or decompressor. - */ - error = 0; - if (data.transmit) { - if (ppp->sc_xc_state != NULL) - (*ppp->sc_xcomp->comp_free)(ppp->sc_xc_state); +#ifdef CONFIG_KERNELD + if (cp == NULL) { + char modname[32]; + sprintf(modname, "ppp-compress-%d", ccp_option[0]); + request_module(modname); + cp = find_compressor(ccp_option[0]); + } +#endif /* CONFIG_KERNELD */ - ppp->sc_xcomp = cp; - ppp->sc_xc_state = cp->comp_alloc(ccp_option, nb); + if (cp == NULL) + goto out_no_comp; + /* + * Found a handler for the protocol - try to allocate + * a compressor or decompressor. + */ + error = 0; + if (data.transmit) { + if (ppp->sc_xc_state != NULL) + (*ppp->sc_xcomp->comp_free)(ppp->sc_xc_state); + ppp->sc_xc_state = NULL; - if (ppp->sc_xc_state == NULL) { - if (ppp->flags & SC_DEBUG) - printk(KERN_DEBUG "%s: comp_alloc failed\n", - ppp->name); - error = -ENOBUFS; - } else { - if (ppp->flags & SC_DEBUG) - printk(KERN_DEBUG "%s: comp_alloc -> %p\n", - ppp->name, ppp->sc_xc_state); - } - } else { - if (ppp->sc_rc_state != NULL) - (*ppp->sc_rcomp->decomp_free)(ppp->sc_rc_state); - ppp->sc_rcomp = cp; - ppp->sc_rc_state = cp->decomp_alloc(ccp_option, nb); - if (ppp->sc_rc_state == NULL) { - if (ppp->flags & SC_DEBUG) - printk(KERN_DEBUG "%s: decomp_alloc failed\n", - ppp->name); - error = -ENOBUFS; - } else { - if (ppp->flags & SC_DEBUG) - printk(KERN_DEBUG "%s: decomp_alloc -> %p\n", - ppp->name, ppp->sc_rc_state); - } - } - return (error); + ppp->sc_xcomp = cp; + ppp->sc_xc_state = cp->comp_alloc(ccp_option, nb); + if (ppp->sc_xc_state == NULL) { + printk(KERN_WARNING "%s: comp_alloc failed\n", + ppp->name); + error = -ENOBUFS; + } else if (ppp->flags & SC_DEBUG) + printk(KERN_DEBUG "%s: comp_alloc -> %p\n", + ppp->name, ppp->sc_xc_state); + } else { + if (ppp->sc_rc_state != NULL) + (*ppp->sc_rcomp->decomp_free)(ppp->sc_rc_state); + ppp->sc_rc_state = NULL; + + ppp->sc_rcomp = cp; + ppp->sc_rc_state = cp->decomp_alloc(ccp_option, nb); + if (ppp->sc_rc_state == NULL) { + printk(KERN_WARNING "%s: decomp_alloc failed\n", + ppp->name); + error = -ENOBUFS; + } else if (ppp->flags & SC_DEBUG) + printk(KERN_DEBUG "%s: decomp_alloc -> %p\n", + ppp->name, ppp->sc_rc_state); } + return error; +out_no_comp: if (ppp->flags & SC_DEBUG) printk(KERN_DEBUG "%s: no compressor for [%x %x %x], %x\n", ppp->name, ccp_option[0], ccp_option[1], @@ -2373,8 +2398,9 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, unsigned int param2, unsigned long param3) { struct ppp *ppp = tty2ppp (tty); - register int temp_i = 0; + register int temp_i = 0, oldflags; int error = 0; + unsigned long flags; /* * Verify the status of the PPP device. */ @@ -2424,16 +2450,18 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, if (error != 0) break; temp_i &= SC_MASK; - temp_i |= (ppp->flags & ~SC_MASK); - if ((ppp->flags & SC_CCP_OPEN) && - (temp_i & SC_CCP_OPEN) == 0) - ppp_ccp_closed (ppp); + if ((ppp->flags & SC_CCP_OPEN) && (temp_i & SC_CCP_OPEN) == 0) + ppp_ccp_closed(ppp); - if ((ppp->flags | temp_i) & SC_DEBUG) + save_flags(flags); + cli(); + oldflags = ppp->flags; + ppp->flags = temp_i |= (ppp->flags & ~SC_MASK); + restore_flags(flags); + if ((oldflags | temp_i) & SC_DEBUG) printk (KERN_INFO "ppp_tty_ioctl: set flags to %x\n", temp_i); - ppp->flags = temp_i; break; /* * Set the compression mode @@ -2518,9 +2546,7 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, /* change absolute times to relative times. */ cur_ddinfo.xmit_idle = (jiffies - ppp->last_xmit) / HZ; cur_ddinfo.recv_idle = (jiffies - ppp->last_recv) / HZ; - COPY_TO_USER (error, - (void *) param3, - &cur_ddinfo, + COPY_TO_USER (error, (void *) param3, &cur_ddinfo, sizeof (cur_ddinfo)); } break; @@ -2528,9 +2554,7 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, * Retrieve the extended async map */ case PPPIOCGXASYNCMAP: - COPY_TO_USER (error, - (void *) param3, - ppp->xmit_async_map, + COPY_TO_USER (error, (void *) param3, ppp->xmit_async_map, sizeof (ppp->xmit_async_map)); break; /* @@ -2540,13 +2564,11 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, { __u32 temp_tbl[8]; - COPY_FROM_USER (error, - temp_tbl, - (void *) param3, + COPY_FROM_USER (error, temp_tbl, (void *) param3, sizeof (temp_tbl)); - if (error != 0) break; + temp_tbl[1] = 0x00000000; temp_tbl[2] &= ~0x40000000; temp_tbl[3] |= 0x60000000; @@ -2576,16 +2598,15 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, temp_i = (temp_i & 255) + 1; if (ppp->flags & SC_DEBUG) printk (KERN_INFO - "ppp_tty_ioctl: set maxcid to %d\n", - temp_i); + "ppp_tty_ioctl: set maxcid to %d\n", temp_i); if (ppp->slcomp != NULL) slhc_free (ppp->slcomp); - ppp->slcomp = slhc_init (16, temp_i); + ppp->slcomp = NULL; + ppp->slcomp = slhc_init (16, temp_i); if (ppp->slcomp == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR - "ppp: no space for compression buffers!\n"); + printk (KERN_ERR "ppp_tty_ioctl: " + "no space for compression buffers!\n"); ppp_release (ppp); error = -ENOMEM; } @@ -2601,9 +2622,7 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, { struct npioctl npi; - COPY_FROM_USER (error, - &npi, - (void *) param3, + COPY_FROM_USER (error, &npi, (void *) param3, sizeof (npi)); if (error != 0) break; @@ -2615,7 +2634,8 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, default: if (ppp->flags & SC_DEBUG) printk(KERN_DEBUG "pppioc[gs]npmode: " - "invalid proto %d\n", npi.protocol); + "invalid protocol %d\n", + npi.protocol); error = -EINVAL; } @@ -2625,9 +2645,7 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, if (param2 == PPPIOCGNPMODE) { npi.mode = ppp->sc_npmode[npi.protocol]; - COPY_TO_USER (error, - (void *) param3, - &npi, + COPY_TO_USER (error, (void *) param3, &npi, sizeof (npi)); break; } @@ -2661,11 +2679,8 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, */ default: if (ppp->flags & SC_DEBUG) - printk (KERN_ERR - "ppp_tty_ioctl: invalid ioctl: %x, addr %lx\n", - param2, - param3); - + printk (KERN_WARNING "ppp_tty_ioctl: " + "invalid ioctl=%x, addr=%lx\n", param2, param3); error = -ENOIOCTLCMD; break; } @@ -2748,8 +2763,13 @@ ppp_tty_poll (struct tty_struct *tty, struct file *filp, poll_table * wait) if (ppp && ppp->magic == PPP_MAGIC && tty == ppp->tty) { CHECK_PPP (0); +#if LINUX_VERSION_CODE < VERSION(2,1,89) poll_wait(&ppp->read_wait, wait); poll_wait(&ppp->write_wait, wait); +#else + poll_wait(filp, &ppp->read_wait, wait); + poll_wait(filp, &ppp->write_wait, wait); +#endif /* Must lock the user buffer area while checking. */ CHECK_BUF_MAGIC(ppp->ubuf); @@ -2787,14 +2807,8 @@ ppp_dev_open (struct device *dev) { struct ppp *ppp = dev2ppp (dev); -#if 0 - /* reset POINTOPOINT every time, since dev_close zaps it! */ - dev->flags |= IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; -#endif - if (ppp2tty (ppp) == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR + printk (KERN_ERR "ppp: %s not connected to a TTY! can't go open!\n", dev->name); return -ENXIO; @@ -2846,10 +2860,7 @@ ppp_dev_ioctl_version (struct ppp *ppp, struct ifreq *ifr) /* * Move the version data */ - COPY_TO_USER (error, - result, - szVersion, - len); + COPY_TO_USER (error, result, szVersion, len); return error; } @@ -2885,10 +2896,7 @@ ppp_dev_ioctl_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev) result = (struct ppp_stats *) ifr->ifr_ifru.ifru_data; - COPY_TO_USER (error, - result, - &temp, - sizeof (temp)); + COPY_TO_USER (error, result, &temp, sizeof (temp)); return error; } @@ -2920,10 +2928,7 @@ ppp_dev_ioctl_comp_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev */ result = (struct ppp_comp_stats *) ifr->ifr_ifru.ifru_data; - COPY_TO_USER (error, - result, - &temp, - sizeof (temp)); + COPY_TO_USER (error, result, &temp, sizeof (temp)); return error; } @@ -3071,6 +3076,11 @@ ppp_dev_xmit_other (struct device *dev, struct ppp *ppp, /* * Send a frame to the remote. */ +#if LINUX_VERSION_CODE < VERSION(2,1,86) +#define FREE_SKB(skb) dev_kfree_skb(skb) +#else +#define FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE) +#endif static int ppp_dev_xmit (sk_buff *skb, struct device *dev) @@ -3091,7 +3101,7 @@ ppp_dev_xmit (sk_buff *skb, struct device *dev) * Avoid timing problem should tty hangup while data is queued to be sent */ if (!ppp->inuse) { - dev_kfree_skb (skb, FREE_WRITE); + FREE_SKB (skb); return 0; } /* @@ -3102,7 +3112,7 @@ ppp_dev_xmit (sk_buff *skb, struct device *dev) printk (KERN_ERR "ppp_dev_xmit: %s not connected to a TTY!\n", dev->name); - dev_kfree_skb (skb, FREE_WRITE); + FREE_SKB (skb); return 0; } /* @@ -3115,7 +3125,7 @@ ppp_dev_xmit (sk_buff *skb, struct device *dev) if (ppp->flags & SC_DEBUG) printk (KERN_CRIT "ppp_dev_xmit: %s Null skb data\n", dev->name); - dev_kfree_skb (skb, FREE_WRITE); + FREE_SKB (skb); return 0; } /* @@ -3156,7 +3166,7 @@ ppp_dev_xmit (sk_buff *skb, struct device *dev) break; default: /* All others have no support at this time. */ - dev_kfree_skb (skb, FREE_WRITE); + FREE_SKB (skb); return 0; } /* @@ -3164,12 +3174,12 @@ ppp_dev_xmit (sk_buff *skb, struct device *dev) */ if (answer == 0) { /* packet queued OK */ - dev_kfree_skb (skb, FREE_WRITE); + FREE_SKB (skb); } else { ppp->wbuf->locked = 0; if (answer < 0) { /* packet should be dropped */ - dev_kfree_skb (skb, FREE_WRITE); + FREE_SKB (skb); answer = 0; } else { /* packet should be queued for later */ @@ -3183,7 +3193,7 @@ ppp_dev_xmit (sk_buff *skb, struct device *dev) * Generate the statistic information for the /proc/net/dev listing. */ -static struct enet_statistics * +static struct net_device_stats * ppp_dev_stats (struct device *dev) { struct ppp *ppp = dev2ppp (dev); @@ -3237,6 +3247,29 @@ ppp_find (int pid_value) return ppp; } +/* Collect hung up channels */ + +static void ppp_sync(void) +{ + struct device *dev; + struct ppp *ppp; + +#if LINUX_VERSION_CODE >= VERSION(2,1,68) + rtnl_lock(); +#endif + for (ppp = ppp_list; ppp != 0; ppp = ppp->next) { + if (!ppp->inuse) { + dev = ppp2dev(ppp); + if (dev->flags & IFF_UP) + dev_close(dev); + } + } +#if LINUX_VERSION_CODE >= VERSION(2,1,68) + rtnl_unlock(); +#endif +} + + /* allocate or create a PPP channel */ static struct ppp * ppp_alloc (void) @@ -3246,11 +3279,24 @@ ppp_alloc (void) struct device *dev; struct ppp *ppp; + ppp_sync(); + /* try to find an free device */ if_num = 0; for (ppp = ppp_list; ppp != 0; ppp = ppp->next) { - if (!test_and_set_bit(0, &ppp->inuse)) + if (!test_and_set_bit(0, &ppp->inuse)) { + + /* Reregister device */ + + dev = ppp2dev(ppp); + unregister_netdev (dev); + + if (register_netdev (dev)) { + printk(KERN_DEBUG "cannot reregister ppp device\n"); + return NULL; + } return ppp; + } ++if_num; } /*