Home | History | Annotate | Line # | Download | only in net
ppp_tty.c revision 1.23.2.6
      1 /*	$NetBSD: ppp_tty.c,v 1.23.2.6 2002/04/01 07:48:26 nathanw 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) 1989 Carnegie Mellon University.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms are permitted
     12  * provided that the above copyright notice and this paragraph are
     13  * duplicated in all such forms and that any documentation,
     14  * advertising materials, and other materials related to such
     15  * distribution and use acknowledge that the software was developed
     16  * by Carnegie Mellon University.  The name of the
     17  * University may not be used to endorse or promote products derived
     18  * from this software without specific prior written permission.
     19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     21  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     22  *
     23  * Drew D. Perkins
     24  * Carnegie Mellon University
     25  * 4910 Forbes Ave.
     26  * Pittsburgh, PA 15213
     27  * (412) 268-8576
     28  * ddp (at) andrew.cmu.edu
     29  *
     30  * Based on:
     31  *	@(#)if_sl.c	7.6.1.2 (Berkeley) 2/15/89
     32  *
     33  * Copyright (c) 1987 Regents of the University of California.
     34  * All rights reserved.
     35  *
     36  * Redistribution and use in source and binary forms are permitted
     37  * provided that the above copyright notice and this paragraph are
     38  * duplicated in all such forms and that any documentation,
     39  * advertising materials, and other materials related to such
     40  * distribution and use acknowledge that the software was developed
     41  * by the University of California, Berkeley.  The name of the
     42  * University may not be used to endorse or promote products derived
     43  * from this software without specific prior written permission.
     44  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     45  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     46  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     47  *
     48  * Serial Line interface
     49  *
     50  * Rick Adams
     51  * Center for Seismic Studies
     52  * 1300 N 17th Street, Suite 1450
     53  * Arlington, Virginia 22209
     54  * (703)276-7900
     55  * rick (at) seismo.ARPA
     56  * seismo!rick
     57  *
     58  * Pounded on heavily by Chris Torek (chris (at) mimsy.umd.edu, umcp-cs!chris).
     59  * Converted to 4.3BSD Beta by Chris Torek.
     60  * Other changes made at Berkeley, based in part on code by Kirk Smith.
     61  *
     62  * Converted to 4.3BSD+ 386BSD by Brad Parker (brad (at) cayman.com)
     63  * Added VJ tcp header compression; more unified ioctls
     64  *
     65  * Extensively modified by Paul Mackerras (paulus (at) cs.anu.edu.au).
     66  * Cleaned up a lot of the mbuf-related code to fix bugs that
     67  * caused system crashes and packet corruption.  Changed pppstart
     68  * so that it doesn't just give up with a "collision" if the whole
     69  * packet doesn't fit in the output ring buffer.
     70  *
     71  * Added priority queueing for interactive IP packets, following
     72  * the model of if_sl.c, plus hooks for bpf.
     73  * Paul Mackerras (paulus (at) cs.anu.edu.au).
     74  */
     75 
     76 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
     77 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
     78 
     79 #include <sys/cdefs.h>
     80 __KERNEL_RCSID(0, "$NetBSD: ppp_tty.c,v 1.23.2.6 2002/04/01 07:48:26 nathanw Exp $");
     81 
     82 #include "ppp.h"
     83 
     84 #include "opt_ppp.h"
     85 #define VJC
     86 #define PPP_COMPRESS
     87 
     88 #include <sys/param.h>
     89 #include <sys/proc.h>
     90 #include <sys/mbuf.h>
     91 #include <sys/dkstat.h>
     92 #include <sys/socket.h>
     93 #include <sys/ioctl.h>
     94 #include <sys/file.h>
     95 #include <sys/tty.h>
     96 #include <sys/kernel.h>
     97 #include <sys/conf.h>
     98 #include <sys/vnode.h>
     99 #include <sys/systm.h>
    100 
    101 #include <net/if.h>
    102 #include <net/if_types.h>
    103 
    104 #ifdef VJC
    105 #include <netinet/in.h>
    106 #include <netinet/in_systm.h>
    107 #include <netinet/ip.h>
    108 #include <net/slcompress.h>
    109 #endif
    110 
    111 #include "bpfilter.h"
    112 #if NBPFILTER > 0 || defined(PPP_FILTER)
    113 #include <net/bpf.h>
    114 #endif
    115 #include <net/ppp_defs.h>
    116 #include <net/if_ppp.h>
    117 #include <net/if_pppvar.h>
    118 
    119 int	pppopen __P((dev_t dev, struct tty *tp));
    120 int	pppclose __P((struct tty *tp, int flag));
    121 int	pppread __P((struct tty *tp, struct uio *uio, int flag));
    122 int	pppwrite __P((struct tty *tp, struct uio *uio, int flag));
    123 int	ppptioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag,
    124 		       struct proc *));
    125 int	pppinput __P((int c, struct tty *tp));
    126 int	pppstart __P((struct tty *tp));
    127 
    128 static void	ppprcvframe __P((struct ppp_softc *sc, struct mbuf *m));
    129 static u_int16_t pppfcs __P((u_int16_t fcs, u_char *cp, int len));
    130 static void	pppsyncstart __P((struct ppp_softc *sc));
    131 static void	pppasyncstart __P((struct ppp_softc *));
    132 static void	pppasyncctlp __P((struct ppp_softc *));
    133 static void	pppasyncrelinq __P((struct ppp_softc *));
    134 static void	ppp_timeout __P((void *));
    135 static void	pppgetm __P((struct ppp_softc *sc));
    136 static void	pppdumpb __P((u_char *b, int l));
    137 static void	ppplogchar __P((struct ppp_softc *, int));
    138 static void	pppdumpframe __P((struct ppp_softc *sc, struct mbuf* m,
    139     int xmit));
    140 
    141 /*
    142  * Some useful mbuf macros not in mbuf.h.
    143  */
    144 #define M_IS_CLUSTER(m)	((m)->m_flags & M_EXT)
    145 
    146 #define M_DATASTART(m)	\
    147 	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
    148 	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
    149 
    150 #define M_DATASIZE(m)	\
    151 	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
    152 	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
    153 
    154 /*
    155  * Does c need to be escaped?
    156  */
    157 #define ESCAPE_P(c)	(sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
    158 
    159 /*
    160  * Procedures for using an async tty interface for PPP.
    161  */
    162 
    163 /* This is a NetBSD-1.0 or later kernel. */
    164 #define CCOUNT(q)	((q)->c_cc)
    165 
    166 #define PPP_LOWAT	100	/* Process more output when < LOWAT on queue */
    167 #define	PPP_HIWAT	400	/* Don't start a new packet if HIWAT on que */
    168 
    169 /*
    170  * Line specific open routine for async tty devices.
    171  * Attach the given tty to the first available ppp unit.
    172  * Called from device open routine or ttioctl.
    173  */
    174 /* ARGSUSED */
    175 int
    176 pppopen(dev, tp)
    177     dev_t dev;
    178     struct tty *tp;
    179 {
    180     struct proc *p = curproc->l_proc;		/* XXX */
    181     struct ppp_softc *sc;
    182     int error, s;
    183 
    184     if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    185 	return (error);
    186 
    187     s = spltty();
    188 
    189     if (tp->t_linesw->l_no == PPPDISC) {
    190 	sc = (struct ppp_softc *) tp->t_sc;
    191 	if (sc != NULL && sc->sc_devp == (void *) tp) {
    192 	    splx(s);
    193 	    return (0);
    194 	}
    195     }
    196 
    197     if ((sc = pppalloc(p->p_pid)) == NULL) {
    198 	splx(s);
    199 	return ENXIO;
    200     }
    201 
    202     if (sc->sc_relinq)
    203 	(*sc->sc_relinq)(sc);	/* get previous owner to relinquish the unit */
    204 
    205 #if NBPFILTER > 0
    206     /* Switch DLT to PPP-over-serial. */
    207     bpf_change_type(&sc->sc_if, DLT_PPP_SERIAL, PPP_HDRLEN);
    208 #endif
    209 
    210     sc->sc_ilen = 0;
    211     sc->sc_m = NULL;
    212     memset(sc->sc_asyncmap, 0, sizeof(sc->sc_asyncmap));
    213     sc->sc_asyncmap[0] = 0xffffffff;
    214     sc->sc_asyncmap[3] = 0x60000000;
    215     sc->sc_rasyncmap = 0;
    216     sc->sc_devp = (void *) tp;
    217     sc->sc_start = pppasyncstart;
    218     sc->sc_ctlp = pppasyncctlp;
    219     sc->sc_relinq = pppasyncrelinq;
    220     sc->sc_outm = NULL;
    221     pppgetm(sc);
    222     sc->sc_if.if_flags |= IFF_RUNNING;
    223     sc->sc_if.if_baudrate = tp->t_ospeed;
    224 
    225     tp->t_sc = (caddr_t) sc;
    226     ttyflush(tp, FREAD | FWRITE);
    227 
    228     splx(s);
    229     return (0);
    230 }
    231 
    232 /*
    233  * Line specific close routine, called from device close routine
    234  * and from ttioctl.
    235  * Detach the tty from the ppp unit.
    236  * Mimics part of ttyclose().
    237  */
    238 int
    239 pppclose(tp, flag)
    240     struct tty *tp;
    241     int flag;
    242 {
    243     struct ppp_softc *sc;
    244     int s;
    245 
    246     s = spltty();
    247     ttyflush(tp, FREAD|FWRITE);
    248     tp->t_linesw = linesw[0]; /* default line discipline */
    249     sc = (struct ppp_softc *) tp->t_sc;
    250     if (sc != NULL) {
    251 	tp->t_sc = NULL;
    252 	if (tp == (struct tty *) sc->sc_devp) {
    253 	    pppasyncrelinq(sc);
    254 	    pppdealloc(sc);
    255 	}
    256     }
    257     splx(s);
    258     return 0;
    259 }
    260 
    261 /*
    262  * Relinquish the interface unit to another device.
    263  */
    264 static void
    265 pppasyncrelinq(sc)
    266     struct ppp_softc *sc;
    267 {
    268     int s;
    269 
    270 #if NBPFILTER > 0
    271     /* Change DLT to back none. */
    272     bpf_change_type(&sc->sc_if, DLT_NULL, 0);
    273 #endif
    274 
    275     s = spltty();
    276     if (sc->sc_outm) {
    277 	m_freem(sc->sc_outm);
    278 	sc->sc_outm = NULL;
    279     }
    280     if (sc->sc_m) {
    281 	m_freem(sc->sc_m);
    282 	sc->sc_m = NULL;
    283     }
    284     if (sc->sc_flags & SC_TIMEOUT) {
    285 	callout_stop(&sc->sc_timo_ch);
    286 	sc->sc_flags &= ~SC_TIMEOUT;
    287     }
    288     splx(s);
    289 }
    290 
    291 /*
    292  * Line specific (tty) read routine.
    293  */
    294 int
    295 pppread(tp, uio, flag)
    296     struct tty *tp;
    297     struct uio *uio;
    298     int flag;
    299 {
    300     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    301     struct mbuf *m, *m0;
    302     int s;
    303     int error = 0;
    304 
    305     if (sc == NULL)
    306 	return 0;
    307     /*
    308      * Loop waiting for input, checking that nothing disasterous
    309      * happens in the meantime.
    310      */
    311     s = spltty();
    312     for (;;) {
    313 	if (tp != (struct tty *) sc->sc_devp ||
    314 	    tp->t_linesw->l_no != PPPDISC) {
    315 	    splx(s);
    316 	    return 0;
    317 	}
    318 	if (sc->sc_inq.ifq_head != NULL)
    319 	    break;
    320 	if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
    321 	    && (tp->t_state & TS_ISOPEN)) {
    322 	    splx(s);
    323 	    return 0;		/* end of file */
    324 	}
    325 	if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
    326 	    splx(s);
    327 	    return (EWOULDBLOCK);
    328 	}
    329 	error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
    330 	if (error) {
    331 	    splx(s);
    332 	    return error;
    333 	}
    334     }
    335 
    336     /* Pull place-holder byte out of canonical queue */
    337     getc(&tp->t_canq);
    338 
    339     /* Get the packet from the input queue */
    340     IF_DEQUEUE(&sc->sc_inq, m0);
    341     splx(s);
    342 
    343     for (m = m0; m && uio->uio_resid; m = m->m_next)
    344 	if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
    345 	    break;
    346     m_freem(m0);
    347     return (error);
    348 }
    349 
    350 /*
    351  * Line specific (tty) write routine.
    352  */
    353 int
    354 pppwrite(tp, uio, flag)
    355     struct tty *tp;
    356     struct uio *uio;
    357     int flag;
    358 {
    359     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    360     struct mbuf *m, *m0, **mp;
    361     struct sockaddr dst;
    362     int len, error;
    363 
    364     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    365 	return 0;		/* wrote 0 bytes */
    366     if (tp->t_linesw->l_no != PPPDISC)
    367 	return (EINVAL);
    368     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    369 	return EIO;
    370     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
    371 	uio->uio_resid < PPP_HDRLEN)
    372 	return (EMSGSIZE);
    373     for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
    374 	MGET(m, M_WAIT, MT_DATA);
    375 	if ((*mp = m) == NULL) {
    376 	    m_freem(m0);
    377 	    return (ENOBUFS);
    378 	}
    379 	m->m_len = 0;
    380 	if (uio->uio_resid >= MCLBYTES / 2)
    381 	    MCLGET(m, M_DONTWAIT);
    382 	len = M_TRAILINGSPACE(m);
    383 	if (len > uio->uio_resid)
    384 	    len = uio->uio_resid;
    385 	if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
    386 	    m_freem(m0);
    387 	    return (error);
    388 	}
    389 	m->m_len = len;
    390     }
    391     dst.sa_family = AF_UNSPEC;
    392     bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
    393     m0->m_data += PPP_HDRLEN;
    394     m0->m_len -= PPP_HDRLEN;
    395     return ((*sc->sc_if.if_output)(&sc->sc_if, m0, &dst, (struct rtentry *)0));
    396 }
    397 
    398 /*
    399  * Line specific (tty) ioctl routine.
    400  * This discipline requires that tty device drivers call
    401  * the line specific l_ioctl routine from their ioctl routines.
    402  */
    403 /* ARGSUSED */
    404 int
    405 ppptioctl(tp, cmd, data, flag, p)
    406     struct tty *tp;
    407     u_long cmd;
    408     caddr_t data;
    409     int flag;
    410     struct proc *p;
    411 {
    412     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    413     int error, s;
    414 
    415     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    416 	return (EPASSTHROUGH);
    417 
    418     error = 0;
    419     switch (cmd) {
    420     case TIOCRCVFRAME:
    421     	ppprcvframe(sc,*((struct mbuf **)data));
    422 	break;
    423 
    424     case PPPIOCSASYNCMAP:
    425 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    426 	    break;
    427 	sc->sc_asyncmap[0] = *(u_int *)data;
    428 	break;
    429 
    430     case PPPIOCGASYNCMAP:
    431 	*(u_int *)data = sc->sc_asyncmap[0];
    432 	break;
    433 
    434     case PPPIOCSRASYNCMAP:
    435 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    436 	    break;
    437 	sc->sc_rasyncmap = *(u_int *)data;
    438 	break;
    439 
    440     case PPPIOCGRASYNCMAP:
    441 	*(u_int *)data = sc->sc_rasyncmap;
    442 	break;
    443 
    444     case PPPIOCSXASYNCMAP:
    445 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    446 	    break;
    447 	s = spltty();
    448 	bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
    449 	sc->sc_asyncmap[1] = 0;		    /* mustn't escape 0x20 - 0x3f */
    450 	sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
    451 	sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
    452 	splx(s);
    453 	break;
    454 
    455     case PPPIOCGXASYNCMAP:
    456 	bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
    457 	break;
    458 
    459     default:
    460 	error = pppioctl(sc, cmd, data, flag, p);
    461 	if (error == 0 && cmd == PPPIOCSMRU)
    462 	    pppgetm(sc);
    463     }
    464 
    465     return error;
    466 }
    467 
    468 /* receive a complete ppp frame from device in synchronous
    469  * hdlc mode. caller gives up ownership of mbuf
    470  */
    471 static void
    472 ppprcvframe(sc, m)
    473 	struct ppp_softc *sc;
    474 	struct mbuf *m;
    475 {
    476 	int len, s;
    477 	struct mbuf *n;
    478 	u_char hdr[4];
    479 	int hlen,count;
    480 
    481 	for (n=m,len=0;n != NULL;n = n->m_next)
    482 		len += n->m_len;
    483 	if (len==0) {
    484 		m_freem(m);
    485 		return;
    486 	}
    487 
    488 	/* extract PPP header from mbuf chain (1 to 4 bytes) */
    489 	for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
    490 		count = (sizeof(hdr)-hlen) < n->m_len ?
    491 				sizeof(hdr)-hlen : n->m_len;
    492 		bcopy(mtod(n,u_char*),&hdr[hlen],count);
    493 		hlen+=count;
    494 	}
    495 
    496 	s = spltty();
    497 
    498 	/* if AFCF compressed then prepend AFCF */
    499 	if (hdr[0] != PPP_ALLSTATIONS) {
    500 		if (sc->sc_flags & SC_REJ_COMP_AC) {
    501 			if (sc->sc_flags & SC_DEBUG)
    502 				printf(
    503 				    "%s: garbage received: 0x%x (need 0xFF)\n",
    504 				    sc->sc_if.if_xname, hdr[0]);
    505 				goto bail;
    506 			}
    507 		M_PREPEND(m,2,M_DONTWAIT);
    508 		if (m==NULL) {
    509 			splx(s);
    510 			return;
    511 		}
    512 		hdr[3] = hdr[1];
    513 		hdr[2] = hdr[0];
    514 		hdr[0] = PPP_ALLSTATIONS;
    515 		hdr[1] = PPP_UI;
    516 		len += 2;
    517 	}
    518 
    519 	/* if protocol field compressed, add MSB of protocol field = 0 */
    520 	if (hdr[2] & 1) {
    521 		/* a compressed protocol */
    522 		M_PREPEND(m,1,M_DONTWAIT);
    523 		if (m==NULL) {
    524 			splx(s);
    525 			return;
    526 		}
    527 		hdr[3] = hdr[2];
    528 		hdr[2] = 0;
    529 		len++;
    530 	}
    531 
    532 	/* valid LSB of protocol field has bit0 set */
    533 	if (!(hdr[3] & 1)) {
    534 		if (sc->sc_flags & SC_DEBUG)
    535 			printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
    536 				(hdr[2] << 8) + hdr[3]);
    537 			goto bail;
    538 	}
    539 
    540 	/* packet beyond configured mru? */
    541 	if (len > sc->sc_mru + PPP_HDRLEN) {
    542 		if (sc->sc_flags & SC_DEBUG)
    543 			printf("%s: packet too big\n", sc->sc_if.if_xname);
    544 		goto bail;
    545 	}
    546 
    547 	/* add expanded 4 byte header to mbuf chain */
    548 	for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
    549 		count = (sizeof(hdr)-hlen) < n->m_len ?
    550 				sizeof(hdr)-hlen : n->m_len;
    551 		bcopy(&hdr[hlen],mtod(n,u_char*),count);
    552 		hlen+=count;
    553 	}
    554 
    555 	/* if_ppp.c requires the PPP header and IP header */
    556 	/* to be contiguous */
    557 	count = len < MHLEN ? len : MHLEN;
    558 	if (m->m_len < count) {
    559 		m = m_pullup(m,count);
    560 		if (m==NULL)
    561 			goto bail;
    562 	}
    563 
    564 	sc->sc_stats.ppp_ibytes += len;
    565 
    566 	if (sc->sc_flags & SC_LOG_RAWIN)
    567 		pppdumpframe(sc,m,0);
    568 
    569 	ppppktin(sc, m, 0);
    570 	splx(s);
    571 	return;
    572 bail:
    573 	m_freem(m);
    574 	splx(s);
    575 }
    576 
    577 /*
    578  * FCS lookup table as calculated by genfcstab.
    579  */
    580 static const u_int16_t fcstab[256] = {
    581 	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
    582 	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
    583 	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
    584 	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
    585 	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
    586 	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
    587 	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
    588 	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
    589 	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
    590 	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
    591 	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
    592 	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
    593 	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
    594 	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
    595 	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
    596 	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
    597 	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
    598 	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
    599 	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
    600 	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
    601 	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
    602 	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
    603 	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
    604 	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
    605 	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
    606 	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
    607 	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
    608 	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
    609 	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
    610 	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
    611 	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
    612 	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
    613 };
    614 
    615 /*
    616  * Calculate a new FCS given the current FCS and the new data.
    617  */
    618 static u_int16_t
    619 pppfcs(fcs, cp, len)
    620     u_int16_t fcs;
    621     u_char *cp;
    622     int len;
    623 {
    624     while (len--)
    625 	fcs = PPP_FCS(fcs, *cp++);
    626     return (fcs);
    627 }
    628 
    629 /* This gets called at splsoftnet from pppasyncstart at various times
    630  * when there is data ready to be sent.
    631  */
    632 static void
    633 pppsyncstart(sc)
    634 	struct ppp_softc *sc;
    635 {
    636 	struct tty *tp = (struct tty *) sc->sc_devp;
    637 	struct mbuf *m, *n;
    638 	int len;
    639 
    640 	for(m = sc->sc_outm;;) {
    641 		if (m == NULL) {
    642 			m = ppp_dequeue(sc);	/* get new packet */
    643 			if (m == NULL)
    644 				break;		/* no more packets */
    645 			if (sc->sc_flags & SC_DEBUG)
    646 				pppdumpframe(sc,m,1);
    647 		}
    648 		for(n=m,len=0;n!=NULL;n=n->m_next)
    649 			len += n->m_len;
    650 
    651 		/* call device driver IOCTL to transmit a frame */
    652 		if ((*cdevsw[major(tp->t_dev)].d_ioctl)
    653 			(tp->t_dev, TIOCXMTFRAME, (caddr_t)&m, 0, 0)) {
    654 			/* busy or error, set as current packet */
    655 			sc->sc_outm = m;
    656 			break;
    657 		}
    658 		sc->sc_outm = m = NULL;
    659 		sc->sc_stats.ppp_obytes += len;
    660 	}
    661 }
    662 
    663 /*
    664  * This gets called at splsoftnet from if_ppp.c at various times
    665  * when there is data ready to be sent.
    666  */
    667 static void
    668 pppasyncstart(sc)
    669     struct ppp_softc *sc;
    670 {
    671     struct tty *tp = (struct tty *) sc->sc_devp;
    672     struct mbuf *m;
    673     int len;
    674     u_char *start, *stop, *cp;
    675     int n, ndone, done, idle;
    676     struct mbuf *m2;
    677     int s;
    678 
    679     if (sc->sc_flags & SC_SYNC){
    680 	pppsyncstart(sc);
    681 	return;
    682     }
    683 
    684     idle = 0;
    685     while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
    686 	/*
    687 	 * See if we have an existing packet partly sent.
    688 	 * If not, get a new packet and start sending it.
    689 	 */
    690 	m = sc->sc_outm;
    691 	if (m == NULL) {
    692 	    /*
    693 	     * Get another packet to be sent.
    694 	     */
    695 	    m = ppp_dequeue(sc);
    696 	    if (m == NULL) {
    697 		idle = 1;
    698 		break;
    699 	    }
    700 
    701 	    /*
    702 	     * The extra PPP_FLAG will start up a new packet, and thus
    703 	     * will flush any accumulated garbage.  We do this whenever
    704 	     * the line may have been idle for some time.
    705 	     */
    706 	    if (CCOUNT(&tp->t_outq) == 0) {
    707 		++sc->sc_stats.ppp_obytes;
    708 		(void) putc(PPP_FLAG, &tp->t_outq);
    709 	    }
    710 
    711 	    /* Calculate the FCS for the first mbuf's worth. */
    712 	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
    713 	}
    714 
    715 	for (;;) {
    716 	    start = mtod(m, u_char *);
    717 	    len = m->m_len;
    718 	    stop = start + len;
    719 	    while (len > 0) {
    720 		/*
    721 		 * Find out how many bytes in the string we can
    722 		 * handle without doing something special.
    723 		 */
    724 		for (cp = start; cp < stop; cp++)
    725 		    if (ESCAPE_P(*cp))
    726 			break;
    727 		n = cp - start;
    728 		if (n) {
    729 		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
    730 		    ndone = n - b_to_q(start, n, &tp->t_outq);
    731 		    len -= ndone;
    732 		    start += ndone;
    733 		    sc->sc_stats.ppp_obytes += ndone;
    734 
    735 		    if (ndone < n)
    736 			break;	/* packet doesn't fit */
    737 		}
    738 		/*
    739 		 * If there are characters left in the mbuf,
    740 		 * the first one must be special.
    741 		 * Put it out in a different form.
    742 		 */
    743 		if (len) {
    744 		    s = spltty();
    745 		    if (putc(PPP_ESCAPE, &tp->t_outq)) {
    746 			splx(s);
    747 			break;
    748 		    }
    749 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
    750 			(void) unputc(&tp->t_outq);
    751 			splx(s);
    752 			break;
    753 		    }
    754 		    splx(s);
    755 		    sc->sc_stats.ppp_obytes += 2;
    756 		    start++;
    757 		    len--;
    758 		}
    759 	    }
    760 
    761 	    /*
    762 	     * If we didn't empty this mbuf, remember where we're up to.
    763 	     * If we emptied the last mbuf, try to add the FCS and closing
    764 	     * flag, and if we can't, leave sc_outm pointing to m, but with
    765 	     * m->m_len == 0, to remind us to output the FCS and flag later.
    766 	     */
    767 	    done = len == 0;
    768 	    if (done && m->m_next == NULL) {
    769 		u_char *p, *q;
    770 		int c;
    771 		u_char endseq[8];
    772 
    773 		/*
    774 		 * We may have to escape the bytes in the FCS.
    775 		 */
    776 		p = endseq;
    777 		c = ~sc->sc_outfcs & 0xFF;
    778 		if (ESCAPE_P(c)) {
    779 		    *p++ = PPP_ESCAPE;
    780 		    *p++ = c ^ PPP_TRANS;
    781 		} else
    782 		    *p++ = c;
    783 		c = (~sc->sc_outfcs >> 8) & 0xFF;
    784 		if (ESCAPE_P(c)) {
    785 		    *p++ = PPP_ESCAPE;
    786 		    *p++ = c ^ PPP_TRANS;
    787 		} else
    788 		    *p++ = c;
    789 		*p++ = PPP_FLAG;
    790 
    791 		/*
    792 		 * Try to output the FCS and flag.  If the bytes
    793 		 * don't all fit, back out.
    794 		 */
    795 		s = spltty();
    796 		for (q = endseq; q < p; ++q)
    797 		    if (putc(*q, &tp->t_outq)) {
    798 			done = 0;
    799 			for (; q > endseq; --q)
    800 			    unputc(&tp->t_outq);
    801 			break;
    802 		    }
    803 		splx(s);
    804 		if (done)
    805 		    sc->sc_stats.ppp_obytes += q - endseq;
    806 	    }
    807 
    808 	    if (!done) {
    809 		/* remember where we got to */
    810 		m->m_data = start;
    811 		m->m_len = len;
    812 		break;
    813 	    }
    814 
    815 	    /* Finished with this mbuf; free it and move on. */
    816 	    MFREE(m, m2);
    817 	    m = m2;
    818 	    if (m == NULL) {
    819 		/* Finished a packet */
    820 		break;
    821 	    }
    822 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
    823 	}
    824 
    825 	/*
    826 	 * If m == NULL, we have finished a packet.
    827 	 * If m != NULL, we've either done as much work this time
    828 	 * as we need to, or else we've filled up the output queue.
    829 	 */
    830 	sc->sc_outm = m;
    831 	if (m)
    832 	    break;
    833     }
    834 
    835     /* Call pppstart to start output again if necessary. */
    836     s = spltty();
    837     pppstart(tp);
    838 
    839     /*
    840      * This timeout is needed for operation on a pseudo-tty,
    841      * because the pty code doesn't call pppstart after it has
    842      * drained the t_outq.
    843      */
    844     if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
    845 	callout_reset(&sc->sc_timo_ch, 1, ppp_timeout, sc);
    846 	sc->sc_flags |= SC_TIMEOUT;
    847     }
    848 
    849     splx(s);
    850 }
    851 
    852 /*
    853  * This gets called when a received packet is placed on
    854  * the inq, at splsoftnet.
    855  */
    856 static void
    857 pppasyncctlp(sc)
    858     struct ppp_softc *sc;
    859 {
    860     struct tty *tp;
    861     int s;
    862 
    863     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
    864     s = spltty();
    865     tp = (struct tty *) sc->sc_devp;
    866     putc(0, &tp->t_canq);
    867     ttwakeup(tp);
    868     splx(s);
    869 }
    870 
    871 /*
    872  * Start output on async tty interface.  If the transmit queue
    873  * has drained sufficiently, arrange for pppasyncstart to be
    874  * called later at splsoftnet.
    875  * Called at spltty or higher.
    876  */
    877 int
    878 pppstart(tp)
    879     struct tty *tp;
    880 {
    881     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    882 
    883     /*
    884      * If there is stuff in the output queue, send it now.
    885      * We are being called in lieu of ttstart and must do what it would.
    886      */
    887     if (tp->t_oproc != NULL)
    888 	(*tp->t_oproc)(tp);
    889 
    890     /*
    891      * If the transmit queue has drained and the tty has not hung up
    892      * or been disconnected from the ppp unit, then tell if_ppp.c that
    893      * we need more output.
    894      */
    895     if ((CCOUNT(&tp->t_outq) >= PPP_LOWAT)
    896 	&& ((sc == NULL) || (sc->sc_flags & SC_TIMEOUT)))
    897 	return 0;
    898 #ifdef ALTQ
    899     /*
    900      * if ALTQ is enabled, don't invoke NETISR_PPP.
    901      * pppintr() could loop without doing anything useful
    902      * under rate-limiting.
    903      */
    904     if (ALTQ_IS_ENABLED(&sc->sc_if.if_snd))
    905 	return 0;
    906 #endif
    907     if (!((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    908 	&& sc != NULL && tp == (struct tty *) sc->sc_devp) {
    909 	ppp_restart(sc);
    910     }
    911 
    912     return 0;
    913 }
    914 
    915 /*
    916  * Timeout routine - try to start some more output.
    917  */
    918 static void
    919 ppp_timeout(x)
    920     void *x;
    921 {
    922     struct ppp_softc *sc = (struct ppp_softc *) x;
    923     struct tty *tp = (struct tty *) sc->sc_devp;
    924     int s;
    925 
    926     s = spltty();
    927     sc->sc_flags &= ~SC_TIMEOUT;
    928     pppstart(tp);
    929     splx(s);
    930 }
    931 
    932 /*
    933  * Allocate enough mbuf to handle current MRU.
    934  */
    935 static void
    936 pppgetm(sc)
    937     struct ppp_softc *sc;
    938 {
    939     struct mbuf *m, **mp;
    940     int len;
    941 
    942     mp = &sc->sc_m;
    943     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
    944 	if ((m = *mp) == NULL) {
    945 	    MGETHDR(m, M_DONTWAIT, MT_DATA);
    946 	    if (m == NULL)
    947 		break;
    948 	    *mp = m;
    949 	    MCLGET(m, M_DONTWAIT);
    950 	}
    951 	len -= M_DATASIZE(m);
    952 	mp = &m->m_next;
    953     }
    954 }
    955 
    956 /*
    957  * tty interface receiver interrupt.
    958  */
    959 static const unsigned paritytab[8] = {
    960     0x96696996, 0x69969669, 0x69969669, 0x96696996,
    961     0x69969669, 0x96696996, 0x96696996, 0x69969669
    962 };
    963 
    964 int
    965 pppinput(c, tp)
    966     int c;
    967     struct tty *tp;
    968 {
    969     struct ppp_softc *sc;
    970     struct mbuf *m;
    971     int ilen, s;
    972 
    973     sc = (struct ppp_softc *) tp->t_sc;
    974     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    975 	return 0;
    976 
    977     ++tk_nin;
    978     ++sc->sc_stats.ppp_ibytes;
    979 
    980     if (c & TTY_FE) {
    981 	/* framing error or overrun on this char - abort packet */
    982 	if (sc->sc_flags & SC_DEBUG)
    983 	    printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
    984 	goto flush;
    985     }
    986 
    987     c &= 0xff;
    988 
    989     /*
    990      * Handle software flow control of output.
    991      */
    992     if (tp->t_iflag & IXON) {
    993 	if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
    994 	    if ((tp->t_state & TS_TTSTOP) == 0) {
    995 		tp->t_state |= TS_TTSTOP;
    996 		(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
    997 	    }
    998 	    return 0;
    999 	}
   1000 	if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
   1001 	    tp->t_state &= ~TS_TTSTOP;
   1002 	    if (tp->t_oproc != NULL)
   1003 		(*tp->t_oproc)(tp);
   1004 	    return 0;
   1005 	}
   1006     }
   1007 
   1008     s = spltty();
   1009     if (c & 0x80)
   1010 	sc->sc_flags |= SC_RCV_B7_1;
   1011     else
   1012 	sc->sc_flags |= SC_RCV_B7_0;
   1013     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
   1014 	sc->sc_flags |= SC_RCV_ODDP;
   1015     else
   1016 	sc->sc_flags |= SC_RCV_EVNP;
   1017     splx(s);
   1018 
   1019     if (sc->sc_flags & SC_LOG_RAWIN)
   1020 	ppplogchar(sc, c);
   1021 
   1022     if (c == PPP_FLAG) {
   1023 	ilen = sc->sc_ilen;
   1024 	sc->sc_ilen = 0;
   1025 
   1026 	if (sc->sc_rawin_count > 0)
   1027 	    ppplogchar(sc, -1);
   1028 
   1029 	/*
   1030 	 * If SC_ESCAPED is set, then we've seen the packet
   1031 	 * abort sequence "}~".
   1032 	 */
   1033 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
   1034 	    || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
   1035 	    s = spltty();
   1036 	    sc->sc_flags |= SC_PKTLOST;	/* note the dropped packet */
   1037 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
   1038 		if (sc->sc_flags & SC_DEBUG)
   1039 		    printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
   1040 			sc->sc_fcs);
   1041 		sc->sc_if.if_ierrors++;
   1042 		sc->sc_stats.ppp_ierrors++;
   1043 	    } else
   1044 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
   1045 	    splx(s);
   1046 	    return 0;
   1047 	}
   1048 
   1049 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
   1050 	    if (ilen) {
   1051 		if (sc->sc_flags & SC_DEBUG)
   1052 		    printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
   1053 		s = spltty();
   1054 		sc->sc_if.if_ierrors++;
   1055 		sc->sc_stats.ppp_ierrors++;
   1056 		sc->sc_flags |= SC_PKTLOST;
   1057 		splx(s);
   1058 	    }
   1059 	    return 0;
   1060 	}
   1061 
   1062 	/*
   1063 	 * Remove FCS trailer.  Somewhat painful...
   1064 	 */
   1065 	ilen -= 2;
   1066 	if (--sc->sc_mc->m_len == 0) {
   1067 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
   1068 		;
   1069 	    sc->sc_mc = m;
   1070 	}
   1071 	sc->sc_mc->m_len--;
   1072 
   1073 	/* excise this mbuf chain */
   1074 	m = sc->sc_m;
   1075 	sc->sc_m = sc->sc_mc->m_next;
   1076 	sc->sc_mc->m_next = NULL;
   1077 
   1078 	ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
   1079 	if (sc->sc_flags & SC_PKTLOST) {
   1080 	    s = spltty();
   1081 	    sc->sc_flags &= ~SC_PKTLOST;
   1082 	    splx(s);
   1083 	}
   1084 
   1085 	pppgetm(sc);
   1086 	return 0;
   1087     }
   1088 
   1089     if (sc->sc_flags & SC_FLUSH) {
   1090 	if (sc->sc_flags & SC_LOG_FLUSH)
   1091 	    ppplogchar(sc, c);
   1092 	return 0;
   1093     }
   1094 
   1095     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
   1096 	return 0;
   1097 
   1098     s = spltty();
   1099     if (sc->sc_flags & SC_ESCAPED) {
   1100 	sc->sc_flags &= ~SC_ESCAPED;
   1101 	c ^= PPP_TRANS;
   1102     } else if (c == PPP_ESCAPE) {
   1103 	sc->sc_flags |= SC_ESCAPED;
   1104 	splx(s);
   1105 	return 0;
   1106     }
   1107     splx(s);
   1108 
   1109     /*
   1110      * Initialize buffer on first octet received.
   1111      * First octet could be address or protocol (when compressing
   1112      * address/control).
   1113      * Second octet is control.
   1114      * Third octet is first or second (when compressing protocol)
   1115      * octet of protocol.
   1116      * Fourth octet is second octet of protocol.
   1117      */
   1118     if (sc->sc_ilen == 0) {
   1119 	/* reset the first input mbuf */
   1120 	if (sc->sc_m == NULL) {
   1121 	    pppgetm(sc);
   1122 	    if (sc->sc_m == NULL) {
   1123 		if (sc->sc_flags & SC_DEBUG)
   1124 		    printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
   1125 		goto flush;
   1126 	    }
   1127 	}
   1128 	m = sc->sc_m;
   1129 	m->m_len = 0;
   1130 	m->m_data = M_DATASTART(sc->sc_m);
   1131 	sc->sc_mc = m;
   1132 	sc->sc_mp = mtod(m, char *);
   1133 	sc->sc_fcs = PPP_INITFCS;
   1134 	if (c != PPP_ALLSTATIONS) {
   1135 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
   1136 		if (sc->sc_flags & SC_DEBUG)
   1137 		    printf("%s: garbage received: 0x%x (need 0xFF)\n",
   1138 		    sc->sc_if.if_xname, c);
   1139 		goto flush;
   1140 	    }
   1141 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
   1142 	    *sc->sc_mp++ = PPP_UI;
   1143 	    sc->sc_ilen += 2;
   1144 	    m->m_len += 2;
   1145 	}
   1146     }
   1147     if (sc->sc_ilen == 1 && c != PPP_UI) {
   1148 	if (sc->sc_flags & SC_DEBUG)
   1149 	    printf("%s: missing UI (0x3), got 0x%x\n",
   1150 		sc->sc_if.if_xname, c);
   1151 	goto flush;
   1152     }
   1153     if (sc->sc_ilen == 2 && (c & 1) == 1) {
   1154 	/* a compressed protocol */
   1155 	*sc->sc_mp++ = 0;
   1156 	sc->sc_ilen++;
   1157 	sc->sc_mc->m_len++;
   1158     }
   1159     if (sc->sc_ilen == 3 && (c & 1) == 0) {
   1160 	if (sc->sc_flags & SC_DEBUG)
   1161 	    printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
   1162 		(sc->sc_mp[-1] << 8) + c);
   1163 	goto flush;
   1164     }
   1165 
   1166     /* packet beyond configured mru? */
   1167     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
   1168 	if (sc->sc_flags & SC_DEBUG)
   1169 	    printf("%s: packet too big\n", sc->sc_if.if_xname);
   1170 	goto flush;
   1171     }
   1172 
   1173     /* is this mbuf full? */
   1174     m = sc->sc_mc;
   1175     if (M_TRAILINGSPACE(m) <= 0) {
   1176 	if (m->m_next == NULL) {
   1177 	    pppgetm(sc);
   1178 	    if (m->m_next == NULL) {
   1179 		if (sc->sc_flags & SC_DEBUG)
   1180 		    printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
   1181 		goto flush;
   1182 	    }
   1183 	}
   1184 	sc->sc_mc = m = m->m_next;
   1185 	m->m_len = 0;
   1186 	m->m_data = M_DATASTART(m);
   1187 	sc->sc_mp = mtod(m, char *);
   1188     }
   1189 
   1190     ++m->m_len;
   1191     *sc->sc_mp++ = c;
   1192     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
   1193     return 0;
   1194 
   1195  flush:
   1196     if (!(sc->sc_flags & SC_FLUSH)) {
   1197 	s = spltty();
   1198 	sc->sc_if.if_ierrors++;
   1199 	sc->sc_stats.ppp_ierrors++;
   1200 	sc->sc_flags |= SC_FLUSH;
   1201 	splx(s);
   1202 	if (sc->sc_flags & SC_LOG_FLUSH)
   1203 	    ppplogchar(sc, c);
   1204     }
   1205     return 0;
   1206 }
   1207 
   1208 #define MAX_DUMP_BYTES	128
   1209 
   1210 static void
   1211 ppplogchar(sc, c)
   1212     struct ppp_softc *sc;
   1213     int c;
   1214 {
   1215     if (c >= 0)
   1216 	sc->sc_rawin[sc->sc_rawin_count++] = c;
   1217     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
   1218 	|| (c < 0 && sc->sc_rawin_count > 0)) {
   1219 	printf("%s input: ", sc->sc_if.if_xname);
   1220 	pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
   1221 	sc->sc_rawin_count = 0;
   1222     }
   1223 }
   1224 
   1225 static void
   1226 pppdumpb(b, l)
   1227     u_char *b;
   1228     int l;
   1229 {
   1230     char buf[3*MAX_DUMP_BYTES+4];
   1231     char *bp = buf;
   1232     static char digits[] = "0123456789abcdef";
   1233 
   1234     while (l--) {
   1235 	if (bp >= buf + sizeof(buf) - 3) {
   1236 	    *bp++ = '>';
   1237 	    break;
   1238 	}
   1239 	*bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
   1240 	*bp++ = digits[*b++ & 0xf];
   1241 	*bp++ = ' ';
   1242     }
   1243 
   1244     *bp = 0;
   1245     printf("%s\n", buf);
   1246 }
   1247 
   1248 static void
   1249 pppdumpframe(sc, m, xmit)
   1250 	struct ppp_softc *sc;
   1251 	struct mbuf* m;
   1252 	int xmit;
   1253 {
   1254 	int i,lcount,copycount,count;
   1255 	char lbuf[16];
   1256 	char *data;
   1257 
   1258 	if (m == NULL)
   1259 		return;
   1260 
   1261 	for(count=m->m_len,data=mtod(m,char*);m != NULL;) {
   1262 		/* build a line of output */
   1263 		for(lcount=0;lcount < sizeof(lbuf);lcount += copycount) {
   1264 			if (!count) {
   1265 				m = m->m_next;
   1266 				if (m == NULL)
   1267 					break;
   1268 				count = m->m_len;
   1269 				data  = mtod(m,char*);
   1270 			}
   1271 			copycount = (count > sizeof(lbuf)-lcount) ?
   1272 					sizeof(lbuf)-lcount : count;
   1273 			bcopy(data,&lbuf[lcount],copycount);
   1274 			data  += copycount;
   1275 			count -= copycount;
   1276 		}
   1277 
   1278 		/* output line (hex 1st, then ascii) */
   1279 		printf("%s %s:", sc->sc_if.if_xname,
   1280 		    xmit ? "output" : "input ");
   1281 		for(i=0;i<lcount;i++)
   1282 			printf("%02x ",(u_char)lbuf[i]);
   1283 		for(;i<sizeof(lbuf);i++)
   1284 			printf("   ");
   1285 		for(i=0;i<lcount;i++)
   1286 			printf("%c",(lbuf[i] >= 040 &&
   1287 			    lbuf[i] <= 0176) ? lbuf[i] : '.');
   1288 		printf("\n");
   1289 	}
   1290 }
   1291