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