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