Home | History | Annotate | Line # | Download | only in net
ppp_tty.c revision 1.45
      1 /*	$NetBSD: ppp_tty.c,v 1.45 2006/11/16 01:33:40 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.45 2006/11/16 01:33:40 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 lwp *l = curlwp;		/* XXX */
    208     struct ppp_softc *sc;
    209     int error, s;
    210 
    211     if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
    212 	&l->l_acflag)) != 0)
    213 	return (error);
    214 
    215     s = spltty();
    216 
    217     if (tp->t_linesw == &ppp_disc) {
    218 	sc = (struct ppp_softc *) tp->t_sc;
    219 	if (sc != NULL && sc->sc_devp == (void *) tp) {
    220 	    splx(s);
    221 	    return (0);
    222 	}
    223     }
    224 
    225     if ((sc = pppalloc(l->l_proc->p_pid)) == NULL) {
    226 	splx(s);
    227 	return ENXIO;
    228     }
    229 
    230     if (sc->sc_relinq)
    231 	(*sc->sc_relinq)(sc);	/* get previous owner to relinquish the unit */
    232 
    233 #if NBPFILTER > 0
    234     /* Switch DLT to PPP-over-serial. */
    235     bpf_change_type(&sc->sc_if, DLT_PPP_SERIAL, PPP_HDRLEN);
    236 #endif
    237 
    238     sc->sc_ilen = 0;
    239     sc->sc_m = NULL;
    240     memset(sc->sc_asyncmap, 0, sizeof(sc->sc_asyncmap));
    241     sc->sc_asyncmap[0] = 0xffffffff;
    242     sc->sc_asyncmap[3] = 0x60000000;
    243     sc->sc_rasyncmap = 0;
    244     sc->sc_devp = (void *) tp;
    245     sc->sc_start = pppasyncstart;
    246     sc->sc_ctlp = pppasyncctlp;
    247     sc->sc_relinq = pppasyncrelinq;
    248     sc->sc_outm = NULL;
    249     pppgetm(sc);
    250     sc->sc_if.if_flags |= IFF_RUNNING;
    251     sc->sc_if.if_baudrate = tp->t_ospeed;
    252 
    253     tp->t_sc = (caddr_t) sc;
    254     ttyflush(tp, FREAD | FWRITE);
    255 
    256     splx(s);
    257     return (0);
    258 }
    259 
    260 /*
    261  * Line specific close routine, called from device close routine
    262  * and from ttioctl.
    263  * Detach the tty from the ppp unit.
    264  * Mimics part of ttyclose().
    265  */
    266 static int
    267 pppclose(struct tty *tp, int flag)
    268 {
    269     struct ppp_softc *sc;
    270     int s;
    271 
    272     s = spltty();
    273     ttyflush(tp, FREAD|FWRITE);
    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 #if NBPFILTER > 0
    297     /* Change DLT to back none. */
    298     bpf_change_type(&sc->sc_if, DLT_NULL, 0);
    299 #endif
    300 
    301     s = spltty();
    302     if (sc->sc_outm) {
    303 	m_freem(sc->sc_outm);
    304 	sc->sc_outm = NULL;
    305     }
    306     if (sc->sc_m) {
    307 	m_freem(sc->sc_m);
    308 	sc->sc_m = NULL;
    309     }
    310     if (sc->sc_flags & SC_TIMEOUT) {
    311 	callout_stop(&sc->sc_timo_ch);
    312 	sc->sc_flags &= ~SC_TIMEOUT;
    313     }
    314     splx(s);
    315 }
    316 
    317 /*
    318  * Line specific (tty) read routine.
    319  */
    320 static int
    321 pppread(struct tty *tp, struct uio *uio, int flag)
    322 {
    323     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    324     struct mbuf *m, *m0;
    325     int s;
    326     int error = 0;
    327 
    328     if (sc == NULL)
    329 	return 0;
    330     /*
    331      * Loop waiting for input, checking that nothing disasterous
    332      * happens in the meantime.
    333      */
    334     s = spltty();
    335     for (;;) {
    336 	if (tp != (struct tty *) sc->sc_devp ||
    337 	    tp->t_linesw != &ppp_disc) {
    338 	    splx(s);
    339 	    return 0;
    340 	}
    341 	if (sc->sc_inq.ifq_head != NULL)
    342 	    break;
    343 	if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
    344 	    && (tp->t_state & TS_ISOPEN)) {
    345 	    splx(s);
    346 	    return 0;		/* end of file */
    347 	}
    348 	if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
    349 	    splx(s);
    350 	    return (EWOULDBLOCK);
    351 	}
    352 	error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
    353 	if (error) {
    354 	    splx(s);
    355 	    return error;
    356 	}
    357     }
    358 
    359     /* Pull place-holder byte out of canonical queue */
    360     getc(&tp->t_canq);
    361 
    362     /* Get the packet from the input queue */
    363     IF_DEQUEUE(&sc->sc_inq, m0);
    364     splx(s);
    365 
    366     for (m = m0; m && uio->uio_resid; m = m->m_next)
    367 	if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
    368 	    break;
    369     m_freem(m0);
    370     return (error);
    371 }
    372 
    373 /*
    374  * Line specific (tty) write routine.
    375  */
    376 static int
    377 pppwrite(struct tty *tp, struct uio *uio, int flag)
    378 {
    379     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    380     struct mbuf *m, *m0;
    381     struct sockaddr dst;
    382     int len, error;
    383 
    384     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    385 	return 0;		/* wrote 0 bytes */
    386     if (tp->t_linesw != &ppp_disc)
    387 	return (EINVAL);
    388     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    389 	return EIO;
    390     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
    391 	uio->uio_resid < PPP_HDRLEN)
    392 	return (EMSGSIZE);
    393 
    394     MGETHDR(m0, M_WAIT, MT_DATA);
    395     if (m0 == NULL)
    396 	return ENOBUFS;
    397 
    398     m0->m_len = 0;
    399     m0->m_pkthdr.len = uio->uio_resid;
    400     m0->m_pkthdr.rcvif = NULL;
    401 
    402     if (uio->uio_resid >= MCLBYTES / 2)
    403 	MCLGET(m0, M_DONTWAIT);
    404 
    405     for (m = m0; uio->uio_resid;) {
    406 	len = M_TRAILINGSPACE(m);
    407 	if (len > uio->uio_resid)
    408 	    len = uio->uio_resid;
    409 	if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
    410 	    m_freem(m0);
    411 	    return (error);
    412 	}
    413 	m->m_len = len;
    414 
    415 	if (uio->uio_resid == 0)
    416 	    break;
    417 
    418 	MGET(m->m_next, M_WAIT, MT_DATA);
    419 	if (m->m_next == NULL) {
    420 	    m_freem(m0);
    421 	    return ENOBUFS;
    422 	}
    423 	m = m->m_next;
    424 	m->m_len = 0;
    425     }
    426     dst.sa_family = AF_UNSPEC;
    427     bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
    428     m_adj(m0, PPP_HDRLEN);
    429     return ((*sc->sc_if.if_output)(&sc->sc_if, m0, &dst, (struct rtentry *)0));
    430 }
    431 
    432 /*
    433  * Line specific (tty) ioctl routine.
    434  * This discipline requires that tty device drivers call
    435  * the line specific l_ioctl routine from their ioctl routines.
    436  */
    437 /* ARGSUSED */
    438 static int
    439 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct lwp *l)
    440 {
    441     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    442     int error, s;
    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(l->l_cred,
    455  	  KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0)
    456 	    break;
    457 	sc->sc_asyncmap[0] = *(u_int *)data;
    458 	break;
    459 
    460     case PPPIOCGASYNCMAP:
    461 	*(u_int *)data = sc->sc_asyncmap[0];
    462 	break;
    463 
    464     case PPPIOCSRASYNCMAP:
    465 	if ((error = kauth_authorize_generic(l->l_cred,
    466 	  KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0)
    467 	    break;
    468 	sc->sc_rasyncmap = *(u_int *)data;
    469 	break;
    470 
    471     case PPPIOCGRASYNCMAP:
    472 	*(u_int *)data = sc->sc_rasyncmap;
    473 	break;
    474 
    475     case PPPIOCSXASYNCMAP:
    476 	if ((error = kauth_authorize_generic(l->l_cred,
    477 	  KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0)
    478 	    break;
    479 	s = spltty();
    480 	bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
    481 	sc->sc_asyncmap[1] = 0;		    /* mustn't escape 0x20 - 0x3f */
    482 	sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
    483 	sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
    484 	splx(s);
    485 	break;
    486 
    487     case PPPIOCGXASYNCMAP:
    488 	bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
    489 	break;
    490 
    491     default:
    492 	error = pppioctl(sc, cmd, data, flag, l);
    493 	if (error == 0 && cmd == PPPIOCSMRU)
    494 	    pppgetm(sc);
    495     }
    496 
    497     return error;
    498 }
    499 
    500 /* receive a complete ppp frame from device in synchronous
    501  * hdlc mode. caller gives up ownership of mbuf
    502  */
    503 static void
    504 ppprcvframe(struct ppp_softc *sc, struct mbuf *m)
    505 {
    506 	int len, s;
    507 	struct mbuf *n;
    508 	u_char hdr[4];
    509 	int hlen,count;
    510 
    511 	for (n=m,len=0;n != NULL;n = n->m_next)
    512 		len += n->m_len;
    513 	if (len==0) {
    514 		m_freem(m);
    515 		return;
    516 	}
    517 
    518 	/* extract PPP header from mbuf chain (1 to 4 bytes) */
    519 	for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
    520 		count = (sizeof(hdr)-hlen) < n->m_len ?
    521 				sizeof(hdr)-hlen : n->m_len;
    522 		bcopy(mtod(n,u_char*),&hdr[hlen],count);
    523 		hlen+=count;
    524 	}
    525 
    526 	s = spltty();
    527 
    528 	/* if AFCF compressed then prepend AFCF */
    529 	if (hdr[0] != PPP_ALLSTATIONS) {
    530 		if (sc->sc_flags & SC_REJ_COMP_AC) {
    531 			if (sc->sc_flags & SC_DEBUG)
    532 				printf(
    533 				    "%s: garbage received: 0x%x (need 0xFF)\n",
    534 				    sc->sc_if.if_xname, hdr[0]);
    535 				goto bail;
    536 			}
    537 		M_PREPEND(m,2,M_DONTWAIT);
    538 		if (m==NULL) {
    539 			splx(s);
    540 			return;
    541 		}
    542 		hdr[3] = hdr[1];
    543 		hdr[2] = hdr[0];
    544 		hdr[0] = PPP_ALLSTATIONS;
    545 		hdr[1] = PPP_UI;
    546 		len += 2;
    547 	}
    548 
    549 	/* if protocol field compressed, add MSB of protocol field = 0 */
    550 	if (hdr[2] & 1) {
    551 		/* a compressed protocol */
    552 		M_PREPEND(m,1,M_DONTWAIT);
    553 		if (m==NULL) {
    554 			splx(s);
    555 			return;
    556 		}
    557 		hdr[3] = hdr[2];
    558 		hdr[2] = 0;
    559 		len++;
    560 	}
    561 
    562 	/* valid LSB of protocol field has bit0 set */
    563 	if (!(hdr[3] & 1)) {
    564 		if (sc->sc_flags & SC_DEBUG)
    565 			printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
    566 				(hdr[2] << 8) + hdr[3]);
    567 			goto bail;
    568 	}
    569 
    570 	/* packet beyond configured mru? */
    571 	if (len > sc->sc_mru + PPP_HDRLEN) {
    572 		if (sc->sc_flags & SC_DEBUG)
    573 			printf("%s: packet too big\n", sc->sc_if.if_xname);
    574 		goto bail;
    575 	}
    576 
    577 	/* add expanded 4 byte header to mbuf chain */
    578 	for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
    579 		count = (sizeof(hdr)-hlen) < n->m_len ?
    580 				sizeof(hdr)-hlen : n->m_len;
    581 		bcopy(&hdr[hlen],mtod(n,u_char*),count);
    582 		hlen+=count;
    583 	}
    584 
    585 	/* if_ppp.c requires the PPP header and IP header */
    586 	/* to be contiguous */
    587 	count = len < MHLEN ? len : MHLEN;
    588 	if (m->m_len < count) {
    589 		m = m_pullup(m,count);
    590 		if (m==NULL)
    591 			goto bail;
    592 	}
    593 
    594 	sc->sc_stats.ppp_ibytes += len;
    595 
    596 	if (sc->sc_flags & SC_LOG_RAWIN)
    597 		pppdumpframe(sc,m,0);
    598 
    599 	ppppktin(sc, m, 0);
    600 	splx(s);
    601 	return;
    602 bail:
    603 	m_freem(m);
    604 	splx(s);
    605 }
    606 
    607 /*
    608  * FCS lookup table as calculated by genfcstab.
    609  */
    610 static const u_int16_t fcstab[256] = {
    611 	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
    612 	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
    613 	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
    614 	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
    615 	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
    616 	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
    617 	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
    618 	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
    619 	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
    620 	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
    621 	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
    622 	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
    623 	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
    624 	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
    625 	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
    626 	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
    627 	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
    628 	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
    629 	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
    630 	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
    631 	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
    632 	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
    633 	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
    634 	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
    635 	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
    636 	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
    637 	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
    638 	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
    639 	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
    640 	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
    641 	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
    642 	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
    643 };
    644 
    645 /*
    646  * Calculate a new FCS given the current FCS and the new data.
    647  */
    648 static u_int16_t
    649 pppfcs(u_int16_t fcs, u_char *cp, int len)
    650 {
    651     while (len--)
    652 	fcs = PPP_FCS(fcs, *cp++);
    653     return (fcs);
    654 }
    655 
    656 /* This gets called at splsoftnet from pppasyncstart at various times
    657  * when there is data ready to be sent.
    658  */
    659 static void
    660 pppsyncstart(struct ppp_softc *sc)
    661 {
    662 	struct tty *tp = (struct tty *) sc->sc_devp;
    663 	struct mbuf *m, *n;
    664 	const struct cdevsw *cdev;
    665 	int len;
    666 
    667 	for(m = sc->sc_outm;;) {
    668 		if (m == NULL) {
    669 			m = ppp_dequeue(sc);	/* get new packet */
    670 			if (m == NULL)
    671 				break;		/* no more packets */
    672 			if (sc->sc_flags & SC_DEBUG)
    673 				pppdumpframe(sc,m,1);
    674 		}
    675 		for(n=m,len=0;n!=NULL;n=n->m_next)
    676 			len += n->m_len;
    677 
    678 		/* call device driver IOCTL to transmit a frame */
    679 		cdev = cdevsw_lookup(tp->t_dev);
    680 		if (cdev == NULL ||
    681 		    (*cdev->d_ioctl)(tp->t_dev, TIOCXMTFRAME, (caddr_t)&m,
    682 				     0, 0)) {
    683 			/* busy or error, set as current packet */
    684 			sc->sc_outm = m;
    685 			break;
    686 		}
    687 		sc->sc_outm = m = NULL;
    688 		sc->sc_stats.ppp_obytes += len;
    689 	}
    690 }
    691 
    692 /*
    693  * This gets called at splsoftnet from if_ppp.c at various times
    694  * when there is data ready to be sent.
    695  */
    696 static void
    697 pppasyncstart(struct ppp_softc *sc)
    698 {
    699     struct tty *tp = (struct tty *) sc->sc_devp;
    700     struct mbuf *m;
    701     int len;
    702     u_char *start, *stop, *cp;
    703     int n, ndone, done, idle;
    704     struct mbuf *m2;
    705     int s;
    706 
    707     if (sc->sc_flags & SC_SYNC){
    708 	pppsyncstart(sc);
    709 	return;
    710     }
    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, u_char *), 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 		    s = spltty();
    773 		    if (putc(PPP_ESCAPE, &tp->t_outq)) {
    774 			splx(s);
    775 			break;
    776 		    }
    777 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
    778 			(void) unputc(&tp->t_outq);
    779 			splx(s);
    780 			break;
    781 		    }
    782 		    splx(s);
    783 		    sc->sc_stats.ppp_obytes += 2;
    784 		    start++;
    785 		    len--;
    786 		}
    787 	    }
    788 
    789 	    /*
    790 	     * If we didn't empty this mbuf, remember where we're up to.
    791 	     * If we emptied the last mbuf, try to add the FCS and closing
    792 	     * flag, and if we can't, leave sc_outm pointing to m, but with
    793 	     * m->m_len == 0, to remind us to output the FCS and flag later.
    794 	     */
    795 	    done = len == 0;
    796 	    if (done && m->m_next == NULL) {
    797 		u_char *p, *q;
    798 		int c;
    799 		u_char endseq[8];
    800 
    801 		/*
    802 		 * We may have to escape the bytes in the FCS.
    803 		 */
    804 		p = endseq;
    805 		c = ~sc->sc_outfcs & 0xFF;
    806 		if (ESCAPE_P(c)) {
    807 		    *p++ = PPP_ESCAPE;
    808 		    *p++ = c ^ PPP_TRANS;
    809 		} else
    810 		    *p++ = c;
    811 		c = (~sc->sc_outfcs >> 8) & 0xFF;
    812 		if (ESCAPE_P(c)) {
    813 		    *p++ = PPP_ESCAPE;
    814 		    *p++ = c ^ PPP_TRANS;
    815 		} else
    816 		    *p++ = c;
    817 		*p++ = PPP_FLAG;
    818 
    819 		/*
    820 		 * Try to output the FCS and flag.  If the bytes
    821 		 * don't all fit, back out.
    822 		 */
    823 		s = spltty();
    824 		for (q = endseq; q < p; ++q)
    825 		    if (putc(*q, &tp->t_outq)) {
    826 			done = 0;
    827 			for (; q > endseq; --q)
    828 			    unputc(&tp->t_outq);
    829 			break;
    830 		    }
    831 		splx(s);
    832 		if (done)
    833 		    sc->sc_stats.ppp_obytes += q - endseq;
    834 	    }
    835 
    836 	    if (!done) {
    837 		/* remember where we got to */
    838 		m->m_data = start;
    839 		m->m_len = len;
    840 		break;
    841 	    }
    842 
    843 	    /* Finished with this mbuf; free it and move on. */
    844 	    MFREE(m, m2);
    845 	    m = m2;
    846 	    if (m == NULL) {
    847 		/* Finished a packet */
    848 		break;
    849 	    }
    850 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
    851 	}
    852 
    853 	/*
    854 	 * If m == NULL, we have finished a packet.
    855 	 * If m != NULL, we've either done as much work this time
    856 	 * as we need to, or else we've filled up the output queue.
    857 	 */
    858 	sc->sc_outm = m;
    859 	if (m)
    860 	    break;
    861     }
    862 
    863     /* Call pppstart to start output again if necessary. */
    864     s = spltty();
    865     pppstart(tp);
    866 
    867     /*
    868      * This timeout is needed for operation on a pseudo-tty,
    869      * because the pty code doesn't call pppstart after it has
    870      * drained the t_outq.
    871      */
    872     if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
    873 	callout_reset(&sc->sc_timo_ch, 1, ppp_timeout, sc);
    874 	sc->sc_flags |= SC_TIMEOUT;
    875     }
    876 
    877     splx(s);
    878 }
    879 
    880 /*
    881  * This gets called when a received packet is placed on
    882  * the inq, at splsoftnet.
    883  */
    884 static void
    885 pppasyncctlp(struct ppp_softc *sc)
    886 {
    887     struct tty *tp;
    888     int s;
    889 
    890     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
    891     s = spltty();
    892     tp = (struct tty *) sc->sc_devp;
    893     putc(0, &tp->t_canq);
    894     ttwakeup(tp);
    895     splx(s);
    896 }
    897 
    898 /*
    899  * Start output on async tty interface.  If the transmit queue
    900  * has drained sufficiently, arrange for pppasyncstart to be
    901  * called later at splsoftnet.
    902  * Called at spltty or higher.
    903  */
    904 static int
    905 pppstart(struct tty *tp)
    906 {
    907     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    908 
    909     /*
    910      * If there is stuff in the output queue, send it now.
    911      * We are being called in lieu of ttstart and must do what it would.
    912      */
    913     if (tp->t_oproc != NULL)
    914 	(*tp->t_oproc)(tp);
    915 
    916     /*
    917      * If the transmit queue has drained and the tty has not hung up
    918      * or been disconnected from the ppp unit, then tell if_ppp.c that
    919      * we need more output.
    920      */
    921     if ((CCOUNT(&tp->t_outq) >= PPP_LOWAT)
    922 	&& ((sc == NULL) || (sc->sc_flags & SC_TIMEOUT)))
    923 	return 0;
    924 #ifdef ALTQ
    925     /*
    926      * if ALTQ is enabled, don't invoke NETISR_PPP.
    927      * pppintr() could loop without doing anything useful
    928      * under rate-limiting.
    929      */
    930     if (ALTQ_IS_ENABLED(&sc->sc_if.if_snd))
    931 	return 0;
    932 #endif
    933     if (!((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    934 	&& sc != NULL && tp == (struct tty *) sc->sc_devp) {
    935 	ppp_restart(sc);
    936     }
    937 
    938     return 0;
    939 }
    940 
    941 /*
    942  * Timeout routine - try to start some more output.
    943  */
    944 static void
    945 ppp_timeout(void *x)
    946 {
    947     struct ppp_softc *sc = (struct ppp_softc *) x;
    948     struct tty *tp = (struct tty *) sc->sc_devp;
    949     int s;
    950 
    951     s = spltty();
    952     sc->sc_flags &= ~SC_TIMEOUT;
    953     pppstart(tp);
    954     splx(s);
    955 }
    956 
    957 /*
    958  * Allocate enough mbuf to handle current MRU.
    959  */
    960 static void
    961 pppgetm(struct ppp_softc *sc)
    962 {
    963     struct mbuf *m, **mp;
    964     int len;
    965 
    966     mp = &sc->sc_m;
    967     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
    968 	if ((m = *mp) == NULL) {
    969 	    MGETHDR(m, M_DONTWAIT, MT_DATA);
    970 	    if (m == NULL)
    971 		break;
    972 	    *mp = m;
    973 	    MCLGET(m, M_DONTWAIT);
    974 	}
    975 	len -= M_DATASIZE(m);
    976 	mp = &m->m_next;
    977     }
    978 }
    979 
    980 /*
    981  * tty interface receiver interrupt.
    982  */
    983 static const unsigned paritytab[8] = {
    984     0x96696996, 0x69969669, 0x69969669, 0x96696996,
    985     0x69969669, 0x96696996, 0x96696996, 0x69969669
    986 };
    987 
    988 static int
    989 pppinput(int c, struct tty *tp)
    990 {
    991     struct ppp_softc *sc;
    992     struct mbuf *m;
    993     const struct cdevsw *cdev;
    994     int ilen, s;
    995 
    996     sc = (struct ppp_softc *) tp->t_sc;
    997     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    998 	return 0;
    999 
   1000     ++tk_nin;
   1001     ++sc->sc_stats.ppp_ibytes;
   1002 
   1003     if (c & TTY_FE) {
   1004 	/* framing error or overrun on this char - abort packet */
   1005 	if (sc->sc_flags & SC_DEBUG)
   1006 	    printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
   1007 	goto flush;
   1008     }
   1009 
   1010     c &= 0xff;
   1011 
   1012     /*
   1013      * Handle software flow control of output.
   1014      */
   1015     if (tp->t_iflag & IXON) {
   1016 	if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
   1017 	    if ((tp->t_state & TS_TTSTOP) == 0) {
   1018 		tp->t_state |= TS_TTSTOP;
   1019 		cdev = cdevsw_lookup(tp->t_dev);
   1020 		if (cdev != NULL)
   1021 			(*cdev->d_stop)(tp, 0);
   1022 	    }
   1023 	    return 0;
   1024 	}
   1025 	if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
   1026 	    tp->t_state &= ~TS_TTSTOP;
   1027 	    if (tp->t_oproc != NULL)
   1028 		(*tp->t_oproc)(tp);
   1029 	    return 0;
   1030 	}
   1031     }
   1032 
   1033     s = spltty();
   1034     if (c & 0x80)
   1035 	sc->sc_flags |= SC_RCV_B7_1;
   1036     else
   1037 	sc->sc_flags |= SC_RCV_B7_0;
   1038     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
   1039 	sc->sc_flags |= SC_RCV_ODDP;
   1040     else
   1041 	sc->sc_flags |= SC_RCV_EVNP;
   1042     splx(s);
   1043 
   1044     ppplogchar(sc, c);
   1045 
   1046     if (c == PPP_FLAG) {
   1047 	ilen = sc->sc_ilen;
   1048 	sc->sc_ilen = 0;
   1049 
   1050 	if ((sc->sc_flags & SC_LOG_RAWIN) && sc->sc_rawin.count > 0)
   1051 	    ppplogchar(sc, -1);
   1052 
   1053 	/*
   1054 	 * If SC_ESCAPED is set, then we've seen the packet
   1055 	 * abort sequence "}~".
   1056 	 */
   1057 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
   1058 	    || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
   1059 	    s = spltty();
   1060 	    sc->sc_flags |= SC_PKTLOST;	/* note the dropped packet */
   1061 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
   1062 		if (sc->sc_flags & SC_DEBUG)
   1063 		    printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
   1064 			sc->sc_fcs);
   1065 		sc->sc_if.if_ierrors++;
   1066 		sc->sc_stats.ppp_ierrors++;
   1067 	    } else
   1068 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
   1069 	    splx(s);
   1070 	    return 0;
   1071 	}
   1072 
   1073 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
   1074 	    if (ilen) {
   1075 		if (sc->sc_flags & SC_DEBUG)
   1076 		    printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
   1077 		s = spltty();
   1078 		sc->sc_if.if_ierrors++;
   1079 		sc->sc_stats.ppp_ierrors++;
   1080 		sc->sc_flags |= SC_PKTLOST;
   1081 		splx(s);
   1082 	    }
   1083 	    return 0;
   1084 	}
   1085 
   1086 	/*
   1087 	 * Remove FCS trailer.  Somewhat painful...
   1088 	 */
   1089 	ilen -= 2;
   1090 	if (--sc->sc_mc->m_len == 0) {
   1091 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
   1092 		;
   1093 	    sc->sc_mc = m;
   1094 	}
   1095 	sc->sc_mc->m_len--;
   1096 
   1097 	/* excise this mbuf chain */
   1098 	m = sc->sc_m;
   1099 	sc->sc_m = sc->sc_mc->m_next;
   1100 	sc->sc_mc->m_next = NULL;
   1101 
   1102 	ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
   1103 	if (sc->sc_flags & SC_PKTLOST) {
   1104 	    s = spltty();
   1105 	    sc->sc_flags &= ~SC_PKTLOST;
   1106 	    splx(s);
   1107 	}
   1108 
   1109 	pppgetm(sc);
   1110 	return 0;
   1111     }
   1112 
   1113     if (sc->sc_flags & SC_FLUSH) {
   1114 	if (sc->sc_flags & SC_LOG_FLUSH)
   1115 	    ppplogchar(sc, c);
   1116 	return 0;
   1117     }
   1118 
   1119     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
   1120 	return 0;
   1121 
   1122     s = spltty();
   1123     if (sc->sc_flags & SC_ESCAPED) {
   1124 	sc->sc_flags &= ~SC_ESCAPED;
   1125 	c ^= PPP_TRANS;
   1126     } else if (c == PPP_ESCAPE) {
   1127 	sc->sc_flags |= SC_ESCAPED;
   1128 	splx(s);
   1129 	return 0;
   1130     }
   1131     splx(s);
   1132 
   1133     /*
   1134      * Initialize buffer on first octet received.
   1135      * First octet could be address or protocol (when compressing
   1136      * address/control).
   1137      * Second octet is control.
   1138      * Third octet is first or second (when compressing protocol)
   1139      * octet of protocol.
   1140      * Fourth octet is second octet of protocol.
   1141      */
   1142     if (sc->sc_ilen == 0) {
   1143 	/* reset the first input mbuf */
   1144 	if (sc->sc_m == NULL) {
   1145 	    pppgetm(sc);
   1146 	    if (sc->sc_m == NULL) {
   1147 		if (sc->sc_flags & SC_DEBUG)
   1148 		    printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
   1149 		goto flush;
   1150 	    }
   1151 	}
   1152 	m = sc->sc_m;
   1153 	m->m_len = 0;
   1154 	m->m_data = M_DATASTART(sc->sc_m);
   1155 	sc->sc_mc = m;
   1156 	sc->sc_mp = mtod(m, char *);
   1157 	sc->sc_fcs = PPP_INITFCS;
   1158 	if (c != PPP_ALLSTATIONS) {
   1159 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
   1160 		if (sc->sc_flags & SC_DEBUG)
   1161 		    printf("%s: garbage received: 0x%x (need 0xFF)\n",
   1162 		    sc->sc_if.if_xname, c);
   1163 		goto flush;
   1164 	    }
   1165 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
   1166 	    *sc->sc_mp++ = PPP_UI;
   1167 	    sc->sc_ilen += 2;
   1168 	    m->m_len += 2;
   1169 	}
   1170     }
   1171     if (sc->sc_ilen == 1 && c != PPP_UI) {
   1172 	if (sc->sc_flags & SC_DEBUG)
   1173 	    printf("%s: missing UI (0x3), got 0x%x\n",
   1174 		sc->sc_if.if_xname, c);
   1175 	goto flush;
   1176     }
   1177     if (sc->sc_ilen == 2 && (c & 1) == 1) {
   1178 	/* a compressed protocol */
   1179 	*sc->sc_mp++ = 0;
   1180 	sc->sc_ilen++;
   1181 	sc->sc_mc->m_len++;
   1182     }
   1183     if (sc->sc_ilen == 3 && (c & 1) == 0) {
   1184 	if (sc->sc_flags & SC_DEBUG)
   1185 	    printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
   1186 		(sc->sc_mp[-1] << 8) + c);
   1187 	goto flush;
   1188     }
   1189 
   1190     /* packet beyond configured mru? */
   1191     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
   1192 	if (sc->sc_flags & SC_DEBUG)
   1193 	    printf("%s: packet too big\n", sc->sc_if.if_xname);
   1194 	goto flush;
   1195     }
   1196 
   1197     /* is this mbuf full? */
   1198     m = sc->sc_mc;
   1199     if (M_TRAILINGSPACE(m) <= 0) {
   1200 	if (m->m_next == NULL) {
   1201 	    pppgetm(sc);
   1202 	    if (m->m_next == NULL) {
   1203 		if (sc->sc_flags & SC_DEBUG)
   1204 		    printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
   1205 		goto flush;
   1206 	    }
   1207 	}
   1208 	sc->sc_mc = m = m->m_next;
   1209 	m->m_len = 0;
   1210 	m->m_data = M_DATASTART(m);
   1211 	sc->sc_mp = mtod(m, char *);
   1212     }
   1213 
   1214     ++m->m_len;
   1215     *sc->sc_mp++ = c;
   1216     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
   1217     return 0;
   1218 
   1219  flush:
   1220     if (!(sc->sc_flags & SC_FLUSH)) {
   1221 	s = spltty();
   1222 	sc->sc_if.if_ierrors++;
   1223 	sc->sc_stats.ppp_ierrors++;
   1224 	sc->sc_flags |= SC_FLUSH;
   1225 	splx(s);
   1226 	if (sc->sc_flags & SC_LOG_FLUSH)
   1227 	    ppplogchar(sc, c);
   1228     }
   1229     return 0;
   1230 }
   1231 
   1232 #define MAX_DUMP_BYTES	128
   1233 
   1234 static void
   1235 ppplogchar(struct ppp_softc *sc, int c)
   1236 {
   1237     if (c >= 0) {
   1238 	sc->sc_rawin.buf[sc->sc_rawin_start++] = c;
   1239 	if (sc->sc_rawin.count < sizeof(sc->sc_rawin.buf))
   1240 	    sc->sc_rawin.count++;
   1241     }
   1242     if (sc->sc_rawin_start >= sizeof(sc->sc_rawin.buf)
   1243 	|| (c < 0 && sc->sc_rawin_start > 0)) {
   1244 	if (sc->sc_flags & (SC_LOG_FLUSH|SC_LOG_RAWIN)) {
   1245 	    printf("%s input: ", sc->sc_if.if_xname);
   1246 	    pppdumpb(sc->sc_rawin.buf, sc->sc_rawin_start);
   1247 	}
   1248 	if (c < 0)
   1249 	    sc->sc_rawin.count = 0;
   1250 	sc->sc_rawin_start = 0;
   1251     }
   1252 }
   1253 
   1254 static void
   1255 pppdumpb(u_char *b, int l)
   1256 {
   1257     char bf[3*MAX_DUMP_BYTES+4];
   1258     char *bp = bf;
   1259 
   1260     while (l--) {
   1261 	if (bp >= bf + sizeof(bf) - 3) {
   1262 	    *bp++ = '>';
   1263 	    break;
   1264 	}
   1265 	*bp++ = hexdigits[*b >> 4]; /* convert byte to ascii hex */
   1266 	*bp++ = hexdigits[*b++ & 0xf];
   1267 	*bp++ = ' ';
   1268     }
   1269 
   1270     *bp = 0;
   1271     printf("%s\n", bf);
   1272 }
   1273 
   1274 static void
   1275 pppdumpframe(struct ppp_softc *sc, struct mbuf *m, int xmit)
   1276 {
   1277 	int i,lcount,copycount,count;
   1278 	char lbuf[16];
   1279 	char *data;
   1280 
   1281 	if (m == NULL)
   1282 		return;
   1283 
   1284 	for(count=m->m_len,data=mtod(m,char*);m != NULL;) {
   1285 		/* build a line of output */
   1286 		for(lcount=0;lcount < sizeof(lbuf);lcount += copycount) {
   1287 			if (!count) {
   1288 				m = m->m_next;
   1289 				if (m == NULL)
   1290 					break;
   1291 				count = m->m_len;
   1292 				data  = mtod(m,char*);
   1293 			}
   1294 			copycount = (count > sizeof(lbuf)-lcount) ?
   1295 					sizeof(lbuf)-lcount : count;
   1296 			bcopy(data,&lbuf[lcount],copycount);
   1297 			data  += copycount;
   1298 			count -= copycount;
   1299 		}
   1300 
   1301 		/* output line (hex 1st, then ascii) */
   1302 		printf("%s %s:", sc->sc_if.if_xname,
   1303 		    xmit ? "output" : "input ");
   1304 		for(i=0;i<lcount;i++)
   1305 			printf("%02x ",(u_char)lbuf[i]);
   1306 		for(;i<sizeof(lbuf);i++)
   1307 			printf("   ");
   1308 		for(i=0;i<lcount;i++)
   1309 			printf("%c",(lbuf[i] >= 040 &&
   1310 			    lbuf[i] <= 0176) ? lbuf[i] : '.');
   1311 		printf("\n");
   1312 	}
   1313 }
   1314