1017 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * PPP async serial channel driver for Linux.4 *5 * Copyright 1999 Paul Mackerras.6 *7 * This driver provides the encapsulation and framing for sending8 * and receiving PPP frames over async serial lines. It relies on9 * the generic PPP layer to give it frames to send and to process10 * received frames. It implements the PPP line discipline.11 *12 * Part of the code in this driver was inspired by the old async-only13 * PPP driver, written by Michael Callahan and Al Longyear, and14 * subsequently hacked by Paul Mackerras.15 */16 17#include <linux/module.h>18#include <linux/kernel.h>19#include <linux/skbuff.h>20#include <linux/tty.h>21#include <linux/netdevice.h>22#include <linux/poll.h>23#include <linux/crc-ccitt.h>24#include <linux/ppp_defs.h>25#include <linux/ppp-ioctl.h>26#include <linux/ppp_channel.h>27#include <linux/spinlock.h>28#include <linux/init.h>29#include <linux/interrupt.h>30#include <linux/jiffies.h>31#include <linux/slab.h>32#include <linux/unaligned.h>33#include <linux/uaccess.h>34#include <asm/string.h>35 36#define PPP_VERSION "2.4.2"37 38#define OBUFSIZE 409639 40/* Structure for storing local state. */41struct asyncppp {42 struct tty_struct *tty;43 unsigned int flags;44 unsigned int state;45 unsigned int rbits;46 int mru;47 spinlock_t xmit_lock;48 spinlock_t recv_lock;49 unsigned long xmit_flags;50 u32 xaccm[8];51 u32 raccm;52 unsigned int bytes_sent;53 unsigned int bytes_rcvd;54 55 struct sk_buff *tpkt;56 int tpkt_pos;57 u16 tfcs;58 unsigned char *optr;59 unsigned char *olim;60 unsigned long last_xmit;61 62 struct sk_buff *rpkt;63 int lcp_fcs;64 struct sk_buff_head rqueue;65 66 struct tasklet_struct tsk;67 68 refcount_t refcnt;69 struct completion dead;70 struct ppp_channel chan; /* interface to generic ppp layer */71 unsigned char obuf[OBUFSIZE];72};73 74/* Bit numbers in xmit_flags */75#define XMIT_WAKEUP 076#define XMIT_FULL 177#define XMIT_BUSY 278 79/* State bits */80#define SC_TOSS 181#define SC_ESCAPE 282#define SC_PREV_ERROR 483 84/* Bits in rbits */85#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)86 87static int flag_time = HZ;88module_param(flag_time, int, 0);89MODULE_PARM_DESC(flag_time, "ppp_async: interval between flagged packets (in clock ticks)");90MODULE_DESCRIPTION("PPP async serial channel module");91MODULE_LICENSE("GPL");92MODULE_ALIAS_LDISC(N_PPP);93 94/*95 * Prototypes.96 */97static int ppp_async_encode(struct asyncppp *ap);98static int ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb);99static int ppp_async_push(struct asyncppp *ap);100static void ppp_async_flush_output(struct asyncppp *ap);101static void ppp_async_input(struct asyncppp *ap, const unsigned char *buf,102 const u8 *flags, int count);103static int ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd,104 unsigned long arg);105static void ppp_async_process(struct tasklet_struct *t);106 107static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,108 int len, int inbound);109 110static const struct ppp_channel_ops async_ops = {111 .start_xmit = ppp_async_send,112 .ioctl = ppp_async_ioctl,113};114 115/*116 * Routines implementing the PPP line discipline.117 */118 119/*120 * We have a potential race on dereferencing tty->disc_data,121 * because the tty layer provides no locking at all - thus one122 * cpu could be running ppp_asynctty_receive while another123 * calls ppp_asynctty_close, which zeroes tty->disc_data and124 * frees the memory that ppp_asynctty_receive is using. The best125 * way to fix this is to use a rwlock in the tty struct, but for now126 * we use a single global rwlock for all ttys in ppp line discipline.127 *128 * FIXME: this is no longer true. The _close path for the ldisc is129 * now guaranteed to be sane.130 */131static DEFINE_RWLOCK(disc_data_lock);132 133static struct asyncppp *ap_get(struct tty_struct *tty)134{135 struct asyncppp *ap;136 137 read_lock(&disc_data_lock);138 ap = tty->disc_data;139 if (ap != NULL)140 refcount_inc(&ap->refcnt);141 read_unlock(&disc_data_lock);142 return ap;143}144 145static void ap_put(struct asyncppp *ap)146{147 if (refcount_dec_and_test(&ap->refcnt))148 complete(&ap->dead);149}150 151/*152 * Called when a tty is put into PPP line discipline. Called in process153 * context.154 */155static int156ppp_asynctty_open(struct tty_struct *tty)157{158 struct asyncppp *ap;159 int err;160 int speed;161 162 if (tty->ops->write == NULL)163 return -EOPNOTSUPP;164 165 err = -ENOMEM;166 ap = kzalloc(sizeof(*ap), GFP_KERNEL);167 if (!ap)168 goto out;169 170 /* initialize the asyncppp structure */171 ap->tty = tty;172 ap->mru = PPP_MRU;173 spin_lock_init(&ap->xmit_lock);174 spin_lock_init(&ap->recv_lock);175 ap->xaccm[0] = ~0U;176 ap->xaccm[3] = 0x60000000U;177 ap->raccm = ~0U;178 ap->optr = ap->obuf;179 ap->olim = ap->obuf;180 ap->lcp_fcs = -1;181 182 skb_queue_head_init(&ap->rqueue);183 tasklet_setup(&ap->tsk, ppp_async_process);184 185 refcount_set(&ap->refcnt, 1);186 init_completion(&ap->dead);187 188 ap->chan.private = ap;189 ap->chan.ops = &async_ops;190 ap->chan.mtu = PPP_MRU;191 speed = tty_get_baud_rate(tty);192 ap->chan.speed = speed;193 err = ppp_register_channel(&ap->chan);194 if (err)195 goto out_free;196 197 tty->disc_data = ap;198 tty->receive_room = 65536;199 return 0;200 201 out_free:202 kfree(ap);203 out:204 return err;205}206 207/*208 * Called when the tty is put into another line discipline209 * or it hangs up. We have to wait for any cpu currently210 * executing in any of the other ppp_asynctty_* routines to211 * finish before we can call ppp_unregister_channel and free212 * the asyncppp struct. This routine must be called from213 * process context, not interrupt or softirq context.214 */215static void216ppp_asynctty_close(struct tty_struct *tty)217{218 struct asyncppp *ap;219 220 write_lock_irq(&disc_data_lock);221 ap = tty->disc_data;222 tty->disc_data = NULL;223 write_unlock_irq(&disc_data_lock);224 if (!ap)225 return;226 227 /*228 * We have now ensured that nobody can start using ap from now229 * on, but we have to wait for all existing users to finish.230 * Note that ppp_unregister_channel ensures that no calls to231 * our channel ops (i.e. ppp_async_send/ioctl) are in progress232 * by the time it returns.233 */234 if (!refcount_dec_and_test(&ap->refcnt))235 wait_for_completion(&ap->dead);236 tasklet_kill(&ap->tsk);237 238 ppp_unregister_channel(&ap->chan);239 kfree_skb(ap->rpkt);240 skb_queue_purge(&ap->rqueue);241 kfree_skb(ap->tpkt);242 kfree(ap);243}244 245/*246 * Called on tty hangup in process context.247 *248 * Wait for I/O to driver to complete and unregister PPP channel.249 * This is already done by the close routine, so just call that.250 */251static void ppp_asynctty_hangup(struct tty_struct *tty)252{253 ppp_asynctty_close(tty);254}255 256/*257 * Read does nothing - no data is ever available this way.258 * Pppd reads and writes packets via /dev/ppp instead.259 */260static ssize_t261ppp_asynctty_read(struct tty_struct *tty, struct file *file, u8 *buf,262 size_t count, void **cookie, unsigned long offset)263{264 return -EAGAIN;265}266 267/*268 * Write on the tty does nothing, the packets all come in269 * from the ppp generic stuff.270 */271static ssize_t272ppp_asynctty_write(struct tty_struct *tty, struct file *file, const u8 *buf,273 size_t count)274{275 return -EAGAIN;276}277 278/*279 * Called in process context only. May be re-entered by multiple280 * ioctl calling threads.281 */282 283static int284ppp_asynctty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)285{286 struct asyncppp *ap = ap_get(tty);287 int err, val;288 int __user *p = (int __user *)arg;289 290 if (!ap)291 return -ENXIO;292 err = -EFAULT;293 switch (cmd) {294 case PPPIOCGCHAN:295 err = -EFAULT;296 if (put_user(ppp_channel_index(&ap->chan), p))297 break;298 err = 0;299 break;300 301 case PPPIOCGUNIT:302 err = -EFAULT;303 if (put_user(ppp_unit_number(&ap->chan), p))304 break;305 err = 0;306 break;307 308 case TCFLSH:309 /* flush our buffers and the serial port's buffer */310 if (arg == TCIOFLUSH || arg == TCOFLUSH)311 ppp_async_flush_output(ap);312 err = n_tty_ioctl_helper(tty, cmd, arg);313 break;314 315 case FIONREAD:316 val = 0;317 if (put_user(val, p))318 break;319 err = 0;320 break;321 322 default:323 /* Try the various mode ioctls */324 err = tty_mode_ioctl(tty, cmd, arg);325 }326 327 ap_put(ap);328 return err;329}330 331/* May sleep, don't call from interrupt level or with interrupts disabled */332static void333ppp_asynctty_receive(struct tty_struct *tty, const u8 *buf, const u8 *cflags,334 size_t count)335{336 struct asyncppp *ap = ap_get(tty);337 unsigned long flags;338 339 if (!ap)340 return;341 spin_lock_irqsave(&ap->recv_lock, flags);342 ppp_async_input(ap, buf, cflags, count);343 spin_unlock_irqrestore(&ap->recv_lock, flags);344 if (!skb_queue_empty(&ap->rqueue))345 tasklet_schedule(&ap->tsk);346 ap_put(ap);347 tty_unthrottle(tty);348}349 350static void351ppp_asynctty_wakeup(struct tty_struct *tty)352{353 struct asyncppp *ap = ap_get(tty);354 355 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);356 if (!ap)357 return;358 set_bit(XMIT_WAKEUP, &ap->xmit_flags);359 tasklet_schedule(&ap->tsk);360 ap_put(ap);361}362 363 364static struct tty_ldisc_ops ppp_ldisc = {365 .owner = THIS_MODULE,366 .num = N_PPP,367 .name = "ppp",368 .open = ppp_asynctty_open,369 .close = ppp_asynctty_close,370 .hangup = ppp_asynctty_hangup,371 .read = ppp_asynctty_read,372 .write = ppp_asynctty_write,373 .ioctl = ppp_asynctty_ioctl,374 .receive_buf = ppp_asynctty_receive,375 .write_wakeup = ppp_asynctty_wakeup,376};377 378static int __init379ppp_async_init(void)380{381 int err;382 383 err = tty_register_ldisc(&ppp_ldisc);384 if (err != 0)385 printk(KERN_ERR "PPP_async: error %d registering line disc.\n",386 err);387 return err;388}389 390/*391 * The following routines provide the PPP channel interface.392 */393static int394ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)395{396 struct asyncppp *ap = chan->private;397 void __user *argp = (void __user *)arg;398 int __user *p = argp;399 int err, val;400 u32 accm[8];401 402 err = -EFAULT;403 switch (cmd) {404 case PPPIOCGFLAGS:405 val = ap->flags | ap->rbits;406 if (put_user(val, p))407 break;408 err = 0;409 break;410 case PPPIOCSFLAGS:411 if (get_user(val, p))412 break;413 ap->flags = val & ~SC_RCV_BITS;414 spin_lock_irq(&ap->recv_lock);415 ap->rbits = val & SC_RCV_BITS;416 spin_unlock_irq(&ap->recv_lock);417 err = 0;418 break;419 420 case PPPIOCGASYNCMAP:421 if (put_user(ap->xaccm[0], (u32 __user *)argp))422 break;423 err = 0;424 break;425 case PPPIOCSASYNCMAP:426 if (get_user(ap->xaccm[0], (u32 __user *)argp))427 break;428 err = 0;429 break;430 431 case PPPIOCGRASYNCMAP:432 if (put_user(ap->raccm, (u32 __user *)argp))433 break;434 err = 0;435 break;436 case PPPIOCSRASYNCMAP:437 if (get_user(ap->raccm, (u32 __user *)argp))438 break;439 err = 0;440 break;441 442 case PPPIOCGXASYNCMAP:443 if (copy_to_user(argp, ap->xaccm, sizeof(ap->xaccm)))444 break;445 err = 0;446 break;447 case PPPIOCSXASYNCMAP:448 if (copy_from_user(accm, argp, sizeof(accm)))449 break;450 accm[2] &= ~0x40000000U; /* can't escape 0x5e */451 accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */452 memcpy(ap->xaccm, accm, sizeof(ap->xaccm));453 err = 0;454 break;455 456 case PPPIOCGMRU:457 if (put_user(ap->mru, p))458 break;459 err = 0;460 break;461 case PPPIOCSMRU:462 if (get_user(val, p))463 break;464 if (val > U16_MAX) {465 err = -EINVAL;466 break;467 }468 if (val < PPP_MRU)469 val = PPP_MRU;470 ap->mru = val;471 err = 0;472 break;473 474 default:475 err = -ENOTTY;476 }477 478 return err;479}480 481/*482 * This is called at softirq level to deliver received packets483 * to the ppp_generic code, and to tell the ppp_generic code484 * if we can accept more output now.485 */486static void ppp_async_process(struct tasklet_struct *t)487{488 struct asyncppp *ap = from_tasklet(ap, t, tsk);489 struct sk_buff *skb;490 491 /* process received packets */492 while ((skb = skb_dequeue(&ap->rqueue)) != NULL) {493 if (skb->cb[0])494 ppp_input_error(&ap->chan, 0);495 ppp_input(&ap->chan, skb);496 }497 498 /* try to push more stuff out */499 if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_async_push(ap))500 ppp_output_wakeup(&ap->chan);501}502 503/*504 * Procedures for encapsulation and framing.505 */506 507/*508 * Procedure to encode the data for async serial transmission.509 * Does octet stuffing (escaping), puts the address/control bytes510 * on if A/C compression is disabled, and does protocol compression.511 * Assumes ap->tpkt != 0 on entry.512 * Returns 1 if we finished the current frame, 0 otherwise.513 */514 515#define PUT_BYTE(ap, buf, c, islcp) do { \516 if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\517 *buf++ = PPP_ESCAPE; \518 *buf++ = c ^ PPP_TRANS; \519 } else \520 *buf++ = c; \521} while (0)522 523static int524ppp_async_encode(struct asyncppp *ap)525{526 int fcs, i, count, c, proto;527 unsigned char *buf, *buflim;528 unsigned char *data;529 int islcp;530 531 buf = ap->obuf;532 ap->olim = buf;533 ap->optr = buf;534 i = ap->tpkt_pos;535 data = ap->tpkt->data;536 count = ap->tpkt->len;537 fcs = ap->tfcs;538 proto = get_unaligned_be16(data);539 540 /*541 * LCP packets with code values between 1 (configure-request)542 * and 7 (code-reject) must be sent as though no options543 * had been negotiated.544 */545 islcp = proto == PPP_LCP && count >= 3 && 1 <= data[2] && data[2] <= 7;546 547 if (i == 0) {548 if (islcp)549 async_lcp_peek(ap, data, count, 0);550 551 /*552 * Start of a new packet - insert the leading FLAG553 * character if necessary.554 */555 if (islcp || flag_time == 0 ||556 time_after_eq(jiffies, ap->last_xmit + flag_time))557 *buf++ = PPP_FLAG;558 ap->last_xmit = jiffies;559 fcs = PPP_INITFCS;560 561 /*562 * Put in the address/control bytes if necessary563 */564 if ((ap->flags & SC_COMP_AC) == 0 || islcp) {565 PUT_BYTE(ap, buf, 0xff, islcp);566 fcs = PPP_FCS(fcs, 0xff);567 PUT_BYTE(ap, buf, 0x03, islcp);568 fcs = PPP_FCS(fcs, 0x03);569 }570 }571 572 /*573 * Once we put in the last byte, we need to put in the FCS574 * and closing flag, so make sure there is at least 7 bytes575 * of free space in the output buffer.576 */577 buflim = ap->obuf + OBUFSIZE - 6;578 while (i < count && buf < buflim) {579 c = data[i++];580 if (i == 1 && c == 0 && (ap->flags & SC_COMP_PROT))581 continue; /* compress protocol field */582 fcs = PPP_FCS(fcs, c);583 PUT_BYTE(ap, buf, c, islcp);584 }585 586 if (i < count) {587 /*588 * Remember where we are up to in this packet.589 */590 ap->olim = buf;591 ap->tpkt_pos = i;592 ap->tfcs = fcs;593 return 0;594 }595 596 /*597 * We have finished the packet. Add the FCS and flag.598 */599 fcs = ~fcs;600 c = fcs & 0xff;601 PUT_BYTE(ap, buf, c, islcp);602 c = (fcs >> 8) & 0xff;603 PUT_BYTE(ap, buf, c, islcp);604 *buf++ = PPP_FLAG;605 ap->olim = buf;606 607 consume_skb(ap->tpkt);608 ap->tpkt = NULL;609 return 1;610}611 612/*613 * Transmit-side routines.614 */615 616/*617 * Send a packet to the peer over an async tty line.618 * Returns 1 iff the packet was accepted.619 * If the packet was not accepted, we will call ppp_output_wakeup620 * at some later time.621 */622static int623ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb)624{625 struct asyncppp *ap = chan->private;626 627 ppp_async_push(ap);628 629 if (test_and_set_bit(XMIT_FULL, &ap->xmit_flags))630 return 0; /* already full */631 ap->tpkt = skb;632 ap->tpkt_pos = 0;633 634 ppp_async_push(ap);635 return 1;636}637 638/*639 * Push as much data as possible out to the tty.640 */641static int642ppp_async_push(struct asyncppp *ap)643{644 int avail, sent, done = 0;645 struct tty_struct *tty = ap->tty;646 int tty_stuffed = 0;647 648 /*649 * We can get called recursively here if the tty write650 * function calls our wakeup function. This can happen651 * for example on a pty with both the master and slave652 * set to PPP line discipline.653 * We use the XMIT_BUSY bit to detect this and get out,654 * leaving the XMIT_WAKEUP bit set to tell the other655 * instance that it may now be able to write more now.656 */657 if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))658 return 0;659 spin_lock_bh(&ap->xmit_lock);660 for (;;) {661 if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))662 tty_stuffed = 0;663 if (!tty_stuffed && ap->optr < ap->olim) {664 avail = ap->olim - ap->optr;665 set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);666 sent = tty->ops->write(tty, ap->optr, avail);667 if (sent < 0)668 goto flush; /* error, e.g. loss of CD */669 ap->optr += sent;670 if (sent < avail)671 tty_stuffed = 1;672 continue;673 }674 if (ap->optr >= ap->olim && ap->tpkt) {675 if (ppp_async_encode(ap)) {676 /* finished processing ap->tpkt */677 clear_bit(XMIT_FULL, &ap->xmit_flags);678 done = 1;679 }680 continue;681 }682 /*683 * We haven't made any progress this time around.684 * Clear XMIT_BUSY to let other callers in, but685 * after doing so we have to check if anyone set686 * XMIT_WAKEUP since we last checked it. If they687 * did, we should try again to set XMIT_BUSY and go688 * around again in case XMIT_BUSY was still set when689 * the other caller tried.690 */691 clear_bit(XMIT_BUSY, &ap->xmit_flags);692 /* any more work to do? if not, exit the loop */693 if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) ||694 (!tty_stuffed && ap->tpkt)))695 break;696 /* more work to do, see if we can do it now */697 if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))698 break;699 }700 spin_unlock_bh(&ap->xmit_lock);701 return done;702 703flush:704 clear_bit(XMIT_BUSY, &ap->xmit_flags);705 if (ap->tpkt) {706 kfree_skb(ap->tpkt);707 ap->tpkt = NULL;708 clear_bit(XMIT_FULL, &ap->xmit_flags);709 done = 1;710 }711 ap->optr = ap->olim;712 spin_unlock_bh(&ap->xmit_lock);713 return done;714}715 716/*717 * Flush output from our internal buffers.718 * Called for the TCFLSH ioctl. Can be entered in parallel719 * but this is covered by the xmit_lock.720 */721static void722ppp_async_flush_output(struct asyncppp *ap)723{724 int done = 0;725 726 spin_lock_bh(&ap->xmit_lock);727 ap->optr = ap->olim;728 if (ap->tpkt != NULL) {729 kfree_skb(ap->tpkt);730 ap->tpkt = NULL;731 clear_bit(XMIT_FULL, &ap->xmit_flags);732 done = 1;733 }734 spin_unlock_bh(&ap->xmit_lock);735 if (done)736 ppp_output_wakeup(&ap->chan);737}738 739/*740 * Receive-side routines.741 */742 743/* see how many ordinary chars there are at the start of buf */744static inline int745scan_ordinary(struct asyncppp *ap, const unsigned char *buf, int count)746{747 int i, c;748 749 for (i = 0; i < count; ++i) {750 c = buf[i];751 if (c == PPP_ESCAPE || c == PPP_FLAG ||752 (c < 0x20 && (ap->raccm & (1 << c)) != 0))753 break;754 }755 return i;756}757 758/* called when a flag is seen - do end-of-packet processing */759static void760process_input_packet(struct asyncppp *ap)761{762 struct sk_buff *skb;763 unsigned char *p;764 unsigned int len, fcs;765 766 skb = ap->rpkt;767 if (ap->state & (SC_TOSS | SC_ESCAPE))768 goto err;769 770 if (skb == NULL)771 return; /* 0-length packet */772 773 /* check the FCS */774 p = skb->data;775 len = skb->len;776 if (len < 3)777 goto err; /* too short */778 fcs = PPP_INITFCS;779 for (; len > 0; --len)780 fcs = PPP_FCS(fcs, *p++);781 if (fcs != PPP_GOODFCS)782 goto err; /* bad FCS */783 skb_trim(skb, skb->len - 2);784 785 /* check for address/control and protocol compression */786 p = skb->data;787 if (p[0] == PPP_ALLSTATIONS) {788 /* chop off address/control */789 if (p[1] != PPP_UI || skb->len < 3)790 goto err;791 p = skb_pull(skb, 2);792 }793 794 /* If protocol field is not compressed, it can be LCP packet */795 if (!(p[0] & 0x01)) {796 unsigned int proto;797 798 if (skb->len < 2)799 goto err;800 proto = (p[0] << 8) + p[1];801 if (proto == PPP_LCP)802 async_lcp_peek(ap, p, skb->len, 1);803 }804 805 /* queue the frame to be processed */806 skb->cb[0] = ap->state;807 skb_queue_tail(&ap->rqueue, skb);808 ap->rpkt = NULL;809 ap->state = 0;810 return;811 812 err:813 /* frame had an error, remember that, reset SC_TOSS & SC_ESCAPE */814 ap->state = SC_PREV_ERROR;815 if (skb) {816 /* make skb appear as freshly allocated */817 skb_trim(skb, 0);818 skb_reserve(skb, - skb_headroom(skb));819 }820}821 822/* Called when the tty driver has data for us. Runs parallel with the823 other ldisc functions but will not be re-entered */824 825static void826ppp_async_input(struct asyncppp *ap, const u8 *buf, const u8 *flags, int count)827{828 struct sk_buff *skb;829 int c, i, j, n, s, f;830 unsigned char *sp;831 832 /* update bits used for 8-bit cleanness detection */833 if (~ap->rbits & SC_RCV_BITS) {834 s = 0;835 for (i = 0; i < count; ++i) {836 c = buf[i];837 if (flags && flags[i] != 0)838 continue;839 s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0;840 c = ((c >> 4) ^ c) & 0xf;841 s |= (0x6996 & (1 << c))? SC_RCV_ODDP: SC_RCV_EVNP;842 }843 ap->rbits |= s;844 }845 846 while (count > 0) {847 /* scan through and see how many chars we can do in bulk */848 if ((ap->state & SC_ESCAPE) && buf[0] == PPP_ESCAPE)849 n = 1;850 else851 n = scan_ordinary(ap, buf, count);852 853 f = 0;854 if (flags && (ap->state & SC_TOSS) == 0) {855 /* check the flags to see if any char had an error */856 for (j = 0; j < n; ++j)857 if ((f = flags[j]) != 0)858 break;859 }860 if (f != 0) {861 /* start tossing */862 ap->state |= SC_TOSS;863 864 } else if (n > 0 && (ap->state & SC_TOSS) == 0) {865 /* stuff the chars in the skb */866 skb = ap->rpkt;867 if (!skb) {868 skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);869 if (!skb)870 goto nomem;871 ap->rpkt = skb;872 }873 if (skb->len == 0) {874 /* Try to get the payload 4-byte aligned.875 * This should match the876 * PPP_ALLSTATIONS/PPP_UI/compressed tests in877 * process_input_packet, but we do not have878 * enough chars here to test buf[1] and buf[2].879 */880 if (buf[0] != PPP_ALLSTATIONS)881 skb_reserve(skb, 2 + (buf[0] & 1));882 }883 if (n > skb_tailroom(skb)) {884 /* packet overflowed MRU */885 ap->state |= SC_TOSS;886 } else {887 sp = skb_put_data(skb, buf, n);888 if (ap->state & SC_ESCAPE) {889 sp[0] ^= PPP_TRANS;890 ap->state &= ~SC_ESCAPE;891 }892 }893 }894 895 if (n >= count)896 break;897 898 c = buf[n];899 if (flags != NULL && flags[n] != 0) {900 ap->state |= SC_TOSS;901 } else if (c == PPP_FLAG) {902 process_input_packet(ap);903 } else if (c == PPP_ESCAPE) {904 ap->state |= SC_ESCAPE;905 } else if (I_IXON(ap->tty)) {906 if (c == START_CHAR(ap->tty))907 start_tty(ap->tty);908 else if (c == STOP_CHAR(ap->tty))909 stop_tty(ap->tty);910 }911 /* otherwise it's a char in the recv ACCM */912 ++n;913 914 buf += n;915 if (flags)916 flags += n;917 count -= n;918 }919 return;920 921 nomem:922 printk(KERN_ERR "PPPasync: no memory (input pkt)\n");923 ap->state |= SC_TOSS;924}925 926/*927 * We look at LCP frames going past so that we can notice928 * and react to the LCP configure-ack from the peer.929 * In the situation where the peer has been sent a configure-ack930 * already, LCP is up once it has sent its configure-ack931 * so the immediately following packet can be sent with the932 * configured LCP options. This allows us to process the following933 * packet correctly without pppd needing to respond quickly.934 *935 * We only respond to the received configure-ack if we have just936 * sent a configure-request, and the configure-ack contains the937 * same data (this is checked using a 16-bit crc of the data).938 */939#define CONFREQ 1 /* LCP code field values */940#define CONFACK 2941#define LCP_MRU 1 /* LCP option numbers */942#define LCP_ASYNCMAP 2943 944static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,945 int len, int inbound)946{947 int dlen, fcs, i, code;948 u32 val;949 950 data += 2; /* skip protocol bytes */951 len -= 2;952 if (len < 4) /* 4 = code, ID, length */953 return;954 code = data[0];955 if (code != CONFACK && code != CONFREQ)956 return;957 dlen = get_unaligned_be16(data + 2);958 if (len < dlen)959 return; /* packet got truncated or length is bogus */960 961 if (code == (inbound? CONFACK: CONFREQ)) {962 /*963 * sent confreq or received confack:964 * calculate the crc of the data from the ID field on.965 */966 fcs = PPP_INITFCS;967 for (i = 1; i < dlen; ++i)968 fcs = PPP_FCS(fcs, data[i]);969 970 if (!inbound) {971 /* outbound confreq - remember the crc for later */972 ap->lcp_fcs = fcs;973 return;974 }975 976 /* received confack, check the crc */977 fcs ^= ap->lcp_fcs;978 ap->lcp_fcs = -1;979 if (fcs != 0)980 return;981 } else if (inbound)982 return; /* not interested in received confreq */983 984 /* process the options in the confack */985 data += 4;986 dlen -= 4;987 /* data[0] is code, data[1] is length */988 while (dlen >= 2 && dlen >= data[1] && data[1] >= 2) {989 switch (data[0]) {990 case LCP_MRU:991 val = get_unaligned_be16(data + 2);992 if (inbound)993 ap->mru = val;994 else995 ap->chan.mtu = val;996 break;997 case LCP_ASYNCMAP:998 val = get_unaligned_be32(data + 2);999 if (inbound)1000 ap->raccm = val;1001 else1002 ap->xaccm[0] = val;1003 break;1004 }1005 dlen -= data[1];1006 data += data[1];1007 }1008}1009 1010static void __exit ppp_async_cleanup(void)1011{1012 tty_unregister_ldisc(&ppp_ldisc);1013}1014 1015module_init(ppp_async_init);1016module_exit(ppp_async_cleanup);1017