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