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