Home | History | Annotate | Line # | Download | only in net
if_ppp.c revision 1.10
      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.10 1994/05/24 02:33:56 cgd 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, struct rtentry *rtp));
    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, -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 	    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, (struct rtentry *)0));
    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_init(&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, rtp)
    614     struct ifnet *ifp;
    615     struct mbuf *m0;
    616     struct sockaddr *dst;
    617     struct rtentry *rtp;
    618 {
    619     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
    620     struct ppp_header *ph;
    621     int protocol, address, control;
    622     u_char *cp;
    623     int s, error;
    624     struct ip *ip;
    625     struct ifqueue *ifq;
    626 
    627     if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
    628 	|| (ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC) {
    629 	error = ENETDOWN;	/* sort of */
    630 	goto bad;
    631     }
    632 
    633     /*
    634      * Compute PPP header.
    635      */
    636     address = PPP_ALLSTATIONS;
    637     control = PPP_UI;
    638     ifq = &ifp->if_snd;
    639     switch (dst->sa_family) {
    640 #ifdef INET
    641     case AF_INET:
    642 	protocol = PPP_IP;
    643 	if ((sc->sc_flags & SC_ENABLE_IP) == 0) {
    644 	    error = ENETDOWN;
    645 	    goto bad;
    646 	}
    647 
    648 	/*
    649 	 * If this is a TCP packet to or from an "interactive" port,
    650 	 * put the packet on the fastq instead.
    651 	 */
    652 	if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) {
    653 	    register int p = ntohl(((int *)ip)[ip->ip_hl]);
    654 	    if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16))
    655 		ifq = &sc->sc_fastq;
    656 	}
    657 	break;
    658 #endif
    659 #ifdef NS
    660     case AF_NS:
    661 	protocol = PPP_XNS;
    662 	break;
    663 #endif
    664     case AF_UNSPEC:
    665 	ph = (struct ppp_header *) dst->sa_data;
    666 	address = ph->ph_address;
    667 	control = ph->ph_control;
    668 	protocol = ntohs(ph->ph_protocol);
    669 	break;
    670     default:
    671 	printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);
    672 	error = EAFNOSUPPORT;
    673 	goto bad;
    674     }
    675 
    676     /*
    677      * Add PPP header.  If no space in first mbuf, allocate another.
    678      * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
    679      */
    680     if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
    681 	m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);
    682 	if (m0 == 0) {
    683 	    error = ENOBUFS;
    684 	    goto bad;
    685 	}
    686 	m0->m_len = 0;
    687     } else
    688 	m0->m_data -= PPP_HDRLEN;
    689 
    690     cp = mtod(m0, u_char *);
    691     *cp++ = address;
    692     *cp++ = control;
    693     *cp++ = protocol >> 8;
    694     *cp++ = protocol & 0xff;
    695     m0->m_len += PPP_HDRLEN;
    696 
    697     if (sc->sc_flags & SC_LOG_OUTPKT) {
    698 	printf("ppp%d output: ", ifp->if_unit);
    699 	pppdumpm(m0, -1);
    700     }
    701 
    702 #if NBPFILTER > 0
    703     /* See if bpf wants to look at the packet. */
    704     if (sc->sc_bpf)
    705 	bpf_mtap(sc->sc_bpf, m0);
    706 #endif
    707 
    708     /*
    709      * Put the packet on the appropriate queue.
    710      */
    711     s = splimp();
    712     if (IF_QFULL(ifq)) {
    713 	IF_DROP(ifq);
    714 	splx(s);
    715 	sc->sc_if.if_oerrors++;
    716 	error = ENOBUFS;
    717 	goto bad;
    718     }
    719     IF_ENQUEUE(ifq, m0);
    720 
    721     /*
    722      * Tell the device to send it out.
    723      */
    724     (*sc->sc_start)(sc);
    725 
    726     splx(s);
    727     return (0);
    728 
    729 bad:
    730     m_freem(m0);
    731     return (error);
    732 }
    733 
    734 /*
    735  * Grab another packet off a queue and apply VJ compression,
    736  * address/control and/or protocol compression if appropriate.
    737  */
    738 struct mbuf *
    739 ppp_dequeue(sc)
    740     struct ppp_softc *sc;
    741 {
    742     int s;
    743     struct mbuf *m;
    744     u_char *cp;
    745     int address, control, protocol;
    746 
    747     s = splimp();
    748     IF_DEQUEUE(&sc->sc_fastq, m);
    749     if (m == NULL)
    750 	IF_DEQUEUE(&sc->sc_if.if_snd, m);
    751     splx(s);
    752     if (m == NULL)
    753 	return NULL;
    754 
    755     /*
    756      * Extract the ppp header of the new packet.
    757      * The ppp header will be in one mbuf.
    758      */
    759     cp = mtod(m, u_char *);
    760     address = cp[0];
    761     control = cp[1];
    762     protocol = (cp[2] << 8) + cp[3];
    763 
    764 #ifdef VJC
    765     /*
    766      * If the packet is a TCP/IP packet, see if we can compress it.
    767      */
    768     if (protocol == PPP_IP && sc->sc_flags & SC_COMP_TCP) {
    769 	struct ip *ip;
    770 	int type;
    771 	struct mbuf *mp;
    772 
    773 	mp = m;
    774 	ip = (struct ip *) (cp + PPP_HDRLEN);
    775 	if (mp->m_len <= PPP_HDRLEN) {
    776 	    mp = mp->m_next;
    777 	    ip = mtod(mp, struct ip *);
    778 	}
    779 	/* this code assumes the IP/TCP header is in one non-shared mbuf */
    780 	if (ip->ip_p == IPPROTO_TCP) {
    781 	    type = sl_compress_tcp(mp, ip, &sc->sc_comp,
    782 				   !(sc->sc_flags & SC_NO_TCP_CCID));
    783 	    switch (type) {
    784 	    case TYPE_UNCOMPRESSED_TCP:
    785 		protocol = PPP_VJC_UNCOMP;
    786 		break;
    787 	    case TYPE_COMPRESSED_TCP:
    788 		protocol = PPP_VJC_COMP;
    789 		cp = mtod(m, u_char *);
    790 		cp[0] = address;	/* header has moved */
    791 		cp[1] = control;
    792 		cp[2] = 0;
    793 		break;
    794 	    }
    795 	    cp[3] = protocol;	/* update protocol in PPP header */
    796 	}
    797     }
    798 #endif	/* VJC */
    799 
    800 #ifdef BSD_COMP
    801     if (protocol < PPP_COMP && (sc->sc_flags & SC_BSD_COMP)) {
    802 	slen = m_totallen(m0);
    803 	clen = pf_bsd_comp(sc->sc_bsd_db, cbuf, proto, m0, slen);
    804     }
    805 #endif	/* BSD_COMP */
    806 
    807     /*
    808      * Compress the address/control and protocol, if possible.
    809      */
    810     if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
    811 	control == PPP_UI && protocol != PPP_ALLSTATIONS &&
    812 	protocol != PPP_LCP) {
    813 	/* can compress address/control */
    814 	m->m_data += 2;
    815 	m->m_len -= 2;
    816     }
    817     if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
    818 	/* can compress protocol */
    819 	if (mtod(m, u_char *) == cp) {
    820 	    cp[2] = cp[1];	/* move address/control up */
    821 	    cp[1] = cp[0];
    822 	}
    823 	++m->m_data;
    824 	--m->m_len;
    825     }
    826 
    827     return m;
    828 }
    829 
    830 /*
    831  * This gets called from pppoutput when a new packet is
    832  * put on a queue.
    833  */
    834 static
    835 pppasyncstart(sc)
    836     register struct ppp_softc *sc;
    837 {
    838     register struct tty *tp = (struct tty *) sc->sc_devp;
    839 
    840     pppstart(tp);
    841 }
    842 
    843 /*
    844  * Start output on async tty interface.  Get another datagram
    845  * to send from the interface queue and start sending it.
    846  */
    847 void
    848 pppstart(tp)
    849     register struct tty *tp;
    850 {
    851     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    852     register struct mbuf *m;
    853     register int len;
    854     register u_char *start, *stop, *cp;
    855     int n, s, ndone, done;
    856     struct mbuf *m2;
    857 
    858     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
    859 	/* sorry, I can't talk now */
    860 	return;
    861     }
    862     if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
    863 	(*tp->t_oproc)(tp);
    864 	return;
    865     }
    866 
    867     for (;;) {
    868 	/*
    869 	 * If there is more in the output queue, just send it now.
    870 	 * We are being called in lieu of ttstart and must do what
    871 	 * it would.
    872 	 */
    873 	if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) {
    874 	    (*tp->t_oproc)(tp);
    875 	    if (CCOUNT(&tp->t_outq) > PPP_HIWAT)
    876 		return;
    877 	}
    878 
    879 	/*
    880 	 * See if we have an existing packet partly sent.
    881 	 * If not, get a new packet and start sending it.
    882 	 * We take packets on the priority queue ahead of those
    883 	 * on the normal queue.
    884 	 */
    885 	m = sc->sc_outm;
    886 	if (m == NULL) {
    887 	    /*
    888 	     * Get another packet to be sent
    889 	     */
    890 	    m = ppp_dequeue(sc);
    891 	    if (m == NULL)
    892 		return;
    893 
    894 	    /*
    895 	     * The extra PPP_FLAG will start up a new packet, and thus
    896 	     * will flush any accumulated garbage.  We do this whenever
    897 	     * the line may have been idle for some time.
    898 	     */
    899 	    if (CCOUNT(&tp->t_outq) == 0) {
    900 		++sc->sc_bytessent;
    901 		(void) putc(PPP_FLAG, &tp->t_outq);
    902 	    }
    903 
    904 	    /* Calculate the FCS for the first mbuf's worth. */
    905 	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
    906 	}
    907 
    908 	for (;;) {
    909 	    start = mtod(m, u_char *);
    910 	    len = m->m_len;
    911 	    stop = start + len;
    912 	    while (len > 0) {
    913 		/*
    914 		 * Find out how many bytes in the string we can
    915 		 * handle without doing something special.
    916 		 */
    917 		for (cp = start; cp < stop; cp++)
    918 		    if (ESCAPE_P(*cp))
    919 			break;
    920 		n = cp - start;
    921 		if (n) {
    922 #ifndef	RB_LEN
    923 		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
    924 		    ndone = n - b_to_q(start, n, &tp->t_outq);
    925 #else
    926 #ifdef	NetBSD
    927 		    /* NetBSD with 2-byte ring buffer entries */
    928 		    ndone = rb_cwrite(&tp->t_out, start, n);
    929 #else
    930 		    /* 386BSD, FreeBSD */
    931 		    int cc, nleft;
    932 		    for (nleft = n; nleft > 0; nleft -= cc) {
    933 			if ((cc = RB_CONTIGPUT(&tp->t_out)) == 0)
    934 			    break;
    935 			cc = min (cc, nleft);
    936 			bcopy((char *)start + n - nleft, tp->t_out.rb_tl, cc);
    937 			tp->t_out.rb_tl = RB_ROLLOVER(&tp->t_out,
    938 						      tp->t_out.rb_tl + cc);
    939 		    }
    940 		    ndone = n - nleft;
    941 #endif	/* NetBSD */
    942 #endif	/* RB_LEN */
    943 		    len -= ndone;
    944 		    start += ndone;
    945 		    sc->sc_bytessent += ndone;
    946 
    947 		    if (ndone < n)
    948 			break;	/* packet doesn't fit */
    949 		}
    950 		/*
    951 		 * If there are characters left in the mbuf,
    952 		 * the first one must be special..
    953 		 * Put it out in a different form.
    954 		 */
    955 		if (len) {
    956 		    if (putc(PPP_ESCAPE, &tp->t_outq))
    957 			break;
    958 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
    959 			(void) unputc(&tp->t_outq);
    960 			break;
    961 		    }
    962 		    sc->sc_bytessent += 2;
    963 		    start++;
    964 		    len--;
    965 		}
    966 	    }
    967 	    /*
    968 	     * If we didn't empty this mbuf, remember where we're up to.
    969 	     * If we emptied the last mbuf, try to add the FCS and closing
    970 	     * flag, and if we can't, leave sc_outm pointing to m, but with
    971 	     * m->m_len == 0, to remind us to output the FCS and flag later.
    972 	     */
    973 	    done = len == 0;
    974 	    if (done && m->m_next == NULL) {
    975 		u_char *p, *q;
    976 		int c;
    977 		u_char endseq[8];
    978 
    979 		/*
    980 		 * We may have to escape the bytes in the FCS.
    981 		 */
    982 		p = endseq;
    983 		c = ~sc->sc_outfcs & 0xFF;
    984 		if (ESCAPE_P(c)) {
    985 		    *p++ = PPP_ESCAPE;
    986 		    *p++ = c ^ PPP_TRANS;
    987 		} else
    988 		    *p++ = c;
    989 		c = (~sc->sc_outfcs >> 8) & 0xFF;
    990 		if (ESCAPE_P(c)) {
    991 		    *p++ = PPP_ESCAPE;
    992 		    *p++ = c ^ PPP_TRANS;
    993 		} else
    994 		    *p++ = c;
    995 		*p++ = PPP_FLAG;
    996 
    997 		/*
    998 		 * Try to output the FCS and flag.  If the bytes
    999 		 * don't all fit, back out.
   1000 		 */
   1001 		for (q = endseq; q < p; ++q)
   1002 		    if (putc(*q, &tp->t_outq)) {
   1003 			done = 0;
   1004 			for (; q > endseq; --q)
   1005 			    unputc(&tp->t_outq);
   1006 			break;
   1007 		    }
   1008 	    }
   1009 
   1010 	    if (!done) {
   1011 		m->m_data = start;
   1012 		m->m_len = len;
   1013 		sc->sc_outm = m;
   1014 		if (tp->t_oproc != NULL)
   1015 		    (*tp->t_oproc)(tp);
   1016 		return;		/* can't do any more at the moment */
   1017 	    }
   1018 
   1019 	    /* Finished with this mbuf; free it and move on. */
   1020 	    MFREE(m, m2);
   1021 	    if (m2 == NULL)
   1022 		break;
   1023 
   1024 	    m = m2;
   1025 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
   1026 	}
   1027 
   1028 	/* Finished a packet */
   1029 	sc->sc_outm = NULL;
   1030 	sc->sc_bytessent++;	/* account for closing flag */
   1031 	sc->sc_if.if_opackets++;
   1032 	sc->sc_if.if_obytes = sc->sc_bytessent;
   1033     }
   1034 }
   1035 
   1036 /*
   1037  * Allocate enough mbuf to handle current MRU.
   1038  */
   1039 static int
   1040 pppgetm(sc)
   1041     register struct ppp_softc *sc;
   1042 {
   1043     struct mbuf *m, **mp;
   1044     int len = HDROFF + sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN;
   1045     int s;
   1046 
   1047     s = splimp();
   1048     for (mp = &sc->sc_m; (m = *mp) != NULL; mp = &m->m_next)
   1049 	if ((len -= M_DATASIZE(m)) <= 0) {
   1050 	    splx(s);
   1051 	    return (1);
   1052 	}
   1053 
   1054     for (;; mp = &m->m_next) {
   1055 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1056 	if (m == 0) {
   1057 	    m_freem(sc->sc_m);
   1058 	    sc->sc_m = NULL;
   1059 	    splx(s);
   1060 	    printf("ppp%d: can't allocate mbuf\n", sc->sc_if.if_unit);
   1061 	    return (0);
   1062 	}
   1063 	*mp = m;
   1064 	MCLGET(m, M_DONTWAIT);
   1065 	if ((len -= M_DATASIZE(m)) <= 0) {
   1066 	    splx(s);
   1067 	    return (1);
   1068 	}
   1069     }
   1070 }
   1071 
   1072 /*
   1073  * Copy mbuf chain.  Would like to use m_copy(), but we need a real copy
   1074  * of the data, not just copies of pointers to the data.
   1075  */
   1076 static struct mbuf *
   1077 ppp_btom(sc)
   1078     struct ppp_softc *sc;
   1079 {
   1080     register struct mbuf *m, **mp;
   1081     struct mbuf *top = sc->sc_m;
   1082 
   1083     /*
   1084      * First check current mbuf.  If we have more than a small mbuf,
   1085      * return the whole cluster and set beginning of buffer to the
   1086      * next mbuf.
   1087      * Else, copy the current bytes into a small mbuf, attach the new
   1088      * mbuf to the end of the chain and set beginning of buffer to the
   1089      * current mbuf.
   1090      */
   1091 
   1092     if (sc->sc_mc->m_len > MHLEN) {
   1093 	sc->sc_m = sc->sc_mc->m_next;
   1094 	sc->sc_mc->m_next = NULL;
   1095     }
   1096     else {
   1097 	/* rather than waste a whole cluster on <= MHLEN bytes,
   1098 	   alloc a small mbuf and copy to it */
   1099 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1100 	if (m == NULL)
   1101 	    return (NULL);
   1102 
   1103 	bcopy(mtod(sc->sc_mc, caddr_t), mtod(m, caddr_t), sc->sc_mc->m_len);
   1104 	m->m_len = sc->sc_mc->m_len;
   1105 	for (mp = &top; *mp != sc->sc_mc; mp = &(*mp)->m_next)
   1106 	    ;
   1107 	*mp = m;
   1108 	sc->sc_m = sc->sc_mc;
   1109     }
   1110 
   1111     /*
   1112      * Try to allocate enough extra mbufs to handle the next packet.
   1113      */
   1114     if (pppgetm(sc) == 0) {
   1115 	m_freem(top);
   1116 	if (pppgetm(sc) == 0)
   1117 	    sc->sc_if.if_flags &= ~IFF_UP;
   1118 	return (NULL);
   1119     }
   1120 
   1121     return (top);
   1122 }
   1123 
   1124 /*
   1125  * PPP packet input routine.
   1126  * The caller has checked and removed the FCS.
   1127  * The return value is 1 if the packet was put on sc->sc_inq,
   1128  * 0 otherwise.
   1129  */
   1130 #define COMPTYPE(proto)	((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
   1131 			 TYPE_UNCOMPRESSED_TCP)
   1132 
   1133 int
   1134 ppppktin(sc, m, ilen)
   1135     struct ppp_softc *sc;
   1136     struct mbuf *m;
   1137     int ilen;
   1138 {
   1139     struct ifqueue *inq;
   1140     int s, xlen, proto, rv;
   1141     struct ppp_header hdr;
   1142 
   1143     sc->sc_if.if_ipackets++;
   1144     rv = 0;
   1145 
   1146     hdr = *mtod(m, struct ppp_header *);
   1147     proto = ntohs(hdr.ph_protocol);
   1148 
   1149 #ifdef VJC
   1150     /*
   1151      * See if we have a VJ-compressed packet to uncompress.
   1152      */
   1153     if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
   1154 	char *pkttype = proto == PPP_VJC_COMP? "": "un";
   1155 
   1156 	if (sc->sc_flags & SC_REJ_COMP_TCP) {
   1157 	    if (sc->sc_flags & SC_DEBUG)
   1158 		printf("ppp%d: %scomp pkt w/o compression; flags 0x%x\n",
   1159 			sc->sc_if.if_unit, pkttype, sc->sc_flags);
   1160 	    sc->sc_if.if_ierrors++;
   1161 	    return 0;
   1162 	}
   1163 
   1164 	m->m_data += PPP_HDRLEN;
   1165 	m->m_len -= PPP_HDRLEN;
   1166 	ilen -= PPP_HDRLEN;
   1167 	xlen = sl_uncompress_tcp_part((u_char **)(&m->m_data),
   1168 					m->m_len, ilen,
   1169 					COMPTYPE(proto), &sc->sc_comp);
   1170 
   1171 	if (xlen == 0) {
   1172 	    if (sc->sc_flags & SC_DEBUG)
   1173 		printf("ppp%d: sl_uncompress failed on type %scomp\n",
   1174 			sc->sc_if.if_unit, pkttype);
   1175 	    sc->sc_if.if_ierrors++;
   1176 	    return 0;
   1177 	}
   1178 
   1179 	/* adjust the first mbuf by the decompressed amt */
   1180 	xlen += PPP_HDRLEN;
   1181 	m->m_len += xlen - ilen;
   1182 	ilen = xlen;
   1183 	m->m_data -= PPP_HDRLEN;
   1184 	proto = PPP_IP;
   1185 
   1186 	/* put the ppp header back in place */
   1187 	hdr.ph_protocol = htons(PPP_IP);
   1188 	*mtod(m, struct ppp_header *) = hdr;
   1189     }
   1190 #endif /* VJC */
   1191 
   1192     /* get this packet as an mbuf chain */
   1193     if ((m = ppp_btom(sc)) == NULL) {
   1194 	sc->sc_if.if_ierrors++;
   1195 	return 0;
   1196     }
   1197     m->m_pkthdr.len = ilen;
   1198     m->m_pkthdr.rcvif = &sc->sc_if;
   1199 
   1200 #if NBPFILTER > 0
   1201     /* See if bpf wants to look at the packet. */
   1202     if (sc->sc_bpf)
   1203 	bpf_mtap(sc->sc_bpf, m);
   1204 #endif
   1205 
   1206     switch (proto) {
   1207 #ifdef INET
   1208     case PPP_IP:
   1209 	/*
   1210 	 * IP packet - take off the ppp header and pass it up to IP.
   1211 	 */
   1212 	if ((sc->sc_if.if_flags & IFF_UP) == 0
   1213 	    || (sc->sc_flags & SC_ENABLE_IP) == 0) {
   1214 	    /* interface is down - drop the packet. */
   1215 	    m_freem(m);
   1216 	    return 0;
   1217 	}
   1218 	m->m_pkthdr.len -= PPP_HDRLEN;
   1219 	m->m_data += PPP_HDRLEN;
   1220 	m->m_len -= PPP_HDRLEN;
   1221 	schednetisr(NETISR_IP);
   1222 	inq = &ipintrq;
   1223 	break;
   1224 #endif
   1225 
   1226     default:
   1227 	/*
   1228 	 * Some other protocol - place on input queue for read().
   1229 	 */
   1230 	inq = &sc->sc_inq;
   1231 	rv = 1;
   1232 	break;
   1233     }
   1234 
   1235     /*
   1236      * Put the packet on the appropriate input queue.
   1237      */
   1238     s = splimp();
   1239     if (IF_QFULL(inq)) {
   1240 	IF_DROP(inq);
   1241 	if (sc->sc_flags & SC_DEBUG)
   1242 	    printf("ppp%d: queue full\n", sc->sc_if.if_unit);
   1243 	sc->sc_if.if_ierrors++;
   1244 	sc->sc_if.if_iqdrops++;
   1245 	m_freem(m);
   1246 	rv = 0;
   1247     } else
   1248 	IF_ENQUEUE(inq, m);
   1249 
   1250     splx(s);
   1251     return rv;
   1252 }
   1253 
   1254 /*
   1255  * tty interface receiver interrupt.
   1256  */
   1257 static unsigned paritytab[8] = {
   1258     0x96696996, 0x69969669, 0x69969669, 0x96696996,
   1259     0x69969669, 0x96696996, 0x96696996, 0x69969669
   1260 };
   1261 
   1262 void
   1263 pppinput(c, tp)
   1264     int c;
   1265     register struct tty *tp;
   1266 {
   1267     register struct ppp_softc *sc;
   1268     struct mbuf *m;
   1269     int ilen;
   1270 
   1271     tk_nin++;
   1272     sc = (struct ppp_softc *) tp->t_sc;
   1273     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
   1274 	return;
   1275 
   1276     ++sc->sc_bytesrcvd;
   1277 
   1278     if (c & TTY_FE) {
   1279 	/* framing error or overrun on this char - abort packet */
   1280 	if (sc->sc_flags & SC_DEBUG)
   1281 	    printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
   1282 	goto flush;
   1283     }
   1284 
   1285     c &= 0xff;
   1286 
   1287     if (c & 0x80)
   1288 	sc->sc_flags |= SC_RCV_B7_1;
   1289     else
   1290 	sc->sc_flags |= SC_RCV_B7_0;
   1291     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
   1292 	sc->sc_flags |= SC_RCV_ODDP;
   1293     else
   1294 	sc->sc_flags |= SC_RCV_EVNP;
   1295 
   1296     if (sc->sc_flags & SC_LOG_RAWIN)
   1297 	ppplogchar(sc, c);
   1298 
   1299     if (c == PPP_FLAG) {
   1300 	ilen = sc->sc_ilen;
   1301 	sc->sc_ilen = 0;
   1302 	sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
   1303 
   1304 	if (sc->sc_rawin_count > 0)
   1305 	    ppplogchar(sc, -1);
   1306 
   1307 	/*
   1308 	 * If SC_ESCAPED is set, then we've seen the packet
   1309 	 * abort sequence "}~".
   1310 	 */
   1311 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
   1312 	    || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
   1313 #ifdef VJC
   1314 	    /*
   1315 	     * If we've missed a packet, we must toss subsequent compressed
   1316 	     * packets which don't have an explicit connection ID.
   1317 	     */
   1318 	    sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);
   1319 #endif
   1320 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
   1321 		if (sc->sc_flags & SC_DEBUG)
   1322 		    printf("ppp%d: bad fcs\n", sc->sc_if.if_unit);
   1323 		sc->sc_if.if_ierrors++;
   1324 	    } else
   1325 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
   1326 	    return;
   1327 	}
   1328 
   1329 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
   1330 	    if (ilen) {
   1331 		if (sc->sc_flags & SC_DEBUG)
   1332 		    printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
   1333 		sc->sc_if.if_ierrors++;
   1334 	    }
   1335 	    return;
   1336 	}
   1337 
   1338 	/*
   1339 	 * Remove FCS trailer.  Somewhat painful...
   1340 	 */
   1341 	ilen -= 2;
   1342 	if (--sc->sc_mc->m_len == 0) {
   1343 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
   1344 		;
   1345 	    sc->sc_mc = m;
   1346 	}
   1347 	sc->sc_mc->m_len--;
   1348 
   1349 	m = sc->sc_m;
   1350 
   1351 	if (sc->sc_flags & SC_LOG_INPKT) {
   1352 	    printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen);
   1353 	    pppdumpm(m, ilen);
   1354 	}
   1355 
   1356 	if (ppppktin(sc, m, ilen)) {
   1357 	    /* Put a placeholder byte in canq for ttselect()/ttnread(). */
   1358 	    putc(0, &tp->t_canq);
   1359 	    ttwakeup(tp);
   1360 	}
   1361 	return;
   1362     }
   1363 
   1364     if (sc->sc_flags & SC_FLUSH) {
   1365 	if (sc->sc_flags & SC_LOG_FLUSH)
   1366 	    ppplogchar(sc, c);
   1367 	return;
   1368     }
   1369 
   1370     if (c == PPP_ESCAPE) {
   1371 	sc->sc_flags |= SC_ESCAPED;
   1372 	return;
   1373     }
   1374     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
   1375 	return;
   1376 
   1377     if (sc->sc_flags & SC_ESCAPED) {
   1378 	sc->sc_flags &= ~SC_ESCAPED;
   1379 	c ^= PPP_TRANS;
   1380     }
   1381 
   1382     /*
   1383      * Initialize buffer on first octet received.
   1384      * First octet could be address or protocol (when compressing
   1385      * address/control).
   1386      * Second octet is control.
   1387      * Third octet is first or second (when compressing protocol)
   1388      * octet of protocol.
   1389      * Fourth octet is second octet of protocol.
   1390      */
   1391     if (sc->sc_ilen == 0) {
   1392 	/* reset the first input mbuf */
   1393 	m = sc->sc_m;
   1394 	m->m_len = 0;
   1395 	m->m_data = M_DATASTART(sc->sc_m) + HDROFF;
   1396 	sc->sc_mc = m;
   1397 	sc->sc_mp = mtod(m, char *);
   1398 	sc->sc_fcs = PPP_INITFCS;
   1399 	if (c != PPP_ALLSTATIONS) {
   1400 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
   1401 		if (sc->sc_flags & SC_DEBUG)
   1402 		    printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
   1403 			   sc->sc_if.if_unit, c);
   1404 		goto flush;
   1405 	    }
   1406 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
   1407 	    *sc->sc_mp++ = PPP_UI;
   1408 	    sc->sc_ilen += 2;
   1409 	    m->m_len += 2;
   1410 	}
   1411     }
   1412     if (sc->sc_ilen == 1 && c != PPP_UI) {
   1413 	if (sc->sc_flags & SC_DEBUG)
   1414 	    printf("ppp%d: missing UI (0x3), got 0x%x\n",
   1415 		   sc->sc_if.if_unit, c);
   1416 	goto flush;
   1417     }
   1418     if (sc->sc_ilen == 2 && (c & 1) == 1) {
   1419 	/* a compressed protocol */
   1420 	*sc->sc_mp++ = 0;
   1421 	sc->sc_ilen++;
   1422 	sc->sc_mc->m_len++;
   1423     }
   1424     if (sc->sc_ilen == 3 && (c & 1) == 0) {
   1425 	if (sc->sc_flags & SC_DEBUG)
   1426 	    printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
   1427 		   (sc->sc_mp[-1] << 8) + c);
   1428 	goto flush;
   1429     }
   1430 
   1431     /* packet beyond configured mru? */
   1432     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
   1433 	if (sc->sc_flags & SC_DEBUG)
   1434 	    printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
   1435 	goto flush;
   1436     }
   1437 
   1438     /* is this mbuf full? */
   1439     m = sc->sc_mc;
   1440     if (M_TRAILINGSPACE(m) <= 0) {
   1441 	sc->sc_mc = m = m->m_next;
   1442 	if (m == NULL) {
   1443 	    printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
   1444 	    goto flush;
   1445 	}
   1446 	m->m_len = 0;
   1447 	m->m_data = M_DATASTART(m);
   1448 	sc->sc_mp = mtod(m, char *);
   1449     }
   1450 
   1451     ++m->m_len;
   1452     *sc->sc_mp++ = c;
   1453     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
   1454     return;
   1455 
   1456  flush:
   1457     if (!(sc->sc_flags & SC_FLUSH)) {
   1458 	sc->sc_if.if_ierrors++;
   1459 	sc->sc_flags |= SC_FLUSH;
   1460 	if (sc->sc_flags & SC_LOG_FLUSH)
   1461 	    ppplogchar(sc, c);
   1462     }
   1463 }
   1464 
   1465 /*
   1466  * Process an ioctl request to interface.
   1467  */
   1468 pppioctl(ifp, cmd, data)
   1469     register struct ifnet *ifp;
   1470     int cmd;
   1471     caddr_t data;
   1472 {
   1473     struct proc *p = curproc;	/* XXX */
   1474     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
   1475     register struct ifaddr *ifa = (struct ifaddr *)data;
   1476     register struct ifreq *ifr = (struct ifreq *)data;
   1477     int s = splimp(), error = 0;
   1478 
   1479 
   1480     switch (cmd) {
   1481     case SIOCSIFFLAGS:
   1482 	if ((ifp->if_flags & IFF_RUNNING) == 0)
   1483 	    ifp->if_flags &= ~IFF_UP;
   1484 	break;
   1485 
   1486     case SIOCSIFADDR:
   1487 	if (ifa->ifa_addr->sa_family != AF_INET)
   1488 	    error = EAFNOSUPPORT;
   1489 	break;
   1490 
   1491     case SIOCSIFDSTADDR:
   1492 	if (ifa->ifa_addr->sa_family != AF_INET)
   1493 	    error = EAFNOSUPPORT;
   1494 	break;
   1495 
   1496     case SIOCSIFMTU:
   1497 	if (error = suser(p->p_ucred, &p->p_acflag))
   1498 	    return (error);
   1499 	sc->sc_if.if_mtu = ifr->ifr_mtu;
   1500 	break;
   1501 
   1502     case SIOCGIFMTU:
   1503 	ifr->ifr_mtu = sc->sc_if.if_mtu;
   1504 	break;
   1505 
   1506     default:
   1507 	error = EINVAL;
   1508     }
   1509     splx(s);
   1510     return (error);
   1511 }
   1512 
   1513 #define MAX_DUMP_BYTES	128
   1514 
   1515 static void
   1516 pppdumpm(m0, pktlen)
   1517     struct mbuf *m0;
   1518     int pktlen;
   1519 {
   1520     char buf[3*MAX_DUMP_BYTES+4];
   1521     char *bp = buf;
   1522     struct mbuf *m;
   1523     static char digits[] = "0123456789abcdef";
   1524 
   1525     for (m = m0; m && pktlen; m = m->m_next) {
   1526 	int l = m->m_len;
   1527 	u_char *rptr = (u_char *)m->m_data;
   1528 
   1529 	if (pktlen > 0) {
   1530 	    l = min(l, pktlen);
   1531 	    pktlen -= l;
   1532 	}
   1533 	while (l--) {
   1534 	    if (bp > buf + sizeof(buf) - 4)
   1535 		goto done;
   1536 	    *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
   1537 	    *bp++ = digits[*rptr++ & 0xf];
   1538 	}
   1539 
   1540 	if (m->m_next) {
   1541 	    if (bp > buf + sizeof(buf) - 3)
   1542 		goto done;
   1543 	    *bp++ = '|';
   1544 	} else
   1545 	    *bp++ = ' ';
   1546     }
   1547 done:
   1548     if (m && pktlen)
   1549 	*bp++ = '>';
   1550     *bp = 0;
   1551     printf("%s\n", buf);
   1552 }
   1553 
   1554 static void
   1555 ppplogchar(sc, c)
   1556     struct ppp_softc *sc;
   1557     int c;
   1558 {
   1559     if (c >= 0)
   1560 	sc->sc_rawin[sc->sc_rawin_count++] = c;
   1561     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
   1562 	|| c < 0 && sc->sc_rawin_count > 0) {
   1563 	printf("ppp%d input: ", sc->sc_if.if_unit);
   1564 	pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
   1565 	sc->sc_rawin_count = 0;
   1566     }
   1567 }
   1568 
   1569 static void
   1570 pppdumpb(b, l)
   1571     u_char *b;
   1572     int l;
   1573 {
   1574     char buf[3*MAX_DUMP_BYTES+4];
   1575     char *bp = buf;
   1576     static char digits[] = "0123456789abcdef";
   1577 
   1578     while (l--) {
   1579 	if (bp >= buf + sizeof(buf) - 3) {
   1580 	    *bp++ = '>';
   1581 	    break;
   1582 	}
   1583 	*bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
   1584 	*bp++ = digits[*b++ & 0xf];
   1585 	*bp++ = ' ';
   1586     }
   1587 
   1588     *bp = 0;
   1589     printf("%s\n", buf);
   1590 }
   1591 
   1592 
   1593 #endif	/* NPPP > 0 */
   1594