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