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