Home | History | Annotate | Line # | Download | only in net
ppp_tty.c revision 1.47.2.1
      1 /*	$NetBSD: ppp_tty.c,v 1.47.2.1 2007/04/05 21:57:51 ad 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.47.2.1 2007/04/05 21:57:51 ad 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, void *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 	NULL)) != 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 = (void *) 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 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     mutex_enter(&tp->t_lock);
    334     for (;;) {
    335 	if (tp != (struct tty *) sc->sc_devp ||
    336 	    tp->t_linesw != &ppp_disc) {
    337 	    mutex_exit(&tp->t_lock);
    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 	    mutex_exit(&tp->t_lock);
    345 	    return 0;		/* end of file */
    346 	}
    347 	if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
    348 	    mutex_exit(&tp->t_lock);
    349 	    return (EWOULDBLOCK);
    350 	}
    351 	error = ttysleep(tp, &tp->t_rawq.c_cv, true, 0);
    352 	if (error) {
    353 	    mutex_exit(&tp->t_lock);
    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     mutex_exit(&tp->t_lock);
    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, void *data, int flag, struct lwp *l)
    439 {
    440     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    441     int error, s;
    442 
    443     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    444 	return (EPASSTHROUGH);
    445 
    446     error = 0;
    447     switch (cmd) {
    448     case TIOCRCVFRAME:
    449     	ppprcvframe(sc,*((struct mbuf **)data));
    450 	break;
    451 
    452     case PPPIOCSASYNCMAP:
    453 	if ((error = kauth_authorize_generic(l->l_cred,
    454  	  KAUTH_GENERIC_ISSUSER, NULL)) != 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(l->l_cred,
    465 	  KAUTH_GENERIC_ISSUSER, NULL)) != 0)
    466 	    break;
    467 	sc->sc_rasyncmap = *(u_int *)data;
    468 	break;
    469 
    470     case PPPIOCGRASYNCMAP:
    471 	*(u_int *)data = sc->sc_rasyncmap;
    472 	break;
    473 
    474     case PPPIOCSXASYNCMAP:
    475 	if ((error = kauth_authorize_generic(l->l_cred,
    476 	  KAUTH_GENERIC_ISSUSER, NULL)) != 0)
    477 	    break;
    478 	s = spltty();
    479 	bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
    480 	sc->sc_asyncmap[1] = 0;		    /* mustn't escape 0x20 - 0x3f */
    481 	sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
    482 	sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
    483 	splx(s);
    484 	break;
    485 
    486     case PPPIOCGXASYNCMAP:
    487 	bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
    488 	break;
    489 
    490     default:
    491 	error = pppioctl(sc, cmd, data, flag, l);
    492 	if (error == 0 && cmd == PPPIOCSMRU)
    493 	    pppgetm(sc);
    494     }
    495 
    496     return error;
    497 }
    498 
    499 /* receive a complete ppp frame from device in synchronous
    500  * hdlc mode. caller gives up ownership of mbuf
    501  */
    502 static void
    503 ppprcvframe(struct ppp_softc *sc, struct mbuf *m)
    504 {
    505 	int len, s;
    506 	struct mbuf *n;
    507 	u_char hdr[4];
    508 	int hlen,count;
    509 
    510 	for (n=m,len=0;n != NULL;n = n->m_next)
    511 		len += n->m_len;
    512 	if (len==0) {
    513 		m_freem(m);
    514 		return;
    515 	}
    516 
    517 	/* extract PPP header from mbuf chain (1 to 4 bytes) */
    518 	for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
    519 		count = (sizeof(hdr)-hlen) < n->m_len ?
    520 				sizeof(hdr)-hlen : n->m_len;
    521 		bcopy(mtod(n,u_char*),&hdr[hlen],count);
    522 		hlen+=count;
    523 	}
    524 
    525 	s = spltty();
    526 
    527 	/* if AFCF compressed then prepend AFCF */
    528 	if (hdr[0] != PPP_ALLSTATIONS) {
    529 		if (sc->sc_flags & SC_REJ_COMP_AC) {
    530 			if (sc->sc_flags & SC_DEBUG)
    531 				printf(
    532 				    "%s: garbage received: 0x%x (need 0xFF)\n",
    533 				    sc->sc_if.if_xname, hdr[0]);
    534 				goto bail;
    535 			}
    536 		M_PREPEND(m,2,M_DONTWAIT);
    537 		if (m==NULL) {
    538 			splx(s);
    539 			return;
    540 		}
    541 		hdr[3] = hdr[1];
    542 		hdr[2] = hdr[0];
    543 		hdr[0] = PPP_ALLSTATIONS;
    544 		hdr[1] = PPP_UI;
    545 		len += 2;
    546 	}
    547 
    548 	/* if protocol field compressed, add MSB of protocol field = 0 */
    549 	if (hdr[2] & 1) {
    550 		/* a compressed protocol */
    551 		M_PREPEND(m,1,M_DONTWAIT);
    552 		if (m==NULL) {
    553 			splx(s);
    554 			return;
    555 		}
    556 		hdr[3] = hdr[2];
    557 		hdr[2] = 0;
    558 		len++;
    559 	}
    560 
    561 	/* valid LSB of protocol field has bit0 set */
    562 	if (!(hdr[3] & 1)) {
    563 		if (sc->sc_flags & SC_DEBUG)
    564 			printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
    565 				(hdr[2] << 8) + hdr[3]);
    566 			goto bail;
    567 	}
    568 
    569 	/* packet beyond configured mru? */
    570 	if (len > sc->sc_mru + PPP_HDRLEN) {
    571 		if (sc->sc_flags & SC_DEBUG)
    572 			printf("%s: packet too big\n", sc->sc_if.if_xname);
    573 		goto bail;
    574 	}
    575 
    576 	/* add expanded 4 byte header to mbuf chain */
    577 	for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
    578 		count = (sizeof(hdr)-hlen) < n->m_len ?
    579 				sizeof(hdr)-hlen : n->m_len;
    580 		bcopy(&hdr[hlen],mtod(n,u_char*),count);
    581 		hlen+=count;
    582 	}
    583 
    584 	/* if_ppp.c requires the PPP header and IP header */
    585 	/* to be contiguous */
    586 	count = len < MHLEN ? len : MHLEN;
    587 	if (m->m_len < count) {
    588 		m = m_pullup(m,count);
    589 		if (m==NULL)
    590 			goto bail;
    591 	}
    592 
    593 	sc->sc_stats.ppp_ibytes += len;
    594 
    595 	if (sc->sc_flags & SC_LOG_RAWIN)
    596 		pppdumpframe(sc,m,0);
    597 
    598 	ppppktin(sc, m, 0);
    599 	splx(s);
    600 	return;
    601 bail:
    602 	m_freem(m);
    603 	splx(s);
    604 }
    605 
    606 /*
    607  * FCS lookup table as calculated by genfcstab.
    608  */
    609 static const u_int16_t fcstab[256] = {
    610 	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
    611 	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
    612 	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
    613 	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
    614 	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
    615 	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
    616 	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
    617 	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
    618 	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
    619 	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
    620 	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
    621 	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
    622 	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
    623 	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
    624 	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
    625 	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
    626 	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
    627 	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
    628 	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
    629 	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
    630 	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
    631 	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
    632 	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
    633 	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
    634 	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
    635 	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
    636 	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
    637 	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
    638 	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
    639 	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
    640 	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
    641 	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
    642 };
    643 
    644 /*
    645  * Calculate a new FCS given the current FCS and the new data.
    646  */
    647 static u_int16_t
    648 pppfcs(u_int16_t fcs, u_char *cp, int len)
    649 {
    650     while (len--)
    651 	fcs = PPP_FCS(fcs, *cp++);
    652     return (fcs);
    653 }
    654 
    655 /* This gets called at splsoftnet from pppasyncstart at various times
    656  * when there is data ready to be sent.
    657  */
    658 static void
    659 pppsyncstart(struct ppp_softc *sc)
    660 {
    661 	struct tty *tp = (struct tty *) sc->sc_devp;
    662 	struct mbuf *m, *n;
    663 	const struct cdevsw *cdev;
    664 	int len;
    665 
    666 	for(m = sc->sc_outm;;) {
    667 		if (m == NULL) {
    668 			m = ppp_dequeue(sc);	/* get new packet */
    669 			if (m == NULL)
    670 				break;		/* no more packets */
    671 			if (sc->sc_flags & SC_DEBUG)
    672 				pppdumpframe(sc,m,1);
    673 		}
    674 		for(n=m,len=0;n!=NULL;n=n->m_next)
    675 			len += n->m_len;
    676 
    677 		/* call device driver IOCTL to transmit a frame */
    678 		cdev = cdevsw_lookup(tp->t_dev);
    679 		if (cdev == NULL ||
    680 		    (*cdev->d_ioctl)(tp->t_dev, TIOCXMTFRAME, (void *)&m,
    681 				     0, 0)) {
    682 			/* busy or error, set as current packet */
    683 			sc->sc_outm = m;
    684 			break;
    685 		}
    686 		sc->sc_outm = m = NULL;
    687 		sc->sc_stats.ppp_obytes += len;
    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     int s;
    705 
    706     if (sc->sc_flags & SC_SYNC){
    707 	pppsyncstart(sc);
    708 	return;
    709     }
    710 
    711     idle = 0;
    712     while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
    713 	/*
    714 	 * See if we have an existing packet partly sent.
    715 	 * If not, get a new packet and start sending it.
    716 	 */
    717 	m = sc->sc_outm;
    718 	if (m == NULL) {
    719 	    /*
    720 	     * Get another packet to be sent.
    721 	     */
    722 	    m = ppp_dequeue(sc);
    723 	    if (m == NULL) {
    724 		idle = 1;
    725 		break;
    726 	    }
    727 
    728 	    /*
    729 	     * The extra PPP_FLAG will start up a new packet, and thus
    730 	     * will flush any accumulated garbage.  We do this whenever
    731 	     * the line may have been idle for some time.
    732 	     */
    733 	    if (CCOUNT(&tp->t_outq) == 0) {
    734 		++sc->sc_stats.ppp_obytes;
    735 		(void) putc(PPP_FLAG, &tp->t_outq);
    736 	    }
    737 
    738 	    /* Calculate the FCS for the first mbuf's worth. */
    739 	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
    740 	}
    741 
    742 	for (;;) {
    743 	    start = mtod(m, u_char *);
    744 	    len = m->m_len;
    745 	    stop = start + len;
    746 	    while (len > 0) {
    747 		/*
    748 		 * Find out how many bytes in the string we can
    749 		 * handle without doing something special.
    750 		 */
    751 		for (cp = start; cp < stop; cp++)
    752 		    if (ESCAPE_P(*cp))
    753 			break;
    754 		n = cp - start;
    755 		if (n) {
    756 		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
    757 		    ndone = n - b_to_q(start, n, &tp->t_outq);
    758 		    len -= ndone;
    759 		    start += ndone;
    760 		    sc->sc_stats.ppp_obytes += ndone;
    761 
    762 		    if (ndone < n)
    763 			break;	/* packet doesn't fit */
    764 		}
    765 		/*
    766 		 * If there are characters left in the mbuf,
    767 		 * the first one must be special.
    768 		 * Put it out in a different form.
    769 		 */
    770 		if (len) {
    771 		    s = spltty();
    772 		    if (putc(PPP_ESCAPE, &tp->t_outq)) {
    773 			splx(s);
    774 			break;
    775 		    }
    776 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
    777 			(void) unputc(&tp->t_outq);
    778 			splx(s);
    779 			break;
    780 		    }
    781 		    splx(s);
    782 		    sc->sc_stats.ppp_obytes += 2;
    783 		    start++;
    784 		    len--;
    785 		}
    786 	    }
    787 
    788 	    /*
    789 	     * If we didn't empty this mbuf, remember where we're up to.
    790 	     * If we emptied the last mbuf, try to add the FCS and closing
    791 	     * flag, and if we can't, leave sc_outm pointing to m, but with
    792 	     * m->m_len == 0, to remind us to output the FCS and flag later.
    793 	     */
    794 	    done = len == 0;
    795 	    if (done && m->m_next == NULL) {
    796 		u_char *p, *q;
    797 		int c;
    798 		u_char endseq[8];
    799 
    800 		/*
    801 		 * We may have to escape the bytes in the FCS.
    802 		 */
    803 		p = endseq;
    804 		c = ~sc->sc_outfcs & 0xFF;
    805 		if (ESCAPE_P(c)) {
    806 		    *p++ = PPP_ESCAPE;
    807 		    *p++ = c ^ PPP_TRANS;
    808 		} else
    809 		    *p++ = c;
    810 		c = (~sc->sc_outfcs >> 8) & 0xFF;
    811 		if (ESCAPE_P(c)) {
    812 		    *p++ = PPP_ESCAPE;
    813 		    *p++ = c ^ PPP_TRANS;
    814 		} else
    815 		    *p++ = c;
    816 		*p++ = PPP_FLAG;
    817 
    818 		/*
    819 		 * Try to output the FCS and flag.  If the bytes
    820 		 * don't all fit, back out.
    821 		 */
    822 		s = spltty();
    823 		for (q = endseq; q < p; ++q)
    824 		    if (putc(*q, &tp->t_outq)) {
    825 			done = 0;
    826 			for (; q > endseq; --q)
    827 			    unputc(&tp->t_outq);
    828 			break;
    829 		    }
    830 		splx(s);
    831 		if (done)
    832 		    sc->sc_stats.ppp_obytes += q - endseq;
    833 	    }
    834 
    835 	    if (!done) {
    836 		/* remember where we got to */
    837 		m->m_data = start;
    838 		m->m_len = len;
    839 		break;
    840 	    }
    841 
    842 	    /* Finished with this mbuf; free it and move on. */
    843 	    MFREE(m, m2);
    844 	    m = m2;
    845 	    if (m == NULL) {
    846 		/* Finished a packet */
    847 		break;
    848 	    }
    849 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
    850 	}
    851 
    852 	/*
    853 	 * If m == NULL, we have finished a packet.
    854 	 * If m != NULL, we've either done as much work this time
    855 	 * as we need to, or else we've filled up the output queue.
    856 	 */
    857 	sc->sc_outm = m;
    858 	if (m)
    859 	    break;
    860     }
    861 
    862     /* Call pppstart to start output again if necessary. */
    863     s = spltty();
    864     pppstart(tp);
    865 
    866     /*
    867      * This timeout is needed for operation on a pseudo-tty,
    868      * because the pty code doesn't call pppstart after it has
    869      * drained the t_outq.
    870      */
    871     if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
    872 	callout_reset(&sc->sc_timo_ch, 1, ppp_timeout, sc);
    873 	sc->sc_flags |= SC_TIMEOUT;
    874     }
    875 
    876     splx(s);
    877 }
    878 
    879 /*
    880  * This gets called when a received packet is placed on
    881  * the inq, at splsoftnet.
    882  */
    883 static void
    884 pppasyncctlp(struct ppp_softc *sc)
    885 {
    886     struct tty *tp;
    887     int s;
    888 
    889     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
    890     s = spltty();
    891     tp = (struct tty *) sc->sc_devp;
    892     putc(0, &tp->t_canq);
    893     ttwakeup(tp);
    894     splx(s);
    895 }
    896 
    897 /*
    898  * Start output on async tty interface.  If the transmit queue
    899  * has drained sufficiently, arrange for pppasyncstart to be
    900  * called later at splsoftnet.
    901  * Called at spltty or higher.
    902  */
    903 static int
    904 pppstart(struct tty *tp)
    905 {
    906     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    907 
    908     /*
    909      * If there is stuff in the output queue, send it now.
    910      * We are being called in lieu of ttstart and must do what it would.
    911      */
    912     if (tp->t_oproc != NULL)
    913 	(*tp->t_oproc)(tp);
    914 
    915     /*
    916      * If the transmit queue has drained and the tty has not hung up
    917      * or been disconnected from the ppp unit, then tell if_ppp.c that
    918      * we need more output.
    919      */
    920     if ((CCOUNT(&tp->t_outq) >= PPP_LOWAT)
    921 	&& ((sc == NULL) || (sc->sc_flags & SC_TIMEOUT)))
    922 	return 0;
    923 #ifdef ALTQ
    924     /*
    925      * if ALTQ is enabled, don't invoke NETISR_PPP.
    926      * pppintr() could loop without doing anything useful
    927      * under rate-limiting.
    928      */
    929     if (ALTQ_IS_ENABLED(&sc->sc_if.if_snd))
    930 	return 0;
    931 #endif
    932     if (!((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    933 	&& sc != NULL && tp == (struct tty *) sc->sc_devp) {
    934 	ppp_restart(sc);
    935     }
    936 
    937     return 0;
    938 }
    939 
    940 /*
    941  * Timeout routine - try to start some more output.
    942  */
    943 static void
    944 ppp_timeout(void *x)
    945 {
    946     struct ppp_softc *sc = (struct ppp_softc *) x;
    947     struct tty *tp = (struct tty *) sc->sc_devp;
    948     int s;
    949 
    950     s = spltty();
    951     sc->sc_flags &= ~SC_TIMEOUT;
    952     pppstart(tp);
    953     splx(s);
    954 }
    955 
    956 /*
    957  * Allocate enough mbuf to handle current MRU.
    958  */
    959 static void
    960 pppgetm(struct ppp_softc *sc)
    961 {
    962     struct mbuf *m, **mp;
    963     int len;
    964 
    965     mp = &sc->sc_m;
    966     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
    967 	if ((m = *mp) == NULL) {
    968 	    MGETHDR(m, M_DONTWAIT, MT_DATA);
    969 	    if (m == NULL)
    970 		break;
    971 	    *mp = m;
    972 	    MCLGET(m, M_DONTWAIT);
    973 	}
    974 	len -= M_DATASIZE(m);
    975 	mp = &m->m_next;
    976     }
    977 }
    978 
    979 /*
    980  * tty interface receiver interrupt.
    981  */
    982 static const unsigned paritytab[8] = {
    983     0x96696996, 0x69969669, 0x69969669, 0x96696996,
    984     0x69969669, 0x96696996, 0x96696996, 0x69969669
    985 };
    986 
    987 static int
    988 pppinput(int c, struct tty *tp)
    989 {
    990     struct ppp_softc *sc;
    991     struct mbuf *m;
    992     const struct cdevsw *cdev;
    993     int ilen, s;
    994 
    995     sc = (struct ppp_softc *) tp->t_sc;
    996     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    997 	return 0;
    998 
    999     ++tk_nin;
   1000     ++sc->sc_stats.ppp_ibytes;
   1001 
   1002     if (c & TTY_FE) {
   1003 	/* framing error or overrun on this char - abort packet */
   1004 	if (sc->sc_flags & SC_DEBUG)
   1005 	    printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
   1006 	goto flush;
   1007     }
   1008 
   1009     c &= 0xff;
   1010 
   1011     /*
   1012      * Handle software flow control of output.
   1013      */
   1014     if (tp->t_iflag & IXON) {
   1015 	if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
   1016 	    if ((tp->t_state & TS_TTSTOP) == 0) {
   1017 		tp->t_state |= TS_TTSTOP;
   1018 		cdev = cdevsw_lookup(tp->t_dev);
   1019 		if (cdev != NULL)
   1020 			(*cdev->d_stop)(tp, 0);
   1021 	    }
   1022 	    return 0;
   1023 	}
   1024 	if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
   1025 	    tp->t_state &= ~TS_TTSTOP;
   1026 	    if (tp->t_oproc != NULL)
   1027 		(*tp->t_oproc)(tp);
   1028 	    return 0;
   1029 	}
   1030     }
   1031 
   1032     s = spltty();
   1033     if (c & 0x80)
   1034 	sc->sc_flags |= SC_RCV_B7_1;
   1035     else
   1036 	sc->sc_flags |= SC_RCV_B7_0;
   1037     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
   1038 	sc->sc_flags |= SC_RCV_ODDP;
   1039     else
   1040 	sc->sc_flags |= SC_RCV_EVNP;
   1041     splx(s);
   1042 
   1043     ppplogchar(sc, c);
   1044 
   1045     if (c == PPP_FLAG) {
   1046 	ilen = sc->sc_ilen;
   1047 	sc->sc_ilen = 0;
   1048 
   1049 	if ((sc->sc_flags & SC_LOG_RAWIN) && sc->sc_rawin.count > 0)
   1050 	    ppplogchar(sc, -1);
   1051 
   1052 	/*
   1053 	 * If SC_ESCAPED is set, then we've seen the packet
   1054 	 * abort sequence "}~".
   1055 	 */
   1056 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
   1057 	    || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
   1058 	    s = spltty();
   1059 	    sc->sc_flags |= SC_PKTLOST;	/* note the dropped packet */
   1060 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
   1061 		if (sc->sc_flags & SC_DEBUG)
   1062 		    printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
   1063 			sc->sc_fcs);
   1064 		sc->sc_if.if_ierrors++;
   1065 		sc->sc_stats.ppp_ierrors++;
   1066 	    } else
   1067 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
   1068 	    splx(s);
   1069 	    return 0;
   1070 	}
   1071 
   1072 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
   1073 	    if (ilen) {
   1074 		if (sc->sc_flags & SC_DEBUG)
   1075 		    printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
   1076 		s = spltty();
   1077 		sc->sc_if.if_ierrors++;
   1078 		sc->sc_stats.ppp_ierrors++;
   1079 		sc->sc_flags |= SC_PKTLOST;
   1080 		splx(s);
   1081 	    }
   1082 	    return 0;
   1083 	}
   1084 
   1085 	/*
   1086 	 * Remove FCS trailer.  Somewhat painful...
   1087 	 */
   1088 	ilen -= 2;
   1089 	if (--sc->sc_mc->m_len == 0) {
   1090 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
   1091 		;
   1092 	    sc->sc_mc = m;
   1093 	}
   1094 	sc->sc_mc->m_len--;
   1095 
   1096 	/* excise this mbuf chain */
   1097 	m = sc->sc_m;
   1098 	sc->sc_m = sc->sc_mc->m_next;
   1099 	sc->sc_mc->m_next = NULL;
   1100 
   1101 	ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
   1102 	if (sc->sc_flags & SC_PKTLOST) {
   1103 	    s = spltty();
   1104 	    sc->sc_flags &= ~SC_PKTLOST;
   1105 	    splx(s);
   1106 	}
   1107 
   1108 	pppgetm(sc);
   1109 	return 0;
   1110     }
   1111 
   1112     if (sc->sc_flags & SC_FLUSH) {
   1113 	if (sc->sc_flags & SC_LOG_FLUSH)
   1114 	    ppplogchar(sc, c);
   1115 	return 0;
   1116     }
   1117 
   1118     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
   1119 	return 0;
   1120 
   1121     s = spltty();
   1122     if (sc->sc_flags & SC_ESCAPED) {
   1123 	sc->sc_flags &= ~SC_ESCAPED;
   1124 	c ^= PPP_TRANS;
   1125     } else if (c == PPP_ESCAPE) {
   1126 	sc->sc_flags |= SC_ESCAPED;
   1127 	splx(s);
   1128 	return 0;
   1129     }
   1130     splx(s);
   1131 
   1132     /*
   1133      * Initialize buffer on first octet received.
   1134      * First octet could be address or protocol (when compressing
   1135      * address/control).
   1136      * Second octet is control.
   1137      * Third octet is first or second (when compressing protocol)
   1138      * octet of protocol.
   1139      * Fourth octet is second octet of protocol.
   1140      */
   1141     if (sc->sc_ilen == 0) {
   1142 	/* reset the first input mbuf */
   1143 	if (sc->sc_m == NULL) {
   1144 	    pppgetm(sc);
   1145 	    if (sc->sc_m == NULL) {
   1146 		if (sc->sc_flags & SC_DEBUG)
   1147 		    printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
   1148 		goto flush;
   1149 	    }
   1150 	}
   1151 	m = sc->sc_m;
   1152 	m->m_len = 0;
   1153 	m->m_data = M_DATASTART(sc->sc_m);
   1154 	sc->sc_mc = m;
   1155 	sc->sc_mp = mtod(m, char *);
   1156 	sc->sc_fcs = PPP_INITFCS;
   1157 	if (c != PPP_ALLSTATIONS) {
   1158 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
   1159 		if (sc->sc_flags & SC_DEBUG)
   1160 		    printf("%s: garbage received: 0x%x (need 0xFF)\n",
   1161 		    sc->sc_if.if_xname, c);
   1162 		goto flush;
   1163 	    }
   1164 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
   1165 	    *sc->sc_mp++ = PPP_UI;
   1166 	    sc->sc_ilen += 2;
   1167 	    m->m_len += 2;
   1168 	}
   1169     }
   1170     if (sc->sc_ilen == 1 && c != PPP_UI) {
   1171 	if (sc->sc_flags & SC_DEBUG)
   1172 	    printf("%s: missing UI (0x3), got 0x%x\n",
   1173 		sc->sc_if.if_xname, c);
   1174 	goto flush;
   1175     }
   1176     if (sc->sc_ilen == 2 && (c & 1) == 1) {
   1177 	/* a compressed protocol */
   1178 	*sc->sc_mp++ = 0;
   1179 	sc->sc_ilen++;
   1180 	sc->sc_mc->m_len++;
   1181     }
   1182     if (sc->sc_ilen == 3 && (c & 1) == 0) {
   1183 	if (sc->sc_flags & SC_DEBUG)
   1184 	    printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
   1185 		(sc->sc_mp[-1] << 8) + c);
   1186 	goto flush;
   1187     }
   1188 
   1189     /* packet beyond configured mru? */
   1190     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
   1191 	if (sc->sc_flags & SC_DEBUG)
   1192 	    printf("%s: packet too big\n", sc->sc_if.if_xname);
   1193 	goto flush;
   1194     }
   1195 
   1196     /* is this mbuf full? */
   1197     m = sc->sc_mc;
   1198     if (M_TRAILINGSPACE(m) <= 0) {
   1199 	if (m->m_next == NULL) {
   1200 	    pppgetm(sc);
   1201 	    if (m->m_next == NULL) {
   1202 		if (sc->sc_flags & SC_DEBUG)
   1203 		    printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
   1204 		goto flush;
   1205 	    }
   1206 	}
   1207 	sc->sc_mc = m = m->m_next;
   1208 	m->m_len = 0;
   1209 	m->m_data = M_DATASTART(m);
   1210 	sc->sc_mp = mtod(m, char *);
   1211     }
   1212 
   1213     ++m->m_len;
   1214     *sc->sc_mp++ = c;
   1215     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
   1216     return 0;
   1217 
   1218  flush:
   1219     if (!(sc->sc_flags & SC_FLUSH)) {
   1220 	s = spltty();
   1221 	sc->sc_if.if_ierrors++;
   1222 	sc->sc_stats.ppp_ierrors++;
   1223 	sc->sc_flags |= SC_FLUSH;
   1224 	splx(s);
   1225 	if (sc->sc_flags & SC_LOG_FLUSH)
   1226 	    ppplogchar(sc, c);
   1227     }
   1228     return 0;
   1229 }
   1230 
   1231 #define MAX_DUMP_BYTES	128
   1232 
   1233 static void
   1234 ppplogchar(struct ppp_softc *sc, int c)
   1235 {
   1236     if (c >= 0) {
   1237 	sc->sc_rawin.buf[sc->sc_rawin_start++] = c;
   1238 	if (sc->sc_rawin.count < sizeof(sc->sc_rawin.buf))
   1239 	    sc->sc_rawin.count++;
   1240     }
   1241     if (sc->sc_rawin_start >= sizeof(sc->sc_rawin.buf)
   1242 	|| (c < 0 && sc->sc_rawin_start > 0)) {
   1243 	if (sc->sc_flags & (SC_LOG_FLUSH|SC_LOG_RAWIN)) {
   1244 	    printf("%s input: ", sc->sc_if.if_xname);
   1245 	    pppdumpb(sc->sc_rawin.buf, sc->sc_rawin_start);
   1246 	}
   1247 	if (c < 0)
   1248 	    sc->sc_rawin.count = 0;
   1249 	sc->sc_rawin_start = 0;
   1250     }
   1251 }
   1252 
   1253 static void
   1254 pppdumpb(u_char *b, int l)
   1255 {
   1256     char bf[3*MAX_DUMP_BYTES+4];
   1257     char *bp = bf;
   1258 
   1259     while (l--) {
   1260 	if (bp >= bf + sizeof(bf) - 3) {
   1261 	    *bp++ = '>';
   1262 	    break;
   1263 	}
   1264 	*bp++ = hexdigits[*b >> 4]; /* convert byte to ascii hex */
   1265 	*bp++ = hexdigits[*b++ & 0xf];
   1266 	*bp++ = ' ';
   1267     }
   1268 
   1269     *bp = 0;
   1270     printf("%s\n", bf);
   1271 }
   1272 
   1273 static void
   1274 pppdumpframe(struct ppp_softc *sc, struct mbuf *m, int xmit)
   1275 {
   1276 	int i,lcount,copycount,count;
   1277 	char lbuf[16];
   1278 	char *data;
   1279 
   1280 	if (m == NULL)
   1281 		return;
   1282 
   1283 	for(count=m->m_len,data=mtod(m,char*);m != NULL;) {
   1284 		/* build a line of output */
   1285 		for(lcount=0;lcount < sizeof(lbuf);lcount += copycount) {
   1286 			if (!count) {
   1287 				m = m->m_next;
   1288 				if (m == NULL)
   1289 					break;
   1290 				count = m->m_len;
   1291 				data  = mtod(m,char*);
   1292 			}
   1293 			copycount = (count > sizeof(lbuf)-lcount) ?
   1294 					sizeof(lbuf)-lcount : count;
   1295 			bcopy(data,&lbuf[lcount],copycount);
   1296 			data  += copycount;
   1297 			count -= copycount;
   1298 		}
   1299 
   1300 		/* output line (hex 1st, then ascii) */
   1301 		printf("%s %s:", sc->sc_if.if_xname,
   1302 		    xmit ? "output" : "input ");
   1303 		for(i=0;i<lcount;i++)
   1304 			printf("%02x ",(u_char)lbuf[i]);
   1305 		for(;i<sizeof(lbuf);i++)
   1306 			printf("   ");
   1307 		for(i=0;i<lcount;i++)
   1308 			printf("%c",(lbuf[i] >= 040 &&
   1309 			    lbuf[i] <= 0176) ? lbuf[i] : '.');
   1310 		printf("\n");
   1311 	}
   1312 }
   1313