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