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