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