X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=linux%2Fppp.c;h=69e5a62a34a188f366bd9219bf48382576402d48;hp=b5681b053a89c801929ed43f3a7237bd62e51faf;hb=969dcc382a4d687d4aa36986cb2d1f13a1260ff9;hpb=9966eb6276e5bf255944a163aabb7e7633b47f34 diff --git a/linux/ppp.c b/linux/ppp.c index b5681b0..69e5a62 100644 --- a/linux/ppp.c +++ b/linux/ppp.c @@ -6,7 +6,7 @@ * Dynamic PPP devices by Jim Freeman . * ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid * - * ==FILEVERSION 960528== + * ==FILEVERSION 970227== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the number above to the @@ -51,7 +51,7 @@ #define PPP_MAX_DEV 256 #endif -/* $Id: ppp.c,v 1.8 1996/09/14 05:37:07 paulus Exp $ +/* $Id: ppp.c,v 1.11 1997/04/30 05:42:36 paulus Exp $ * Added dynamic allocation of channels to eliminate * compiled-in limits on the number of channels. * @@ -59,15 +59,23 @@ * released under the GNU General Public License Version 2. */ +#include #include -#include #include #include #include #include #include #include + +#undef VERSION +/* a nice define to generate linux version numbers */ +#define VERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch)) + +#if LINUX_VERSION_CODE < VERSION(2,1,14) #include +#endif + #include #include #include @@ -77,7 +85,6 @@ #include /* used in new tty drivers */ #include #include -#include #include #include #include @@ -99,14 +106,7 @@ typedef struct sk_buff sk_buff; #include #include #include - -#undef PACKETPTR -#define PACKETPTR 1 #include -#undef PACKETPTR - -#define bsd_decompress (*ppp->sc_rcomp->decompress) -#define bsd_compress (*ppp->sc_xcomp->compress) #ifndef PPP_IPX #define PPP_IPX 0x2b /* IPX protocol over PPP */ @@ -116,6 +116,49 @@ typedef struct sk_buff sk_buff; #define PPP_LQR 0xc025 /* Link Quality Reporting Protocol */ #endif +#if LINUX_VERSION_CODE >= VERSION(2,1,4) +#include +#define GET_USER(error,value,addr) error = get_user(value,addr) +#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 +#define PUT_USER(error,value,addr) error = put_user(value,addr) +#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 + +#if LINUX_VERSION_CODE >= VERSION(2,1,5) +#include +#endif + +#else /* 2.0.x and 2.1.x before 2.1.4 */ + +#define GET_USER(error,value,addr) \ +do { \ + error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \ + if (error == 0) \ + value = get_user(addr); \ +} while (0) + +#define COPY_FROM_USER(error,dest,src,size) \ +do { \ + error = verify_area (VERIFY_READ, (void *) src, size); \ + if (error == 0) \ + memcpy_fromfs (dest, src, size); \ +} while (0) + +#define PUT_USER(error,value,addr) \ +do { \ + error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \ + if (error == 0) \ + put_user (value, addr); \ +} while (0) + +#define COPY_TO_USER(error,dest,src,size) \ +do { \ + error = verify_area (VERIFY_WRITE, (void *) dest, size); \ + if (error == 0) \ + memcpy_tofs (dest, src, size); \ +} while (0) + +#endif + static int ppp_register_compressor (struct compressor *cp); static void ppp_unregister_compressor (struct compressor *cp); @@ -144,7 +187,6 @@ static int rcv_proto_lqr (struct ppp *, __u16, __u8 *, int); static void ppp_doframe_lower (struct ppp *, __u8 *, int); static int ppp_doframe (struct ppp *); -extern int ppp_bsd_compressor_init(void); static void ppp_proto_ccp (struct ppp *ppp, __u8 *dp, int len, int rcvd); static int rcv_proto_ccp (struct ppp *, __u16, __u8 *, int); @@ -180,10 +222,14 @@ 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 *); + +#if LINUX_VERSION_CODE < VERSION(2,1,15) static int ppp_dev_header (sk_buff *, struct device *, __u16, void *, void *, unsigned int); static int ppp_dev_rebuild (void *eth, struct device *dev, - unsigned long raddr, struct sk_buff *skb); + unsigned long raddr, struct sk_buff *skb); +#endif + /* * TTY callbacks */ @@ -193,7 +239,7 @@ static int ppp_tty_read (struct tty_struct *, struct file *, __u8 *, static int ppp_tty_write (struct tty_struct *, struct file *, const __u8 *, unsigned int); static int ppp_tty_ioctl (struct tty_struct *, struct file *, unsigned int, - unsigned long); + unsigned long); static int ppp_tty_select (struct tty_struct *tty, struct inode *inode, struct file *filp, int sel_type, select_table * wait); static int ppp_tty_open (struct tty_struct *); @@ -249,7 +295,7 @@ static ppp_ctrl_t *ppp_list = NULL; static char ppp_warning[] = KERN_WARNING "PPP: ALERT! not INUSE! %d\n"; static char szVersion[] = PPP_VERSION; - + /* * Information for the protocol decoder */ @@ -341,7 +387,7 @@ ppp_first_time (void) int status; printk (KERN_INFO - "PPP: version %s (dynamic channel allocation)" + "PPP: version %s (demand dialling)" "\n", szVersion); #ifndef MODULE /* slhc module logic has its own copyright announcement */ @@ -349,13 +395,13 @@ ppp_first_time (void) "TCP compression code copyright 1989 Regents of the " "University of California\n"); #endif - + printk (KERN_INFO "PPP Dynamic channel allocation code copyright 1995 " "Caldera, Inc.\n"); /* * Register the tty discipline - */ + */ (void) memset (&ppp_ldisc, 0, sizeof (ppp_ldisc)); ppp_ldisc.magic = TTY_LDISC_MAGIC; ppp_ldisc.open = ppp_tty_open; @@ -367,7 +413,7 @@ ppp_first_time (void) ppp_ldisc.receive_room = ppp_tty_room; ppp_ldisc.receive_buf = ppp_tty_receive; ppp_ldisc.write_wakeup = ppp_tty_wakeup; - + status = tty_register_ldisc (N_PPP, &ppp_ldisc); if (status == 0) printk (KERN_INFO "PPP line discipline registered.\n"); @@ -388,8 +434,11 @@ ppp_init_dev (struct device *dev) { int indx; +#if LINUX_VERSION_CODE < VERSION(2,1,15) dev->hard_header = ppp_dev_header; dev->rebuild_header = ppp_dev_rebuild; +#endif + dev->hard_header_len = PPP_HARD_HDR_LEN; /* device INFO */ @@ -447,7 +496,8 @@ ppp_init_ctrl_blk (register struct ppp *ppp) ppp->last_xmit = jiffies - flag_time; /* clear statistics */ - memset (&ppp->stats, '\0', sizeof (struct pppstat)); + memset(&ppp->stats, 0, sizeof (struct pppstat)); + memset(&ppp->estats, 0, sizeof(struct enet_statistics)); /* Reset the demand dial information */ ppp->ddinfo.xmit_idle= /* time since last NP packet sent */ @@ -458,6 +508,7 @@ ppp_init_ctrl_blk (register struct ppp *ppp) ppp->sc_rc_state = NULL; } +#if LINUX_VERSION_CODE < VERSION(2,1,18) static struct symbol_table ppp_syms = { #include X(ppp_register_compressor), @@ -465,6 +516,11 @@ static struct symbol_table ppp_syms = { X(ppp_crc16_table), #include }; +#else +EXPORT_SYMBOL(ppp_register_compressor); +EXPORT_SYMBOL(ppp_unregister_compressor); +EXPORT_SYMBOL(ppp_crc16_table); +#endif /* called at boot/load time for each ppp device defined in the kernel */ @@ -478,8 +534,10 @@ ppp_init (struct device *dev) if (first_time) { first_time = 0; answer = ppp_first_time(); +#if LINUX_VERSION_CODE < VERSION(2,1,18) if (answer == 0) (void) register_symtab (&ppp_syms); +#endif } if (answer == 0) answer = -ENODEV; @@ -580,10 +638,6 @@ ppp_changedmtu (struct ppp *ppp, int new_mtu, int new_mru) mru = PPP_MRU; mru += 10; - - if (ppp->flags & SC_DEBUG) - printk (KERN_INFO "ppp: channel %s mtu = %d, mru = %d\n", - dev->name, new_mtu, new_mru); new_wbuf = ppp_alloc_buf (mtu+PPP_HARD_HDR_LEN, BUFFER_TYPE_DEV_WR); new_tbuf = ppp_alloc_buf ((PPP_MTU * 2) + 24, BUFFER_TYPE_TTY_WR); @@ -689,9 +743,9 @@ ppp_release (struct ppp *ppp) ppp_ccp_closed (ppp); - /* Ensure that the pppd process is not hanging on select() */ - wake_up_interruptible (&ppp->read_wait); - wake_up_interruptible (&ppp->write_wait); + /* Ensure that the pppd process is not hanging on select() */ + wake_up_interruptible (&ppp->read_wait); + wake_up_interruptible (&ppp->write_wait); if (tty != NULL && tty->disc_data == ppp) tty->disc_data = NULL; /* Break the tty->ppp link */ @@ -723,16 +777,18 @@ ppp_release (struct ppp *ppp) ppp->inuse = 0; ppp->tty = NULL; + ppp->backup_tty = NULL; } /* - * Device callback. + * TTY callback. * - * Called when the PPP device goes down in response to an ifconfig request. + * Called when the line discipline is changed to something + * else, the tty is closed, or the tty detects a hangup. */ static void -ppp_tty_close_local (struct tty_struct *tty, int sc_xfer) +ppp_tty_close (struct tty_struct *tty) { struct ppp *ppp = tty2ppp (tty); @@ -741,24 +797,27 @@ ppp_tty_close_local (struct tty_struct *tty, int sc_xfer) if (ppp->flags & SC_DEBUG) printk (KERN_WARNING "ppp: trying to close unopened tty!\n"); + return; + } + CHECK_PPP_VOID(); + tty->disc_data = NULL; + if (tty == ppp->backup_tty) + ppp->backup_tty = 0; + if (tty != ppp->tty) + return; + if (ppp->backup_tty) { + ppp->tty = ppp->backup_tty; } else { - CHECK_PPP_VOID(); - ppp->sc_xfer = sc_xfer; + ppp->sc_xfer = 0; if (ppp->flags & SC_DEBUG) printk (KERN_INFO "ppp: channel %s closing.\n", - ppp2dev(ppp) -> name); + ppp2dev(ppp)->name); ppp_release (ppp); MOD_DEC_USE_COUNT; } } } -static void -ppp_tty_close (struct tty_struct *tty) -{ - ppp_tty_close_local (tty, 0); -} - /* * TTY callback. * @@ -785,70 +844,74 @@ ppp_tty_open (struct tty_struct *tty) * Allocate the structure from the system */ ppp = ppp_find(current->pid); - if (ppp == NULL) { - ppp = ppp_find(0); - if (ppp == NULL) - ppp = ppp_alloc(); - } + if (ppp != NULL) { + /* + * If we are taking over a ppp unit which is currently + * connected to a loopback pty, there's not much to do. + */ + ppp->tty = tty; + tty->disc_data = ppp; - if (ppp == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR - "ppp_tty_open: couldn't allocate ppp channel\n"); - return -ENFILE; - } + } else { + ppp = ppp_alloc(); + if (ppp == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR "ppp_alloc failed\n"); + return -ENFILE; + } /* * Initialize the control block */ - ppp_init_ctrl_blk (ppp); - ppp->tty = tty; - tty->disc_data = ppp; -/* - * Flush any pending characters in the driver and discipline. - */ - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer (tty); - - if (tty->driver.flush_buffer) - tty->driver.flush_buffer (tty); + ppp_init_ctrl_blk (ppp); + ppp->tty = tty; + tty->disc_data = ppp; /* * Allocate space for the default VJ header compression slots */ - 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"); - ppp_release (ppp); - return -ENOMEM; - } + 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"); + ppp_release (ppp); + return -ENOMEM; + } /* * Allocate space for the MTU and MRU buffers */ - if (ppp_changedmtu (ppp, ppp2dev(ppp)->mtu, ppp->mru) == 0) { - ppp_release (ppp); - return -ENOMEM; - } + if (ppp_changedmtu (ppp, ppp2dev(ppp)->mtu, ppp->mru) == 0) { + ppp_release (ppp); + return -ENOMEM; + } /* * Allocate space for a user level buffer */ - ppp->ubuf = ppp_alloc_buf (RBUFSIZE, BUFFER_TYPE_TTY_RD); - if (ppp->ubuf == NULL) { + 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"); + ppp_release (ppp); + return -ENOMEM; + } + if (ppp->flags & SC_DEBUG) - printk (KERN_ERR - "ppp_tty_open: no space for user receive buffer\n"); - ppp_release (ppp); - return -ENOMEM; - } + printk (KERN_INFO "ppp: channel %s open\n", + ppp2dev(ppp)->name); - if (ppp->flags & SC_DEBUG) - printk (KERN_INFO "ppp: channel %s open\n", - ppp2dev(ppp)->name); + for (indx = 0; indx < NUM_NP; ++indx) + ppp->sc_npmode[indx] = NPMODE_PASS; - for (indx = 0; indx < NUM_NP; ++indx) - ppp->sc_npmode[indx] = NPMODE_PASS; + MOD_INC_USE_COUNT; + } +/* + * Flush any pending characters in the driver and discipline. + */ + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer (tty); - MOD_INC_USE_COUNT; + if (tty->driver.flush_buffer) + tty->driver.flush_buffer (tty); return (ppp->line); } @@ -968,6 +1031,11 @@ ppp_tty_wakeup (struct tty_struct *tty) if (ppp->magic != PPP_MAGIC) return; + + if (tty != ppp->tty) { + tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + return; + } /* * Ensure that there is a transmission pending. Clear the re-entry flag if * there is no pending buffer. Otherwise, send the buffer. @@ -1055,9 +1123,11 @@ ppp_tty_receive (struct tty_struct *tty, const __u8 * data, register struct ppp_buffer *buf = NULL; __u8 chr; - if (count >= TTY_FLIPBUF_SIZE) - printk(KERN_WARNING "ppp_tty_receive: got %d chars\n", count); - + /* + * This can happen if stuff comes in on the backup tty. + */ + if (tty != ppp->tty) + return; /* * Fetch the pointer to the buffer. Be careful about race conditions. */ @@ -1091,16 +1161,24 @@ ppp_tty_receive (struct tty_struct *tty, const __u8 * data, ppp->bytes_rcvd++; chr = *data++; if (flags) { - if (*flags && ppp->toss == 0) + if (*flags && ppp->toss == 0) { ppp->toss = *flags; + switch (ppp->toss) { + case TTY_OVERRUN: + ++ppp->estats.rx_fifo_errors; + break; + case TTY_FRAME: + case TTY_BREAK: + ++ppp->estats.rx_frame_errors; + break; + } + } ++flags; } /* - * Set the flags for 8 data bits and no parity. - * - * Actually, it sets the flags for d7 being 0/1 and parity being even/odd - * so that the normal processing would have all flags set at the end of the - * session. A missing flag bit would denote an error condition. + * Set the flags for d7 being 0/1 and parity being even/odd so that + * the normal processing would have all flags set at the end of the + * session. A missing flag bit indicates an error condition. */ #ifdef CHECK_CHARACTERS @@ -1132,6 +1210,7 @@ ppp_tty_receive (struct tty_struct *tty, const __u8 * data, * then clean up the VJ tables. */ if (ppp_doframe (ppp) == 0) { + ++ppp->stats.ppp_ierrors; slhc_toss (ppp->slcomp); } /* @@ -1152,11 +1231,8 @@ ppp_tty_receive (struct tty_struct *tty, const __u8 * data, break; /* If this is a control char to be ignored, do so */ - if (in_rmap (ppp, chr)) { - if (ppp->flags & SC_DEBUG) - printk(KERN_DEBUG "ignoring control char %x\n", chr); + if (in_rmap (ppp, chr)) break; - } /* * Modify the next character if preceded by escape. @@ -1184,7 +1260,7 @@ ppp_tty_receive (struct tty_struct *tty, const __u8 * data, * The peer sent too much data. Set the flags to discard the current frame * and wait for the re-synchronization FLAG to be sent. */ - ppp->stats.ppp_ierrors++; + ++ppp->estats.rx_length_errors; ppp->toss |= 0xC0; break; } @@ -1219,7 +1295,10 @@ ppp_rcv_rx (struct ppp *ppp, __u16 proto, __u8 * data, int count) /* * Tag the frame and kick it to the proper receive routine */ +#if LINUX_VERSION_CODE < VERSION(2,1,15) skb->free = 1; +#endif + ppp->ddinfo.recv_idle = jiffies; netif_rx (skb); return 1; @@ -1344,11 +1423,6 @@ rcv_proto_unknown (struct ppp *ppp, __u16 proto, if (ppp->tty->fasync != NULL) kill_fasync (ppp->tty->fasync, SIGIO); - if (ppp->flags & SC_DEBUG) - printk (KERN_INFO - "ppp: successfully queued %d bytes, flags = %x\n", - len + 2, ppp->flags); - return 1; /* * The buffer is full. Unlock the header @@ -1356,14 +1430,14 @@ rcv_proto_unknown (struct ppp *ppp, __u16 proto, failure: clear_bit (0, &ppp->ubuf->locked); if (ppp->flags & SC_DEBUG) - printk (KERN_INFO + printk (KERN_DEBUG "ppp_us_queue: ran out of buffer space.\n"); } /* * Discard the frame. There are no takers for this protocol. */ if (ppp->flags & SC_DEBUG) - printk (KERN_WARNING + printk (KERN_DEBUG "ppp: dropping packet on the floor.\n"); slhc_toss (ppp->slcomp); return 0; @@ -1422,7 +1496,7 @@ static void ppp_proto_ccp (struct ppp *ppp, __u8 *dp, int len, int rcvd) opt_len, ppp2dev (ppp)->base_addr, 0, - ppp->flags)) + ppp->flags & SC_DEBUG)) ppp->flags |= SC_COMP_RUN; break; } @@ -1439,7 +1513,7 @@ static void ppp_proto_ccp (struct ppp *ppp, __u8 *dp, int len, int rcvd) ppp2dev (ppp)->base_addr, 0, ppp->mru, - ppp->flags)) { + ppp->flags & SC_DEBUG)) { ppp->flags |= SC_DECOMP_RUN; ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR); } @@ -1481,9 +1555,6 @@ rcv_proto_lqr (struct ppp *ppp, __u16 proto, __u8 * data, int len) return rcv_proto_unknown (ppp, proto, data, len); } -/* on entry, a received frame is in ppp->rbuf.bufr - check it and dispose as appropriate */ - static void ppp_doframe_lower (struct ppp *ppp, __u8 *data, int count) { __u16 proto = PPP_PROTOCOL (data); @@ -1491,7 +1562,7 @@ static void ppp_doframe_lower (struct ppp *ppp, __u8 *data, int count) /* * Ignore empty frames */ - if (count <= 4) + if (count <= PPP_HDRLEN) return; /* * Count the frame and print it @@ -1533,11 +1604,10 @@ ppp_doframe (struct ppp *ppp) * the damaged frame. */ if (ppp->toss) { - if (ppp->flags & SC_DEBUG) + if ((ppp->flags & SC_DEBUG) && count > 0) printk (KERN_DEBUG "ppp_toss: tossing frame, reason = %x\n", ppp->toss); - ppp->stats.ppp_ierrors++; return 0; } /* @@ -1551,11 +1621,10 @@ ppp_doframe (struct ppp *ppp) */ if (count < PPP_HARD_HDR_LEN) { if (ppp->flags & SC_DEBUG) - printk (KERN_WARNING + printk (KERN_DEBUG "ppp: got runt ppp frame, %d chars\n", count); - slhc_toss (ppp->slcomp); - ppp->stats.ppp_ierrors++; - return 1; + ++ppp->estats.rx_length_errors; + return 0; } /* * Verify the CRC of the frame and discard the CRC characters from the @@ -1563,12 +1632,12 @@ ppp_doframe (struct ppp *ppp) */ if (ppp->rbuf->fcs != PPP_GOODFCS) { if (ppp->flags & SC_DEBUG) { - printk (KERN_WARNING - "ppp: frame with bad fcs, excess = %x, length = %d\n", - ppp->rbuf->fcs ^ PPP_GOODFCS, count); + printk (KERN_DEBUG + "ppp: frame with bad fcs, length = %d\n", + count); ppp_print_buffer("bad frame", data, count); } - ppp->stats.ppp_ierrors++; + ++ppp->estats.rx_crc_errors; return 0; } count -= 2; /* ignore the fcs characters */ @@ -1610,60 +1679,48 @@ ppp_doframe (struct ppp *ppp) /* * If the frame is compressed then decompress it. */ - new_data = kmalloc (ppp->mru + 4, GFP_ATOMIC); + 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"); - slhc_toss (ppp->slcomp); - (*ppp->sc_rcomp->incomp) (ppp->sc_rc_state, - data, - count); - return 1; + new_count = DECOMP_ERROR; + } else { + new_count = (*ppp->sc_rcomp->decompress) + (ppp->sc_rc_state, data, count, + new_data, ppp->mru + PPP_HDRLEN); } -/* - * Decompress the frame - */ - new_count = bsd_decompress (ppp->sc_rc_state, - data, - count, - new_data, - ppp->mru + 4); switch (new_count) { default: ppp_doframe_lower (ppp, new_data, new_count); kfree (new_data); return 1; - case DECOMP_OK: - break; - case DECOMP_ERROR: ppp->flags |= SC_DC_ERROR; break; case DECOMP_FATALERROR: ppp->flags |= SC_DC_FERROR; + if (ppp->flags & SC_DEBUG) + printk(KERN_ERR "ppp: fatal decomp error\n"); break; } /* * Log the error condition and discard the frame. */ - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR - "ppp_proto_comp: " - "decompress err %d\n", new_count); - kfree (new_data); + if (new_data != 0) + kfree (new_data); slhc_toss (ppp->slcomp); - return 1; - } + ++ppp->stats.ppp_ierrors; + } else { /* * The frame is not special. Pass it through the compressor without * actually compressing the data */ - (*ppp->sc_rcomp->incomp) (ppp->sc_rc_state, - data, - count); + (*ppp->sc_rcomp->incomp) (ppp->sc_rc_state, + data, count); + } } /* * Process the uncompressed frame. @@ -1691,6 +1748,7 @@ ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, struct ppp *ppp = tty2ppp (tty); __u8 c; int len, indx; + int error; #define GETC(c) \ { \ @@ -1708,17 +1766,13 @@ ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, return -EIO; CHECK_PPP (-ENXIO); - - if (ppp->flags & SC_DEBUG) - printk (KERN_DEBUG - "ppp_tty_read: called buf=%p nr=%u\n", - buf, nr); /* * Acquire the read lock. */ for (;;) { ppp = tty2ppp (tty); - if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse) + if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse + || tty != ppp->tty) return 0; if (set_bit (0, &ppp->ubuf->locked) != 0) { @@ -1758,13 +1812,8 @@ ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, if (len == 0) { /* no data */ clear_bit (0, &ppp->ubuf->locked); - if (file->f_flags & O_NONBLOCK) { - if (ppp->flags & SC_DEBUG) - printk (KERN_DEBUG - "ppp_tty_read: no data " - "(EAGAIN)\n"); + if (file->f_flags & O_NONBLOCK) return -EAGAIN; - } current->timeout = 0; if (ppp->flags & SC_DEBUG) @@ -1776,11 +1825,6 @@ ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, return -EINTR; continue; } -/* - * Reset the time of the last read operation. - */ - if (ppp->flags & SC_DEBUG) - printk (KERN_DEBUG "ppp_tty_read: len = %d\n", len); /* * Ensure that the frame will fit within the caller's buffer. If not, then * discard the frame from the input buffer. @@ -1813,8 +1857,10 @@ ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, * Fake the insertion of the ADDRESS and CONTROL information because these * were not saved in the buffer. */ - put_user (PPP_ALLSTATIONS, buf++); - put_user (PPP_UI, buf++); + PUT_USER (error, (u_char) PPP_ALLSTATIONS, buf); + ++buf; + PUT_USER (error, (u_char) PPP_UI, buf); + ++buf; indx = len; /* @@ -1822,7 +1868,7 @@ ppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf, */ while (indx-- > 0) { GETC (c); - put_user (c, buf); + PUT_USER (error, c, buf); ++buf; } @@ -1849,7 +1895,7 @@ ppp_stuff_char (struct ppp *ppp, register struct ppp_buffer *buf, */ if (ppp->flags & SC_DEBUG) { if ((buf->count < 0) || (buf->count > 3000)) - printk (KERN_DEBUG "ppp_stuff_char: %x %d\n", + printk (KERN_DEBUG "ppp_stuff_char: %d %x\n", (unsigned int) buf->count, (unsigned int) chr); } @@ -1876,9 +1922,13 @@ static void ppp_dev_xmit_lower (struct ppp *ppp, struct ppp_buffer *buf, __u8 *data, int count, int non_ip) { - __u16 write_fcs; + __u16 write_fcs; int address, control; int proto; + + ++ppp->stats.ppp_opackets; + ppp->stats.ppp_ooctects += count; + /* * Insert the leading FLAG character */ @@ -1985,32 +2035,20 @@ ppp_dev_xmit_frame (struct ppp *ppp, struct ppp_buffer *buf, return 1; } - new_count = bsd_compress (ppp->sc_xc_state, - data, - new_data, - count, - count); - - if (new_count > 0) { - ++ppp->stats.ppp_opackets; - ppp->stats.ppp_ooctects += new_count; + new_count = (*ppp->sc_xcomp->compress) + (ppp->sc_xc_state, data, new_data, count, count); - ppp_dev_xmit_lower (ppp, buf, new_data, - new_count, 0); + if (new_count > 0 && (ppp->flags & SC_CCP_UP)) { + ppp_dev_xmit_lower (ppp, buf, new_data, new_count, 0); kfree (new_data); return 0; } /* - * The frame could not be compressed. + * The frame could not be compressed, or it could not be sent in + * compressed form because CCP is not yet up. */ kfree (new_data); } -/* - * The frame may not be compressed. Update the statistics before the - * count field is destroyed. The frame will be transmitted. - */ - ++ppp->stats.ppp_opackets; - ppp->stats.ppp_ooctects += count; /* * Go to the escape encoding */ @@ -2080,12 +2118,13 @@ ppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data, /* * Ensure that the caller does not wish to send too much. */ - if (count > PPP_MTU) { + if (count > PPP_MTU + PPP_HDRLEN) { if (ppp->flags & SC_DEBUG) printk (KERN_WARNING "ppp_tty_write: truncating user packet " - "from %u to mtu %d\n", count, PPP_MTU); - count = PPP_MTU; + "from %u to mtu %d\n", count, + PPP_MTU + PPP_HDRLEN); + count = PPP_MTU + PPP_HDRLEN; } /* * Allocate a buffer for the data and fetch it from the user space. @@ -2108,7 +2147,8 @@ ppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data, interruptible_sleep_on (&ppp->write_wait); ppp = tty2ppp (tty); - if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse) { + if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse + || tty != ppp->tty) { kfree (new_data); return 0; } @@ -2119,16 +2159,18 @@ ppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data, } } /* - * Ensure that the caller's buffer is valid. + * Retrieve the user's buffer */ - status = verify_area (VERIFY_READ, data, count); + COPY_FROM_USER (status, + new_data, + data, + count); + if (status != 0) { kfree (new_data); ppp->tbuf->locked = 0; return status; } - - memcpy_fromfs (new_data, data, count); /* * Change the LQR frame */ @@ -2157,21 +2199,26 @@ ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp) /* * Fetch the compression parameters */ - error = verify_area (VERIFY_READ, odp, sizeof (data)); - if (error == 0) { - memcpy_fromfs (&data, odp, sizeof (data)); - nb = data.length; - ptr = data.ptr; - if ((__u32) nb >= (__u32)CCP_MAX_OPTION_LENGTH) - nb = CCP_MAX_OPTION_LENGTH; - - error = verify_area (VERIFY_READ, ptr, nb); - } + COPY_FROM_USER (error, + &data, + odp, + sizeof (data)); if (error != 0) return error; - memcpy_fromfs (ccp_option, ptr, nb); + nb = data.length; + ptr = data.ptr; + if ((__u32) nb >= (__u32)CCP_MAX_OPTION_LENGTH) + nb = CCP_MAX_OPTION_LENGTH; + + COPY_FROM_USER (error, + ccp_option, + ptr, + nb); + + if (error != 0) + return error; if (ccp_option[1] < 2) /* preliminary check on the length byte */ return (-EINVAL); @@ -2206,7 +2253,7 @@ ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp) if (ppp->flags & SC_DEBUG) printk("ppp%ld: decomp_alloc failed\n", ppp2dev (ppp)->base_addr); - error = ENOBUFS; + error = -ENOBUFS; } ppp->flags &= ~SC_DECOMP_RUN; } @@ -2226,7 +2273,7 @@ ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp) static int ppp_tty_ioctl (struct tty_struct *tty, struct file * file, - unsigned int param2, unsigned long param3) + unsigned int param2, unsigned long param3) { struct ppp *ppp = tty2ppp (tty); register int temp_i = 0; @@ -2251,10 +2298,8 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, */ switch (param2) { case PPPIOCSMRU: - error = verify_area (VERIFY_READ, (void *) param3, - sizeof (temp_i)); + GET_USER (error, temp_i, (int *) param3); if (error == 0) { - temp_i = get_user ((int *) param3); if (ppp->flags & SC_DEBUG) printk (KERN_INFO "ppp_tty_ioctl: set mru to %x\n", temp_i); @@ -2267,29 +2312,20 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, * Fetch the flags */ case PPPIOCGFLAGS: - error = verify_area (VERIFY_WRITE, (void *) param3, - sizeof (temp_i)); - if (error == 0) { - temp_i = (ppp->flags & SC_MASK); + temp_i = (ppp->flags & SC_MASK); #ifndef CHECK_CHARACTERS /* Don't generate errors if we don't check chars. */ - temp_i |= SC_RCV_B7_1 | SC_RCV_B7_0 | - SC_RCV_ODDP | SC_RCV_EVNP; + temp_i |= SC_RCV_B7_1 | SC_RCV_B7_0 | + SC_RCV_ODDP | SC_RCV_EVNP; #endif - put_user (temp_i, (int *) param3); - if (ppp->flags & SC_DEBUG) - printk (KERN_DEBUG - "ppp_tty_ioctl: get flags: addr %lx flags " - "%x\n", param3, temp_i); - } + PUT_USER (error, temp_i, (int *) param3); break; /* * Set the flags for the various options */ case PPPIOCSFLAGS: - error = verify_area (VERIFY_READ, (void *) param3, - sizeof (temp_i)); + GET_USER (error, temp_i, (int *) param3); if (error == 0) { - temp_i = get_user ((int *) param3) & SC_MASK; + temp_i &= SC_MASK; temp_i |= (ppp->flags & ~SC_MASK); if ((ppp->flags & SC_CCP_OPEN) && @@ -2313,26 +2349,15 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, * Retrieve the transmit async map */ case PPPIOCGASYNCMAP: - error = verify_area (VERIFY_WRITE, (void *) param3, - sizeof (temp_i)); - if (error == 0) { - put_user (ppp->xmit_async_map[0], (int *) param3); - if (ppp->flags & SC_DEBUG) - printk (KERN_INFO - "ppp_tty_ioctl: get asyncmap: addr " - "%lx asyncmap %x\n", - param3, - ppp->xmit_async_map[0]); - } + PUT_USER (error, ppp->xmit_async_map[0], (int *) param3); break; /* * Set the transmit async map */ case PPPIOCSASYNCMAP: - error = verify_area (VERIFY_READ, (void *) param3, - sizeof (temp_i)); + GET_USER (error, temp_i, (int *) param3); if (error == 0) { - ppp->xmit_async_map[0] = get_user ((int *) param3); + ppp->xmit_async_map[0] = temp_i; if (ppp->flags & SC_DEBUG) printk (KERN_INFO "ppp_tty_ioctl: set xmit asyncmap %x\n", @@ -2343,10 +2368,9 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, * Set the receive async map */ case PPPIOCSRASYNCMAP: - error = verify_area (VERIFY_READ, (void *) param3, - sizeof (temp_i)); + GET_USER (error, temp_i, (int *) param3); if (error == 0) { - ppp->recv_async_map = get_user ((int *) param3); + ppp->recv_async_map = temp_i; if (ppp->flags & SC_DEBUG) printk (KERN_INFO "ppp_tty_ioctl: set rcv asyncmap %x\n", @@ -2357,13 +2381,11 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, * Obtain the unit number for this device. */ case PPPIOCGUNIT: - error = verify_area (VERIFY_WRITE, (void *) param3, - sizeof (temp_i)); + PUT_USER (error, ppp2dev (ppp)->base_addr, (int *) param3); if (error == 0) { - put_user (ppp2dev (ppp)->base_addr, (int *) param3); if (ppp->flags & SC_DEBUG) printk (KERN_INFO - "ppp_tty_ioctl: get unit: %ld", + "ppp_tty_ioctl: get unit: %ld\n", ppp2dev (ppp)->base_addr); } break; @@ -2371,10 +2393,9 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, * Set the debug level */ case PPPIOCSDEBUG: - error = verify_area (VERIFY_READ, (void *) param3, - sizeof (temp_i)); + GET_USER (error, temp_i, (int *) param3); if (error == 0) { - temp_i = (get_user ((int *) param3) & 0x1F) << 16; + temp_i = (temp_i & 0x1F) << 16; temp_i |= (ppp->flags & ~0x1F0000); if ((ppp->flags | temp_i) & SC_DEBUG) @@ -2387,82 +2408,65 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, * Get the debug level */ case PPPIOCGDEBUG: - error = verify_area (VERIFY_WRITE, (void *) param3, - sizeof (temp_i)); - if (error == 0) { - temp_i = (ppp->flags >> 16) & 0x1F; - put_user (temp_i, (int *) param3); - - if (ppp->flags & SC_DEBUG) - printk (KERN_INFO - "ppp_tty_ioctl: get debug level %d\n", - temp_i); - } + temp_i = (ppp->flags >> 16) & 0x1F; + PUT_USER (error, temp_i, (int *) param3); break; /* * Get the times since the last send/receive frame operation */ case PPPIOCGIDLE: - error = verify_area (VERIFY_WRITE, (void *) param3, - sizeof (struct ppp_idle)); - if (error == 0) { + { struct ppp_idle cur_ddinfo; __u32 cur_jiffies = jiffies; /* change absolute times to relative times. */ cur_ddinfo.xmit_idle = (cur_jiffies - ppp->ddinfo.xmit_idle) / HZ; cur_ddinfo.recv_idle = (cur_jiffies - ppp->ddinfo.recv_idle) / HZ; - memcpy_tofs ((void *) param3, &cur_ddinfo, - sizeof (cur_ddinfo)); - if (ppp->flags & SC_DEBUG) - printk (KERN_INFO - "ppp_tty_ioctl: read demand dial info\n"); + COPY_TO_USER (error, + (void *) param3, + &cur_ddinfo, + sizeof (cur_ddinfo)); } break; /* * Retrieve the extended async map */ case PPPIOCGXASYNCMAP: - error = verify_area (VERIFY_WRITE, - (void *) param3, - sizeof (ppp->xmit_async_map)); - if (error == 0) { - memcpy_tofs ((void *) param3, - ppp->xmit_async_map, - sizeof (ppp->xmit_async_map)); - - if (ppp->flags & SC_DEBUG) - printk (KERN_INFO - "ppp_tty_ioctl: get xasyncmap: addr %lx\n", - param3); - } + COPY_TO_USER (error, + (void *) param3, + ppp->xmit_async_map, + sizeof (ppp->xmit_async_map)); break; /* * Set the async extended map */ case PPPIOCSXASYNCMAP: - error = verify_area (VERIFY_READ, (void *) param3, - sizeof (ppp->xmit_async_map)); - if (error == 0) { + { __u32 temp_tbl[8]; - memcpy_fromfs (temp_tbl, (void *) param3, - sizeof (ppp->xmit_async_map)); - temp_tbl[1] = 0x00000000; - temp_tbl[2] &= ~0x40000000; - temp_tbl[3] |= 0x60000000; - - if ((temp_tbl[2] & temp_tbl[3]) != 0 || - (temp_tbl[4] & temp_tbl[5]) != 0 || - (temp_tbl[6] & temp_tbl[7]) != 0) - error = -EINVAL; - else { - memcpy (ppp->xmit_async_map, temp_tbl, - sizeof (ppp->xmit_async_map)); - - if (ppp->flags & SC_DEBUG) - printk (KERN_INFO - "ppp_tty_ioctl: set xasyncmap\n"); + COPY_FROM_USER (error, + temp_tbl, + (void *) param3, + sizeof (temp_tbl)); + + if (error == 0) { + temp_tbl[1] = 0x00000000; + temp_tbl[2] &= ~0x40000000; + temp_tbl[3] |= 0x60000000; + + if ((temp_tbl[2] & temp_tbl[3]) != 0 || + (temp_tbl[4] & temp_tbl[5]) != 0 || + (temp_tbl[6] & temp_tbl[7]) != 0) + error = -EINVAL; + else { + memcpy (ppp->xmit_async_map, + temp_tbl, + sizeof (ppp->xmit_async_map)); + + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: set xasyncmap\n"); + } } } break; @@ -2470,10 +2474,9 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, * Set the maximum VJ header compression slot number. */ case PPPIOCSMAXCID: - error = verify_area (VERIFY_READ, (void *) param3, - sizeof (temp_i)); + GET_USER (error, temp_i, (int *) param3); if (error == 0) { - temp_i = get_user ((int *) param3) + 1; + temp_i = (temp_i & 255) + 1; if (ppp->flags & SC_DEBUG) printk (KERN_INFO "ppp_tty_ioctl: set maxcid to %d\n", @@ -2493,24 +2496,30 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, break; case PPPIOCXFERUNIT: - ppp_tty_close_local (tty, current->pid); + ppp->backup_tty = tty; + ppp->sc_xfer = current->pid; break; case PPPIOCGNPMODE: case PPPIOCSNPMODE: - error = verify_area (VERIFY_READ, (void *) param3, - sizeof (struct npioctl)); - if (error == 0) { + { struct npioctl npi; - memcpy_fromfs (&npi, - (void *) param3, - sizeof (npi)); + COPY_FROM_USER (error, + &npi, + (void *) param3, + sizeof (npi)); + + if (error != 0) + break; switch (npi.protocol) { case PPP_IP: npi.protocol = NP_IP; break; default: + if (ppp->flags & SC_DEBUG) + printk(KERN_DEBUG "pppioc[gs]npmode: " + "invalid proto %d\n", npi.protocol); error = -EINVAL; } @@ -2519,15 +2528,11 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, if (param2 == PPPIOCGNPMODE) { npi.mode = ppp->sc_npmode[npi.protocol]; - error = verify_area (VERIFY_WRITE, - (void *) param3, - sizeof (npi)); - if (error != 0) - break; - memcpy_tofs ((void *) param3, - &npi, - sizeof (npi)); + COPY_TO_USER (error, + (void *) param3, + &npi, + sizeof (npi)); break; } @@ -2549,15 +2554,11 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file, break; case FIONREAD: - error = verify_area (VERIFY_WRITE, - (void *) param3, - sizeof (int)); - if (error == 0) { + { int count = ppp->ubuf->tail - ppp->ubuf->head; if (count < 0) count += (ppp->ubuf->size + 1); - - put_user (count, (int *) param3); + PUT_USER (error, count, (int *) param3); } break; /* @@ -2594,7 +2595,7 @@ ppp_tty_select (struct tty_struct *tty, struct inode *inode, if (!ppp) return -EBADF; - if (ppp->magic != PPP_MAGIC) + if (ppp->magic != PPP_MAGIC || tty != ppp->tty) return -EBADF; CHECK_PPP (0); @@ -2687,10 +2688,6 @@ ppp_dev_close (struct device *dev) struct ppp *ppp = dev2ppp (dev); if (ppp2tty (ppp) == NULL) { - if (ppp->flags & SC_DEBUG) - printk (KERN_ERR - "ppp: %s not connected to a TTY! can't go down!\n", - dev->name); return -ENXIO; } /* @@ -2713,19 +2710,15 @@ static int ppp_dev_ioctl_version (struct ppp *ppp, struct ifreq *ifr) { int error; - int len; - char *result; -/* - * Must have write access to the buffer. - */ - result = (char *) ifr->ifr_ifru.ifru_data; - len = strlen (szVersion) + 1; - error = verify_area (VERIFY_WRITE, result, len); + char *result = (char *) ifr->ifr_ifru.ifru_data; + int len = strlen (szVersion) + 1; /* * Move the version data */ - if (error == 0) - memcpy_tofs (result, szVersion, len); + COPY_TO_USER (error, + result, + szVersion, + len); return error; } @@ -2739,19 +2732,12 @@ ppp_dev_ioctl_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev) { struct ppp_stats *result, temp; int error; -/* - * Must have write access to the buffer. - */ - result = (struct ppp_stats *) ifr->ifr_ifru.ifru_data; - error = verify_area (VERIFY_WRITE, - result, - sizeof (temp)); /* * Supply the information for the caller. First move the version data * then move the ppp stats; and finally the vj stats. */ memset (&temp, 0, sizeof(temp)); - if (error == 0 && dev->flags & IFF_UP) { + if (dev->flags & IFF_UP) { memcpy (&temp.p, &ppp->stats, sizeof (struct pppstat)); if (ppp->slcomp != NULL) { temp.vj.vjs_packets = ppp->slcomp->sls_o_compressed+ @@ -2766,8 +2752,13 @@ ppp_dev_ioctl_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev) } } - if (error == 0) - memcpy_tofs (result, &temp, sizeof (temp)); + result = (struct ppp_stats *) ifr->ifr_ifru.ifru_data; + + COPY_TO_USER (error, + result, + &temp, + sizeof (temp)); + return error; } @@ -2780,18 +2771,11 @@ ppp_dev_ioctl_comp_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev { struct ppp_comp_stats *result, temp; int error; -/* - * Must have write access to the buffer. - */ - result = (struct ppp_comp_stats *) ifr->ifr_ifru.ifru_data; - error = verify_area (VERIFY_WRITE, - result, - sizeof (temp)); /* * Supply the information for the caller. */ memset (&temp, 0, sizeof(temp)); - if (error == 0 && dev->flags & IFF_UP) { + if (dev->flags & IFF_UP) { if (ppp->sc_xc_state != NULL) (*ppp->sc_xcomp->comp_stat) (ppp->sc_xc_state, &temp.c); @@ -2803,8 +2787,13 @@ ppp_dev_ioctl_comp_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev /* * Move the data to the caller's buffer */ - if (error == 0) - memcpy_tofs (result, &temp, sizeof (temp)); + result = (struct ppp_comp_stats *) ifr->ifr_ifru.ifru_data; + + COPY_TO_USER (error, + result, + &temp, + sizeof (temp)); + return error; } @@ -2888,17 +2877,11 @@ ppp_dev_xmit_ip (struct device *dev, struct ppp *ppp, __u8 *data) break; case NPMODE_ERROR: - if (ppp->flags & SC_DEBUG) - printk (KERN_WARNING - "ppp_dev_xmit: npmode = NPMODE_ERROR on %s\n", - dev->name); - return 0; - case NPMODE_DROP: if (ppp->flags & SC_DEBUG) - printk (KERN_WARNING - "ppp_dev_xmit: npmode = NPMODE_DROP on %s\n", - dev->name); + printk (KERN_DEBUG + "ppp_dev_xmit: npmode = %d on %s\n", + ppp->sc_npmode[NP_IP], dev->name); return 0; case NPMODE_QUEUE: @@ -3078,6 +3061,14 @@ ppp_dev_xmit (sk_buff *skb, struct device *dev) */ len = skb->len; data = skb_data(skb); + + if (data == (__u8 *) 0) { + if (ppp->flags & SC_DEBUG) + printk (KERN_CRIT "ppp_dev_xmit: %s Null skb data\n", + dev->name); + dev_kfree_skb (skb, FREE_WRITE); + return 0; + } /* * Look at the protocol in the skb to determine the difference between * an IP frame and an IPX frame. @@ -3113,31 +3104,16 @@ static struct enet_statistics * ppp_dev_stats (struct device *dev) { struct ppp *ppp = dev2ppp (dev); - static struct enet_statistics ppp_stats; - - ppp_stats.rx_packets = ppp->stats.ppp_ipackets; - ppp_stats.rx_errors = ppp->stats.ppp_ierrors; - ppp_stats.rx_dropped = ppp->stats.ppp_ierrors; - ppp_stats.rx_fifo_errors = 0; - ppp_stats.rx_length_errors = 0; - ppp_stats.rx_over_errors = 0; - ppp_stats.rx_crc_errors = 0; - ppp_stats.rx_frame_errors = 0; - ppp_stats.tx_packets = ppp->stats.ppp_opackets; - ppp_stats.tx_errors = ppp->stats.ppp_oerrors; - ppp_stats.tx_dropped = 0; - ppp_stats.tx_fifo_errors = 0; - ppp_stats.collisions = 0; - ppp_stats.tx_carrier_errors = 0; - ppp_stats.tx_aborted_errors = 0; - ppp_stats.tx_window_errors = 0; - ppp_stats.tx_heartbeat_errors = 0; - if (ppp->flags & SC_DEBUG) - printk (KERN_INFO "ppp_dev_stats called\n"); - return &ppp_stats; + ppp->estats.rx_packets = ppp->stats.ppp_ipackets; + ppp->estats.rx_errors = ppp->stats.ppp_ierrors; + ppp->estats.tx_packets = ppp->stats.ppp_opackets; + ppp->estats.tx_errors = ppp->stats.ppp_oerrors; + + return &ppp->estats; } +#if LINUX_VERSION_CODE < VERSION(2,1,15) static int ppp_dev_header (sk_buff *skb, struct device *dev, __u16 type, void *daddr, void *saddr, unsigned int len) @@ -3147,10 +3123,11 @@ static int ppp_dev_header (sk_buff *skb, struct device *dev, static int ppp_dev_rebuild (void *eth, struct device *dev, - unsigned long raddr, struct sk_buff *skb) + unsigned long raddr, struct sk_buff *skb) { return (0); } +#endif /************************************************************* * UTILITIES @@ -3168,15 +3145,13 @@ ppp_find (int pid_value) /* try to find the exact same free device which we had before */ ctl = ppp_list; if_num = 0; - + while (ctl) { ppp = ctl2ppp (ctl); - if (!set_bit(0, &ppp->inuse)) { - if (ppp->sc_xfer == pid_value) { - ppp->sc_xfer = 0; - return (ppp); - } - clear_bit (0, &ppp->inuse); + if (ppp->sc_xfer == pid_value) { + set_bit(0, &ppp->inuse); + ppp->sc_xfer = 0; + return (ppp); } ctl = ctl->next; if (++if_num == max_dev) @@ -3198,7 +3173,7 @@ ppp_alloc (void) /* try to find an free device */ ctl = ppp_list; if_num = 0; - + while (ctl) { ppp = ctl2ppp (ctl); if (!set_bit(0, &ppp->inuse)) @@ -3221,8 +3196,9 @@ ppp_alloc (void) ppp->line = if_num; ppp->tty = NULL; + ppp->backup_tty = NULL; ppp->dev = dev; - + dev->next = NULL; dev->init = ppp_init_dev; dev->name = ctl->name; @@ -3230,7 +3206,7 @@ ppp_alloc (void) dev->priv = (void *) ppp; sprintf (dev->name, "ppp%d", if_num); - + /* link in the new channel */ ctl->next = ppp_list; ppp_list = ctl; @@ -3413,8 +3389,10 @@ init_module(void) if (status != 0) printk (KERN_INFO "PPP: ppp_init() failure %d\n", status); +#if LINUX_VERSION_CODE < VERSION(2,1,18) else (void) register_symtab (&ppp_syms); +#endif return (status); } @@ -3469,7 +3447,7 @@ cleanup_module(void) "PPP: ppp line discipline successfully unregistered\n"); /* * De-register the devices so that there is no problem with them - */ + */ next_ctl = ppp_list; while (next_ctl) { ctl = next_ctl;