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