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