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