Home | History | Annotate | Line # | Download | only in net
ppp_tty.c revision 1.61.2.2
      1 /*	$NetBSD: ppp_tty.c,v 1.61.2.2 2016/11/04 14:49:21 pgoyette Exp $	*/
      2 /*	Id: ppp_tty.c,v 1.3 1996/07/01 01:04:11 paulus Exp 	*/
      3 
      4 /*
      5  * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
      6  * 	       tty devices.
      7  *
      8  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  *
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  *
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in
     19  *    the documentation and/or other materials provided with the
     20  *    distribution.
     21  *
     22  * 3. The name "Carnegie Mellon University" must not be used to
     23  *    endorse or promote products derived from this software without
     24  *    prior written permission. For permission or any legal
     25  *    details, please contact
     26  *      Office of Technology Transfer
     27  *      Carnegie Mellon University
     28  *      5000 Forbes Avenue
     29  *      Pittsburgh, PA  15213-3890
     30  *      (412) 268-4387, fax: (412) 268-7395
     31  *      tech-transfer (at) andrew.cmu.edu
     32  *
     33  * 4. Redistributions of any form whatsoever must retain the following
     34  *    acknowledgment:
     35  *    "This product includes software developed by Computing Services
     36  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
     37  *
     38  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
     39  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     40  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
     41  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     42  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     43  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     44  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     45  *
     46  * Based on:
     47  *	@(#)if_sl.c	7.6.1.2 (Berkeley) 2/15/89
     48  *
     49  * Copyright (c) 1987 Regents of the University of California.
     50  * All rights reserved.
     51  *
     52  * Redistribution and use in source and binary forms are permitted
     53  * provided that the above copyright notice and this paragraph are
     54  * duplicated in all such forms and that any documentation,
     55  * advertising materials, and other materials related to such
     56  * distribution and use acknowledge that the software was developed
     57  * by the University of California, Berkeley.  The name of the
     58  * University may not be used to endorse or promote products derived
     59  * from this software without specific prior written permission.
     60  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     61  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     62  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     63  *
     64  * Serial Line interface
     65  *
     66  * Rick Adams
     67  * Center for Seismic Studies
     68  * 1300 N 17th Street, Suite 1450
     69  * Arlington, Virginia 22209
     70  * (703)276-7900
     71  * rick (at) seismo.ARPA
     72  * seismo!rick
     73  *
     74  * Pounded on heavily by Chris Torek (chris (at) mimsy.umd.edu, umcp-cs!chris).
     75  * Converted to 4.3BSD Beta by Chris Torek.
     76  * Other changes made at Berkeley, based in part on code by Kirk Smith.
     77  *
     78  * Converted to 4.3BSD+ 386BSD by Brad Parker (brad (at) cayman.com)
     79  * Added VJ tcp header compression; more unified ioctls
     80  *
     81  * Extensively modified by Paul Mackerras (paulus (at) cs.anu.edu.au).
     82  * Cleaned up a lot of the mbuf-related code to fix bugs that
     83  * caused system crashes and packet corruption.  Changed pppstart
     84  * so that it doesn't just give up with a "collision" if the whole
     85  * packet doesn't fit in the output ring buffer.
     86  *
     87  * Added priority queueing for interactive IP packets, following
     88  * the model of if_sl.c, plus hooks for bpf.
     89  * Paul Mackerras (paulus (at) cs.anu.edu.au).
     90  */
     91 
     92 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
     93 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
     94 
     95 #include <sys/cdefs.h>
     96 __KERNEL_RCSID(0, "$NetBSD: ppp_tty.c,v 1.61.2.2 2016/11/04 14:49:21 pgoyette Exp $");
     97 
     98 #ifdef _KERNEL_OPT
     99 #include "opt_ppp.h"
    100 #endif
    101 #define VJC
    102 #define PPP_COMPRESS
    103 
    104 #include <sys/param.h>
    105 #include <sys/proc.h>
    106 #include <sys/mbuf.h>
    107 #include <sys/dkstat.h>
    108 #include <sys/socket.h>
    109 #include <sys/ioctl.h>
    110 #include <sys/file.h>
    111 #include <sys/tty.h>
    112 #include <sys/kernel.h>
    113 #include <sys/conf.h>
    114 #include <sys/vnode.h>
    115 #include <sys/systm.h>
    116 #include <sys/kauth.h>
    117 
    118 #include <net/if.h>
    119 #include <net/if_types.h>
    120 
    121 #ifdef VJC
    122 #include <netinet/in.h>
    123 #include <netinet/in_systm.h>
    124 #include <netinet/ip.h>
    125 #include <net/slcompress.h>
    126 #endif
    127 
    128 #include <net/bpf.h>
    129 #include <net/ppp_defs.h>
    130 #include <net/if_ppp.h>
    131 #include <net/if_pppvar.h>
    132 
    133 static int	pppopen(dev_t dev, struct tty *tp);
    134 static int	pppclose(struct tty *tp, int flag);
    135 static int	pppread(struct tty *tp, struct uio *uio, int flag);
    136 static int	pppwrite(struct tty *tp, struct uio *uio, int flag);
    137 static int	ppptioctl(struct tty *tp, u_long cmd, void *data, int flag,
    138 			  struct lwp *);
    139 static int	pppinput(int c, struct tty *tp);
    140 static int	pppstart(struct tty *tp);
    141 
    142 struct linesw ppp_disc = {	/* XXX should be static */
    143 	.l_name = "ppp",
    144 	.l_open = pppopen,
    145 	.l_close = pppclose,
    146 	.l_read = pppread,
    147 	.l_write = pppwrite,
    148 	.l_ioctl = ppptioctl,
    149 	.l_rint = pppinput,
    150 	.l_start = pppstart,
    151 	.l_modem = ttymodem,
    152 	.l_poll = ttpoll
    153 };
    154 
    155 static void	ppprcvframe(struct ppp_softc *sc, struct mbuf *m);
    156 static uint16_t pppfcs(uint16_t fcs, const uint8_t *cp, int len);
    157 static void	pppsyncstart(struct ppp_softc *sc);
    158 static void	pppasyncstart(struct ppp_softc *);
    159 static void	pppasyncctlp(struct ppp_softc *);
    160 static void	pppasyncrelinq(struct ppp_softc *);
    161 static void	ppp_timeout(void *);
    162 static void	pppgetm(struct ppp_softc *sc);
    163 static void	pppdumpb(u_char *b, int l);
    164 static void	ppplogchar(struct ppp_softc *, int);
    165 static void	pppdumpframe(struct ppp_softc *sc, struct mbuf* m, int xmit);
    166 
    167 /*
    168  * Some useful mbuf macros not in mbuf.h.
    169  */
    170 #define M_IS_CLUSTER(m)	((m)->m_flags & M_EXT)
    171 
    172 #define M_DATASTART(m)	\
    173 	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
    174 	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
    175 
    176 #define M_DATASIZE(m)	\
    177 	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
    178 	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
    179 
    180 /*
    181  * Does c need to be escaped?
    182  */
    183 #define ESCAPE_P(c)	(sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
    184 
    185 /*
    186  * Procedures for using an async tty interface for PPP.
    187  */
    188 
    189 /* This is a NetBSD-1.0 or later kernel. */
    190 #define CCOUNT(q)	((q)->c_cc)
    191 
    192 #define PPP_LOWAT	100	/* Process more output when < LOWAT on queue */
    193 #define	PPP_HIWAT	400	/* Don't start a new packet if HIWAT on que */
    194 
    195 /*
    196  * Line specific open routine for async tty devices.
    197  * Attach the given tty to the first available ppp unit.
    198  * Called from device open routine or ttioctl.
    199  */
    200 /* ARGSUSED */
    201 static int
    202 pppopen(dev_t dev, struct tty *tp)
    203 {
    204     struct lwp *l = curlwp;		/* XXX */
    205     struct ppp_softc *sc;
    206     int error, s;
    207 
    208     error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE_PPP,
    209 	KAUTH_REQ_NETWORK_INTERFACE_PPP_ADD, NULL, NULL, NULL);
    210     if (error)
    211 	return (error);
    212 
    213     s = spltty();
    214 
    215     if (tp->t_linesw == &ppp_disc) {
    216 	sc = (struct ppp_softc *) tp->t_sc;
    217 	if (sc != NULL && sc->sc_devp == (void *) tp) {
    218 	    splx(s);
    219 	    return (0);
    220 	}
    221     }
    222 
    223     if ((sc = pppalloc(l->l_proc->p_pid)) == NULL) {
    224 	splx(s);
    225 	return ENXIO;
    226     }
    227 
    228     if (sc->sc_relinq)
    229 	(*sc->sc_relinq)(sc);	/* get previous owner to relinquish the unit */
    230 
    231     /* Switch DLT to PPP-over-serial. */
    232     bpf_change_type(&sc->sc_if, DLT_PPP_SERIAL, PPP_HDRLEN);
    233 
    234     sc->sc_ilen = 0;
    235     sc->sc_m = NULL;
    236     memset(sc->sc_asyncmap, 0, sizeof(sc->sc_asyncmap));
    237     sc->sc_asyncmap[0] = 0xffffffff;
    238     sc->sc_asyncmap[3] = 0x60000000;
    239     sc->sc_rasyncmap = 0;
    240     sc->sc_devp = (void *) tp;
    241     sc->sc_start = pppasyncstart;
    242     sc->sc_ctlp = pppasyncctlp;
    243     sc->sc_relinq = pppasyncrelinq;
    244     sc->sc_outm = NULL;
    245     pppgetm(sc);
    246     sc->sc_if.if_flags |= IFF_RUNNING;
    247     sc->sc_if.if_baudrate = tp->t_ospeed;
    248 
    249     tp->t_sc = (void *) sc;
    250     mutex_spin_enter(&tty_lock);
    251     ttyflush(tp, FREAD | FWRITE);
    252     mutex_spin_exit(&tty_lock);
    253 
    254     splx(s);
    255     return (0);
    256 }
    257 
    258 /*
    259  * Line specific close routine, called from device close routine
    260  * and from ttioctl.
    261  * Detach the tty from the ppp unit.
    262  * Mimics part of ttyclose().
    263  */
    264 static int
    265 pppclose(struct tty *tp, int flag)
    266 {
    267     struct ppp_softc *sc;
    268     int s;
    269 
    270     s = spltty();
    271     mutex_spin_enter(&tty_lock);
    272     ttyflush(tp, FREAD|FWRITE);
    273     mutex_spin_exit(&tty_lock);	/* XXX */
    274     ttyldisc_release(tp->t_linesw);
    275     tp->t_linesw = ttyldisc_default();
    276     sc = (struct ppp_softc *) tp->t_sc;
    277     if (sc != NULL) {
    278 	tp->t_sc = NULL;
    279 	if (tp == (struct tty *) sc->sc_devp) {
    280 	    pppasyncrelinq(sc);
    281 	    pppdealloc(sc);
    282 	}
    283     }
    284     splx(s);
    285     return 0;
    286 }
    287 
    288 /*
    289  * Relinquish the interface unit to another device.
    290  */
    291 static void
    292 pppasyncrelinq(struct ppp_softc *sc)
    293 {
    294     int s;
    295 
    296     /* Change DLT to back none. */
    297     bpf_change_type(&sc->sc_if, DLT_NULL, 0);
    298 
    299     s = spltty();
    300     if (sc->sc_outm) {
    301 	m_freem(sc->sc_outm);
    302 	sc->sc_outm = NULL;
    303     }
    304     if (sc->sc_m) {
    305 	m_freem(sc->sc_m);
    306 	sc->sc_m = NULL;
    307     }
    308     if (sc->sc_flags & SC_TIMEOUT) {
    309 	callout_stop(&sc->sc_timo_ch);
    310 	sc->sc_flags &= ~SC_TIMEOUT;
    311     }
    312     splx(s);
    313 }
    314 
    315 /*
    316  * Line specific (tty) read routine.
    317  */
    318 static int
    319 pppread(struct tty *tp, struct uio *uio, int flag)
    320 {
    321     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    322     struct mbuf *m, *m0;
    323     int error = 0;
    324 
    325     if (sc == NULL)
    326 	return 0;
    327     /*
    328      * Loop waiting for input, checking that nothing disasterous
    329      * happens in the meantime.
    330      */
    331     mutex_spin_enter(&tty_lock);
    332     for (;;) {
    333 	if (tp != (struct tty *) sc->sc_devp ||
    334 	    tp->t_linesw != &ppp_disc) {
    335 	    mutex_spin_exit(&tty_lock);
    336 	    return 0;
    337 	}
    338 	if (sc->sc_inq.ifq_head != NULL)
    339 	    break;
    340 	if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
    341 	    && (tp->t_state & TS_ISOPEN)) {
    342 	    mutex_spin_exit(&tty_lock);
    343 	    return 0;		/* end of file */
    344 	}
    345 	if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
    346 	    mutex_spin_exit(&tty_lock);
    347 	    return (EWOULDBLOCK);
    348 	}
    349 	error = ttysleep(tp, &tp->t_rawcv, true, 0);
    350 	if (error) {
    351 	    mutex_spin_exit(&tty_lock);
    352 	    return error;
    353 	}
    354     }
    355 
    356     /* Pull place-holder byte out of canonical queue */
    357     getc(&tp->t_canq);
    358 
    359     /* Get the packet from the input queue */
    360     IF_DEQUEUE(&sc->sc_inq, m0);
    361     mutex_spin_exit(&tty_lock);
    362 
    363     for (m = m0; m && uio->uio_resid; m = m->m_next)
    364 	if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
    365 	    break;
    366     m_freem(m0);
    367     return (error);
    368 }
    369 
    370 /*
    371  * Line specific (tty) write routine.
    372  */
    373 static int
    374 pppwrite(struct tty *tp, struct uio *uio, int flag)
    375 {
    376     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    377     struct mbuf *m, *m0;
    378     struct sockaddr dst;
    379     int len, error;
    380 
    381     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    382 	return 0;		/* wrote 0 bytes */
    383     if (tp->t_linesw != &ppp_disc)
    384 	return (EINVAL);
    385     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    386 	return EIO;
    387     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
    388 	uio->uio_resid < PPP_HDRLEN)
    389 	return (EMSGSIZE);
    390 
    391     MGETHDR(m0, M_WAIT, MT_DATA);
    392     if (m0 == NULL)
    393 	return ENOBUFS;
    394 
    395     m0->m_len = 0;
    396     m0->m_pkthdr.len = uio->uio_resid;
    397     m_reset_rcvif(m0);
    398 
    399     if (uio->uio_resid >= MCLBYTES / 2)
    400 	MCLGET(m0, M_DONTWAIT);
    401 
    402     for (m = m0; uio->uio_resid;) {
    403 	len = M_TRAILINGSPACE(m);
    404 	if (len > uio->uio_resid)
    405 	    len = uio->uio_resid;
    406 	if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
    407 	    m_freem(m0);
    408 	    return (error);
    409 	}
    410 	m->m_len = len;
    411 
    412 	if (uio->uio_resid == 0)
    413 	    break;
    414 
    415 	MGET(m->m_next, M_WAIT, MT_DATA);
    416 	if (m->m_next == NULL) {
    417 	    m_freem(m0);
    418 	    return ENOBUFS;
    419 	}
    420 	m = m->m_next;
    421 	m->m_len = 0;
    422     }
    423     dst.sa_family = AF_UNSPEC;
    424     bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
    425     m_adj(m0, PPP_HDRLEN);
    426     return if_output_lock(&sc->sc_if, &sc->sc_if, m0, &dst, (struct rtentry *)0);
    427 }
    428 
    429 /*
    430  * Line specific (tty) ioctl routine.
    431  * This discipline requires that tty device drivers call
    432  * the line specific l_ioctl routine from their ioctl routines.
    433  */
    434 /* ARGSUSED */
    435 static int
    436 ppptioctl(struct tty *tp, u_long cmd, void *data, int flag, struct lwp *l)
    437 {
    438     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    439     int error, s;
    440 
    441     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    442 	return (EPASSTHROUGH);
    443 
    444     error = 0;
    445     switch (cmd) {
    446     case TIOCRCVFRAME:
    447     	ppprcvframe(sc,*((struct mbuf **)data));
    448 	break;
    449 
    450     case PPPIOCSASYNCMAP:
    451 	if ((error = kauth_authorize_device_tty(l->l_cred,
    452  	  KAUTH_DEVICE_TTY_PRIVSET, tp)) != 0)
    453 	    break;
    454 	sc->sc_asyncmap[0] = *(u_int *)data;
    455 	break;
    456 
    457     case PPPIOCGASYNCMAP:
    458 	*(u_int *)data = sc->sc_asyncmap[0];
    459 	break;
    460 
    461     case PPPIOCSRASYNCMAP:
    462 	if ((error = kauth_authorize_device_tty(l->l_cred,
    463 	  KAUTH_DEVICE_TTY_PRIVSET, tp)) != 0)
    464 	    break;
    465 	sc->sc_rasyncmap = *(u_int *)data;
    466 	break;
    467 
    468     case PPPIOCGRASYNCMAP:
    469 	*(u_int *)data = sc->sc_rasyncmap;
    470 	break;
    471 
    472     case PPPIOCSXASYNCMAP:
    473 	if ((error = kauth_authorize_device_tty(l->l_cred,
    474 	  KAUTH_DEVICE_TTY_PRIVSET, tp)) != 0)
    475 	    break;
    476 	s = spltty();
    477 	bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
    478 	sc->sc_asyncmap[1] = 0;		    /* mustn't escape 0x20 - 0x3f */
    479 	sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
    480 	sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
    481 	splx(s);
    482 	break;
    483 
    484     case PPPIOCGXASYNCMAP:
    485 	bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
    486 	break;
    487 
    488     default:
    489 	error = pppioctl(sc, cmd, data, flag, l);
    490 	if (error == 0 && cmd == PPPIOCSMRU)
    491 	    pppgetm(sc);
    492     }
    493 
    494     return error;
    495 }
    496 
    497 /* receive a complete ppp frame from device in synchronous
    498  * hdlc mode. caller gives up ownership of mbuf
    499  */
    500 static void
    501 ppprcvframe(struct ppp_softc *sc, struct mbuf *m)
    502 {
    503 	int len, s;
    504 	struct mbuf *n;
    505 	u_char hdr[4];
    506 	int hlen,count;
    507 
    508 	for (n=m,len=0;n != NULL;n = n->m_next)
    509 		len += n->m_len;
    510 	if (len==0) {
    511 		m_freem(m);
    512 		return;
    513 	}
    514 
    515 	/* extract PPP header from mbuf chain (1 to 4 bytes) */
    516 	for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
    517 		count = (sizeof(hdr)-hlen) < n->m_len ?
    518 				sizeof(hdr)-hlen : n->m_len;
    519 		bcopy(mtod(n,u_char*),&hdr[hlen],count);
    520 		hlen+=count;
    521 	}
    522 
    523 	s = spltty();
    524 
    525 	/* if AFCF compressed then prepend AFCF */
    526 	if (hdr[0] != PPP_ALLSTATIONS) {
    527 		if (sc->sc_flags & SC_REJ_COMP_AC) {
    528 			if (sc->sc_flags & SC_DEBUG)
    529 				printf(
    530 				    "%s: garbage received: 0x%x (need 0xFF)\n",
    531 				    sc->sc_if.if_xname, hdr[0]);
    532 				goto bail;
    533 			}
    534 		M_PREPEND(m,2,M_DONTWAIT);
    535 		if (m==NULL) {
    536 			splx(s);
    537 			return;
    538 		}
    539 		hdr[3] = hdr[1];
    540 		hdr[2] = hdr[0];
    541 		hdr[0] = PPP_ALLSTATIONS;
    542 		hdr[1] = PPP_UI;
    543 		len += 2;
    544 	}
    545 
    546 	/* if protocol field compressed, add MSB of protocol field = 0 */
    547 	if (hdr[2] & 1) {
    548 		/* a compressed protocol */
    549 		M_PREPEND(m,1,M_DONTWAIT);
    550 		if (m==NULL) {
    551 			splx(s);
    552 			return;
    553 		}
    554 		hdr[3] = hdr[2];
    555 		hdr[2] = 0;
    556 		len++;
    557 	}
    558 
    559 	/* valid LSB of protocol field has bit0 set */
    560 	if (!(hdr[3] & 1)) {
    561 		if (sc->sc_flags & SC_DEBUG)
    562 			printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
    563 				(hdr[2] << 8) + hdr[3]);
    564 			goto bail;
    565 	}
    566 
    567 	/* packet beyond configured mru? */
    568 	if (len > sc->sc_mru + PPP_HDRLEN) {
    569 		if (sc->sc_flags & SC_DEBUG)
    570 			printf("%s: packet too big\n", sc->sc_if.if_xname);
    571 		goto bail;
    572 	}
    573 
    574 	/* add expanded 4 byte header to mbuf chain */
    575 	for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
    576 		count = (sizeof(hdr)-hlen) < n->m_len ?
    577 				sizeof(hdr)-hlen : n->m_len;
    578 		bcopy(&hdr[hlen],mtod(n,u_char*),count);
    579 		hlen+=count;
    580 	}
    581 
    582 	/* if_ppp.c requires the PPP header and IP header */
    583 	/* to be contiguous */
    584 	count = len < MHLEN ? len : MHLEN;
    585 	if (m->m_len < count) {
    586 		m = m_pullup(m,count);
    587 		if (m==NULL)
    588 			goto bail;
    589 	}
    590 
    591 	sc->sc_stats.ppp_ibytes += len;
    592 
    593 	if (sc->sc_flags & SC_LOG_RAWIN)
    594 		pppdumpframe(sc,m,0);
    595 
    596 	ppppktin(sc, m, 0);
    597 	splx(s);
    598 	return;
    599 bail:
    600 	m_freem(m);
    601 	splx(s);
    602 }
    603 
    604 /*
    605  * FCS lookup table as calculated by genfcstab.
    606  */
    607 static const uint16_t fcstab[256] = {
    608 	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
    609 	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
    610 	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
    611 	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
    612 	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
    613 	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
    614 	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
    615 	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
    616 	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
    617 	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
    618 	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
    619 	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
    620 	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
    621 	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
    622 	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
    623 	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
    624 	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
    625 	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
    626 	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
    627 	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
    628 	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
    629 	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
    630 	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
    631 	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
    632 	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
    633 	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
    634 	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
    635 	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
    636 	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
    637 	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
    638 	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
    639 	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
    640 };
    641 
    642 /*
    643  * Calculate a new FCS given the current FCS and the new data.
    644  */
    645 static uint16_t
    646 pppfcs(uint16_t fcs, const uint8_t *cp, int len)
    647 {
    648     while (len--)
    649 	fcs = PPP_FCS(fcs, *cp++);
    650     return (fcs);
    651 }
    652 
    653 /* This gets called at splsoftnet from pppasyncstart at various times
    654  * when there is data ready to be sent.
    655  */
    656 static void
    657 pppsyncstart(struct ppp_softc *sc)
    658 {
    659 	struct tty *tp = (struct tty *) sc->sc_devp;
    660 	struct mbuf *m, *n;
    661 	const struct cdevsw *cdev;
    662 	int len;
    663 
    664 	for(m = sc->sc_outm;;) {
    665 		if (m == NULL) {
    666 			m = ppp_dequeue(sc);	/* get new packet */
    667 			if (m == NULL)
    668 				break;		/* no more packets */
    669 			if (sc->sc_flags & SC_DEBUG)
    670 				pppdumpframe(sc,m,1);
    671 		}
    672 		for(n=m,len=0;n!=NULL;n=n->m_next)
    673 			len += n->m_len;
    674 
    675 		/* call device driver IOCTL to transmit a frame */
    676 		cdev = cdevsw_lookup_acquire(tp->t_dev);
    677 		if (cdev == NULL ||
    678 		    (*cdev->d_ioctl)(tp->t_dev, TIOCXMTFRAME, (void *)&m,
    679 				     0, 0)) {
    680 			/* busy or error, set as current packet */
    681 			sc->sc_outm = m;
    682 			break;
    683 		}
    684 		sc->sc_outm = m = NULL;
    685 		sc->sc_stats.ppp_obytes += len;
    686 		if (cdev != NULL)
    687 			cdevsw_release(cdev);
    688 	}
    689 }
    690 
    691 /*
    692  * This gets called at splsoftnet from if_ppp.c at various times
    693  * when there is data ready to be sent.
    694  */
    695 static void
    696 pppasyncstart(struct ppp_softc *sc)
    697 {
    698     struct tty *tp = (struct tty *) sc->sc_devp;
    699     struct mbuf *m;
    700     int len;
    701     u_char *start, *stop, *cp;
    702     int n, ndone, done, idle;
    703     struct mbuf *m2;
    704 
    705     if (sc->sc_flags & SC_SYNC){
    706 	pppsyncstart(sc);
    707 	return;
    708     }
    709 
    710     mutex_spin_enter(&tty_lock);
    711 
    712     idle = 0;
    713     while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
    714 	/*
    715 	 * See if we have an existing packet partly sent.
    716 	 * If not, get a new packet and start sending it.
    717 	 */
    718 	m = sc->sc_outm;
    719 	if (m == NULL) {
    720 	    /*
    721 	     * Get another packet to be sent.
    722 	     */
    723 	    m = ppp_dequeue(sc);
    724 	    if (m == NULL) {
    725 		idle = 1;
    726 		break;
    727 	    }
    728 
    729 	    /*
    730 	     * The extra PPP_FLAG will start up a new packet, and thus
    731 	     * will flush any accumulated garbage.  We do this whenever
    732 	     * the line may have been idle for some time.
    733 	     */
    734 	    if (CCOUNT(&tp->t_outq) == 0) {
    735 		++sc->sc_stats.ppp_obytes;
    736 		(void) putc(PPP_FLAG, &tp->t_outq);
    737 	    }
    738 
    739 	    /* Calculate the FCS for the first mbuf's worth. */
    740 	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, uint8_t *), m->m_len);
    741 	}
    742 
    743 	for (;;) {
    744 	    start = mtod(m, u_char *);
    745 	    len = m->m_len;
    746 	    stop = start + len;
    747 	    while (len > 0) {
    748 		/*
    749 		 * Find out how many bytes in the string we can
    750 		 * handle without doing something special.
    751 		 */
    752 		for (cp = start; cp < stop; cp++)
    753 		    if (ESCAPE_P(*cp))
    754 			break;
    755 		n = cp - start;
    756 		if (n) {
    757 		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
    758 		    ndone = n - b_to_q(start, n, &tp->t_outq);
    759 		    len -= ndone;
    760 		    start += ndone;
    761 		    sc->sc_stats.ppp_obytes += ndone;
    762 
    763 		    if (ndone < n)
    764 			break;	/* packet doesn't fit */
    765 		}
    766 		/*
    767 		 * If there are characters left in the mbuf,
    768 		 * the first one must be special.
    769 		 * Put it out in a different form.
    770 		 */
    771 		if (len) {
    772 		    if (putc(PPP_ESCAPE, &tp->t_outq))
    773 			break;
    774 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
    775 			(void) unputc(&tp->t_outq);
    776 			break;
    777 		    }
    778 		    sc->sc_stats.ppp_obytes += 2;
    779 		    start++;
    780 		    len--;
    781 		}
    782 	    }
    783 
    784 	    /*
    785 	     * If we didn't empty this mbuf, remember where we're up to.
    786 	     * If we emptied the last mbuf, try to add the FCS and closing
    787 	     * flag, and if we can't, leave sc_outm pointing to m, but with
    788 	     * m->m_len == 0, to remind us to output the FCS and flag later.
    789 	     */
    790 	    done = len == 0;
    791 	    if (done && m->m_next == NULL) {
    792 		u_char *p, *q;
    793 		int c;
    794 		u_char endseq[8];
    795 
    796 		/*
    797 		 * We may have to escape the bytes in the FCS.
    798 		 */
    799 		p = endseq;
    800 		c = ~sc->sc_outfcs & 0xFF;
    801 		if (ESCAPE_P(c)) {
    802 		    *p++ = PPP_ESCAPE;
    803 		    *p++ = c ^ PPP_TRANS;
    804 		} else
    805 		    *p++ = c;
    806 		c = (~sc->sc_outfcs >> 8) & 0xFF;
    807 		if (ESCAPE_P(c)) {
    808 		    *p++ = PPP_ESCAPE;
    809 		    *p++ = c ^ PPP_TRANS;
    810 		} else
    811 		    *p++ = c;
    812 		*p++ = PPP_FLAG;
    813 
    814 		/*
    815 		 * Try to output the FCS and flag.  If the bytes
    816 		 * don't all fit, back out.
    817 		 */
    818 		for (q = endseq; q < p; ++q)
    819 		    if (putc(*q, &tp->t_outq)) {
    820 			done = 0;
    821 			for (; q > endseq; --q)
    822 			    unputc(&tp->t_outq);
    823 			break;
    824 		    }
    825 		if (done)
    826 		    sc->sc_stats.ppp_obytes += q - endseq;
    827 	    }
    828 
    829 	    if (!done) {
    830 		/* remember where we got to */
    831 		m->m_data = start;
    832 		m->m_len = len;
    833 		break;
    834 	    }
    835 
    836 	    /* Finished with this mbuf; free it and move on. */
    837 	    m = m2 = m_free(m);
    838 	    if (m == NULL) {
    839 		/* Finished a packet */
    840 		break;
    841 	    }
    842 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, uint8_t *), m->m_len);
    843 	}
    844 
    845 	/*
    846 	 * If m == NULL, we have finished a packet.
    847 	 * If m != NULL, we've either done as much work this time
    848 	 * as we need to, or else we've filled up the output queue.
    849 	 */
    850 	sc->sc_outm = m;
    851 	if (m)
    852 	    break;
    853     }
    854 
    855     /* Call pppstart to start output again if necessary. */
    856     pppstart(tp);
    857 
    858     /*
    859      * This timeout is needed for operation on a pseudo-tty,
    860      * because the pty code doesn't call pppstart after it has
    861      * drained the t_outq.
    862      */
    863     if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
    864 	callout_reset(&sc->sc_timo_ch, 1, ppp_timeout, sc);
    865 	sc->sc_flags |= SC_TIMEOUT;
    866     }
    867 
    868     mutex_spin_exit(&tty_lock);
    869 }
    870 
    871 /*
    872  * This gets called when a received packet is placed on
    873  * the inq, at splsoftnet.
    874  */
    875 static void
    876 pppasyncctlp(struct ppp_softc *sc)
    877 {
    878     struct tty *tp;
    879 
    880     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
    881     mutex_spin_enter(&tty_lock);
    882     tp = (struct tty *) sc->sc_devp;
    883     putc(0, &tp->t_canq);
    884     ttwakeup(tp);
    885     mutex_spin_exit(&tty_lock);
    886 }
    887 
    888 /*
    889  * Start output on async tty interface.  If the transmit queue
    890  * has drained sufficiently, arrange for pppasyncstart to be
    891  * called later at splsoftnet.
    892  * Called at spltty or higher.
    893  */
    894 static int
    895 pppstart(struct tty *tp)
    896 {
    897     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    898 
    899     /*
    900      * If there is stuff in the output queue, send it now.
    901      * We are being called in lieu of ttstart and must do what it would.
    902      */
    903     if (tp->t_oproc != NULL)
    904 	(*tp->t_oproc)(tp);
    905 
    906     /*
    907      * If the transmit queue has drained and the tty has not hung up
    908      * or been disconnected from the ppp unit, then tell if_ppp.c that
    909      * we need more output.
    910      */
    911     if ((CCOUNT(&tp->t_outq) >= PPP_LOWAT)
    912 	&& ((sc == NULL) || (sc->sc_flags & SC_TIMEOUT)))
    913 	return 0;
    914 #ifdef ALTQ
    915     /*
    916      * if ALTQ is enabled, don't invoke NETISR_PPP.
    917      * pppintr() could loop without doing anything useful
    918      * under rate-limiting.
    919      */
    920     if (ALTQ_IS_ENABLED(&sc->sc_if.if_snd))
    921 	return 0;
    922 #endif
    923     if (!((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    924 	&& sc != NULL && tp == (struct tty *) sc->sc_devp) {
    925 	ppp_restart(sc);
    926     }
    927 
    928     return 0;
    929 }
    930 
    931 /*
    932  * Timeout routine - try to start some more output.
    933  */
    934 static void
    935 ppp_timeout(void *x)
    936 {
    937     struct ppp_softc *sc = (struct ppp_softc *) x;
    938     struct tty *tp = (struct tty *) sc->sc_devp;
    939 
    940     mutex_spin_enter(&tty_lock);
    941     sc->sc_flags &= ~SC_TIMEOUT;
    942     pppstart(tp);
    943     mutex_spin_exit(&tty_lock);
    944 }
    945 
    946 /*
    947  * Allocate enough mbuf to handle current MRU.
    948  */
    949 static void
    950 pppgetm(struct ppp_softc *sc)
    951 {
    952     struct mbuf *m, **mp;
    953     int len;
    954 
    955     mp = &sc->sc_m;
    956     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
    957 	if ((m = *mp) == NULL) {
    958 	    MGETHDR(m, M_DONTWAIT, MT_DATA);
    959 	    if (m == NULL)
    960 		break;
    961 	    *mp = m;
    962 	    MCLGET(m, M_DONTWAIT);
    963 	}
    964 	len -= M_DATASIZE(m);
    965 	mp = &m->m_next;
    966     }
    967 }
    968 
    969 /*
    970  * tty interface receiver interrupt.
    971  */
    972 static const unsigned paritytab[8] = {
    973     0x96696996, 0x69969669, 0x69969669, 0x96696996,
    974     0x69969669, 0x96696996, 0x96696996, 0x69969669
    975 };
    976 
    977 static int
    978 pppinput(int c, struct tty *tp)
    979 {
    980     struct ppp_softc *sc;
    981     struct mbuf *m;
    982     int ilen, s;
    983     int result;
    984 
    985     sc = (struct ppp_softc *) tp->t_sc;
    986     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    987 	return 0;
    988 
    989     ++tk_nin;
    990     ++sc->sc_stats.ppp_ibytes;
    991 
    992     if (c & TTY_FE) {
    993 	/* framing error or overrun on this char - abort packet */
    994 	if (sc->sc_flags & SC_DEBUG)
    995 	    printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
    996 	goto flush;
    997     }
    998 
    999     c &= 0xff;
   1000 
   1001     /*
   1002      * Handle software flow control of output.
   1003      */
   1004     result = tty_try_xonxoff(tp, c);
   1005     if (result == 0) {
   1006 	    /* Character was recognized and consumed. */
   1007 	    return 0;
   1008     }
   1009     /* Character wasn't consumed, continue processing it. */
   1010 
   1011     s = spltty();
   1012     if (c & 0x80)
   1013 	sc->sc_flags |= SC_RCV_B7_1;
   1014     else
   1015 	sc->sc_flags |= SC_RCV_B7_0;
   1016     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
   1017 	sc->sc_flags |= SC_RCV_ODDP;
   1018     else
   1019 	sc->sc_flags |= SC_RCV_EVNP;
   1020     splx(s);
   1021 
   1022     ppplogchar(sc, c);
   1023 
   1024     if (c == PPP_FLAG) {
   1025 	ilen = sc->sc_ilen;
   1026 	sc->sc_ilen = 0;
   1027 
   1028 	if ((sc->sc_flags & SC_LOG_RAWIN) && sc->sc_rawin.count > 0)
   1029 	    ppplogchar(sc, -1);
   1030 
   1031 	/*
   1032 	 * If SC_ESCAPED is set, then we've seen the packet
   1033 	 * abort sequence "}~".
   1034 	 */
   1035 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
   1036 	    || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
   1037 	    s = spltty();
   1038 	    sc->sc_flags |= SC_PKTLOST;	/* note the dropped packet */
   1039 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
   1040 		if (sc->sc_flags & SC_DEBUG)
   1041 		    printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
   1042 			sc->sc_fcs);
   1043 		sc->sc_if.if_ierrors++;
   1044 		sc->sc_stats.ppp_ierrors++;
   1045 	    } else
   1046 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
   1047 	    splx(s);
   1048 	    return 0;
   1049 	}
   1050 
   1051 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
   1052 	    if (ilen) {
   1053 		if (sc->sc_flags & SC_DEBUG)
   1054 		    printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
   1055 		s = spltty();
   1056 		sc->sc_if.if_ierrors++;
   1057 		sc->sc_stats.ppp_ierrors++;
   1058 		sc->sc_flags |= SC_PKTLOST;
   1059 		splx(s);
   1060 	    }
   1061 	    return 0;
   1062 	}
   1063 
   1064 	/*
   1065 	 * Remove FCS trailer.  Somewhat painful...
   1066 	 */
   1067 	ilen -= 2;
   1068 	if (--sc->sc_mc->m_len == 0) {
   1069 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
   1070 		;
   1071 	    sc->sc_mc = m;
   1072 	}
   1073 	sc->sc_mc->m_len--;
   1074 
   1075 	/* excise this mbuf chain */
   1076 	m = sc->sc_m;
   1077 	sc->sc_m = sc->sc_mc->m_next;
   1078 	sc->sc_mc->m_next = NULL;
   1079 
   1080 	ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
   1081 	if (sc->sc_flags & SC_PKTLOST) {
   1082 	    s = spltty();
   1083 	    sc->sc_flags &= ~SC_PKTLOST;
   1084 	    splx(s);
   1085 	}
   1086 
   1087 	pppgetm(sc);
   1088 	return 0;
   1089     }
   1090 
   1091     if (sc->sc_flags & SC_FLUSH) {
   1092 	if (sc->sc_flags & SC_LOG_FLUSH)
   1093 	    ppplogchar(sc, c);
   1094 	return 0;
   1095     }
   1096 
   1097     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
   1098 	return 0;
   1099 
   1100     s = spltty();
   1101     if (sc->sc_flags & SC_ESCAPED) {
   1102 	sc->sc_flags &= ~SC_ESCAPED;
   1103 	c ^= PPP_TRANS;
   1104     } else if (c == PPP_ESCAPE) {
   1105 	sc->sc_flags |= SC_ESCAPED;
   1106 	splx(s);
   1107 	return 0;
   1108     }
   1109     splx(s);
   1110 
   1111     /*
   1112      * Initialize buffer on first octet received.
   1113      * First octet could be address or protocol (when compressing
   1114      * address/control).
   1115      * Second octet is control.
   1116      * Third octet is first or second (when compressing protocol)
   1117      * octet of protocol.
   1118      * Fourth octet is second octet of protocol.
   1119      */
   1120     if (sc->sc_ilen == 0) {
   1121 	/* reset the first input mbuf */
   1122 	if (sc->sc_m == NULL) {
   1123 	    pppgetm(sc);
   1124 	    if (sc->sc_m == NULL) {
   1125 		if (sc->sc_flags & SC_DEBUG)
   1126 		    printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
   1127 		goto flush;
   1128 	    }
   1129 	}
   1130 	m = sc->sc_m;
   1131 	m->m_len = 0;
   1132 	m->m_data = M_DATASTART(sc->sc_m);
   1133 	sc->sc_mc = m;
   1134 	sc->sc_mp = mtod(m, char *);
   1135 	sc->sc_fcs = PPP_INITFCS;
   1136 	if (c != PPP_ALLSTATIONS) {
   1137 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
   1138 		if (sc->sc_flags & SC_DEBUG)
   1139 		    printf("%s: garbage received: 0x%x (need 0xFF)\n",
   1140 		    sc->sc_if.if_xname, c);
   1141 		goto flush;
   1142 	    }
   1143 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
   1144 	    *sc->sc_mp++ = PPP_UI;
   1145 	    sc->sc_ilen += 2;
   1146 	    m->m_len += 2;
   1147 	}
   1148     }
   1149     if (sc->sc_ilen == 1 && c != PPP_UI) {
   1150 	if (sc->sc_flags & SC_DEBUG)
   1151 	    printf("%s: missing UI (0x3), got 0x%x\n",
   1152 		sc->sc_if.if_xname, c);
   1153 	goto flush;
   1154     }
   1155     if (sc->sc_ilen == 2 && (c & 1) == 1) {
   1156 	/* a compressed protocol */
   1157 	*sc->sc_mp++ = 0;
   1158 	sc->sc_ilen++;
   1159 	sc->sc_mc->m_len++;
   1160     }
   1161     if (sc->sc_ilen == 3 && (c & 1) == 0) {
   1162 	if (sc->sc_flags & SC_DEBUG)
   1163 	    printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
   1164 		(sc->sc_mp[-1] << 8) + c);
   1165 	goto flush;
   1166     }
   1167 
   1168     /* packet beyond configured mru? */
   1169     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
   1170 	if (sc->sc_flags & SC_DEBUG)
   1171 	    printf("%s: packet too big\n", sc->sc_if.if_xname);
   1172 	goto flush;
   1173     }
   1174 
   1175     /* is this mbuf full? */
   1176     m = sc->sc_mc;
   1177     if (M_TRAILINGSPACE(m) <= 0) {
   1178 	if (m->m_next == NULL) {
   1179 	    pppgetm(sc);
   1180 	    if (m->m_next == NULL) {
   1181 		if (sc->sc_flags & SC_DEBUG)
   1182 		    printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
   1183 		goto flush;
   1184 	    }
   1185 	}
   1186 	sc->sc_mc = m = m->m_next;
   1187 	m->m_len = 0;
   1188 	m->m_data = M_DATASTART(m);
   1189 	sc->sc_mp = mtod(m, char *);
   1190     }
   1191 
   1192     ++m->m_len;
   1193     *sc->sc_mp++ = c;
   1194     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
   1195     return 0;
   1196 
   1197  flush:
   1198     if (!(sc->sc_flags & SC_FLUSH)) {
   1199 	s = spltty();
   1200 	sc->sc_if.if_ierrors++;
   1201 	sc->sc_stats.ppp_ierrors++;
   1202 	sc->sc_flags |= SC_FLUSH;
   1203 	splx(s);
   1204 	if (sc->sc_flags & SC_LOG_FLUSH)
   1205 	    ppplogchar(sc, c);
   1206     }
   1207     return 0;
   1208 }
   1209 
   1210 #define MAX_DUMP_BYTES	128
   1211 
   1212 static void
   1213 ppplogchar(struct ppp_softc *sc, int c)
   1214 {
   1215     if (c >= 0) {
   1216 	sc->sc_rawin.buf[sc->sc_rawin_start++] = c;
   1217 	if (sc->sc_rawin.count < sizeof(sc->sc_rawin.buf))
   1218 	    sc->sc_rawin.count++;
   1219     }
   1220     if (sc->sc_rawin_start >= sizeof(sc->sc_rawin.buf)
   1221 	|| (c < 0 && sc->sc_rawin_start > 0)) {
   1222 	if (sc->sc_flags & (SC_LOG_FLUSH|SC_LOG_RAWIN)) {
   1223 	    printf("%s input: ", sc->sc_if.if_xname);
   1224 	    pppdumpb(sc->sc_rawin.buf, sc->sc_rawin_start);
   1225 	}
   1226 	if (c < 0)
   1227 	    sc->sc_rawin.count = 0;
   1228 	sc->sc_rawin_start = 0;
   1229     }
   1230 }
   1231 
   1232 static void
   1233 pppdumpb(u_char *b, int l)
   1234 {
   1235     char bf[3*MAX_DUMP_BYTES+4];
   1236     char *bp = bf;
   1237 
   1238     while (l--) {
   1239 	if (bp >= bf + sizeof(bf) - 3) {
   1240 	    *bp++ = '>';
   1241 	    break;
   1242 	}
   1243 	*bp++ = hexdigits[*b >> 4]; /* convert byte to ascii hex */
   1244 	*bp++ = hexdigits[*b++ & 0xf];
   1245 	*bp++ = ' ';
   1246     }
   1247 
   1248     *bp = 0;
   1249     printf("%s\n", bf);
   1250 }
   1251 
   1252 static void
   1253 pppdumpframe(struct ppp_softc *sc, struct mbuf *m, int xmit)
   1254 {
   1255 	int i,lcount,copycount,count;
   1256 	char lbuf[16];
   1257 	char *data;
   1258 
   1259 	if (m == NULL)
   1260 		return;
   1261 
   1262 	for(count=m->m_len,data=mtod(m,char*);m != NULL;) {
   1263 		/* build a line of output */
   1264 		for(lcount=0;lcount < sizeof(lbuf);lcount += copycount) {
   1265 			if (!count) {
   1266 				m = m->m_next;
   1267 				if (m == NULL)
   1268 					break;
   1269 				count = m->m_len;
   1270 				data  = mtod(m,char*);
   1271 			}
   1272 			copycount = (count > sizeof(lbuf)-lcount) ?
   1273 					sizeof(lbuf)-lcount : count;
   1274 			bcopy(data,&lbuf[lcount],copycount);
   1275 			data  += copycount;
   1276 			count -= copycount;
   1277 		}
   1278 
   1279 		/* output line (hex 1st, then ascii) */
   1280 		printf("%s %s:", sc->sc_if.if_xname,
   1281 		    xmit ? "output" : "input ");
   1282 		for(i=0;i<lcount;i++)
   1283 			printf("%02x ",(u_char)lbuf[i]);
   1284 		for(;i<sizeof(lbuf);i++)
   1285 			printf("   ");
   1286 		for(i=0;i<lcount;i++)
   1287 			printf("%c",(lbuf[i] >= 040 &&
   1288 			    lbuf[i] <= 0176) ? lbuf[i] : '.');
   1289 		printf("\n");
   1290 	}
   1291 }
   1292