Home | History | Annotate | Line # | Download | only in net
ppp_tty.c revision 1.41.10.3
      1 /*	$NetBSD: ppp_tty.c,v 1.41.10.3 2006/05/06 23:31:59 christos 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.41.10.3 2006/05/06 23:31:59 christos Exp $");
     97 
     98 #include "ppp.h"
     99 
    100 #include "opt_ppp.h"
    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 "bpfilter.h"
    129 #if NBPFILTER > 0 || defined(PPP_FILTER)
    130 #include <net/bpf.h>
    131 #endif
    132 #include <net/ppp_defs.h>
    133 #include <net/if_ppp.h>
    134 #include <net/if_pppvar.h>
    135 
    136 static int	pppopen(dev_t dev, struct tty *tp);
    137 static int	pppclose(struct tty *tp, int flag);
    138 static int	pppread(struct tty *tp, struct uio *uio, int flag);
    139 static int	pppwrite(struct tty *tp, struct uio *uio, int flag);
    140 static int	ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
    141 			  struct lwp *);
    142 static int	pppinput(int c, struct tty *tp);
    143 static int	pppstart(struct tty *tp);
    144 
    145 struct linesw ppp_disc = {	/* XXX should be static */
    146 	.l_name = "ppp",
    147 	.l_open = pppopen,
    148 	.l_close = pppclose,
    149 	.l_read = pppread,
    150 	.l_write = pppwrite,
    151 	.l_ioctl = ppptioctl,
    152 	.l_rint = pppinput,
    153 	.l_start = pppstart,
    154 	.l_modem = ttymodem,
    155 	.l_poll = ttpoll
    156 };
    157 
    158 static void	ppprcvframe(struct ppp_softc *sc, struct mbuf *m);
    159 static u_int16_t pppfcs(u_int16_t fcs, u_char *cp, int len);
    160 static void	pppsyncstart(struct ppp_softc *sc);
    161 static void	pppasyncstart(struct ppp_softc *);
    162 static void	pppasyncctlp(struct ppp_softc *);
    163 static void	pppasyncrelinq(struct ppp_softc *);
    164 static void	ppp_timeout(void *);
    165 static void	pppgetm(struct ppp_softc *sc);
    166 static void	pppdumpb(u_char *b, int l);
    167 static void	ppplogchar(struct ppp_softc *, int);
    168 static void	pppdumpframe(struct ppp_softc *sc, struct mbuf* m, int xmit);
    169 
    170 /*
    171  * Some useful mbuf macros not in mbuf.h.
    172  */
    173 #define M_IS_CLUSTER(m)	((m)->m_flags & M_EXT)
    174 
    175 #define M_DATASTART(m)	\
    176 	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
    177 	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
    178 
    179 #define M_DATASIZE(m)	\
    180 	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
    181 	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
    182 
    183 /*
    184  * Does c need to be escaped?
    185  */
    186 #define ESCAPE_P(c)	(sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
    187 
    188 /*
    189  * Procedures for using an async tty interface for PPP.
    190  */
    191 
    192 /* This is a NetBSD-1.0 or later kernel. */
    193 #define CCOUNT(q)	((q)->c_cc)
    194 
    195 #define PPP_LOWAT	100	/* Process more output when < LOWAT on queue */
    196 #define	PPP_HIWAT	400	/* Don't start a new packet if HIWAT on que */
    197 
    198 /*
    199  * Line specific open routine for async tty devices.
    200  * Attach the given tty to the first available ppp unit.
    201  * Called from device open routine or ttioctl.
    202  */
    203 /* ARGSUSED */
    204 static int
    205 pppopen(dev_t dev, struct tty *tp)
    206 {
    207     struct proc *p = curproc;		/* XXX */
    208     struct ppp_softc *sc;
    209     int error, s;
    210 
    211     if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0)
    212 	return (error);
    213 
    214     s = spltty();
    215 
    216     if (tp->t_linesw == &ppp_disc) {
    217 	sc = (struct ppp_softc *) tp->t_sc;
    218 	if (sc != NULL && sc->sc_devp == (void *) tp) {
    219 	    splx(s);
    220 	    return (0);
    221 	}
    222     }
    223 
    224     if ((sc = pppalloc(p->p_pid)) == NULL) {
    225 	splx(s);
    226 	return ENXIO;
    227     }
    228 
    229     if (sc->sc_relinq)
    230 	(*sc->sc_relinq)(sc);	/* get previous owner to relinquish the unit */
    231 
    232 #if NBPFILTER > 0
    233     /* Switch DLT to PPP-over-serial. */
    234     bpf_change_type(&sc->sc_if, DLT_PPP_SERIAL, PPP_HDRLEN);
    235 #endif
    236 
    237     sc->sc_ilen = 0;
    238     sc->sc_m = NULL;
    239     memset(sc->sc_asyncmap, 0, sizeof(sc->sc_asyncmap));
    240     sc->sc_asyncmap[0] = 0xffffffff;
    241     sc->sc_asyncmap[3] = 0x60000000;
    242     sc->sc_rasyncmap = 0;
    243     sc->sc_devp = (void *) tp;
    244     sc->sc_start = pppasyncstart;
    245     sc->sc_ctlp = pppasyncctlp;
    246     sc->sc_relinq = pppasyncrelinq;
    247     sc->sc_outm = NULL;
    248     pppgetm(sc);
    249     sc->sc_if.if_flags |= IFF_RUNNING;
    250     sc->sc_if.if_baudrate = tp->t_ospeed;
    251 
    252     tp->t_sc = (caddr_t) sc;
    253     ttyflush(tp, FREAD | FWRITE);
    254 
    255     splx(s);
    256     return (0);
    257 }
    258 
    259 /*
    260  * Line specific close routine, called from device close routine
    261  * and from ttioctl.
    262  * Detach the tty from the ppp unit.
    263  * Mimics part of ttyclose().
    264  */
    265 static int
    266 pppclose(struct tty *tp, int flag)
    267 {
    268     struct ppp_softc *sc;
    269     int s;
    270 
    271     s = spltty();
    272     ttyflush(tp, FREAD|FWRITE);
    273     ttyldisc_release(tp->t_linesw);
    274     tp->t_linesw = ttyldisc_default();
    275     sc = (struct ppp_softc *) tp->t_sc;
    276     if (sc != NULL) {
    277 	tp->t_sc = NULL;
    278 	if (tp == (struct tty *) sc->sc_devp) {
    279 	    pppasyncrelinq(sc);
    280 	    pppdealloc(sc);
    281 	}
    282     }
    283     splx(s);
    284     return 0;
    285 }
    286 
    287 /*
    288  * Relinquish the interface unit to another device.
    289  */
    290 static void
    291 pppasyncrelinq(struct ppp_softc *sc)
    292 {
    293     int s;
    294 
    295 #if NBPFILTER > 0
    296     /* Change DLT to back none. */
    297     bpf_change_type(&sc->sc_if, DLT_NULL, 0);
    298 #endif
    299 
    300     s = spltty();
    301     if (sc->sc_outm) {
    302 	m_freem(sc->sc_outm);
    303 	sc->sc_outm = NULL;
    304     }
    305     if (sc->sc_m) {
    306 	m_freem(sc->sc_m);
    307 	sc->sc_m = NULL;
    308     }
    309     if (sc->sc_flags & SC_TIMEOUT) {
    310 	callout_stop(&sc->sc_timo_ch);
    311 	sc->sc_flags &= ~SC_TIMEOUT;
    312     }
    313     splx(s);
    314 }
    315 
    316 /*
    317  * Line specific (tty) read routine.
    318  */
    319 static int
    320 pppread(struct tty *tp, struct uio *uio, int flag)
    321 {
    322     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    323     struct mbuf *m, *m0;
    324     int s;
    325     int error = 0;
    326 
    327     if (sc == NULL)
    328 	return 0;
    329     /*
    330      * Loop waiting for input, checking that nothing disasterous
    331      * happens in the meantime.
    332      */
    333     s = spltty();
    334     for (;;) {
    335 	if (tp != (struct tty *) sc->sc_devp ||
    336 	    tp->t_linesw != &ppp_disc) {
    337 	    splx(s);
    338 	    return 0;
    339 	}
    340 	if (sc->sc_inq.ifq_head != NULL)
    341 	    break;
    342 	if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
    343 	    && (tp->t_state & TS_ISOPEN)) {
    344 	    splx(s);
    345 	    return 0;		/* end of file */
    346 	}
    347 	if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
    348 	    splx(s);
    349 	    return (EWOULDBLOCK);
    350 	}
    351 	error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
    352 	if (error) {
    353 	    splx(s);
    354 	    return error;
    355 	}
    356     }
    357 
    358     /* Pull place-holder byte out of canonical queue */
    359     getc(&tp->t_canq);
    360 
    361     /* Get the packet from the input queue */
    362     IF_DEQUEUE(&sc->sc_inq, m0);
    363     splx(s);
    364 
    365     for (m = m0; m && uio->uio_resid; m = m->m_next)
    366 	if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
    367 	    break;
    368     m_freem(m0);
    369     return (error);
    370 }
    371 
    372 /*
    373  * Line specific (tty) write routine.
    374  */
    375 static int
    376 pppwrite(struct tty *tp, struct uio *uio, int flag)
    377 {
    378     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    379     struct mbuf *m, *m0;
    380     struct sockaddr dst;
    381     int len, error;
    382 
    383     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    384 	return 0;		/* wrote 0 bytes */
    385     if (tp->t_linesw != &ppp_disc)
    386 	return (EINVAL);
    387     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    388 	return EIO;
    389     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
    390 	uio->uio_resid < PPP_HDRLEN)
    391 	return (EMSGSIZE);
    392 
    393     MGETHDR(m0, M_WAIT, MT_DATA);
    394     if (m0 == NULL)
    395 	return ENOBUFS;
    396 
    397     m0->m_len = 0;
    398     m0->m_pkthdr.len = uio->uio_resid;
    399     m0->m_pkthdr.rcvif = NULL;
    400 
    401     if (uio->uio_resid >= MCLBYTES / 2)
    402 	MCLGET(m0, M_DONTWAIT);
    403 
    404     for (m = m0; uio->uio_resid;) {
    405 	len = M_TRAILINGSPACE(m);
    406 	if (len > uio->uio_resid)
    407 	    len = uio->uio_resid;
    408 	if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
    409 	    m_freem(m0);
    410 	    return (error);
    411 	}
    412 	m->m_len = len;
    413 
    414 	if (uio->uio_resid == 0)
    415 	    break;
    416 
    417 	MGET(m->m_next, M_WAIT, MT_DATA);
    418 	if (m->m_next == NULL) {
    419 	    m_freem(m0);
    420 	    return ENOBUFS;
    421 	}
    422 	m = m->m_next;
    423 	m->m_len = 0;
    424     }
    425     dst.sa_family = AF_UNSPEC;
    426     bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
    427     m_adj(m0, PPP_HDRLEN);
    428     return ((*sc->sc_if.if_output)(&sc->sc_if, m0, &dst, (struct rtentry *)0));
    429 }
    430 
    431 /*
    432  * Line specific (tty) ioctl routine.
    433  * This discipline requires that tty device drivers call
    434  * the line specific l_ioctl routine from their ioctl routines.
    435  */
    436 /* ARGSUSED */
    437 static int
    438 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct lwp *l)
    439 {
    440     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    441     int error, s;
    442     struct proc *p = l->l_proc;
    443 
    444     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    445 	return (EPASSTHROUGH);
    446 
    447     error = 0;
    448     switch (cmd) {
    449     case TIOCRCVFRAME:
    450     	ppprcvframe(sc,*((struct mbuf **)data));
    451 	break;
    452 
    453     case PPPIOCSASYNCMAP:
    454 	if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0)
    455 	    break;
    456 	sc->sc_asyncmap[0] = *(u_int *)data;
    457 	break;
    458 
    459     case PPPIOCGASYNCMAP:
    460 	*(u_int *)data = sc->sc_asyncmap[0];
    461 	break;
    462 
    463     case PPPIOCSRASYNCMAP:
    464 	if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0)
    465 	    break;
    466 	sc->sc_rasyncmap = *(u_int *)data;
    467 	break;
    468 
    469     case PPPIOCGRASYNCMAP:
    470 	*(u_int *)data = sc->sc_rasyncmap;
    471 	break;
    472 
    473     case PPPIOCSXASYNCMAP:
    474 	if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 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, p);
    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 u_int16_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 u_int16_t
    646 pppfcs(u_int16_t fcs, u_char *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(tp->t_dev);
    677 		if (cdev == NULL ||
    678 		    (*cdev->d_ioctl)(tp->t_dev, TIOCXMTFRAME, (caddr_t)&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 	}
    687 }
    688 
    689 /*
    690  * This gets called at splsoftnet from if_ppp.c at various times
    691  * when there is data ready to be sent.
    692  */
    693 static void
    694 pppasyncstart(struct ppp_softc *sc)
    695 {
    696     struct tty *tp = (struct tty *) sc->sc_devp;
    697     struct mbuf *m;
    698     int len;
    699     u_char *start, *stop, *cp;
    700     int n, ndone, done, idle;
    701     struct mbuf *m2;
    702     int s;
    703 
    704     if (sc->sc_flags & SC_SYNC){
    705 	pppsyncstart(sc);
    706 	return;
    707     }
    708 
    709     idle = 0;
    710     while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
    711 	/*
    712 	 * See if we have an existing packet partly sent.
    713 	 * If not, get a new packet and start sending it.
    714 	 */
    715 	m = sc->sc_outm;
    716 	if (m == NULL) {
    717 	    /*
    718 	     * Get another packet to be sent.
    719 	     */
    720 	    m = ppp_dequeue(sc);
    721 	    if (m == NULL) {
    722 		idle = 1;
    723 		break;
    724 	    }
    725 
    726 	    /*
    727 	     * The extra PPP_FLAG will start up a new packet, and thus
    728 	     * will flush any accumulated garbage.  We do this whenever
    729 	     * the line may have been idle for some time.
    730 	     */
    731 	    if (CCOUNT(&tp->t_outq) == 0) {
    732 		++sc->sc_stats.ppp_obytes;
    733 		(void) putc(PPP_FLAG, &tp->t_outq);
    734 	    }
    735 
    736 	    /* Calculate the FCS for the first mbuf's worth. */
    737 	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
    738 	}
    739 
    740 	for (;;) {
    741 	    start = mtod(m, u_char *);
    742 	    len = m->m_len;
    743 	    stop = start + len;
    744 	    while (len > 0) {
    745 		/*
    746 		 * Find out how many bytes in the string we can
    747 		 * handle without doing something special.
    748 		 */
    749 		for (cp = start; cp < stop; cp++)
    750 		    if (ESCAPE_P(*cp))
    751 			break;
    752 		n = cp - start;
    753 		if (n) {
    754 		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
    755 		    ndone = n - b_to_q(start, n, &tp->t_outq);
    756 		    len -= ndone;
    757 		    start += ndone;
    758 		    sc->sc_stats.ppp_obytes += ndone;
    759 
    760 		    if (ndone < n)
    761 			break;	/* packet doesn't fit */
    762 		}
    763 		/*
    764 		 * If there are characters left in the mbuf,
    765 		 * the first one must be special.
    766 		 * Put it out in a different form.
    767 		 */
    768 		if (len) {
    769 		    s = spltty();
    770 		    if (putc(PPP_ESCAPE, &tp->t_outq)) {
    771 			splx(s);
    772 			break;
    773 		    }
    774 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
    775 			(void) unputc(&tp->t_outq);
    776 			splx(s);
    777 			break;
    778 		    }
    779 		    splx(s);
    780 		    sc->sc_stats.ppp_obytes += 2;
    781 		    start++;
    782 		    len--;
    783 		}
    784 	    }
    785 
    786 	    /*
    787 	     * If we didn't empty this mbuf, remember where we're up to.
    788 	     * If we emptied the last mbuf, try to add the FCS and closing
    789 	     * flag, and if we can't, leave sc_outm pointing to m, but with
    790 	     * m->m_len == 0, to remind us to output the FCS and flag later.
    791 	     */
    792 	    done = len == 0;
    793 	    if (done && m->m_next == NULL) {
    794 		u_char *p, *q;
    795 		int c;
    796 		u_char endseq[8];
    797 
    798 		/*
    799 		 * We may have to escape the bytes in the FCS.
    800 		 */
    801 		p = endseq;
    802 		c = ~sc->sc_outfcs & 0xFF;
    803 		if (ESCAPE_P(c)) {
    804 		    *p++ = PPP_ESCAPE;
    805 		    *p++ = c ^ PPP_TRANS;
    806 		} else
    807 		    *p++ = c;
    808 		c = (~sc->sc_outfcs >> 8) & 0xFF;
    809 		if (ESCAPE_P(c)) {
    810 		    *p++ = PPP_ESCAPE;
    811 		    *p++ = c ^ PPP_TRANS;
    812 		} else
    813 		    *p++ = c;
    814 		*p++ = PPP_FLAG;
    815 
    816 		/*
    817 		 * Try to output the FCS and flag.  If the bytes
    818 		 * don't all fit, back out.
    819 		 */
    820 		s = spltty();
    821 		for (q = endseq; q < p; ++q)
    822 		    if (putc(*q, &tp->t_outq)) {
    823 			done = 0;
    824 			for (; q > endseq; --q)
    825 			    unputc(&tp->t_outq);
    826 			break;
    827 		    }
    828 		splx(s);
    829 		if (done)
    830 		    sc->sc_stats.ppp_obytes += q - endseq;
    831 	    }
    832 
    833 	    if (!done) {
    834 		/* remember where we got to */
    835 		m->m_data = start;
    836 		m->m_len = len;
    837 		break;
    838 	    }
    839 
    840 	    /* Finished with this mbuf; free it and move on. */
    841 	    MFREE(m, m2);
    842 	    m = m2;
    843 	    if (m == NULL) {
    844 		/* Finished a packet */
    845 		break;
    846 	    }
    847 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
    848 	}
    849 
    850 	/*
    851 	 * If m == NULL, we have finished a packet.
    852 	 * If m != NULL, we've either done as much work this time
    853 	 * as we need to, or else we've filled up the output queue.
    854 	 */
    855 	sc->sc_outm = m;
    856 	if (m)
    857 	    break;
    858     }
    859 
    860     /* Call pppstart to start output again if necessary. */
    861     s = spltty();
    862     pppstart(tp);
    863 
    864     /*
    865      * This timeout is needed for operation on a pseudo-tty,
    866      * because the pty code doesn't call pppstart after it has
    867      * drained the t_outq.
    868      */
    869     if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
    870 	callout_reset(&sc->sc_timo_ch, 1, ppp_timeout, sc);
    871 	sc->sc_flags |= SC_TIMEOUT;
    872     }
    873 
    874     splx(s);
    875 }
    876 
    877 /*
    878  * This gets called when a received packet is placed on
    879  * the inq, at splsoftnet.
    880  */
    881 static void
    882 pppasyncctlp(struct ppp_softc *sc)
    883 {
    884     struct tty *tp;
    885     int s;
    886 
    887     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
    888     s = spltty();
    889     tp = (struct tty *) sc->sc_devp;
    890     putc(0, &tp->t_canq);
    891     ttwakeup(tp);
    892     splx(s);
    893 }
    894 
    895 /*
    896  * Start output on async tty interface.  If the transmit queue
    897  * has drained sufficiently, arrange for pppasyncstart to be
    898  * called later at splsoftnet.
    899  * Called at spltty or higher.
    900  */
    901 static int
    902 pppstart(struct tty *tp)
    903 {
    904     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    905 
    906     /*
    907      * If there is stuff in the output queue, send it now.
    908      * We are being called in lieu of ttstart and must do what it would.
    909      */
    910     if (tp->t_oproc != NULL)
    911 	(*tp->t_oproc)(tp);
    912 
    913     /*
    914      * If the transmit queue has drained and the tty has not hung up
    915      * or been disconnected from the ppp unit, then tell if_ppp.c that
    916      * we need more output.
    917      */
    918     if ((CCOUNT(&tp->t_outq) >= PPP_LOWAT)
    919 	&& ((sc == NULL) || (sc->sc_flags & SC_TIMEOUT)))
    920 	return 0;
    921 #ifdef ALTQ
    922     /*
    923      * if ALTQ is enabled, don't invoke NETISR_PPP.
    924      * pppintr() could loop without doing anything useful
    925      * under rate-limiting.
    926      */
    927     if (ALTQ_IS_ENABLED(&sc->sc_if.if_snd))
    928 	return 0;
    929 #endif
    930     if (!((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    931 	&& sc != NULL && tp == (struct tty *) sc->sc_devp) {
    932 	ppp_restart(sc);
    933     }
    934 
    935     return 0;
    936 }
    937 
    938 /*
    939  * Timeout routine - try to start some more output.
    940  */
    941 static void
    942 ppp_timeout(void *x)
    943 {
    944     struct ppp_softc *sc = (struct ppp_softc *) x;
    945     struct tty *tp = (struct tty *) sc->sc_devp;
    946     int s;
    947 
    948     s = spltty();
    949     sc->sc_flags &= ~SC_TIMEOUT;
    950     pppstart(tp);
    951     splx(s);
    952 }
    953 
    954 /*
    955  * Allocate enough mbuf to handle current MRU.
    956  */
    957 static void
    958 pppgetm(struct ppp_softc *sc)
    959 {
    960     struct mbuf *m, **mp;
    961     int len;
    962 
    963     mp = &sc->sc_m;
    964     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
    965 	if ((m = *mp) == NULL) {
    966 	    MGETHDR(m, M_DONTWAIT, MT_DATA);
    967 	    if (m == NULL)
    968 		break;
    969 	    *mp = m;
    970 	    MCLGET(m, M_DONTWAIT);
    971 	}
    972 	len -= M_DATASIZE(m);
    973 	mp = &m->m_next;
    974     }
    975 }
    976 
    977 /*
    978  * tty interface receiver interrupt.
    979  */
    980 static const unsigned paritytab[8] = {
    981     0x96696996, 0x69969669, 0x69969669, 0x96696996,
    982     0x69969669, 0x96696996, 0x96696996, 0x69969669
    983 };
    984 
    985 static int
    986 pppinput(int c, struct tty *tp)
    987 {
    988     struct ppp_softc *sc;
    989     struct mbuf *m;
    990     const struct cdevsw *cdev;
    991     int ilen, s;
    992 
    993     sc = (struct ppp_softc *) tp->t_sc;
    994     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    995 	return 0;
    996 
    997     ++tk_nin;
    998     ++sc->sc_stats.ppp_ibytes;
    999 
   1000     if (c & TTY_FE) {
   1001 	/* framing error or overrun on this char - abort packet */
   1002 	if (sc->sc_flags & SC_DEBUG)
   1003 	    printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
   1004 	goto flush;
   1005     }
   1006 
   1007     c &= 0xff;
   1008 
   1009     /*
   1010      * Handle software flow control of output.
   1011      */
   1012     if (tp->t_iflag & IXON) {
   1013 	if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
   1014 	    if ((tp->t_state & TS_TTSTOP) == 0) {
   1015 		tp->t_state |= TS_TTSTOP;
   1016 		cdev = cdevsw_lookup(tp->t_dev);
   1017 		if (cdev != NULL)
   1018 			(*cdev->d_stop)(tp, 0);
   1019 	    }
   1020 	    return 0;
   1021 	}
   1022 	if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
   1023 	    tp->t_state &= ~TS_TTSTOP;
   1024 	    if (tp->t_oproc != NULL)
   1025 		(*tp->t_oproc)(tp);
   1026 	    return 0;
   1027 	}
   1028     }
   1029 
   1030     s = spltty();
   1031     if (c & 0x80)
   1032 	sc->sc_flags |= SC_RCV_B7_1;
   1033     else
   1034 	sc->sc_flags |= SC_RCV_B7_0;
   1035     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
   1036 	sc->sc_flags |= SC_RCV_ODDP;
   1037     else
   1038 	sc->sc_flags |= SC_RCV_EVNP;
   1039     splx(s);
   1040 
   1041     ppplogchar(sc, c);
   1042 
   1043     if (c == PPP_FLAG) {
   1044 	ilen = sc->sc_ilen;
   1045 	sc->sc_ilen = 0;
   1046 
   1047 	if ((sc->sc_flags & SC_LOG_RAWIN) && sc->sc_rawin.count > 0)
   1048 	    ppplogchar(sc, -1);
   1049 
   1050 	/*
   1051 	 * If SC_ESCAPED is set, then we've seen the packet
   1052 	 * abort sequence "}~".
   1053 	 */
   1054 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
   1055 	    || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
   1056 	    s = spltty();
   1057 	    sc->sc_flags |= SC_PKTLOST;	/* note the dropped packet */
   1058 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
   1059 		if (sc->sc_flags & SC_DEBUG)
   1060 		    printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
   1061 			sc->sc_fcs);
   1062 		sc->sc_if.if_ierrors++;
   1063 		sc->sc_stats.ppp_ierrors++;
   1064 	    } else
   1065 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
   1066 	    splx(s);
   1067 	    return 0;
   1068 	}
   1069 
   1070 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
   1071 	    if (ilen) {
   1072 		if (sc->sc_flags & SC_DEBUG)
   1073 		    printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
   1074 		s = spltty();
   1075 		sc->sc_if.if_ierrors++;
   1076 		sc->sc_stats.ppp_ierrors++;
   1077 		sc->sc_flags |= SC_PKTLOST;
   1078 		splx(s);
   1079 	    }
   1080 	    return 0;
   1081 	}
   1082 
   1083 	/*
   1084 	 * Remove FCS trailer.  Somewhat painful...
   1085 	 */
   1086 	ilen -= 2;
   1087 	if (--sc->sc_mc->m_len == 0) {
   1088 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
   1089 		;
   1090 	    sc->sc_mc = m;
   1091 	}
   1092 	sc->sc_mc->m_len--;
   1093 
   1094 	/* excise this mbuf chain */
   1095 	m = sc->sc_m;
   1096 	sc->sc_m = sc->sc_mc->m_next;
   1097 	sc->sc_mc->m_next = NULL;
   1098 
   1099 	ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
   1100 	if (sc->sc_flags & SC_PKTLOST) {
   1101 	    s = spltty();
   1102 	    sc->sc_flags &= ~SC_PKTLOST;
   1103 	    splx(s);
   1104 	}
   1105 
   1106 	pppgetm(sc);
   1107 	return 0;
   1108     }
   1109 
   1110     if (sc->sc_flags & SC_FLUSH) {
   1111 	if (sc->sc_flags & SC_LOG_FLUSH)
   1112 	    ppplogchar(sc, c);
   1113 	return 0;
   1114     }
   1115 
   1116     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
   1117 	return 0;
   1118 
   1119     s = spltty();
   1120     if (sc->sc_flags & SC_ESCAPED) {
   1121 	sc->sc_flags &= ~SC_ESCAPED;
   1122 	c ^= PPP_TRANS;
   1123     } else if (c == PPP_ESCAPE) {
   1124 	sc->sc_flags |= SC_ESCAPED;
   1125 	splx(s);
   1126 	return 0;
   1127     }
   1128     splx(s);
   1129 
   1130     /*
   1131      * Initialize buffer on first octet received.
   1132      * First octet could be address or protocol (when compressing
   1133      * address/control).
   1134      * Second octet is control.
   1135      * Third octet is first or second (when compressing protocol)
   1136      * octet of protocol.
   1137      * Fourth octet is second octet of protocol.
   1138      */
   1139     if (sc->sc_ilen == 0) {
   1140 	/* reset the first input mbuf */
   1141 	if (sc->sc_m == NULL) {
   1142 	    pppgetm(sc);
   1143 	    if (sc->sc_m == NULL) {
   1144 		if (sc->sc_flags & SC_DEBUG)
   1145 		    printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
   1146 		goto flush;
   1147 	    }
   1148 	}
   1149 	m = sc->sc_m;
   1150 	m->m_len = 0;
   1151 	m->m_data = M_DATASTART(sc->sc_m);
   1152 	sc->sc_mc = m;
   1153 	sc->sc_mp = mtod(m, char *);
   1154 	sc->sc_fcs = PPP_INITFCS;
   1155 	if (c != PPP_ALLSTATIONS) {
   1156 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
   1157 		if (sc->sc_flags & SC_DEBUG)
   1158 		    printf("%s: garbage received: 0x%x (need 0xFF)\n",
   1159 		    sc->sc_if.if_xname, c);
   1160 		goto flush;
   1161 	    }
   1162 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
   1163 	    *sc->sc_mp++ = PPP_UI;
   1164 	    sc->sc_ilen += 2;
   1165 	    m->m_len += 2;
   1166 	}
   1167     }
   1168     if (sc->sc_ilen == 1 && c != PPP_UI) {
   1169 	if (sc->sc_flags & SC_DEBUG)
   1170 	    printf("%s: missing UI (0x3), got 0x%x\n",
   1171 		sc->sc_if.if_xname, c);
   1172 	goto flush;
   1173     }
   1174     if (sc->sc_ilen == 2 && (c & 1) == 1) {
   1175 	/* a compressed protocol */
   1176 	*sc->sc_mp++ = 0;
   1177 	sc->sc_ilen++;
   1178 	sc->sc_mc->m_len++;
   1179     }
   1180     if (sc->sc_ilen == 3 && (c & 1) == 0) {
   1181 	if (sc->sc_flags & SC_DEBUG)
   1182 	    printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
   1183 		(sc->sc_mp[-1] << 8) + c);
   1184 	goto flush;
   1185     }
   1186 
   1187     /* packet beyond configured mru? */
   1188     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
   1189 	if (sc->sc_flags & SC_DEBUG)
   1190 	    printf("%s: packet too big\n", sc->sc_if.if_xname);
   1191 	goto flush;
   1192     }
   1193 
   1194     /* is this mbuf full? */
   1195     m = sc->sc_mc;
   1196     if (M_TRAILINGSPACE(m) <= 0) {
   1197 	if (m->m_next == NULL) {
   1198 	    pppgetm(sc);
   1199 	    if (m->m_next == NULL) {
   1200 		if (sc->sc_flags & SC_DEBUG)
   1201 		    printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
   1202 		goto flush;
   1203 	    }
   1204 	}
   1205 	sc->sc_mc = m = m->m_next;
   1206 	m->m_len = 0;
   1207 	m->m_data = M_DATASTART(m);
   1208 	sc->sc_mp = mtod(m, char *);
   1209     }
   1210 
   1211     ++m->m_len;
   1212     *sc->sc_mp++ = c;
   1213     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
   1214     return 0;
   1215 
   1216  flush:
   1217     if (!(sc->sc_flags & SC_FLUSH)) {
   1218 	s = spltty();
   1219 	sc->sc_if.if_ierrors++;
   1220 	sc->sc_stats.ppp_ierrors++;
   1221 	sc->sc_flags |= SC_FLUSH;
   1222 	splx(s);
   1223 	if (sc->sc_flags & SC_LOG_FLUSH)
   1224 	    ppplogchar(sc, c);
   1225     }
   1226     return 0;
   1227 }
   1228 
   1229 #define MAX_DUMP_BYTES	128
   1230 
   1231 static void
   1232 ppplogchar(struct ppp_softc *sc, int c)
   1233 {
   1234     if (c >= 0) {
   1235 	sc->sc_rawin.buf[sc->sc_rawin_start++] = c;
   1236 	if (sc->sc_rawin.count < sizeof(sc->sc_rawin.buf))
   1237 	    sc->sc_rawin.count++;
   1238     }
   1239     if (sc->sc_rawin_start >= sizeof(sc->sc_rawin.buf)
   1240 	|| (c < 0 && sc->sc_rawin_start > 0)) {
   1241 	if (sc->sc_flags & (SC_LOG_FLUSH|SC_LOG_RAWIN)) {
   1242 	    printf("%s input: ", sc->sc_if.if_xname);
   1243 	    pppdumpb(sc->sc_rawin.buf, sc->sc_rawin_start);
   1244 	}
   1245 	if (c < 0)
   1246 	    sc->sc_rawin.count = 0;
   1247 	sc->sc_rawin_start = 0;
   1248     }
   1249 }
   1250 
   1251 static void
   1252 pppdumpb(u_char *b, int l)
   1253 {
   1254     char bf[3*MAX_DUMP_BYTES+4];
   1255     char *bp = bf;
   1256 
   1257     while (l--) {
   1258 	if (bp >= bf + sizeof(bf) - 3) {
   1259 	    *bp++ = '>';
   1260 	    break;
   1261 	}
   1262 	*bp++ = hexdigits[*b >> 4]; /* convert byte to ascii hex */
   1263 	*bp++ = hexdigits[*b++ & 0xf];
   1264 	*bp++ = ' ';
   1265     }
   1266 
   1267     *bp = 0;
   1268     printf("%s\n", bf);
   1269 }
   1270 
   1271 static void
   1272 pppdumpframe(struct ppp_softc *sc, struct mbuf *m, int xmit)
   1273 {
   1274 	int i,lcount,copycount,count;
   1275 	char lbuf[16];
   1276 	char *data;
   1277 
   1278 	if (m == NULL)
   1279 		return;
   1280 
   1281 	for(count=m->m_len,data=mtod(m,char*);m != NULL;) {
   1282 		/* build a line of output */
   1283 		for(lcount=0;lcount < sizeof(lbuf);lcount += copycount) {
   1284 			if (!count) {
   1285 				m = m->m_next;
   1286 				if (m == NULL)
   1287 					break;
   1288 				count = m->m_len;
   1289 				data  = mtod(m,char*);
   1290 			}
   1291 			copycount = (count > sizeof(lbuf)-lcount) ?
   1292 					sizeof(lbuf)-lcount : count;
   1293 			bcopy(data,&lbuf[lcount],copycount);
   1294 			data  += copycount;
   1295 			count -= copycount;
   1296 		}
   1297 
   1298 		/* output line (hex 1st, then ascii) */
   1299 		printf("%s %s:", sc->sc_if.if_xname,
   1300 		    xmit ? "output" : "input ");
   1301 		for(i=0;i<lcount;i++)
   1302 			printf("%02x ",(u_char)lbuf[i]);
   1303 		for(;i<sizeof(lbuf);i++)
   1304 			printf("   ");
   1305 		for(i=0;i<lcount;i++)
   1306 			printf("%c",(lbuf[i] >= 040 &&
   1307 			    lbuf[i] <= 0176) ? lbuf[i] : '.');
   1308 		printf("\n");
   1309 	}
   1310 }
   1311