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