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