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