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