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