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