Home | History | Annotate | Line # | Download | only in net
ppp_tty.c revision 1.47.14.1
      1 /*	$NetBSD: ppp_tty.c,v 1.47.14.1 2007/11/11 16:48:25 joerg 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.14.1 2007/11/11 16:48:25 joerg 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     int s;
    892 
    893     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
    894     s = spltty();
    895     tp = (struct tty *) sc->sc_devp;
    896     putc(0, &tp->t_canq);
    897     ttwakeup(tp);
    898     splx(s);
    899 }
    900 
    901 /*
    902  * Start output on async tty interface.  If the transmit queue
    903  * has drained sufficiently, arrange for pppasyncstart to be
    904  * called later at splsoftnet.
    905  * Called at spltty or higher.
    906  */
    907 static int
    908 pppstart(struct tty *tp)
    909 {
    910     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    911 
    912     /*
    913      * If there is stuff in the output queue, send it now.
    914      * We are being called in lieu of ttstart and must do what it would.
    915      */
    916     if (tp->t_oproc != NULL)
    917 	(*tp->t_oproc)(tp);
    918 
    919     /*
    920      * If the transmit queue has drained and the tty has not hung up
    921      * or been disconnected from the ppp unit, then tell if_ppp.c that
    922      * we need more output.
    923      */
    924     if ((CCOUNT(&tp->t_outq) >= PPP_LOWAT)
    925 	&& ((sc == NULL) || (sc->sc_flags & SC_TIMEOUT)))
    926 	return 0;
    927 #ifdef ALTQ
    928     /*
    929      * if ALTQ is enabled, don't invoke NETISR_PPP.
    930      * pppintr() could loop without doing anything useful
    931      * under rate-limiting.
    932      */
    933     if (ALTQ_IS_ENABLED(&sc->sc_if.if_snd))
    934 	return 0;
    935 #endif
    936     if (!((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    937 	&& sc != NULL && tp == (struct tty *) sc->sc_devp) {
    938 	ppp_restart(sc);
    939     }
    940 
    941     return 0;
    942 }
    943 
    944 /*
    945  * Timeout routine - try to start some more output.
    946  */
    947 static void
    948 ppp_timeout(void *x)
    949 {
    950     struct ppp_softc *sc = (struct ppp_softc *) x;
    951     struct tty *tp = (struct tty *) sc->sc_devp;
    952     int s;
    953 
    954     s = spltty();
    955     sc->sc_flags &= ~SC_TIMEOUT;
    956     pppstart(tp);
    957     splx(s);
    958 }
    959 
    960 /*
    961  * Allocate enough mbuf to handle current MRU.
    962  */
    963 static void
    964 pppgetm(struct ppp_softc *sc)
    965 {
    966     struct mbuf *m, **mp;
    967     int len;
    968 
    969     mp = &sc->sc_m;
    970     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
    971 	if ((m = *mp) == NULL) {
    972 	    MGETHDR(m, M_DONTWAIT, MT_DATA);
    973 	    if (m == NULL)
    974 		break;
    975 	    *mp = m;
    976 	    MCLGET(m, M_DONTWAIT);
    977 	}
    978 	len -= M_DATASIZE(m);
    979 	mp = &m->m_next;
    980     }
    981 }
    982 
    983 /*
    984  * tty interface receiver interrupt.
    985  */
    986 static const unsigned paritytab[8] = {
    987     0x96696996, 0x69969669, 0x69969669, 0x96696996,
    988     0x69969669, 0x96696996, 0x96696996, 0x69969669
    989 };
    990 
    991 static int
    992 pppinput(int c, struct tty *tp)
    993 {
    994     struct ppp_softc *sc;
    995     struct mbuf *m;
    996     const struct cdevsw *cdev;
    997     int ilen, s;
    998 
    999     sc = (struct ppp_softc *) tp->t_sc;
   1000     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
   1001 	return 0;
   1002 
   1003     ++tk_nin;
   1004     ++sc->sc_stats.ppp_ibytes;
   1005 
   1006     if (c & TTY_FE) {
   1007 	/* framing error or overrun on this char - abort packet */
   1008 	if (sc->sc_flags & SC_DEBUG)
   1009 	    printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
   1010 	goto flush;
   1011     }
   1012 
   1013     c &= 0xff;
   1014 
   1015     /*
   1016      * Handle software flow control of output.
   1017      */
   1018     if (tp->t_iflag & IXON) {
   1019 	if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
   1020 	    if ((tp->t_state & TS_TTSTOP) == 0) {
   1021 		tp->t_state |= TS_TTSTOP;
   1022 		cdev = cdevsw_lookup(tp->t_dev);
   1023 		if (cdev != NULL)
   1024 			(*cdev->d_stop)(tp, 0);
   1025 	    }
   1026 	    return 0;
   1027 	}
   1028 	if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
   1029 	    tp->t_state &= ~TS_TTSTOP;
   1030 	    if (tp->t_oproc != NULL)
   1031 		(*tp->t_oproc)(tp);
   1032 	    return 0;
   1033 	}
   1034     }
   1035 
   1036     s = spltty();
   1037     if (c & 0x80)
   1038 	sc->sc_flags |= SC_RCV_B7_1;
   1039     else
   1040 	sc->sc_flags |= SC_RCV_B7_0;
   1041     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
   1042 	sc->sc_flags |= SC_RCV_ODDP;
   1043     else
   1044 	sc->sc_flags |= SC_RCV_EVNP;
   1045     splx(s);
   1046 
   1047     ppplogchar(sc, c);
   1048 
   1049     if (c == PPP_FLAG) {
   1050 	ilen = sc->sc_ilen;
   1051 	sc->sc_ilen = 0;
   1052 
   1053 	if ((sc->sc_flags & SC_LOG_RAWIN) && sc->sc_rawin.count > 0)
   1054 	    ppplogchar(sc, -1);
   1055 
   1056 	/*
   1057 	 * If SC_ESCAPED is set, then we've seen the packet
   1058 	 * abort sequence "}~".
   1059 	 */
   1060 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
   1061 	    || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
   1062 	    s = spltty();
   1063 	    sc->sc_flags |= SC_PKTLOST;	/* note the dropped packet */
   1064 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
   1065 		if (sc->sc_flags & SC_DEBUG)
   1066 		    printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
   1067 			sc->sc_fcs);
   1068 		sc->sc_if.if_ierrors++;
   1069 		sc->sc_stats.ppp_ierrors++;
   1070 	    } else
   1071 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
   1072 	    splx(s);
   1073 	    return 0;
   1074 	}
   1075 
   1076 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
   1077 	    if (ilen) {
   1078 		if (sc->sc_flags & SC_DEBUG)
   1079 		    printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
   1080 		s = spltty();
   1081 		sc->sc_if.if_ierrors++;
   1082 		sc->sc_stats.ppp_ierrors++;
   1083 		sc->sc_flags |= SC_PKTLOST;
   1084 		splx(s);
   1085 	    }
   1086 	    return 0;
   1087 	}
   1088 
   1089 	/*
   1090 	 * Remove FCS trailer.  Somewhat painful...
   1091 	 */
   1092 	ilen -= 2;
   1093 	if (--sc->sc_mc->m_len == 0) {
   1094 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
   1095 		;
   1096 	    sc->sc_mc = m;
   1097 	}
   1098 	sc->sc_mc->m_len--;
   1099 
   1100 	/* excise this mbuf chain */
   1101 	m = sc->sc_m;
   1102 	sc->sc_m = sc->sc_mc->m_next;
   1103 	sc->sc_mc->m_next = NULL;
   1104 
   1105 	ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
   1106 	if (sc->sc_flags & SC_PKTLOST) {
   1107 	    s = spltty();
   1108 	    sc->sc_flags &= ~SC_PKTLOST;
   1109 	    splx(s);
   1110 	}
   1111 
   1112 	pppgetm(sc);
   1113 	return 0;
   1114     }
   1115 
   1116     if (sc->sc_flags & SC_FLUSH) {
   1117 	if (sc->sc_flags & SC_LOG_FLUSH)
   1118 	    ppplogchar(sc, c);
   1119 	return 0;
   1120     }
   1121 
   1122     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
   1123 	return 0;
   1124 
   1125     s = spltty();
   1126     if (sc->sc_flags & SC_ESCAPED) {
   1127 	sc->sc_flags &= ~SC_ESCAPED;
   1128 	c ^= PPP_TRANS;
   1129     } else if (c == PPP_ESCAPE) {
   1130 	sc->sc_flags |= SC_ESCAPED;
   1131 	splx(s);
   1132 	return 0;
   1133     }
   1134     splx(s);
   1135 
   1136     /*
   1137      * Initialize buffer on first octet received.
   1138      * First octet could be address or protocol (when compressing
   1139      * address/control).
   1140      * Second octet is control.
   1141      * Third octet is first or second (when compressing protocol)
   1142      * octet of protocol.
   1143      * Fourth octet is second octet of protocol.
   1144      */
   1145     if (sc->sc_ilen == 0) {
   1146 	/* reset the first input mbuf */
   1147 	if (sc->sc_m == NULL) {
   1148 	    pppgetm(sc);
   1149 	    if (sc->sc_m == NULL) {
   1150 		if (sc->sc_flags & SC_DEBUG)
   1151 		    printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
   1152 		goto flush;
   1153 	    }
   1154 	}
   1155 	m = sc->sc_m;
   1156 	m->m_len = 0;
   1157 	m->m_data = M_DATASTART(sc->sc_m);
   1158 	sc->sc_mc = m;
   1159 	sc->sc_mp = mtod(m, char *);
   1160 	sc->sc_fcs = PPP_INITFCS;
   1161 	if (c != PPP_ALLSTATIONS) {
   1162 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
   1163 		if (sc->sc_flags & SC_DEBUG)
   1164 		    printf("%s: garbage received: 0x%x (need 0xFF)\n",
   1165 		    sc->sc_if.if_xname, c);
   1166 		goto flush;
   1167 	    }
   1168 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
   1169 	    *sc->sc_mp++ = PPP_UI;
   1170 	    sc->sc_ilen += 2;
   1171 	    m->m_len += 2;
   1172 	}
   1173     }
   1174     if (sc->sc_ilen == 1 && c != PPP_UI) {
   1175 	if (sc->sc_flags & SC_DEBUG)
   1176 	    printf("%s: missing UI (0x3), got 0x%x\n",
   1177 		sc->sc_if.if_xname, c);
   1178 	goto flush;
   1179     }
   1180     if (sc->sc_ilen == 2 && (c & 1) == 1) {
   1181 	/* a compressed protocol */
   1182 	*sc->sc_mp++ = 0;
   1183 	sc->sc_ilen++;
   1184 	sc->sc_mc->m_len++;
   1185     }
   1186     if (sc->sc_ilen == 3 && (c & 1) == 0) {
   1187 	if (sc->sc_flags & SC_DEBUG)
   1188 	    printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
   1189 		(sc->sc_mp[-1] << 8) + c);
   1190 	goto flush;
   1191     }
   1192 
   1193     /* packet beyond configured mru? */
   1194     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
   1195 	if (sc->sc_flags & SC_DEBUG)
   1196 	    printf("%s: packet too big\n", sc->sc_if.if_xname);
   1197 	goto flush;
   1198     }
   1199 
   1200     /* is this mbuf full? */
   1201     m = sc->sc_mc;
   1202     if (M_TRAILINGSPACE(m) <= 0) {
   1203 	if (m->m_next == NULL) {
   1204 	    pppgetm(sc);
   1205 	    if (m->m_next == NULL) {
   1206 		if (sc->sc_flags & SC_DEBUG)
   1207 		    printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
   1208 		goto flush;
   1209 	    }
   1210 	}
   1211 	sc->sc_mc = m = m->m_next;
   1212 	m->m_len = 0;
   1213 	m->m_data = M_DATASTART(m);
   1214 	sc->sc_mp = mtod(m, char *);
   1215     }
   1216 
   1217     ++m->m_len;
   1218     *sc->sc_mp++ = c;
   1219     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
   1220     return 0;
   1221 
   1222  flush:
   1223     if (!(sc->sc_flags & SC_FLUSH)) {
   1224 	s = spltty();
   1225 	sc->sc_if.if_ierrors++;
   1226 	sc->sc_stats.ppp_ierrors++;
   1227 	sc->sc_flags |= SC_FLUSH;
   1228 	splx(s);
   1229 	if (sc->sc_flags & SC_LOG_FLUSH)
   1230 	    ppplogchar(sc, c);
   1231     }
   1232     return 0;
   1233 }
   1234 
   1235 #define MAX_DUMP_BYTES	128
   1236 
   1237 static void
   1238 ppplogchar(struct ppp_softc *sc, int c)
   1239 {
   1240     if (c >= 0) {
   1241 	sc->sc_rawin.buf[sc->sc_rawin_start++] = c;
   1242 	if (sc->sc_rawin.count < sizeof(sc->sc_rawin.buf))
   1243 	    sc->sc_rawin.count++;
   1244     }
   1245     if (sc->sc_rawin_start >= sizeof(sc->sc_rawin.buf)
   1246 	|| (c < 0 && sc->sc_rawin_start > 0)) {
   1247 	if (sc->sc_flags & (SC_LOG_FLUSH|SC_LOG_RAWIN)) {
   1248 	    printf("%s input: ", sc->sc_if.if_xname);
   1249 	    pppdumpb(sc->sc_rawin.buf, sc->sc_rawin_start);
   1250 	}
   1251 	if (c < 0)
   1252 	    sc->sc_rawin.count = 0;
   1253 	sc->sc_rawin_start = 0;
   1254     }
   1255 }
   1256 
   1257 static void
   1258 pppdumpb(u_char *b, int l)
   1259 {
   1260     char bf[3*MAX_DUMP_BYTES+4];
   1261     char *bp = bf;
   1262 
   1263     while (l--) {
   1264 	if (bp >= bf + sizeof(bf) - 3) {
   1265 	    *bp++ = '>';
   1266 	    break;
   1267 	}
   1268 	*bp++ = hexdigits[*b >> 4]; /* convert byte to ascii hex */
   1269 	*bp++ = hexdigits[*b++ & 0xf];
   1270 	*bp++ = ' ';
   1271     }
   1272 
   1273     *bp = 0;
   1274     printf("%s\n", bf);
   1275 }
   1276 
   1277 static void
   1278 pppdumpframe(struct ppp_softc *sc, struct mbuf *m, int xmit)
   1279 {
   1280 	int i,lcount,copycount,count;
   1281 	char lbuf[16];
   1282 	char *data;
   1283 
   1284 	if (m == NULL)
   1285 		return;
   1286 
   1287 	for(count=m->m_len,data=mtod(m,char*);m != NULL;) {
   1288 		/* build a line of output */
   1289 		for(lcount=0;lcount < sizeof(lbuf);lcount += copycount) {
   1290 			if (!count) {
   1291 				m = m->m_next;
   1292 				if (m == NULL)
   1293 					break;
   1294 				count = m->m_len;
   1295 				data  = mtod(m,char*);
   1296 			}
   1297 			copycount = (count > sizeof(lbuf)-lcount) ?
   1298 					sizeof(lbuf)-lcount : count;
   1299 			bcopy(data,&lbuf[lcount],copycount);
   1300 			data  += copycount;
   1301 			count -= copycount;
   1302 		}
   1303 
   1304 		/* output line (hex 1st, then ascii) */
   1305 		printf("%s %s:", sc->sc_if.if_xname,
   1306 		    xmit ? "output" : "input ");
   1307 		for(i=0;i<lcount;i++)
   1308 			printf("%02x ",(u_char)lbuf[i]);
   1309 		for(;i<sizeof(lbuf);i++)
   1310 			printf("   ");
   1311 		for(i=0;i<lcount;i++)
   1312 			printf("%c",(lbuf[i] >= 040 &&
   1313 			    lbuf[i] <= 0176) ? lbuf[i] : '.');
   1314 		printf("\n");
   1315 	}
   1316 }
   1317