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