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