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