Home | History | Annotate | Line # | Download | only in net
if_ppp.c revision 1.15
      1 /*	$NetBSD: if_ppp.c,v 1.15 1994/07/03 06:44:03 deraadt Exp $	*/
      2 
      3 /*
      4  * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
      5  *
      6  * Copyright (c) 1989 Carnegie Mellon University.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms are permitted
     10  * provided that the above copyright notice and this paragraph are
     11  * duplicated in all such forms and that any documentation,
     12  * advertising materials, and other materials related to such
     13  * distribution and use acknowledge that the software was developed
     14  * by Carnegie Mellon University.  The name of the
     15  * University may not be used to endorse or promote products derived
     16  * from this software without specific prior written permission.
     17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     19  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     20  *
     21  * Drew D. Perkins
     22  * Carnegie Mellon University
     23  * 4910 Forbes Ave.
     24  * Pittsburgh, PA 15213
     25  * (412) 268-8576
     26  * ddp (at) andrew.cmu.edu
     27  *
     28  * Based on:
     29  *	@(#)if_sl.c	7.6.1.2 (Berkeley) 2/15/89
     30  *
     31  * Copyright (c) 1987 Regents of the University of California.
     32  * All rights reserved.
     33  *
     34  * Redistribution and use in source and binary forms are permitted
     35  * provided that the above copyright notice and this paragraph are
     36  * duplicated in all such forms and that any documentation,
     37  * advertising materials, and other materials related to such
     38  * distribution and use acknowledge that the software was developed
     39  * by the University of California, Berkeley.  The name of the
     40  * University may not be used to endorse or promote products derived
     41  * from this software without specific prior written permission.
     42  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     43  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     44  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     45  *
     46  * Serial Line interface
     47  *
     48  * Rick Adams
     49  * Center for Seismic Studies
     50  * 1300 N 17th Street, Suite 1450
     51  * Arlington, Virginia 22209
     52  * (703)276-7900
     53  * rick (at) seismo.ARPA
     54  * seismo!rick
     55  *
     56  * Pounded on heavily by Chris Torek (chris (at) mimsy.umd.edu, umcp-cs!chris).
     57  * Converted to 4.3BSD Beta by Chris Torek.
     58  * Other changes made at Berkeley, based in part on code by Kirk Smith.
     59  *
     60  * Converted to 4.3BSD+ 386BSD by Brad Parker (brad (at) cayman.com)
     61  * Added VJ tcp header compression; more unified ioctls
     62  *
     63  * Extensively modified by Paul Mackerras (paulus (at) cs.anu.edu.au).
     64  * Cleaned up a lot of the mbuf-related code to fix bugs that
     65  * caused system crashes and packet corruption.  Changed pppstart
     66  * so that it doesn't just give up with a collision if the whole
     67  * packet doesn't fit in the output ring buffer.
     68  *
     69  * Added priority queueing for interactive IP packets, following
     70  * the model of if_sl.c, plus hooks for bpf.
     71  * Paul Mackerras (paulus (at) cs.anu.edu.au).
     72  */
     73 
     74 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
     75 
     76 #include "ppp.h"
     77 #if NPPP > 0
     78 
     79 #define VJC
     80 
     81 #include <sys/param.h>
     82 #include <sys/proc.h>
     83 #include <sys/mbuf.h>
     84 #include <sys/buf.h>
     85 #include <sys/dkstat.h>
     86 #include <sys/socket.h>
     87 #include <sys/ioctl.h>
     88 #include <sys/file.h>
     89 #include <sys/tty.h>
     90 #include <sys/kernel.h>
     91 #include <sys/conf.h>
     92 #include <sys/vnode.h>
     93 
     94 #include <net/if.h>
     95 #include <net/if_types.h>
     96 #include <net/netisr.h>
     97 #include <net/route.h>
     98 
     99 #if INET
    100 #include <netinet/in.h>
    101 #include <netinet/in_systm.h>
    102 #include <netinet/in_var.h>
    103 #include <netinet/ip.h>
    104 #endif
    105 
    106 #include "bpfilter.h"
    107 #if NBPFILTER > 0
    108 #include <sys/time.h>
    109 #include <net/bpf.h>
    110 #endif
    111 
    112 #ifdef VJC
    113 #include <net/slcompress.h>
    114 #define HDROFF	MAX_HDR
    115 /* HDROFF should really be 128, but other parts of the system will
    116    panic on TCP+IP headers bigger than MAX_HDR = MHLEN (100). */
    117 
    118 #else
    119 #define	HDROFF	(0)
    120 #endif
    121 
    122 #include <net/if_ppp.h>
    123 #include <machine/cpu.h>
    124 
    125 /* This is a NetBSD-current kernel. */
    126 #define CCOUNT(q)	((q)->c_cc)
    127 
    128 #define	PPP_HIWAT	400	/* Don't start a new packet if HIWAT on que */
    129 
    130 struct ppp_softc ppp_softc[NPPP];
    131 
    132 void	pppattach __P((void));
    133 int	pppopen __P((dev_t dev, struct tty *tp));
    134 void	pppclose __P((struct tty *tp, int flag));
    135 int	pppread __P((struct tty *tp, struct uio *uio, int flag));
    136 int	pppwrite __P((struct tty *tp, struct uio *uio, int flag));
    137 int	ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag,
    138 		       struct proc *));
    139 int	pppoutput __P((struct ifnet *ifp, struct mbuf *m0,
    140 		       struct sockaddr *dst, struct rtentry *rtp));
    141 void	pppinput __P((int c, struct tty *tp));
    142 int	pppioctl __P((struct ifnet *ifp, int cmd, caddr_t data));
    143 void	pppstart __P((struct tty *tp));
    144 
    145 static int	pppasyncstart __P((struct ppp_softc *));
    146 static u_short	pppfcs __P((u_short fcs, u_char *cp, int len));
    147 static int	pppgetm __P((struct ppp_softc *sc));
    148 static void	pppdumpm __P((struct mbuf *m0, int pktlen));
    149 static void	pppdumpb __P((u_char *b, int l));
    150 static void	ppplogchar __P((struct ppp_softc *, int));
    151 
    152 /*
    153  * Some useful mbuf macros not in mbuf.h.
    154  */
    155 #define M_DATASTART(m)	\
    156 	((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf : \
    157 	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
    158 
    159 #define M_DATASIZE(m)	\
    160 	((m)->m_flags & M_EXT ? (m)->m_ext.ext_size : \
    161 	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
    162 
    163 /*
    164  * The following disgusting hack gets around the problem that IP TOS
    165  * can't be set yet.  We want to put "interactive" traffic on a high
    166  * priority queue.  To decide if traffic is interactive, we check that
    167  * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control.
    168  */
    169 static u_short interactive_ports[8] = {
    170 	0,	513,	0,	0,
    171 	0,	21,	0,	23,
    172 };
    173 #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
    174 
    175 /*
    176  * Does c need to be escaped?
    177  */
    178 #define ESCAPE_P(c)	(sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
    179 
    180 /*
    181  * Called from boot code to establish ppp interfaces.
    182  */
    183 void
    184 pppattach()
    185 {
    186     register struct ppp_softc *sc;
    187     register int i = 0;
    188 
    189     for (sc = ppp_softc; i < NPPP; sc++) {
    190 	sc->sc_if.if_name = "ppp";
    191 	sc->sc_if.if_unit = i++;
    192 	sc->sc_if.if_mtu = PPP_MTU;
    193 	sc->sc_if.if_flags = IFF_POINTOPOINT;
    194 	sc->sc_if.if_type = IFT_PPP;
    195 	sc->sc_if.if_hdrlen = PPP_HDRLEN;
    196 	sc->sc_if.if_ioctl = pppioctl;
    197 	sc->sc_if.if_output = pppoutput;
    198 	sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
    199 	sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
    200 	sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
    201 	if_attach(&sc->sc_if);
    202 #if NBPFILTER > 0
    203 	bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);
    204 #endif
    205     }
    206 }
    207 
    208 /*
    209  * Allocate a ppp interface unit and initialize it.
    210  */
    211 struct ppp_softc *
    212 pppalloc(pid)
    213     pid_t pid;
    214 {
    215     int nppp;
    216     struct ppp_softc *sc;
    217 
    218     for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
    219 	if (sc->sc_xfer == pid) {
    220 	    sc->sc_xfer = 0;
    221 	    break;
    222 	}
    223     if (nppp >= NPPP)
    224 	for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
    225 	    if (sc->sc_devp == NULL)
    226 		break;
    227     if (nppp >= NPPP)
    228 	return NULL;
    229 
    230     sc->sc_flags = 0;
    231     sc->sc_mru = PPP_MRU;
    232 #ifdef VJC
    233     sl_compress_init(&sc->sc_comp, -1);
    234 #endif
    235     sc->sc_if.if_flags |= IFF_RUNNING;
    236 
    237     return sc;
    238 }
    239 
    240 /*
    241  * Deallocate a ppp unit.
    242  */
    243 pppdealloc(sc)
    244     struct ppp_softc *sc;
    245 {
    246     struct mbuf *m;
    247 
    248     if_down(&sc->sc_if);
    249     sc->sc_devp = NULL;
    250     sc->sc_xfer = 0;
    251     for (;;) {
    252 	IF_DEQUEUE(&sc->sc_inq, m);
    253 	if (m == NULL)
    254 	    break;
    255 	m_freem(m);
    256     }
    257     for (;;) {
    258 	IF_DEQUEUE(&sc->sc_fastq, m);
    259 	if (m == NULL)
    260 	    break;
    261 	m_freem(m);
    262     }
    263     sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
    264 }
    265 
    266 /*
    267  * Line specific open routine for async tty devices.
    268  * Attach the given tty to the first available ppp unit.
    269  */
    270 /* ARGSUSED */
    271 int
    272 pppopen(dev, tp)
    273     dev_t dev;
    274     register struct tty *tp;
    275 {
    276     struct proc *p = curproc;		/* XXX */
    277     register struct ppp_softc *sc;
    278     int error, s, i;
    279 
    280     if (error = suser(p->p_ucred, &p->p_acflag))
    281 	return (error);
    282 
    283     if (tp->t_line == PPPDISC) {
    284 	sc = (struct ppp_softc *) tp->t_sc;
    285 	if (sc != NULL && sc->sc_devp == (void *) tp)
    286 	    return (0);
    287     }
    288 
    289     if ((sc = pppalloc(p->p_pid)) == NULL)
    290 	return ENXIO;
    291 
    292     if (sc->sc_outm != NULL) {
    293 	m_freem(sc->sc_outm);
    294 	sc->sc_outm = NULL;
    295     }
    296 
    297     if (pppgetm(sc) == 0) {
    298 	sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
    299 	return (ENOBUFS);
    300     }
    301 
    302     sc->sc_ilen = 0;
    303     bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
    304     sc->sc_asyncmap[0] = 0xffffffff;
    305     sc->sc_asyncmap[3] = 0x60000000;
    306     sc->sc_rasyncmap = 0;
    307     sc->sc_devp = (void *) tp;
    308     sc->sc_start = pppasyncstart;
    309 
    310     tp->t_sc = (caddr_t) sc;
    311     ttyflush(tp, FREAD | FWRITE);
    312 
    313     return (0);
    314 }
    315 
    316 /*
    317  * Line specific close routine.
    318  * Detach the tty from the ppp unit.
    319  * Mimics part of ttyclose().
    320  */
    321 void
    322 pppclose(tp, flag)
    323     struct tty *tp;
    324     int flag;
    325 {
    326     register struct ppp_softc *sc;
    327     struct mbuf *m;
    328     int s;
    329 
    330     ttywflush(tp);
    331     s = splimp();		/* paranoid; splnet probably ok */
    332     tp->t_line = 0;
    333     sc = (struct ppp_softc *)tp->t_sc;
    334     if (sc != NULL) {
    335 	tp->t_sc = NULL;
    336 	if (tp == (struct tty *) sc->sc_devp) {
    337 	    m_freem(sc->sc_outm);
    338 	    sc->sc_outm = NULL;
    339 	    m_freem(sc->sc_m);
    340 	    sc->sc_m = NULL;
    341 	    pppdealloc(sc);
    342 	}
    343     }
    344     splx(s);
    345 }
    346 
    347 /*
    348  * Line specific (tty) read routine.
    349  */
    350 int
    351 pppread(tp, uio, flag)
    352     register struct tty *tp;
    353     struct uio *uio;
    354     int flag;
    355 {
    356     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    357     struct mbuf *m, *m0;
    358     register int s;
    359     int error = 0;
    360 
    361     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    362 	return 0;		/* end of file */
    363     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    364 	return 0;
    365     s = splimp();
    366     while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) {
    367 	if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
    368 	    splx(s);
    369 	    return (EWOULDBLOCK);
    370 	}
    371 	error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
    372 	if (error) {
    373 	    splx(s);
    374 	    return error;
    375 	}
    376     }
    377     if (tp->t_line != PPPDISC) {
    378 	splx(s);
    379 	return (-1);
    380     }
    381 
    382     /* Pull place-holder byte out of canonical queue */
    383     getc(&tp->t_canq);
    384 
    385     /* Get the packet from the input queue */
    386     IF_DEQUEUE(&sc->sc_inq, m0);
    387     splx(s);
    388 
    389     for (m = m0; m && uio->uio_resid; m = m->m_next)
    390 	if (error = uiomove(mtod(m, u_char *), m->m_len, uio))
    391 	    break;
    392     m_freem(m0);
    393     return (error);
    394 }
    395 
    396 /*
    397  * Line specific (tty) write routine.
    398  */
    399 int
    400 pppwrite(tp, uio, flag)
    401     register struct tty *tp;
    402     struct uio *uio;
    403     int flag;
    404 {
    405     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    406     struct mbuf *m, *m0, **mp;
    407     struct sockaddr dst;
    408     struct ppp_header *ph1, *ph2;
    409     int len, error;
    410 
    411     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    412 	return 0;		/* wrote 0 bytes */
    413     if (tp->t_line != PPPDISC)
    414 	return (EINVAL);
    415     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    416 	return EIO;
    417     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
    418 	uio->uio_resid < PPP_HDRLEN)
    419 	return (EMSGSIZE);
    420     for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
    421 	MGET(m, M_WAIT, MT_DATA);
    422 	if ((*mp = m) == NULL) {
    423 	    m_freem(m0);
    424 	    return (ENOBUFS);
    425 	}
    426 	m->m_len = 0;
    427 	if (uio->uio_resid >= MCLBYTES / 2)
    428 	    MCLGET(m, M_DONTWAIT);
    429 	len = M_TRAILINGSPACE(m);
    430 	if (len > uio->uio_resid)
    431 	    len = uio->uio_resid;
    432 	if (error = uiomove(mtod(m, u_char *), len, uio)) {
    433 	    m_freem(m0);
    434 	    return (error);
    435 	}
    436 	m->m_len = len;
    437     }
    438     dst.sa_family = AF_UNSPEC;
    439     ph1 = (struct ppp_header *) &dst.sa_data;
    440     ph2 = mtod(m0, struct ppp_header *);
    441     *ph1 = *ph2;
    442     m0->m_data += PPP_HDRLEN;
    443     m0->m_len -= PPP_HDRLEN;
    444     return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
    445 }
    446 
    447 /*
    448  * Line specific (tty) ioctl routine.
    449  * Provide a way to get the ppp unit number.
    450  * This discipline requires that tty device drivers call
    451  * the line specific l_ioctl routine from their ioctl routines.
    452  */
    453 /* ARGSUSED */
    454 int
    455 ppptioctl(tp, cmd, data, flag, p)
    456     struct tty *tp;
    457     caddr_t data;
    458     int cmd, flag;
    459     struct proc *p;
    460 {
    461     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    462     int s, error, flags, mru;
    463 
    464     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    465 	return -1;
    466 
    467     switch (cmd) {
    468     case FIONREAD:
    469 	*(int *)data = sc->sc_inq.ifq_len;
    470 	break;
    471 
    472     case PPPIOCGUNIT:
    473 	*(int *)data = sc->sc_if.if_unit;
    474 	break;
    475 
    476     case PPPIOCGFLAGS:
    477 	*(u_int *)data = sc->sc_flags;
    478 	break;
    479 
    480     case PPPIOCSFLAGS:
    481 	if (error = suser(p->p_ucred, &p->p_acflag))
    482 	    return (error);
    483 	flags = *(int *)data & SC_MASK;
    484 	s = splimp();
    485 	sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
    486 	splx(s);
    487 	break;
    488 
    489     case PPPIOCSASYNCMAP:
    490 	if (error = suser(p->p_ucred, &p->p_acflag))
    491 	    return (error);
    492 	sc->sc_asyncmap[0] = *(u_int *)data;
    493 	break;
    494 
    495     case PPPIOCGASYNCMAP:
    496 	*(u_int *)data = sc->sc_asyncmap[0];
    497 	break;
    498 
    499     case PPPIOCSRASYNCMAP:
    500 	if (error = suser(p->p_ucred, &p->p_acflag))
    501 	    return (error);
    502 	sc->sc_rasyncmap = *(u_int *)data;
    503 	break;
    504 
    505     case PPPIOCGRASYNCMAP:
    506 	*(u_int *)data = sc->sc_rasyncmap;
    507 	break;
    508 
    509     case PPPIOCSXASYNCMAP:
    510 	if (error = suser(p->p_ucred, &p->p_acflag))
    511 	    return (error);
    512 	bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
    513 	sc->sc_asyncmap[1] = 0;		    /* mustn't escape 0x20 - 0x3f */
    514 	sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
    515 	sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
    516 	break;
    517 
    518     case PPPIOCGXASYNCMAP:
    519 	bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
    520 	break;
    521 
    522     case PPPIOCSMRU:
    523 	if (error = suser(p->p_ucred, &p->p_acflag))
    524 	    return (error);
    525 	mru = *(int *)data;
    526 	if (mru >= PPP_MRU && mru <= PPP_MAXMRU) {
    527 	    sc->sc_mru = mru;
    528 	    if (pppgetm(sc) == 0) {
    529 		error = ENOBUFS;
    530 		sc->sc_mru = PPP_MRU;
    531 		if (pppgetm(sc) == 0)
    532 		    sc->sc_if.if_flags &= ~IFF_UP;
    533 	    }
    534 	}
    535 	break;
    536 
    537     case PPPIOCGMRU:
    538 	*(int *)data = sc->sc_mru;
    539 	break;
    540 
    541 #ifdef VJC
    542     case PPPIOCSMAXCID:
    543 	if (error = suser(p->p_ucred, &p->p_acflag))
    544 	    return (error);
    545 	sl_compress_init(&sc->sc_comp, *(int *)data);
    546 	break;
    547 #endif
    548 
    549     case PPPIOCXFERUNIT:
    550 	if (error = suser(p->p_ucred, &p->p_acflag))
    551 	    return (error);
    552 	sc->sc_xfer = p->p_pid;
    553 	break;
    554 
    555     default:
    556 	return (-1);
    557     }
    558     return (0);
    559 }
    560 
    561 /*
    562  * FCS lookup table as calculated by genfcstab.
    563  */
    564 static u_short fcstab[256] = {
    565 	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
    566 	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
    567 	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
    568 	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
    569 	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
    570 	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
    571 	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
    572 	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
    573 	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
    574 	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
    575 	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
    576 	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
    577 	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
    578 	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
    579 	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
    580 	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
    581 	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
    582 	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
    583 	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
    584 	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
    585 	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
    586 	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
    587 	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
    588 	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
    589 	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
    590 	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
    591 	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
    592 	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
    593 	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
    594 	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
    595 	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
    596 	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
    597 };
    598 
    599 /*
    600  * Calculate a new FCS given the current FCS and the new data.
    601  */
    602 static u_short
    603 pppfcs(fcs, cp, len)
    604     register u_short fcs;
    605     register u_char *cp;
    606     register int len;
    607 {
    608     while (len--)
    609 	fcs = PPP_FCS(fcs, *cp++);
    610     return (fcs);
    611 }
    612 
    613 /*
    614  * Queue a packet.  Start transmission if not active.
    615  * Packet is placed in Information field of PPP frame.
    616  */
    617 int
    618 pppoutput(ifp, m0, dst, rtp)
    619     struct ifnet *ifp;
    620     struct mbuf *m0;
    621     struct sockaddr *dst;
    622     struct rtentry *rtp;
    623 {
    624     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
    625     struct ppp_header *ph;
    626     int protocol, address, control;
    627     u_char *cp;
    628     int s, error;
    629     struct ip *ip;
    630     struct ifqueue *ifq;
    631 
    632     if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
    633 	|| (ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC) {
    634 	error = ENETDOWN;	/* sort of */
    635 	goto bad;
    636     }
    637 
    638     /*
    639      * Compute PPP header.
    640      */
    641     address = PPP_ALLSTATIONS;
    642     control = PPP_UI;
    643     ifq = &ifp->if_snd;
    644     switch (dst->sa_family) {
    645 #ifdef INET
    646     case AF_INET:
    647 	protocol = PPP_IP;
    648 	if ((sc->sc_flags & SC_ENABLE_IP) == 0) {
    649 	    error = ENETDOWN;
    650 	    goto bad;
    651 	}
    652 
    653 	/*
    654 	 * If this is a TCP packet to or from an "interactive" port,
    655 	 * put the packet on the fastq instead.
    656 	 */
    657 	if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) {
    658 	    register int p = ntohl(((int *)ip)[ip->ip_hl]);
    659 	    if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16))
    660 		ifq = &sc->sc_fastq;
    661 	}
    662 	break;
    663 #endif
    664 #ifdef NS
    665     case AF_NS:
    666 	protocol = PPP_XNS;
    667 	break;
    668 #endif
    669     case AF_UNSPEC:
    670 	ph = (struct ppp_header *) dst->sa_data;
    671 	address = ph->ph_address;
    672 	control = ph->ph_control;
    673 	protocol = ntohs(ph->ph_protocol);
    674 	break;
    675     default:
    676 	printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);
    677 	error = EAFNOSUPPORT;
    678 	goto bad;
    679     }
    680 
    681     /*
    682      * Add PPP header.  If no space in first mbuf, allocate another.
    683      * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
    684      */
    685     if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
    686 	m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);
    687 	if (m0 == 0) {
    688 	    error = ENOBUFS;
    689 	    goto bad;
    690 	}
    691 	m0->m_len = 0;
    692     } else
    693 	m0->m_data -= PPP_HDRLEN;
    694 
    695     cp = mtod(m0, u_char *);
    696     *cp++ = address;
    697     *cp++ = control;
    698     *cp++ = protocol >> 8;
    699     *cp++ = protocol & 0xff;
    700     m0->m_len += PPP_HDRLEN;
    701 
    702     if (sc->sc_flags & SC_LOG_OUTPKT) {
    703 	printf("ppp%d output: ", ifp->if_unit);
    704 	pppdumpm(m0, -1);
    705     }
    706 
    707 #if NBPFILTER > 0
    708     /* See if bpf wants to look at the packet. */
    709     if (sc->sc_bpf)
    710 	bpf_mtap(sc->sc_bpf, m0);
    711 #endif
    712 
    713     /*
    714      * Put the packet on the appropriate queue.
    715      */
    716     s = splimp();
    717     if (IF_QFULL(ifq)) {
    718 	IF_DROP(ifq);
    719 	splx(s);
    720 	sc->sc_if.if_oerrors++;
    721 	error = ENOBUFS;
    722 	goto bad;
    723     }
    724     IF_ENQUEUE(ifq, m0);
    725 
    726     /*
    727      * Tell the device to send it out.
    728      */
    729     (*sc->sc_start)(sc);
    730 
    731     splx(s);
    732     return (0);
    733 
    734 bad:
    735     m_freem(m0);
    736     return (error);
    737 }
    738 
    739 /*
    740  * Grab another packet off a queue and apply VJ compression,
    741  * address/control and/or protocol compression if appropriate.
    742  */
    743 struct mbuf *
    744 ppp_dequeue(sc)
    745     struct ppp_softc *sc;
    746 {
    747     int s;
    748     struct mbuf *m, *mp;
    749     u_char *cp;
    750     int address, control, protocol;
    751 
    752     s = splimp();
    753     IF_DEQUEUE(&sc->sc_fastq, m);
    754     if (m == NULL)
    755 	IF_DEQUEUE(&sc->sc_if.if_snd, m);
    756     splx(s);
    757     if (m == NULL)
    758 	return NULL;
    759 
    760     /*
    761      * Extract the ppp header of the new packet.
    762      * The ppp header will be in one mbuf.
    763      */
    764     cp = mtod(m, u_char *);
    765     address = cp[0];
    766     control = cp[1];
    767     protocol = (cp[2] << 8) + cp[3];
    768 
    769     switch (protocol) {
    770 #ifdef VJC
    771     case PPP_IP:
    772 	/*
    773 	 * If the packet is a TCP/IP packet, see if we can compress it.
    774 	 */
    775 	if (sc->sc_flags & SC_COMP_TCP) {
    776 	    struct ip *ip;
    777 	    int type;
    778 
    779 	    mp = m;
    780 	    ip = (struct ip *) (cp + PPP_HDRLEN);
    781 	    if (mp->m_len <= PPP_HDRLEN) {
    782 		mp = mp->m_next;
    783 		if (mp == NULL)
    784 		    break;
    785 		ip = mtod(mp, struct ip *);
    786 	    }
    787 	    /* this code assumes the IP/TCP header is in one non-shared mbuf */
    788 	    if (ip->ip_p == IPPROTO_TCP) {
    789 		type = sl_compress_tcp(mp, ip, &sc->sc_comp,
    790 				       !(sc->sc_flags & SC_NO_TCP_CCID));
    791 		switch (type) {
    792 		case TYPE_UNCOMPRESSED_TCP:
    793 		    protocol = PPP_VJC_UNCOMP;
    794 		    break;
    795 		case TYPE_COMPRESSED_TCP:
    796 		    protocol = PPP_VJC_COMP;
    797 		    cp = mtod(m, u_char *);
    798 		    cp[0] = address;	/* header has moved */
    799 		    cp[1] = control;
    800 		    cp[2] = 0;
    801 		    break;
    802 		}
    803 		cp[3] = protocol;	/* update protocol in PPP header */
    804 	    }
    805 	}
    806 #endif	/* VJC */
    807     }
    808 
    809     /*
    810      * Compress the address/control and protocol, if possible.
    811      */
    812     if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
    813 	control == PPP_UI && protocol != PPP_ALLSTATIONS &&
    814 	protocol != PPP_LCP) {
    815 	/* can compress address/control */
    816 	m->m_data += 2;
    817 	m->m_len -= 2;
    818     }
    819     if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
    820 	/* can compress protocol */
    821 	if (mtod(m, u_char *) == cp) {
    822 	    cp[2] = cp[1];	/* move address/control up */
    823 	    cp[1] = cp[0];
    824 	}
    825 	++m->m_data;
    826 	--m->m_len;
    827     }
    828 
    829     return m;
    830 }
    831 
    832 /*
    833  * This gets called from pppoutput when a new packet is
    834  * put on a queue.
    835  */
    836 static
    837 pppasyncstart(sc)
    838     register struct ppp_softc *sc;
    839 {
    840     register struct tty *tp = (struct tty *) sc->sc_devp;
    841 
    842     pppstart(tp);
    843 }
    844 
    845 /*
    846  * Start output on async tty interface.  Get another datagram
    847  * to send from the interface queue and start sending it.
    848  */
    849 void
    850 pppstart(tp)
    851     register struct tty *tp;
    852 {
    853     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    854     register struct mbuf *m;
    855     register int len;
    856     register u_char *start, *stop, *cp;
    857     int n, s, ndone, done;
    858     struct mbuf *m2;
    859 
    860     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
    861 	/* sorry, I can't talk now */
    862 	return;
    863     }
    864     if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
    865 	(*tp->t_oproc)(tp);
    866 	return;
    867     }
    868 
    869     for (;;) {
    870 	/*
    871 	 * If there is more in the output queue, just send it now.
    872 	 * We are being called in lieu of ttstart and must do what
    873 	 * it would.
    874 	 */
    875 	if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) {
    876 	    (*tp->t_oproc)(tp);
    877 	    if (CCOUNT(&tp->t_outq) > PPP_HIWAT)
    878 		return;
    879 	}
    880 
    881 	/*
    882 	 * See if we have an existing packet partly sent.
    883 	 * If not, get a new packet and start sending it.
    884 	 * We take packets on the priority queue ahead of those
    885 	 * on the normal queue.
    886 	 */
    887 	m = sc->sc_outm;
    888 	if (m == NULL) {
    889 	    /*
    890 	     * Get another packet to be sent
    891 	     */
    892 	    m = ppp_dequeue(sc);
    893 	    if (m == NULL)
    894 		return;
    895 
    896 	    /*
    897 	     * The extra PPP_FLAG will start up a new packet, and thus
    898 	     * will flush any accumulated garbage.  We do this whenever
    899 	     * the line may have been idle for some time.
    900 	     */
    901 	    if (CCOUNT(&tp->t_outq) == 0) {
    902 		++sc->sc_bytessent;
    903 		(void) putc(PPP_FLAG, &tp->t_outq);
    904 	    }
    905 
    906 	    /* Calculate the FCS for the first mbuf's worth. */
    907 	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
    908 	}
    909 
    910 	for (;;) {
    911 	    start = mtod(m, u_char *);
    912 	    len = m->m_len;
    913 	    stop = start + len;
    914 	    while (len > 0) {
    915 		/*
    916 		 * Find out how many bytes in the string we can
    917 		 * handle without doing something special.
    918 		 */
    919 		for (cp = start; cp < stop; cp++)
    920 		    if (ESCAPE_P(*cp))
    921 			break;
    922 		n = cp - start;
    923 		if (n) {
    924 		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
    925 		    ndone = n - b_to_q(start, n, &tp->t_outq);
    926 		    len -= ndone;
    927 		    start += ndone;
    928 		    sc->sc_bytessent += ndone;
    929 
    930 		    if (ndone < n)
    931 			break;	/* packet doesn't fit */
    932 		}
    933 		/*
    934 		 * If there are characters left in the mbuf,
    935 		 * the first one must be special..
    936 		 * Put it out in a different form.
    937 		 */
    938 		if (len) {
    939 		    if (putc(PPP_ESCAPE, &tp->t_outq))
    940 			break;
    941 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
    942 			(void) unputc(&tp->t_outq);
    943 			break;
    944 		    }
    945 		    sc->sc_bytessent += 2;
    946 		    start++;
    947 		    len--;
    948 		}
    949 	    }
    950 	    /*
    951 	     * If we didn't empty this mbuf, remember where we're up to.
    952 	     * If we emptied the last mbuf, try to add the FCS and closing
    953 	     * flag, and if we can't, leave sc_outm pointing to m, but with
    954 	     * m->m_len == 0, to remind us to output the FCS and flag later.
    955 	     */
    956 	    done = len == 0;
    957 	    if (done && m->m_next == NULL) {
    958 		u_char *p, *q;
    959 		int c;
    960 		u_char endseq[8];
    961 
    962 		/*
    963 		 * We may have to escape the bytes in the FCS.
    964 		 */
    965 		p = endseq;
    966 		c = ~sc->sc_outfcs & 0xFF;
    967 		if (ESCAPE_P(c)) {
    968 		    *p++ = PPP_ESCAPE;
    969 		    *p++ = c ^ PPP_TRANS;
    970 		} else
    971 		    *p++ = c;
    972 		c = (~sc->sc_outfcs >> 8) & 0xFF;
    973 		if (ESCAPE_P(c)) {
    974 		    *p++ = PPP_ESCAPE;
    975 		    *p++ = c ^ PPP_TRANS;
    976 		} else
    977 		    *p++ = c;
    978 		*p++ = PPP_FLAG;
    979 
    980 		/*
    981 		 * Try to output the FCS and flag.  If the bytes
    982 		 * don't all fit, back out.
    983 		 */
    984 		for (q = endseq; q < p; ++q)
    985 		    if (putc(*q, &tp->t_outq)) {
    986 			done = 0;
    987 			for (; q > endseq; --q)
    988 			    unputc(&tp->t_outq);
    989 			break;
    990 		    }
    991 	    }
    992 
    993 	    if (!done) {
    994 		m->m_data = start;
    995 		m->m_len = len;
    996 		sc->sc_outm = m;
    997 		if (tp->t_oproc != NULL)
    998 		    (*tp->t_oproc)(tp);
    999 		return;		/* can't do any more at the moment */
   1000 	    }
   1001 
   1002 	    /* Finished with this mbuf; free it and move on. */
   1003 	    MFREE(m, m2);
   1004 	    if (m2 == NULL)
   1005 		break;
   1006 
   1007 	    m = m2;
   1008 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
   1009 	}
   1010 
   1011 	/* Finished a packet */
   1012 	sc->sc_outm = NULL;
   1013 	sc->sc_bytessent++;	/* account for closing flag */
   1014 	sc->sc_if.if_opackets++;
   1015 	sc->sc_if.if_obytes = sc->sc_bytessent;
   1016     }
   1017 }
   1018 
   1019 /*
   1020  * Allocate enough mbuf to handle current MRU.
   1021  */
   1022 static int
   1023 pppgetm(sc)
   1024     register struct ppp_softc *sc;
   1025 {
   1026     struct mbuf *m, **mp;
   1027     int len = HDROFF + sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN;
   1028     int s;
   1029 
   1030     s = splimp();
   1031     for (mp = &sc->sc_m; (m = *mp) != NULL; mp = &m->m_next)
   1032 	if ((len -= M_DATASIZE(m)) <= 0) {
   1033 	    splx(s);
   1034 	    return (1);
   1035 	}
   1036 
   1037     for (;; mp = &m->m_next) {
   1038 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1039 	if (m == 0) {
   1040 	    m_freem(sc->sc_m);
   1041 	    sc->sc_m = NULL;
   1042 	    splx(s);
   1043 	    printf("ppp%d: can't allocate mbuf\n", sc->sc_if.if_unit);
   1044 	    return (0);
   1045 	}
   1046 	*mp = m;
   1047 	MCLGET(m, M_DONTWAIT);
   1048 	if ((len -= M_DATASIZE(m)) <= 0) {
   1049 	    splx(s);
   1050 	    return (1);
   1051 	}
   1052     }
   1053 }
   1054 
   1055 /*
   1056  * PPP packet input routine.
   1057  * The caller has checked and removed the FCS and has inserted
   1058  * the address/control bytes and the protocol high byte if they
   1059  * were omitted.  The data in the first mbuf should start HDROFF
   1060  * bytes from the beginning of the mbuf data storage area.
   1061  * The return value is 1 if the packet was put on sc->sc_inq,
   1062  * 0 otherwise.
   1063  */
   1064 #define COMPTYPE(proto)	((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
   1065 			 TYPE_UNCOMPRESSED_TCP)
   1066 
   1067 int
   1068 ppppktin(sc, m)
   1069     struct ppp_softc *sc;
   1070     struct mbuf *m;
   1071 {
   1072     struct ifqueue *inq;
   1073     int s, ilen, xlen, proto, rv;
   1074     u_char *cp, adrs, ctrl;
   1075     struct mbuf *mp;
   1076 
   1077     sc->sc_if.if_ipackets++;
   1078     rv = 0;
   1079 
   1080     cp = mtod(m, u_char *);
   1081     adrs = cp[0];
   1082     ctrl = cp[1];
   1083     proto = (cp[2] << 8) + cp[3];
   1084 
   1085     ilen = 0;
   1086     for (mp = m; mp != NULL; mp = mp->m_next)
   1087 	ilen += mp->m_len;
   1088 
   1089 #ifdef VJC
   1090     /*
   1091      * See if we have a VJ-compressed packet to uncompress.
   1092      */
   1093     if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
   1094 	char *pkttype = proto == PPP_VJC_COMP? "": "un";
   1095 
   1096 	if (sc->sc_flags & SC_REJ_COMP_TCP) {
   1097 	    if (sc->sc_flags & SC_DEBUG)
   1098 		printf("ppp%d: %scomp pkt w/o compression; flags 0x%x\n",
   1099 			sc->sc_if.if_unit, pkttype, sc->sc_flags);
   1100 	    sc->sc_if.if_ierrors++;
   1101 	    return 0;
   1102 	}
   1103 
   1104 	m->m_data += PPP_HDRLEN;
   1105 	m->m_len -= PPP_HDRLEN;
   1106 	ilen -= PPP_HDRLEN;
   1107 	xlen = sl_uncompress_tcp_part((u_char **)(&m->m_data),
   1108 					m->m_len, ilen,
   1109 					COMPTYPE(proto), &sc->sc_comp);
   1110 
   1111 	if (xlen == 0) {
   1112 	    if (sc->sc_flags & SC_DEBUG)
   1113 		printf("ppp%d: sl_uncompress failed on type %scomp\n",
   1114 			sc->sc_if.if_unit, pkttype);
   1115 	    sc->sc_if.if_ierrors++;
   1116 	    return 0;
   1117 	}
   1118 
   1119 	/* adjust the first mbuf by the decompressed amt */
   1120 	xlen += PPP_HDRLEN;
   1121 	m->m_len += xlen - ilen;
   1122 	ilen = xlen;
   1123 	m->m_data -= PPP_HDRLEN;
   1124 	proto = PPP_IP;
   1125 
   1126 	/* put the ppp header back in place */
   1127 	if (cp != mtod(m, u_char *)) {
   1128 	    cp = mtod(m, u_char *);
   1129 	    cp[0] = adrs;
   1130 	    cp[1] = ctrl;
   1131 	    cp[2] = 0;
   1132 	}
   1133 	cp[3] = PPP_IP;
   1134     }
   1135 #endif /* VJC */
   1136 
   1137     /*
   1138      * If the packet will fit in a header mbuf, don't waste a
   1139      * whole cluster on it.
   1140      */
   1141     if (ilen <= MHLEN) {
   1142 	MGETHDR(mp, M_DONTWAIT, MT_DATA);
   1143 	if (mp != NULL) {
   1144 	    m_copydata(m, 0, ilen, mtod(mp, caddr_t));
   1145 	    m_freem(m);
   1146 	    m = mp;
   1147 	    m->m_len = ilen;
   1148 	}
   1149     }
   1150     m->m_pkthdr.len = ilen;
   1151     m->m_pkthdr.rcvif = &sc->sc_if;
   1152 
   1153 #if NBPFILTER > 0
   1154     /* See if bpf wants to look at the packet. */
   1155     if (sc->sc_bpf)
   1156 	bpf_mtap(sc->sc_bpf, m);
   1157 #endif
   1158 
   1159     switch (proto) {
   1160 #ifdef INET
   1161     case PPP_IP:
   1162 	/*
   1163 	 * IP packet - take off the ppp header and pass it up to IP.
   1164 	 */
   1165 	if ((sc->sc_if.if_flags & IFF_UP) == 0
   1166 	    || (sc->sc_flags & SC_ENABLE_IP) == 0) {
   1167 	    /* interface is down - drop the packet. */
   1168 	    m_freem(m);
   1169 	    return 0;
   1170 	}
   1171 	m->m_pkthdr.len -= PPP_HDRLEN;
   1172 	m->m_data += PPP_HDRLEN;
   1173 	m->m_len -= PPP_HDRLEN;
   1174 	schednetisr(NETISR_IP);
   1175 	inq = &ipintrq;
   1176 	break;
   1177 #endif
   1178 
   1179     default:
   1180 	/*
   1181 	 * Some other protocol - place on input queue for read().
   1182 	 */
   1183 	inq = &sc->sc_inq;
   1184 	rv = 1;
   1185 	break;
   1186     }
   1187 
   1188     /*
   1189      * Put the packet on the appropriate input queue.
   1190      */
   1191     s = splimp();
   1192     if (IF_QFULL(inq)) {
   1193 	IF_DROP(inq);
   1194 	if (sc->sc_flags & SC_DEBUG)
   1195 	    printf("ppp%d: queue full\n", sc->sc_if.if_unit);
   1196 	sc->sc_if.if_ierrors++;
   1197 	sc->sc_if.if_iqdrops++;
   1198 	m_freem(m);
   1199 	rv = 0;
   1200     } else
   1201 	IF_ENQUEUE(inq, m);
   1202 
   1203     splx(s);
   1204     return rv;
   1205 }
   1206 
   1207 /*
   1208  * tty interface receiver interrupt.
   1209  */
   1210 static unsigned paritytab[8] = {
   1211     0x96696996, 0x69969669, 0x69969669, 0x96696996,
   1212     0x69969669, 0x96696996, 0x96696996, 0x69969669
   1213 };
   1214 
   1215 void
   1216 pppinput(c, tp)
   1217     int c;
   1218     register struct tty *tp;
   1219 {
   1220     register struct ppp_softc *sc;
   1221     struct mbuf *m;
   1222     int ilen;
   1223 
   1224     tk_nin++;
   1225     sc = (struct ppp_softc *) tp->t_sc;
   1226     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
   1227 	return;
   1228 
   1229     ++sc->sc_bytesrcvd;
   1230 
   1231     if (c & TTY_FE) {
   1232 	/* framing error or overrun on this char - abort packet */
   1233 	if (sc->sc_flags & SC_DEBUG)
   1234 	    printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
   1235 	goto flush;
   1236     }
   1237 
   1238     c &= 0xff;
   1239 
   1240     if (c & 0x80)
   1241 	sc->sc_flags |= SC_RCV_B7_1;
   1242     else
   1243 	sc->sc_flags |= SC_RCV_B7_0;
   1244     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
   1245 	sc->sc_flags |= SC_RCV_ODDP;
   1246     else
   1247 	sc->sc_flags |= SC_RCV_EVNP;
   1248 
   1249     if (sc->sc_flags & SC_LOG_RAWIN)
   1250 	ppplogchar(sc, c);
   1251 
   1252     if (c == PPP_FLAG) {
   1253 	ilen = sc->sc_ilen;
   1254 	sc->sc_ilen = 0;
   1255 	sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
   1256 
   1257 	if (sc->sc_rawin_count > 0)
   1258 	    ppplogchar(sc, -1);
   1259 
   1260 	/*
   1261 	 * If SC_ESCAPED is set, then we've seen the packet
   1262 	 * abort sequence "}~".
   1263 	 */
   1264 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
   1265 	    || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
   1266 #ifdef VJC
   1267 	    /*
   1268 	     * If we've missed a packet, we must toss subsequent compressed
   1269 	     * packets which don't have an explicit connection ID.
   1270 	     */
   1271 	    sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);
   1272 #endif
   1273 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
   1274 		if (sc->sc_flags & SC_DEBUG)
   1275 		    printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
   1276 			   sc->sc_fcs);
   1277 		sc->sc_if.if_ierrors++;
   1278 	    } else
   1279 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
   1280 	    return;
   1281 	}
   1282 
   1283 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
   1284 	    if (ilen) {
   1285 		if (sc->sc_flags & SC_DEBUG)
   1286 		    printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
   1287 		sc->sc_if.if_ierrors++;
   1288 	    }
   1289 	    return;
   1290 	}
   1291 
   1292 	/*
   1293 	 * Remove FCS trailer.  Somewhat painful...
   1294 	 */
   1295 	ilen -= 2;
   1296 	if (--sc->sc_mc->m_len == 0) {
   1297 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
   1298 		;
   1299 	    sc->sc_mc = m;
   1300 	}
   1301 	sc->sc_mc->m_len--;
   1302 
   1303 	/* excise this mbuf chain */
   1304 	m = sc->sc_m;
   1305 	sc->sc_m = sc->sc_mc->m_next;
   1306 	sc->sc_mc->m_next = NULL;
   1307 
   1308 	if (sc->sc_flags & SC_LOG_INPKT) {
   1309 	    printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen);
   1310 	    pppdumpm(m, ilen);
   1311 	}
   1312 
   1313 	if (ppppktin(sc, m)) {
   1314 	    /* Put a placeholder byte in canq for ttselect()/ttnread(). */
   1315 	    putc(0, &tp->t_canq);
   1316 	    ttwakeup(tp);
   1317 	}
   1318 
   1319 	if (!pppgetm(sc))
   1320 	    sc->sc_if.if_flags &= ~IFF_UP;
   1321 
   1322 	return;
   1323     }
   1324 
   1325     if (sc->sc_flags & SC_FLUSH) {
   1326 	if (sc->sc_flags & SC_LOG_FLUSH)
   1327 	    ppplogchar(sc, c);
   1328 	return;
   1329     }
   1330 
   1331     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
   1332 	return;
   1333 
   1334     if (sc->sc_flags & SC_ESCAPED) {
   1335 	sc->sc_flags &= ~SC_ESCAPED;
   1336 	c ^= PPP_TRANS;
   1337     } else if (c == PPP_ESCAPE) {
   1338 	sc->sc_flags |= SC_ESCAPED;
   1339 	return;
   1340     }
   1341 
   1342     /*
   1343      * Initialize buffer on first octet received.
   1344      * First octet could be address or protocol (when compressing
   1345      * address/control).
   1346      * Second octet is control.
   1347      * Third octet is first or second (when compressing protocol)
   1348      * octet of protocol.
   1349      * Fourth octet is second octet of protocol.
   1350      */
   1351     if (sc->sc_ilen == 0) {
   1352 	/* reset the first input mbuf */
   1353 	m = sc->sc_m;
   1354 	m->m_len = 0;
   1355 	m->m_data = M_DATASTART(sc->sc_m) + HDROFF;
   1356 	sc->sc_mc = m;
   1357 	sc->sc_mp = mtod(m, char *);
   1358 	sc->sc_fcs = PPP_INITFCS;
   1359 	if (c != PPP_ALLSTATIONS) {
   1360 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
   1361 		if (sc->sc_flags & SC_DEBUG)
   1362 		    printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
   1363 			   sc->sc_if.if_unit, c);
   1364 		goto flush;
   1365 	    }
   1366 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
   1367 	    *sc->sc_mp++ = PPP_UI;
   1368 	    sc->sc_ilen += 2;
   1369 	    m->m_len += 2;
   1370 	}
   1371     }
   1372     if (sc->sc_ilen == 1 && c != PPP_UI) {
   1373 	if (sc->sc_flags & SC_DEBUG)
   1374 	    printf("ppp%d: missing UI (0x3), got 0x%x\n",
   1375 		   sc->sc_if.if_unit, c);
   1376 	goto flush;
   1377     }
   1378     if (sc->sc_ilen == 2 && (c & 1) == 1) {
   1379 	/* a compressed protocol */
   1380 	*sc->sc_mp++ = 0;
   1381 	sc->sc_ilen++;
   1382 	sc->sc_mc->m_len++;
   1383     }
   1384     if (sc->sc_ilen == 3 && (c & 1) == 0) {
   1385 	if (sc->sc_flags & SC_DEBUG)
   1386 	    printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
   1387 		   (sc->sc_mp[-1] << 8) + c);
   1388 	goto flush;
   1389     }
   1390 
   1391     /* packet beyond configured mru? */
   1392     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
   1393 	if (sc->sc_flags & SC_DEBUG)
   1394 	    printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
   1395 	goto flush;
   1396     }
   1397 
   1398     /* is this mbuf full? */
   1399     m = sc->sc_mc;
   1400     if (M_TRAILINGSPACE(m) <= 0) {
   1401 	sc->sc_mc = m = m->m_next;
   1402 	if (m == NULL) {
   1403 	    printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
   1404 	    goto flush;
   1405 	}
   1406 	m->m_len = 0;
   1407 	m->m_data = M_DATASTART(m);
   1408 	sc->sc_mp = mtod(m, char *);
   1409     }
   1410 
   1411     ++m->m_len;
   1412     *sc->sc_mp++ = c;
   1413     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
   1414     return;
   1415 
   1416  flush:
   1417     if (!(sc->sc_flags & SC_FLUSH)) {
   1418 	sc->sc_if.if_ierrors++;
   1419 	sc->sc_flags |= SC_FLUSH;
   1420 	if (sc->sc_flags & SC_LOG_FLUSH)
   1421 	    ppplogchar(sc, c);
   1422     }
   1423 }
   1424 
   1425 /*
   1426  * Process an ioctl request to interface.
   1427  */
   1428 pppioctl(ifp, cmd, data)
   1429     register struct ifnet *ifp;
   1430     int cmd;
   1431     caddr_t data;
   1432 {
   1433     struct proc *p = curproc;	/* XXX */
   1434     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
   1435     register struct ifaddr *ifa = (struct ifaddr *)data;
   1436     register struct ifreq *ifr = (struct ifreq *)data;
   1437     int s = splimp(), error = 0;
   1438 
   1439 
   1440     switch (cmd) {
   1441     case SIOCSIFFLAGS:
   1442 	if ((ifp->if_flags & IFF_RUNNING) == 0)
   1443 	    ifp->if_flags &= ~IFF_UP;
   1444 	break;
   1445 
   1446     case SIOCSIFADDR:
   1447 	if (ifa->ifa_addr->sa_family != AF_INET)
   1448 	    error = EAFNOSUPPORT;
   1449 	break;
   1450 
   1451     case SIOCSIFDSTADDR:
   1452 	if (ifa->ifa_addr->sa_family != AF_INET)
   1453 	    error = EAFNOSUPPORT;
   1454 	break;
   1455 
   1456     case SIOCSIFMTU:
   1457 	if (error = suser(p->p_ucred, &p->p_acflag))
   1458 	    break;
   1459 	sc->sc_if.if_mtu = ifr->ifr_mtu;
   1460 	break;
   1461 
   1462     case SIOCGIFMTU:
   1463 	ifr->ifr_mtu = sc->sc_if.if_mtu;
   1464 	break;
   1465 
   1466     default:
   1467 	error = EINVAL;
   1468     }
   1469     splx(s);
   1470     return (error);
   1471 }
   1472 
   1473 #define MAX_DUMP_BYTES	128
   1474 
   1475 static void
   1476 pppdumpm(m0, pktlen)
   1477     struct mbuf *m0;
   1478     int pktlen;
   1479 {
   1480     char buf[3*MAX_DUMP_BYTES+4];
   1481     char *bp = buf;
   1482     struct mbuf *m;
   1483     static char digits[] = "0123456789abcdef";
   1484 
   1485     for (m = m0; m && pktlen; m = m->m_next) {
   1486 	int l = m->m_len;
   1487 	u_char *rptr = (u_char *)m->m_data;
   1488 
   1489 	if (pktlen > 0) {
   1490 	    if (l > pktlen)
   1491 		l = pktlen;
   1492 	    pktlen -= l;
   1493 	}
   1494 	while (l--) {
   1495 	    if (bp > buf + sizeof(buf) - 4)
   1496 		goto done;
   1497 	    *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
   1498 	    *bp++ = digits[*rptr++ & 0xf];
   1499 	}
   1500 
   1501 	if (m->m_next) {
   1502 	    if (bp > buf + sizeof(buf) - 3)
   1503 		goto done;
   1504 	    *bp++ = '|';
   1505 	} else
   1506 	    *bp++ = ' ';
   1507     }
   1508 done:
   1509     if (m && pktlen)
   1510 	*bp++ = '>';
   1511     *bp = 0;
   1512     printf("%s\n", buf);
   1513 }
   1514 
   1515 static void
   1516 ppplogchar(sc, c)
   1517     struct ppp_softc *sc;
   1518     int c;
   1519 {
   1520     if (c >= 0)
   1521 	sc->sc_rawin[sc->sc_rawin_count++] = c;
   1522     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
   1523 	|| c < 0 && sc->sc_rawin_count > 0) {
   1524 	printf("ppp%d input: ", sc->sc_if.if_unit);
   1525 	pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
   1526 	sc->sc_rawin_count = 0;
   1527     }
   1528 }
   1529 
   1530 static void
   1531 pppdumpb(b, l)
   1532     u_char *b;
   1533     int l;
   1534 {
   1535     char buf[3*MAX_DUMP_BYTES+4];
   1536     char *bp = buf;
   1537     static char digits[] = "0123456789abcdef";
   1538 
   1539     while (l--) {
   1540 	if (bp >= buf + sizeof(buf) - 3) {
   1541 	    *bp++ = '>';
   1542 	    break;
   1543 	}
   1544 	*bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
   1545 	*bp++ = digits[*b++ & 0xf];
   1546 	*bp++ = ' ';
   1547     }
   1548 
   1549     *bp = 0;
   1550     printf("%s\n", buf);
   1551 }
   1552 
   1553 
   1554 #endif	/* NPPP > 0 */
   1555