Home | History | Annotate | Line # | Download | only in net
if_ppp.c revision 1.3.2.3
      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.3 1993/10/27 01:42:19 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 
    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 #if 0
    674     /* don't hang forever if we lose an interrupt */
    675     if (CCOUNT(&sc->sc_ttyp->t_outq) == 0)
    676 #endif
    677 	pppstart(sc->sc_ttyp);
    678     splx(s);
    679     return (0);
    680 
    681 bad:
    682     m_freem(m0);
    683     return (error);
    684 }
    685 
    686 /*
    687  * Start output on interface.  Get another datagram
    688  * to send from the interface queue and map it to
    689  * the interface before starting output.
    690  */
    691 void
    692 pppstart(tp)
    693     register struct tty *tp;
    694 {
    695     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    696     register struct mbuf *m;
    697     register int len;
    698     register u_char *start, *stop, *cp;
    699     int n, s, ndone, done;
    700     struct mbuf *m2;
    701     int address, control, protocol;
    702     int compac, compprot, nb;
    703 
    704     for (;;) {
    705 	/*
    706 	 * If there is more in the output queue, just send it now.
    707 	 * We are being called in lieu of ttstart and must do what
    708 	 * it would.
    709 	 */
    710 	if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) {
    711 	    (*tp->t_oproc)(tp);
    712 	    if (CCOUNT(&tp->t_outq) > PPP_HIWAT)
    713 		return;
    714 	}
    715 	/*
    716 	 * This happens briefly when the line shuts down.
    717 	 */
    718 	if (sc == NULL)
    719 	    return;
    720 
    721 	/*
    722 	 * See if we have an existing packet partly sent.
    723 	 * If not, get a new packet and start sending it.
    724 	 * We take packets on the priority queue ahead of those
    725 	 * on the normal queue.
    726 	 */
    727 	m = sc->sc_outm;
    728 	if (m == NULL) {
    729 	    s = splimp();
    730 	    IF_DEQUEUE(&sc->sc_fastq, m);
    731 	    if (m == NULL)
    732 		IF_DEQUEUE(&sc->sc_if.if_snd, m);
    733 	    splx(s);
    734 	    if (m == NULL)
    735 		return;
    736 
    737 	    /*
    738 	     * Extract the ppp header of the new packet.
    739 	     * The ppp header will be in one mbuf.
    740 	     */
    741 	    cp = mtod(m, u_char *);
    742 	    address = *cp++;
    743 	    control = *cp++;
    744 	    protocol = *cp++;
    745 	    protocol = (protocol << 8) + *cp++;
    746 	    m->m_data += PPP_HEADER_LEN;
    747 	    m->m_len -= PPP_HEADER_LEN;
    748 
    749 #ifdef VJC
    750 	    /*
    751 	     * If the packet is a TCP/IP packet, see if we can compress it.
    752 	     */
    753 	    if (protocol == PPP_IP && sc->sc_flags & SC_COMP_TCP) {
    754 		struct ip *ip;
    755 		int type;
    756 		struct mbuf *mp;
    757 
    758 		mp = m;
    759 		if (mp->m_len <= 0) {
    760 		    mp = mp->m_next;
    761 		    cp = mtod(mp, u_char *);
    762 		}
    763 		ip = (struct ip *) cp;
    764 		if (ip->ip_p == IPPROTO_TCP) {
    765 		    type = sl_compress_tcp(mp, ip, &sc->sc_comp,
    766 					   !(sc->sc_flags & SC_NO_TCP_CCID));
    767 		    switch (type) {
    768 		    case TYPE_UNCOMPRESSED_TCP:
    769 			protocol = PPP_VJC_UNCOMP;
    770 			break;
    771 		    case TYPE_COMPRESSED_TCP:
    772 			protocol = PPP_VJC_COMP;
    773 			break;
    774 		    }
    775 		}
    776 	    }
    777 #endif
    778 
    779 	    /*
    780 	     * Compress the address/control and protocol, if possible.
    781 	     */
    782 	    compac = sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
    783 		control == PPP_UI && protocol != PPP_ALLSTATIONS &&
    784 		protocol != PPP_LCP;
    785 	    compprot = sc->sc_flags & SC_COMP_PROT && protocol < 0x100;
    786 	    nb = (compac ? 0 : 2) + (compprot ? 1 : 2);
    787 	    m->m_data -= nb;
    788 	    m->m_len += nb;
    789 
    790 	    cp = mtod(m, u_char *);
    791 	    if (!compac) {
    792 		*cp++ = address;
    793 		*cp++ = control;
    794 	    }
    795 	    if (!compprot)
    796 		*cp++ = protocol >> 8;
    797 	    *cp++ = protocol;
    798 
    799 	    /*
    800 	     * The extra PPP_FLAG will start up a new packet, and thus
    801 	     * will flush any accumulated garbage.  We do this whenever
    802 	     * the line may have been idle for some time.
    803 	     */
    804 	    if (CCOUNT(&tp->t_outq) == 0) {
    805 		++sc->sc_bytessent;
    806 		(void) putc(PPP_FLAG, &tp->t_outq);
    807 	    }
    808 
    809 	    /* Calculate the FCS for the first mbuf's worth. */
    810 	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
    811 	}
    812 
    813 	for (;;) {
    814 	    start = mtod(m, u_char *);
    815 	    len = m->m_len;
    816 	    stop = start + len;
    817 	    while (len > 0) {
    818 		/*
    819 		 * Find out how many bytes in the string we can
    820 		 * handle without doing something special.
    821 		 */
    822 		for (cp = start; cp < stop; cp++)
    823 		    if (ESCAPE_P(*cp))
    824 			break;
    825 		n = cp - start;
    826 		if (n) {
    827 #ifndef	RB_LEN
    828 		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
    829 		    ndone = n - b_to_q(start, n, &tp->t_outq);
    830 #else
    831 #ifdef	NetBSD
    832 		    /* NetBSD, 0.8 or earlier */
    833 		    ndone = rb_cwrite(&tp->t_out, start, n);
    834 #else
    835 		    /* 386BSD */
    836 		    int cc, nleft;
    837 		    for (nleft = n; nleft > 0; nleft -= cc) {
    838 			if ((cc = RB_CONTIGPUT(&tp->t_out)) == 0)
    839 			    break;
    840 			cc = min (cc, nleft);
    841 			bcopy((char *)start, tp->t_out.rb_tl, cc);
    842 			tp->t_out.rb_tl = RB_ROLLOVER(&tp->t_out,
    843 						      tp->t_out.rb_tl + cc);
    844 		    }
    845 		    ndone = n - nleft;
    846 #endif	/* NetBSD */
    847 #endif	/* RB_LEN */
    848 		    len -= ndone;
    849 		    start += ndone;
    850 		    sc->sc_bytessent += ndone;
    851 
    852 		    if (ndone < n)
    853 			break;	/* packet doesn't fit */
    854 		}
    855 		/*
    856 		 * If there are characters left in the mbuf,
    857 		 * the first one must be special..
    858 		 * Put it out in a different form.
    859 		 */
    860 		if (len) {
    861 		    if (putc(PPP_ESCAPE, &tp->t_outq))
    862 			break;
    863 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
    864 			(void) unputc(&tp->t_outq);
    865 			break;
    866 		    }
    867 		    sc->sc_bytessent += 2;
    868 		    start++;
    869 		    len--;
    870 		}
    871 	    }
    872 	    /*
    873 	     * If we didn't empty this mbuf, remember where we're up to.
    874 	     * If we emptied the last mbuf, try to add the FCS and closing
    875 	     * flag, and if we can't, leave sc_outm pointing to m, but with
    876 	     * m->m_len == 0, to remind us to output the FCS and flag later.
    877 	     */
    878 	    done = len == 0;
    879 	    if (done && m->m_next == NULL) {
    880 		u_char *p, *q;
    881 		int c;
    882 		u_char endseq[8];
    883 
    884 		/*
    885 		 * We may have to escape the bytes in the FCS.
    886 		 */
    887 		p = endseq;
    888 		c = ~sc->sc_outfcs & 0xFF;
    889 		if (ESCAPE_P(c)) {
    890 		    *p++ = PPP_ESCAPE;
    891 		    *p++ = c ^ PPP_TRANS;
    892 		} else
    893 		    *p++ = c;
    894 		c = (~sc->sc_outfcs >> 8) & 0xFF;
    895 		if (ESCAPE_P(c)) {
    896 		    *p++ = PPP_ESCAPE;
    897 		    *p++ = c ^ PPP_TRANS;
    898 		} else
    899 		    *p++ = c;
    900 		*p++ = PPP_FLAG;
    901 
    902 		/*
    903 		 * Try to output the FCS and flag.  If the bytes
    904 		 * don't all fit, back out.
    905 		 */
    906 		for (q = endseq; q < p; ++q)
    907 		    if (putc(*q, &tp->t_outq)) {
    908 			done = 0;
    909 			for (; q > endseq; --q)
    910 			    unputc(&tp->t_outq);
    911 			break;
    912 		    }
    913 	    }
    914 
    915 	    if (!done) {
    916 		m->m_data = start;
    917 		m->m_len = len;
    918 		sc->sc_outm = m;
    919 		if (tp->t_oproc != NULL)
    920 		    (*tp->t_oproc)(tp);
    921 		return;		/* can't do any more at the moment */
    922 	    }
    923 
    924 	    /* Finished with this mbuf; free it and move on. */
    925 	    MFREE(m, m2);
    926 	    if (m2 == NULL)
    927 		break;
    928 
    929 	    m = m2;
    930 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
    931 	}
    932 
    933 	/* Finished a packet */
    934 	sc->sc_outm = NULL;
    935 	sc->sc_bytessent++;	/* account for closing flag */
    936 	sc->sc_if.if_opackets++;
    937 	sc->sc_if.if_obytes = sc->sc_bytessent;
    938     }
    939 }
    940 
    941 /*
    942  * Allocate enough mbuf to handle current MRU.
    943  */
    944 static int
    945 pppinit(sc)
    946     register struct ppp_softc *sc;
    947 {
    948     struct mbuf *m, **mp;
    949     int len = HDROFF + sc->sc_mru + PPP_HEADER_LEN + PPP_FCS_LEN;
    950     int s;
    951 
    952     s = splimp();
    953     for (mp = &sc->sc_m; (m = *mp) != NULL; mp = &m->m_next)
    954 	if ((len -= M_DATASIZE(m)) <= 0) {
    955 	    splx(s);
    956 	    return (1);
    957 	}
    958 
    959     for (;; mp = &m->m_next) {
    960 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    961 	if (m == 0) {
    962 	    m_freem(sc->sc_m);
    963 	    sc->sc_m = NULL;
    964 	    splx(s);
    965 	    printf("ppp%d: can't allocate mbuf\n", sc->sc_if.if_unit);
    966 	    return (0);
    967 	}
    968 	*mp = m;
    969 	MCLGET(m, M_DONTWAIT);
    970 	if ((len -= M_DATASIZE(m)) <= 0) {
    971 	    splx(s);
    972 	    return (1);
    973 	}
    974     }
    975 }
    976 
    977 /*
    978  * Copy mbuf chain.  Would like to use m_copy(), but we need a real copy
    979  * of the data, not just copies of pointers to the data.
    980  */
    981 static struct mbuf *
    982 ppp_btom(sc)
    983     struct ppp_softc *sc;
    984 {
    985     register struct mbuf *m, **mp;
    986     struct mbuf *top = sc->sc_m;
    987 
    988     /*
    989      * First check current mbuf.  If we have more than a small mbuf,
    990      * return the whole cluster and set beginning of buffer to the
    991      * next mbuf.
    992      * Else, copy the current bytes into a small mbuf, attach the new
    993      * mbuf to the end of the chain and set beginning of buffer to the
    994      * current mbuf.
    995      */
    996 
    997     if (sc->sc_mc->m_len > MHLEN) {
    998 	sc->sc_m = sc->sc_mc->m_next;
    999 	sc->sc_mc->m_next = NULL;
   1000     }
   1001     else {
   1002 	/* rather than waste a whole cluster on <= MHLEN bytes,
   1003 	   alloc a small mbuf and copy to it */
   1004 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1005 	if (m == NULL)
   1006 	    return (NULL);
   1007 
   1008 	bcopy(mtod(sc->sc_mc, caddr_t), mtod(m, caddr_t), sc->sc_mc->m_len);
   1009 	m->m_len = sc->sc_mc->m_len;
   1010 	for (mp = &top; *mp != sc->sc_mc; mp = &(*mp)->m_next)
   1011 	    ;
   1012 	*mp = m;
   1013 	sc->sc_m = sc->sc_mc;
   1014     }
   1015 
   1016     /*
   1017      * Try to allocate enough extra mbufs to handle the next packet.
   1018      */
   1019     if (pppinit(sc) == 0) {
   1020 	m_freem(top);
   1021 	if (pppinit(sc) == 0)
   1022 	    sc->sc_if.if_flags &= ~IFF_UP;
   1023 	return (NULL);
   1024     }
   1025 
   1026     return (top);
   1027 }
   1028 
   1029 /*
   1030  * tty interface receiver interrupt.
   1031  */
   1032 #define COMPTYPE(proto)	((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
   1033 			 TYPE_UNCOMPRESSED_TCP)
   1034 
   1035 void
   1036 pppinput(c, tp)
   1037     int c;
   1038     register struct tty *tp;
   1039 {
   1040     register struct ppp_softc *sc;
   1041     struct mbuf *m;
   1042     struct ifqueue *inq;
   1043     int s, ilen, xlen, proto;
   1044     struct ppp_header hdr;
   1045 
   1046     tk_nin++;
   1047     sc = (struct ppp_softc *)tp->t_sc;
   1048     if (sc == NULL)
   1049 	return;
   1050 
   1051     ++sc->sc_if.if_ibytes;
   1052 
   1053     if (c & TTY_FE) {
   1054 	/* framing error or overrun on this char - abort packet */
   1055 	if (ppp_debug)
   1056 	    printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
   1057 	goto flush;
   1058     }
   1059 
   1060     c &= 0xff;
   1061 
   1062     if (sc->sc_if.if_unit == ppp_raw_in_debug) {
   1063 	ppp_rawin[ppp_rawin_count++] = c;
   1064 	if (ppp_rawin_count >= sizeof(ppp_rawin)) {
   1065 	    printf("raw ppp%d: ", ppp_raw_in_debug);
   1066 	    pppdumpb(ppp_rawin, ppp_rawin_count);
   1067 	    ppp_rawin_count = 0;
   1068 	}
   1069     }
   1070 
   1071     if (c == PPP_FLAG) {
   1072 	ilen = sc->sc_ilen;
   1073 	sc->sc_ilen = 0;
   1074 
   1075 	if (sc->sc_flags & SC_FLUSH
   1076 	    || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
   1077 #ifdef VJC
   1078 	    /*
   1079 	     * If we've missed a packet, we must toss subsequent compressed
   1080 	     * packets which don't have an explicit connection ID.
   1081 	     */
   1082 	    sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);
   1083 #endif
   1084 	    if ((sc->sc_flags & SC_FLUSH) == 0){
   1085 		if (ppp_debug)
   1086 		    printf("ppp%d: bad fcs\n", sc->sc_if.if_unit);
   1087 		sc->sc_if.if_ierrors++;
   1088 	    } else
   1089 		sc->sc_flags &= ~SC_FLUSH;
   1090 	    return;
   1091 	}
   1092 
   1093 	if (ilen < PPP_HEADER_LEN + PPP_FCS_LEN) {
   1094 	    if (ilen) {
   1095 		if (ppp_debug)
   1096 		    printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
   1097 		sc->sc_if.if_ierrors++;
   1098 	    }
   1099 	    return;
   1100 	}
   1101 
   1102 	/*
   1103 	 * Remove FCS trailer.  Somewhat painful...
   1104 	 */
   1105 	ilen -= 2;
   1106 	if (--sc->sc_mc->m_len == 0) {
   1107 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
   1108 		;
   1109 	    sc->sc_mc = m;
   1110 	}
   1111 	sc->sc_mc->m_len--;
   1112 
   1113 	sc->sc_if.if_ipackets++;
   1114 	m = sc->sc_m;
   1115 
   1116 	if (ppp_async_in_debug) {
   1117 	    printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen);
   1118 	    pppdumpm(m, ilen);
   1119 	}
   1120 
   1121 	hdr = *mtod(m, struct ppp_header *);
   1122 	proto = ntohs(hdr.ph_protocol);
   1123 
   1124 #ifdef VJC
   1125 	/*
   1126 	 * See if we have a VJ-compressed packet to uncompress.
   1127 	 */
   1128 	if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
   1129 	    char *pkttype = proto == PPP_VJC_COMP? "": "un";
   1130 
   1131 	    if (sc->sc_flags & SC_REJ_COMP_TCP) {
   1132 		if (ppp_debug)
   1133 		    printf("ppp%d: %scomp pkt w/o compression; flags 0x%x\n",
   1134 			   sc->sc_if.if_unit, pkttype, sc->sc_flags);
   1135 		sc->sc_if.if_ierrors++;
   1136 		return;
   1137 	    }
   1138 
   1139 	    m->m_data += PPP_HEADER_LEN;
   1140 	    m->m_len -= PPP_HEADER_LEN;
   1141 	    ilen -= PPP_HEADER_LEN;
   1142 	    xlen = sl_uncompress_tcp_part((u_char **)(&m->m_data),
   1143 					  m->m_len, ilen,
   1144 					  COMPTYPE(proto), &sc->sc_comp);
   1145 
   1146 	    if (xlen == 0) {
   1147 		if (ppp_debug)
   1148 		    printf("ppp%d: sl_uncompress failed on type %scomp\n",
   1149 			   sc->sc_if.if_unit, pkttype);
   1150 		sc->sc_if.if_ierrors++;
   1151 		return;
   1152 	    }
   1153 
   1154 	    /* adjust the first mbuf by the decompressed amt */
   1155 	    xlen += PPP_HEADER_LEN;
   1156 	    m->m_len += xlen - ilen;
   1157 	    ilen = xlen;
   1158 	    m->m_data -= PPP_HEADER_LEN;
   1159 	    proto = PPP_IP;
   1160 
   1161 #if NBPFILTER > 0
   1162 	    /* put the ppp header back in place */
   1163 	    hdr.ph_protocol = htons(PPP_IP);
   1164 	    *mtod(m, struct ppp_header *) = hdr;
   1165 #endif /* NBPFILTER */
   1166 	}
   1167 #endif /* VJC */
   1168 
   1169 	/* get this packet as an mbuf chain */
   1170 	if ((m = ppp_btom(sc)) == NULL) {
   1171 	    sc->sc_if.if_ierrors++;
   1172 	    return;
   1173 	}
   1174 	m->m_pkthdr.len = ilen;
   1175 	m->m_pkthdr.rcvif = &sc->sc_if;
   1176 
   1177 #if NBPFILTER > 0
   1178 	/* See if bpf wants to look at the packet. */
   1179 	if (sc->sc_bpf)
   1180 	    bpf_mtap(sc->sc_bpf, m);
   1181 #endif
   1182 
   1183 	switch (proto) {
   1184 #ifdef INET
   1185 	case PPP_IP:
   1186 	    /*
   1187 	     * IP packet - take off the ppp header and pass it up to IP.
   1188 	     */
   1189 	    if ((sc->sc_if.if_flags & IFF_UP) == 0) {
   1190 		/* interface is down - drop the packet. */
   1191 		m_freem(m);
   1192 		sc->sc_if.if_ierrors++;
   1193 		return;
   1194 	    }
   1195 	    m->m_pkthdr.len -= PPP_HEADER_LEN;
   1196 	    m->m_data += PPP_HEADER_LEN;
   1197 	    m->m_len -= PPP_HEADER_LEN;
   1198 	    schednetisr(NETISR_IP);
   1199 	    inq = &ipintrq;
   1200 	    break;
   1201 #endif
   1202 
   1203 	default:
   1204 	    /*
   1205 	     * Some other protocol - place on input queue for read().
   1206 	     * Put a placeholder byte in canq for ttselect()/ttnread().
   1207 	     */
   1208 	    putc(0, &tp->t_canq);
   1209 	    ttwakeup(tp);
   1210 	    inq = &sc->sc_inq;
   1211 	    break;
   1212 	}
   1213 
   1214 	/*
   1215 	 * Put the packet on the appropriate input queue.
   1216 	 */
   1217 	s = splimp();
   1218 	if (IF_QFULL(inq)) {
   1219 	    IF_DROP(inq);
   1220 	    if (ppp_debug)
   1221 		printf("ppp%d: queue full\n", sc->sc_if.if_unit);
   1222 	    sc->sc_if.if_ierrors++;
   1223 	    sc->sc_if.if_iqdrops++;
   1224 	    m_freem(m);
   1225 	} else
   1226 	    IF_ENQUEUE(inq, m);
   1227 
   1228 	splx(s);
   1229 	return;
   1230     }
   1231 
   1232     if (sc->sc_flags & SC_FLUSH)
   1233 	return;
   1234     if (c == PPP_ESCAPE) {
   1235 	sc->sc_flags |= SC_ESCAPED;
   1236 	return;
   1237     }
   1238     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
   1239 	return;
   1240 
   1241     if (sc->sc_flags & SC_ESCAPED) {
   1242 	sc->sc_flags &= ~SC_ESCAPED;
   1243 	c ^= PPP_TRANS;
   1244     }
   1245 
   1246     /*
   1247      * Initialize buffer on first octet received.
   1248      * First octet could be address or protocol (when compressing
   1249      * address/control).
   1250      * Second octet is control.
   1251      * Third octet is first or second (when compressing protocol)
   1252      * octet of protocol.
   1253      * Fourth octet is second octet of protocol.
   1254      */
   1255     if (sc->sc_ilen == 0) {
   1256 	/* reset the first input mbuf */
   1257 	m = sc->sc_m;
   1258 	m->m_len = 0;
   1259 	m->m_data = M_DATASTART(sc->sc_m) + HDROFF;
   1260 	sc->sc_mc = m;
   1261 	sc->sc_mp = mtod(m, char *);
   1262 	sc->sc_fcs = PPP_INITFCS;
   1263 	if (c != PPP_ALLSTATIONS) {
   1264 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
   1265 		if (ppp_debug)
   1266 		    printf("ppp%d: missing ALLSTATIONS, got 0x%x; flags %x\n",
   1267 			   sc->sc_if.if_unit, c, sc->sc_flags);
   1268 		goto flush;
   1269 	    }
   1270 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
   1271 	    *sc->sc_mp++ = PPP_UI;
   1272 	    sc->sc_ilen += 2;
   1273 	    m->m_len += 2;
   1274 	}
   1275     }
   1276     if (sc->sc_ilen == 1 && c != PPP_UI) {
   1277 	if (ppp_debug)
   1278 	    printf("ppp%d: missing UI, got 0x%x\n", sc->sc_if.if_unit, c);
   1279 	goto flush;
   1280     }
   1281     if (sc->sc_ilen == 2 && (c & 1) == 1) {
   1282 	/* RFC1331 says we have to accept a compressed protocol */
   1283 	*sc->sc_mp++ = 0;
   1284 	sc->sc_ilen++;
   1285 	sc->sc_mc->m_len++;
   1286     }
   1287     if (sc->sc_ilen == 3 && (c & 1) == 0) {
   1288 	if (ppp_debug)
   1289 	    printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
   1290 		   (sc->sc_mp[-1] << 8) + c);
   1291 	goto flush;
   1292     }
   1293 
   1294     /* packet beyond configured mru? */
   1295     if (++sc->sc_ilen > sc->sc_mru + PPP_HEADER_LEN + PPP_FCS_LEN) {
   1296 	if (ppp_debug)
   1297 	    printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
   1298 	goto flush;
   1299     }
   1300 
   1301     /* is this mbuf full? */
   1302     m = sc->sc_mc;
   1303     if (M_TRAILINGSPACE(m) <= 0) {
   1304 	sc->sc_mc = m = m->m_next;
   1305 	if (m == NULL) {
   1306 	    printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
   1307 	    goto flush;
   1308 	}
   1309 	m->m_len = 0;
   1310 	m->m_data = M_DATASTART(m);
   1311 	sc->sc_mp = mtod(m, char *);
   1312     }
   1313 
   1314     ++m->m_len;
   1315     *sc->sc_mp++ = c;
   1316     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
   1317     return;
   1318 
   1319  flush:
   1320     sc->sc_if.if_ierrors++;
   1321     sc->sc_flags |= SC_FLUSH;
   1322 }
   1323 
   1324 /*
   1325  * Process an ioctl request to interface.
   1326  */
   1327 pppioctl(ifp, cmd, data)
   1328     register struct ifnet *ifp;
   1329     int cmd;
   1330     caddr_t data;
   1331 {
   1332     struct proc *p = curproc;	/* XXX */
   1333     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
   1334     register struct ifaddr *ifa = (struct ifaddr *)data;
   1335     register struct ifreq *ifr = (struct ifreq *)data;
   1336     int s = splimp(), error = 0;
   1337 
   1338 
   1339     switch (cmd) {
   1340     case SIOCSIFFLAGS:
   1341 	if ((ifp->if_flags & IFF_RUNNING) == 0)
   1342 	    ifp->if_flags &= ~IFF_UP;
   1343 	break;
   1344 
   1345     case SIOCSIFADDR:
   1346 	if (ifa->ifa_addr->sa_family != AF_INET)
   1347 	    error = EAFNOSUPPORT;
   1348 	break;
   1349 
   1350     case SIOCSIFDSTADDR:
   1351 	if (ifa->ifa_addr->sa_family != AF_INET)
   1352 	    error = EAFNOSUPPORT;
   1353 	break;
   1354 
   1355     case SIOCSIFMTU:
   1356 	if (error = suser(p->p_ucred, &p->p_acflag))
   1357 	    return (error);
   1358 	sc->sc_if.if_mtu = ifr->ifr_mtu;
   1359 	break;
   1360 
   1361     case SIOCGIFMTU:
   1362 	ifr->ifr_mtu = sc->sc_if.if_mtu;
   1363 	break;
   1364 
   1365     default:
   1366 	error = EINVAL;
   1367     }
   1368     splx(s);
   1369     return (error);
   1370 }
   1371 
   1372 #define MAX_DUMP_BYTES	128
   1373 
   1374 static void
   1375 pppdumpm(m0, pktlen)
   1376     struct mbuf *m0;
   1377     int pktlen;
   1378 {
   1379     char buf[2*MAX_DUMP_BYTES+4];
   1380     char *bp = buf;
   1381     struct mbuf *m;
   1382     static char digits[] = "0123456789abcdef";
   1383 
   1384     for (m = m0; m && pktlen; m = m->m_next) {
   1385 	int l = m->m_len;
   1386 	u_char *rptr = (u_char *)m->m_data;
   1387 
   1388 	if (pktlen > 0) {
   1389 	    l = min(l, pktlen);
   1390 	    pktlen -= l;
   1391 	}
   1392 	while (l--) {
   1393 	    if (bp > buf + sizeof(buf) - 4)
   1394 		goto done;
   1395 	    *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
   1396 	    *bp++ = digits[*rptr++ & 0xf];
   1397 	}
   1398 
   1399 	if (m->m_next) {
   1400 	    if (bp > buf + sizeof(buf) - 3)
   1401 		goto done;
   1402 	    *bp++ = '|';
   1403 	}
   1404     }
   1405 done:
   1406     if (m && pktlen)
   1407 	*bp++ = '>';
   1408     *bp = 0;
   1409     printf("%s\n", buf);
   1410 }
   1411 
   1412 static void
   1413 pppdumpb(b, l)
   1414     u_char *b;
   1415     int l;
   1416 {
   1417     char buf[2*MAX_DUMP_BYTES+4];
   1418     char *bp = buf;
   1419     static char digits[] = "0123456789abcdef";
   1420 
   1421     while (l--) {
   1422 	*bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
   1423 	*bp++ = digits[*b++ & 0xf];
   1424 	if (bp >= buf + sizeof(buf) - 2) {
   1425 	    *bp++ = '>';
   1426 	    break;
   1427 	}
   1428     }
   1429 
   1430     *bp = 0;
   1431     printf("%s\n", buf);
   1432 }
   1433 
   1434 
   1435 #endif	/* NPPP > 0 */
   1436