Home | History | Annotate | Line # | Download | only in net
ppp_tty.c revision 1.4
      1  1.4  christos /*	$NetBSD: ppp_tty.c,v 1.4 1996/02/13 22:00:30 christos Exp $	*/
      2  1.1    paulus 
      3  1.1    paulus /*
      4  1.1    paulus  * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
      5  1.1    paulus  * 	       tty devices.
      6  1.1    paulus  *
      7  1.1    paulus  * Copyright (c) 1989 Carnegie Mellon University.
      8  1.1    paulus  * All rights reserved.
      9  1.1    paulus  *
     10  1.1    paulus  * Redistribution and use in source and binary forms are permitted
     11  1.1    paulus  * provided that the above copyright notice and this paragraph are
     12  1.1    paulus  * duplicated in all such forms and that any documentation,
     13  1.1    paulus  * advertising materials, and other materials related to such
     14  1.1    paulus  * distribution and use acknowledge that the software was developed
     15  1.1    paulus  * by Carnegie Mellon University.  The name of the
     16  1.1    paulus  * University may not be used to endorse or promote products derived
     17  1.1    paulus  * from this software without specific prior written permission.
     18  1.1    paulus  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     19  1.1    paulus  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     20  1.1    paulus  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     21  1.1    paulus  *
     22  1.1    paulus  * Drew D. Perkins
     23  1.1    paulus  * Carnegie Mellon University
     24  1.1    paulus  * 4910 Forbes Ave.
     25  1.1    paulus  * Pittsburgh, PA 15213
     26  1.1    paulus  * (412) 268-8576
     27  1.1    paulus  * ddp (at) andrew.cmu.edu
     28  1.1    paulus  *
     29  1.1    paulus  * Based on:
     30  1.1    paulus  *	@(#)if_sl.c	7.6.1.2 (Berkeley) 2/15/89
     31  1.1    paulus  *
     32  1.1    paulus  * Copyright (c) 1987 Regents of the University of California.
     33  1.1    paulus  * All rights reserved.
     34  1.1    paulus  *
     35  1.1    paulus  * Redistribution and use in source and binary forms are permitted
     36  1.1    paulus  * provided that the above copyright notice and this paragraph are
     37  1.1    paulus  * duplicated in all such forms and that any documentation,
     38  1.1    paulus  * advertising materials, and other materials related to such
     39  1.1    paulus  * distribution and use acknowledge that the software was developed
     40  1.1    paulus  * by the University of California, Berkeley.  The name of the
     41  1.1    paulus  * University may not be used to endorse or promote products derived
     42  1.1    paulus  * from this software without specific prior written permission.
     43  1.1    paulus  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     44  1.1    paulus  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     45  1.1    paulus  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     46  1.1    paulus  *
     47  1.1    paulus  * Serial Line interface
     48  1.1    paulus  *
     49  1.1    paulus  * Rick Adams
     50  1.1    paulus  * Center for Seismic Studies
     51  1.1    paulus  * 1300 N 17th Street, Suite 1450
     52  1.1    paulus  * Arlington, Virginia 22209
     53  1.1    paulus  * (703)276-7900
     54  1.1    paulus  * rick (at) seismo.ARPA
     55  1.1    paulus  * seismo!rick
     56  1.1    paulus  *
     57  1.1    paulus  * Pounded on heavily by Chris Torek (chris (at) mimsy.umd.edu, umcp-cs!chris).
     58  1.1    paulus  * Converted to 4.3BSD Beta by Chris Torek.
     59  1.1    paulus  * Other changes made at Berkeley, based in part on code by Kirk Smith.
     60  1.1    paulus  *
     61  1.1    paulus  * Converted to 4.3BSD+ 386BSD by Brad Parker (brad (at) cayman.com)
     62  1.1    paulus  * Added VJ tcp header compression; more unified ioctls
     63  1.1    paulus  *
     64  1.1    paulus  * Extensively modified by Paul Mackerras (paulus (at) cs.anu.edu.au).
     65  1.1    paulus  * Cleaned up a lot of the mbuf-related code to fix bugs that
     66  1.1    paulus  * caused system crashes and packet corruption.  Changed pppstart
     67  1.1    paulus  * so that it doesn't just give up with a collision if the whole
     68  1.1    paulus  * packet doesn't fit in the output ring buffer.
     69  1.1    paulus  *
     70  1.1    paulus  * Added priority queueing for interactive IP packets, following
     71  1.1    paulus  * the model of if_sl.c, plus hooks for bpf.
     72  1.1    paulus  * Paul Mackerras (paulus (at) cs.anu.edu.au).
     73  1.1    paulus  */
     74  1.1    paulus 
     75  1.1    paulus /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
     76  1.1    paulus /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
     77  1.1    paulus 
     78  1.1    paulus #include "ppp.h"
     79  1.1    paulus #if NPPP > 0
     80  1.1    paulus 
     81  1.1    paulus #define VJC
     82  1.1    paulus #define PPP_COMPRESS
     83  1.1    paulus 
     84  1.1    paulus #include <sys/param.h>
     85  1.1    paulus #include <sys/proc.h>
     86  1.1    paulus #include <sys/mbuf.h>
     87  1.1    paulus #include <sys/dkstat.h>
     88  1.1    paulus #include <sys/socket.h>
     89  1.1    paulus #include <sys/ioctl.h>
     90  1.1    paulus #include <sys/file.h>
     91  1.1    paulus #include <sys/tty.h>
     92  1.1    paulus #include <sys/kernel.h>
     93  1.1    paulus #include <sys/conf.h>
     94  1.1    paulus #include <sys/vnode.h>
     95  1.4  christos #include <sys/systm.h>
     96  1.1    paulus 
     97  1.1    paulus #include <net/if.h>
     98  1.1    paulus #include <net/if_types.h>
     99  1.1    paulus 
    100  1.1    paulus #ifdef VJC
    101  1.1    paulus #include <netinet/in.h>
    102  1.1    paulus #include <netinet/in_systm.h>
    103  1.1    paulus #include <netinet/ip.h>
    104  1.1    paulus #include <net/slcompress.h>
    105  1.1    paulus #endif
    106  1.1    paulus 
    107  1.1    paulus #include <net/ppp_defs.h>
    108  1.1    paulus #include <net/if_ppp.h>
    109  1.1    paulus #include <net/if_pppvar.h>
    110  1.1    paulus 
    111  1.1    paulus int	pppopen __P((dev_t dev, struct tty *tp));
    112  1.1    paulus int	pppclose __P((struct tty *tp, int flag));
    113  1.1    paulus int	pppread __P((struct tty *tp, struct uio *uio, int flag));
    114  1.1    paulus int	pppwrite __P((struct tty *tp, struct uio *uio, int flag));
    115  1.1    paulus int	ppptioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag,
    116  1.1    paulus 		       struct proc *));
    117  1.1    paulus int	pppinput __P((int c, struct tty *tp));
    118  1.1    paulus int	pppstart __P((struct tty *tp));
    119  1.1    paulus 
    120  1.1    paulus static u_int16_t pppfcs __P((u_int16_t fcs, u_char *cp, int len));
    121  1.1    paulus static void	pppasyncstart __P((struct ppp_softc *));
    122  1.1    paulus static void	pppasyncctlp __P((struct ppp_softc *));
    123  1.1    paulus static void	pppasyncrelinq __P((struct ppp_softc *));
    124  1.1    paulus static void	ppp_timeout __P((void *));
    125  1.1    paulus static void	pppgetm __P((struct ppp_softc *sc));
    126  1.1    paulus static void	pppdumpb __P((u_char *b, int l));
    127  1.1    paulus static void	ppplogchar __P((struct ppp_softc *, int));
    128  1.1    paulus 
    129  1.1    paulus /*
    130  1.1    paulus  * Some useful mbuf macros not in mbuf.h.
    131  1.1    paulus  */
    132  1.1    paulus #define M_IS_CLUSTER(m)	((m)->m_flags & M_EXT)
    133  1.1    paulus 
    134  1.1    paulus #define M_DATASTART(m)	\
    135  1.1    paulus 	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
    136  1.1    paulus 	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
    137  1.1    paulus 
    138  1.1    paulus #define M_DATASIZE(m)	\
    139  1.1    paulus 	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
    140  1.1    paulus 	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
    141  1.1    paulus 
    142  1.1    paulus /*
    143  1.1    paulus  * Does c need to be escaped?
    144  1.1    paulus  */
    145  1.1    paulus #define ESCAPE_P(c)	(sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
    146  1.1    paulus 
    147  1.1    paulus /*
    148  1.1    paulus  * Procedures for using an async tty interface for PPP.
    149  1.1    paulus  */
    150  1.1    paulus 
    151  1.1    paulus /* This is a NetBSD-1.0 or later kernel. */
    152  1.1    paulus #define CCOUNT(q)	((q)->c_cc)
    153  1.1    paulus 
    154  1.1    paulus #define	PPP_HIWAT	400	/* Don't start a new packet if HIWAT on que */
    155  1.1    paulus 
    156  1.1    paulus /*
    157  1.1    paulus  * Line specific open routine for async tty devices.
    158  1.1    paulus  * Attach the given tty to the first available ppp unit.
    159  1.1    paulus  * Called from device open routine or ttioctl.
    160  1.1    paulus  */
    161  1.1    paulus /* ARGSUSED */
    162  1.1    paulus int
    163  1.1    paulus pppopen(dev, tp)
    164  1.1    paulus     dev_t dev;
    165  1.1    paulus     register struct tty *tp;
    166  1.1    paulus {
    167  1.1    paulus     struct proc *p = curproc;		/* XXX */
    168  1.1    paulus     register struct ppp_softc *sc;
    169  1.4  christos     int error, s;
    170  1.1    paulus 
    171  1.4  christos     if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    172  1.1    paulus 	return (error);
    173  1.1    paulus 
    174  1.1    paulus     s = spltty();
    175  1.1    paulus 
    176  1.1    paulus     if (tp->t_line == PPPDISC) {
    177  1.1    paulus 	sc = (struct ppp_softc *) tp->t_sc;
    178  1.1    paulus 	if (sc != NULL && sc->sc_devp == (void *) tp) {
    179  1.1    paulus 	    splx(s);
    180  1.1    paulus 	    return (0);
    181  1.1    paulus 	}
    182  1.1    paulus     }
    183  1.1    paulus 
    184  1.1    paulus     if ((sc = pppalloc(p->p_pid)) == NULL) {
    185  1.1    paulus 	splx(s);
    186  1.1    paulus 	return ENXIO;
    187  1.1    paulus     }
    188  1.1    paulus 
    189  1.1    paulus     if (sc->sc_relinq)
    190  1.1    paulus 	(*sc->sc_relinq)(sc);	/* get previous owner to relinquish the unit */
    191  1.1    paulus 
    192  1.1    paulus     sc->sc_ilen = 0;
    193  1.1    paulus     sc->sc_m = NULL;
    194  1.1    paulus     bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
    195  1.1    paulus     sc->sc_asyncmap[0] = 0xffffffff;
    196  1.1    paulus     sc->sc_asyncmap[3] = 0x60000000;
    197  1.1    paulus     sc->sc_rasyncmap = 0;
    198  1.1    paulus     sc->sc_devp = (void *) tp;
    199  1.1    paulus     sc->sc_start = pppasyncstart;
    200  1.1    paulus     sc->sc_ctlp = pppasyncctlp;
    201  1.1    paulus     sc->sc_relinq = pppasyncrelinq;
    202  1.1    paulus     sc->sc_outm = NULL;
    203  1.1    paulus     pppgetm(sc);
    204  1.1    paulus     sc->sc_if.if_flags |= IFF_RUNNING;
    205  1.3   mycroft     sc->sc_if.if_baudrate = tp->t_ospeed;
    206  1.1    paulus 
    207  1.1    paulus     tp->t_sc = (caddr_t) sc;
    208  1.1    paulus     ttyflush(tp, FREAD | FWRITE);
    209  1.1    paulus 
    210  1.1    paulus     splx(s);
    211  1.1    paulus     return (0);
    212  1.1    paulus }
    213  1.1    paulus 
    214  1.1    paulus /*
    215  1.1    paulus  * Line specific close routine, called from device close routine
    216  1.1    paulus  * and from ttioctl.
    217  1.1    paulus  * Detach the tty from the ppp unit.
    218  1.1    paulus  * Mimics part of ttyclose().
    219  1.1    paulus  */
    220  1.1    paulus int
    221  1.1    paulus pppclose(tp, flag)
    222  1.1    paulus     struct tty *tp;
    223  1.1    paulus     int flag;
    224  1.1    paulus {
    225  1.1    paulus     register struct ppp_softc *sc;
    226  1.1    paulus     int s;
    227  1.1    paulus 
    228  1.1    paulus     s = spltty();
    229  1.1    paulus     ttywflush(tp);
    230  1.1    paulus     tp->t_line = 0;
    231  1.1    paulus     sc = (struct ppp_softc *) tp->t_sc;
    232  1.1    paulus     if (sc != NULL) {
    233  1.1    paulus 	tp->t_sc = NULL;
    234  1.1    paulus 	if (tp == (struct tty *) sc->sc_devp) {
    235  1.1    paulus 	    pppasyncrelinq(sc);
    236  1.1    paulus 	    pppdealloc(sc);
    237  1.1    paulus 	}
    238  1.1    paulus     }
    239  1.1    paulus     splx(s);
    240  1.1    paulus     return 0;
    241  1.1    paulus }
    242  1.1    paulus 
    243  1.1    paulus /*
    244  1.1    paulus  * Relinquish the interface unit to another device.
    245  1.1    paulus  */
    246  1.1    paulus static void
    247  1.1    paulus pppasyncrelinq(sc)
    248  1.1    paulus     struct ppp_softc *sc;
    249  1.1    paulus {
    250  1.1    paulus     int s;
    251  1.1    paulus 
    252  1.1    paulus     s = spltty();
    253  1.1    paulus     if (sc->sc_outm) {
    254  1.1    paulus 	m_freem(sc->sc_outm);
    255  1.1    paulus 	sc->sc_outm = NULL;
    256  1.1    paulus     }
    257  1.1    paulus     if (sc->sc_m) {
    258  1.1    paulus 	m_freem(sc->sc_m);
    259  1.1    paulus 	sc->sc_m = NULL;
    260  1.1    paulus     }
    261  1.1    paulus     if (sc->sc_flags & SC_TIMEOUT) {
    262  1.1    paulus 	untimeout(ppp_timeout, (void *) sc);
    263  1.1    paulus 	sc->sc_flags &= ~SC_TIMEOUT;
    264  1.1    paulus     }
    265  1.1    paulus     splx(s);
    266  1.1    paulus }
    267  1.1    paulus 
    268  1.1    paulus /*
    269  1.1    paulus  * Line specific (tty) read routine.
    270  1.1    paulus  */
    271  1.1    paulus int
    272  1.1    paulus pppread(tp, uio, flag)
    273  1.1    paulus     register struct tty *tp;
    274  1.1    paulus     struct uio *uio;
    275  1.1    paulus     int flag;
    276  1.1    paulus {
    277  1.1    paulus     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    278  1.1    paulus     struct mbuf *m, *m0;
    279  1.1    paulus     register int s;
    280  1.1    paulus     int error = 0;
    281  1.1    paulus 
    282  1.1    paulus     if (sc == NULL)
    283  1.1    paulus 	return 0;
    284  1.1    paulus     /*
    285  1.1    paulus      * Loop waiting for input, checking that nothing disasterous
    286  1.1    paulus      * happens in the meantime.
    287  1.1    paulus      */
    288  1.1    paulus     s = spltty();
    289  1.1    paulus     for (;;) {
    290  1.1    paulus 	if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
    291  1.1    paulus 	    splx(s);
    292  1.1    paulus 	    return 0;
    293  1.1    paulus 	}
    294  1.1    paulus 	if (sc->sc_inq.ifq_head != NULL)
    295  1.1    paulus 	    break;
    296  1.1    paulus 	if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
    297  1.1    paulus 	    && (tp->t_state & TS_ISOPEN)) {
    298  1.1    paulus 	    splx(s);
    299  1.1    paulus 	    return 0;		/* end of file */
    300  1.1    paulus 	}
    301  1.1    paulus 	if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
    302  1.1    paulus 	    splx(s);
    303  1.1    paulus 	    return (EWOULDBLOCK);
    304  1.1    paulus 	}
    305  1.1    paulus 	error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
    306  1.1    paulus 	if (error) {
    307  1.1    paulus 	    splx(s);
    308  1.1    paulus 	    return error;
    309  1.1    paulus 	}
    310  1.1    paulus     }
    311  1.1    paulus 
    312  1.1    paulus     /* Pull place-holder byte out of canonical queue */
    313  1.1    paulus     getc(&tp->t_canq);
    314  1.1    paulus 
    315  1.1    paulus     /* Get the packet from the input queue */
    316  1.1    paulus     IF_DEQUEUE(&sc->sc_inq, m0);
    317  1.1    paulus     splx(s);
    318  1.1    paulus 
    319  1.1    paulus     for (m = m0; m && uio->uio_resid; m = m->m_next)
    320  1.4  christos 	if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
    321  1.1    paulus 	    break;
    322  1.1    paulus     m_freem(m0);
    323  1.1    paulus     return (error);
    324  1.1    paulus }
    325  1.1    paulus 
    326  1.1    paulus /*
    327  1.1    paulus  * Line specific (tty) write routine.
    328  1.1    paulus  */
    329  1.1    paulus int
    330  1.1    paulus pppwrite(tp, uio, flag)
    331  1.1    paulus     register struct tty *tp;
    332  1.1    paulus     struct uio *uio;
    333  1.1    paulus     int flag;
    334  1.1    paulus {
    335  1.1    paulus     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
    336  1.1    paulus     struct mbuf *m, *m0, **mp;
    337  1.1    paulus     struct sockaddr dst;
    338  1.1    paulus     int len, error;
    339  1.1    paulus 
    340  1.1    paulus     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    341  1.1    paulus 	return 0;		/* wrote 0 bytes */
    342  1.1    paulus     if (tp->t_line != PPPDISC)
    343  1.1    paulus 	return (EINVAL);
    344  1.1    paulus     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    345  1.1    paulus 	return EIO;
    346  1.1    paulus     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
    347  1.1    paulus 	uio->uio_resid < PPP_HDRLEN)
    348  1.1    paulus 	return (EMSGSIZE);
    349  1.1    paulus     for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
    350  1.1    paulus 	MGET(m, M_WAIT, MT_DATA);
    351  1.1    paulus 	if ((*mp = m) == NULL) {
    352  1.1    paulus 	    m_freem(m0);
    353  1.1    paulus 	    return (ENOBUFS);
    354  1.1    paulus 	}
    355  1.1    paulus 	m->m_len = 0;
    356  1.1    paulus 	if (uio->uio_resid >= MCLBYTES / 2)
    357  1.1    paulus 	    MCLGET(m, M_DONTWAIT);
    358  1.1    paulus 	len = M_TRAILINGSPACE(m);
    359  1.1    paulus 	if (len > uio->uio_resid)
    360  1.1    paulus 	    len = uio->uio_resid;
    361  1.4  christos 	if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
    362  1.1    paulus 	    m_freem(m0);
    363  1.1    paulus 	    return (error);
    364  1.1    paulus 	}
    365  1.1    paulus 	m->m_len = len;
    366  1.1    paulus     }
    367  1.1    paulus     dst.sa_family = AF_UNSPEC;
    368  1.1    paulus     bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
    369  1.1    paulus     m0->m_data += PPP_HDRLEN;
    370  1.1    paulus     m0->m_len -= PPP_HDRLEN;
    371  1.1    paulus     return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
    372  1.1    paulus }
    373  1.1    paulus 
    374  1.1    paulus /*
    375  1.1    paulus  * Line specific (tty) ioctl routine.
    376  1.1    paulus  * This discipline requires that tty device drivers call
    377  1.1    paulus  * the line specific l_ioctl routine from their ioctl routines.
    378  1.1    paulus  */
    379  1.1    paulus /* ARGSUSED */
    380  1.1    paulus int
    381  1.1    paulus ppptioctl(tp, cmd, data, flag, p)
    382  1.1    paulus     struct tty *tp;
    383  1.1    paulus     u_long cmd;
    384  1.1    paulus     caddr_t data;
    385  1.1    paulus     int flag;
    386  1.1    paulus     struct proc *p;
    387  1.1    paulus {
    388  1.1    paulus     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    389  1.1    paulus     int error, s;
    390  1.1    paulus 
    391  1.1    paulus     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    392  1.1    paulus 	return -1;
    393  1.1    paulus 
    394  1.1    paulus     error = 0;
    395  1.1    paulus     switch (cmd) {
    396  1.1    paulus     case PPPIOCSASYNCMAP:
    397  1.4  christos 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    398  1.1    paulus 	    break;
    399  1.1    paulus 	sc->sc_asyncmap[0] = *(u_int *)data;
    400  1.1    paulus 	break;
    401  1.1    paulus 
    402  1.1    paulus     case PPPIOCGASYNCMAP:
    403  1.1    paulus 	*(u_int *)data = sc->sc_asyncmap[0];
    404  1.1    paulus 	break;
    405  1.1    paulus 
    406  1.1    paulus     case PPPIOCSRASYNCMAP:
    407  1.4  christos 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    408  1.1    paulus 	    break;
    409  1.1    paulus 	sc->sc_rasyncmap = *(u_int *)data;
    410  1.1    paulus 	break;
    411  1.1    paulus 
    412  1.1    paulus     case PPPIOCGRASYNCMAP:
    413  1.1    paulus 	*(u_int *)data = sc->sc_rasyncmap;
    414  1.1    paulus 	break;
    415  1.1    paulus 
    416  1.1    paulus     case PPPIOCSXASYNCMAP:
    417  1.4  christos 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    418  1.1    paulus 	    break;
    419  1.1    paulus 	s = spltty();
    420  1.1    paulus 	bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
    421  1.1    paulus 	sc->sc_asyncmap[1] = 0;		    /* mustn't escape 0x20 - 0x3f */
    422  1.1    paulus 	sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
    423  1.1    paulus 	sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
    424  1.1    paulus 	splx(s);
    425  1.1    paulus 	break;
    426  1.1    paulus 
    427  1.1    paulus     case PPPIOCGXASYNCMAP:
    428  1.1    paulus 	bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
    429  1.1    paulus 	break;
    430  1.1    paulus 
    431  1.1    paulus     default:
    432  1.1    paulus 	error = pppioctl(sc, cmd, data, flag, p);
    433  1.1    paulus 	if (error == 0 && cmd == PPPIOCSMRU)
    434  1.1    paulus 	    pppgetm(sc);
    435  1.1    paulus     }
    436  1.1    paulus 
    437  1.1    paulus     return error;
    438  1.1    paulus }
    439  1.1    paulus 
    440  1.1    paulus /*
    441  1.1    paulus  * FCS lookup table as calculated by genfcstab.
    442  1.1    paulus  */
    443  1.1    paulus static u_int16_t fcstab[256] = {
    444  1.1    paulus 	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
    445  1.1    paulus 	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
    446  1.1    paulus 	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
    447  1.1    paulus 	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
    448  1.1    paulus 	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
    449  1.1    paulus 	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
    450  1.1    paulus 	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
    451  1.1    paulus 	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
    452  1.1    paulus 	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
    453  1.1    paulus 	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
    454  1.1    paulus 	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
    455  1.1    paulus 	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
    456  1.1    paulus 	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
    457  1.1    paulus 	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
    458  1.1    paulus 	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
    459  1.1    paulus 	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
    460  1.1    paulus 	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
    461  1.1    paulus 	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
    462  1.1    paulus 	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
    463  1.1    paulus 	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
    464  1.1    paulus 	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
    465  1.1    paulus 	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
    466  1.1    paulus 	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
    467  1.1    paulus 	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
    468  1.1    paulus 	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
    469  1.1    paulus 	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
    470  1.1    paulus 	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
    471  1.1    paulus 	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
    472  1.1    paulus 	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
    473  1.1    paulus 	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
    474  1.1    paulus 	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
    475  1.1    paulus 	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
    476  1.1    paulus };
    477  1.1    paulus 
    478  1.1    paulus /*
    479  1.1    paulus  * Calculate a new FCS given the current FCS and the new data.
    480  1.1    paulus  */
    481  1.1    paulus static u_int16_t
    482  1.1    paulus pppfcs(fcs, cp, len)
    483  1.1    paulus     register u_int16_t fcs;
    484  1.1    paulus     register u_char *cp;
    485  1.1    paulus     register int len;
    486  1.1    paulus {
    487  1.1    paulus     while (len--)
    488  1.1    paulus 	fcs = PPP_FCS(fcs, *cp++);
    489  1.1    paulus     return (fcs);
    490  1.1    paulus }
    491  1.1    paulus 
    492  1.1    paulus /*
    493  1.1    paulus  * This gets called from pppoutput when a new packet is
    494  1.1    paulus  * put on a queue, at splsoftnet.
    495  1.1    paulus  */
    496  1.1    paulus static void
    497  1.1    paulus pppasyncstart(sc)
    498  1.1    paulus     register struct ppp_softc *sc;
    499  1.1    paulus {
    500  1.1    paulus     register struct tty *tp = (struct tty *) sc->sc_devp;
    501  1.1    paulus     int s;
    502  1.1    paulus 
    503  1.1    paulus     s = spltty();
    504  1.1    paulus     pppstart(tp);
    505  1.1    paulus     splx(s);
    506  1.1    paulus }
    507  1.1    paulus 
    508  1.1    paulus /*
    509  1.1    paulus  * This gets called when a received packet is placed on
    510  1.1    paulus  * the inq, at splsoftnet.
    511  1.1    paulus  */
    512  1.1    paulus static void
    513  1.1    paulus pppasyncctlp(sc)
    514  1.1    paulus     struct ppp_softc *sc;
    515  1.1    paulus {
    516  1.1    paulus     struct tty *tp;
    517  1.1    paulus     int s;
    518  1.1    paulus 
    519  1.1    paulus     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
    520  1.1    paulus     s = spltty();
    521  1.1    paulus     tp = (struct tty *) sc->sc_devp;
    522  1.1    paulus     putc(0, &tp->t_canq);
    523  1.1    paulus     ttwakeup(tp);
    524  1.1    paulus     splx(s);
    525  1.1    paulus }
    526  1.1    paulus 
    527  1.1    paulus /*
    528  1.1    paulus  * Start output on async tty interface.  Get another datagram
    529  1.1    paulus  * to send from the interface queue and start sending it.
    530  1.1    paulus  * Called at spltty or higher.
    531  1.1    paulus  */
    532  1.1    paulus int
    533  1.1    paulus pppstart(tp)
    534  1.1    paulus     register struct tty *tp;
    535  1.1    paulus {
    536  1.1    paulus     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
    537  1.1    paulus     register struct mbuf *m;
    538  1.1    paulus     register int len;
    539  1.1    paulus     register u_char *start, *stop, *cp;
    540  1.4  christos     int n, ndone, done, idle;
    541  1.1    paulus     struct mbuf *m2;
    542  1.1    paulus 
    543  1.4  christos     if (((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
    544  1.1    paulus 	|| sc == NULL || tp != (struct tty *) sc->sc_devp) {
    545  1.1    paulus 	if (tp->t_oproc != NULL)
    546  1.1    paulus 	    (*tp->t_oproc)(tp);
    547  1.1    paulus 	return 0;
    548  1.1    paulus     }
    549  1.1    paulus 
    550  1.1    paulus     idle = 0;
    551  1.1    paulus     while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
    552  1.1    paulus 	/*
    553  1.1    paulus 	 * See if we have an existing packet partly sent.
    554  1.1    paulus 	 * If not, get a new packet and start sending it.
    555  1.1    paulus 	 */
    556  1.1    paulus 	m = sc->sc_outm;
    557  1.1    paulus 	if (m == NULL) {
    558  1.1    paulus 	    /*
    559  1.1    paulus 	     * Get another packet to be sent.
    560  1.1    paulus 	     */
    561  1.1    paulus 	    m = ppp_dequeue(sc);
    562  1.1    paulus 	    if (m == NULL) {
    563  1.1    paulus 		idle = 1;
    564  1.1    paulus 		break;
    565  1.1    paulus 	    }
    566  1.1    paulus 
    567  1.1    paulus 	    /*
    568  1.1    paulus 	     * The extra PPP_FLAG will start up a new packet, and thus
    569  1.1    paulus 	     * will flush any accumulated garbage.  We do this whenever
    570  1.1    paulus 	     * the line may have been idle for some time.
    571  1.1    paulus 	     */
    572  1.1    paulus 	    if (CCOUNT(&tp->t_outq) == 0) {
    573  1.1    paulus 		++sc->sc_bytessent;
    574  1.1    paulus 		(void) putc(PPP_FLAG, &tp->t_outq);
    575  1.1    paulus 	    }
    576  1.1    paulus 
    577  1.1    paulus 	    /* Calculate the FCS for the first mbuf's worth. */
    578  1.1    paulus 	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
    579  1.3   mycroft 	    sc->sc_if.if_lastchange = time;
    580  1.1    paulus 	}
    581  1.1    paulus 
    582  1.1    paulus 	for (;;) {
    583  1.1    paulus 	    start = mtod(m, u_char *);
    584  1.1    paulus 	    len = m->m_len;
    585  1.1    paulus 	    stop = start + len;
    586  1.1    paulus 	    while (len > 0) {
    587  1.1    paulus 		/*
    588  1.1    paulus 		 * Find out how many bytes in the string we can
    589  1.1    paulus 		 * handle without doing something special.
    590  1.1    paulus 		 */
    591  1.1    paulus 		for (cp = start; cp < stop; cp++)
    592  1.1    paulus 		    if (ESCAPE_P(*cp))
    593  1.1    paulus 			break;
    594  1.1    paulus 		n = cp - start;
    595  1.1    paulus 		if (n) {
    596  1.1    paulus 		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
    597  1.1    paulus 		    ndone = n - b_to_q(start, n, &tp->t_outq);
    598  1.1    paulus 		    len -= ndone;
    599  1.1    paulus 		    start += ndone;
    600  1.1    paulus 		    sc->sc_bytessent += ndone;
    601  1.1    paulus 
    602  1.1    paulus 		    if (ndone < n)
    603  1.1    paulus 			break;	/* packet doesn't fit */
    604  1.1    paulus 		}
    605  1.1    paulus 		/*
    606  1.1    paulus 		 * If there are characters left in the mbuf,
    607  1.1    paulus 		 * the first one must be special..
    608  1.1    paulus 		 * Put it out in a different form.
    609  1.1    paulus 		 */
    610  1.1    paulus 		if (len) {
    611  1.1    paulus 		    if (putc(PPP_ESCAPE, &tp->t_outq))
    612  1.1    paulus 			break;
    613  1.1    paulus 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
    614  1.1    paulus 			(void) unputc(&tp->t_outq);
    615  1.1    paulus 			break;
    616  1.1    paulus 		    }
    617  1.1    paulus 		    sc->sc_bytessent += 2;
    618  1.1    paulus 		    start++;
    619  1.1    paulus 		    len--;
    620  1.1    paulus 		}
    621  1.1    paulus 	    }
    622  1.1    paulus 
    623  1.1    paulus 	    /*
    624  1.1    paulus 	     * If we didn't empty this mbuf, remember where we're up to.
    625  1.1    paulus 	     * If we emptied the last mbuf, try to add the FCS and closing
    626  1.1    paulus 	     * flag, and if we can't, leave sc_outm pointing to m, but with
    627  1.1    paulus 	     * m->m_len == 0, to remind us to output the FCS and flag later.
    628  1.1    paulus 	     */
    629  1.1    paulus 	    done = len == 0;
    630  1.1    paulus 	    if (done && m->m_next == NULL) {
    631  1.1    paulus 		u_char *p, *q;
    632  1.1    paulus 		int c;
    633  1.1    paulus 		u_char endseq[8];
    634  1.1    paulus 
    635  1.1    paulus 		/*
    636  1.1    paulus 		 * We may have to escape the bytes in the FCS.
    637  1.1    paulus 		 */
    638  1.1    paulus 		p = endseq;
    639  1.1    paulus 		c = ~sc->sc_outfcs & 0xFF;
    640  1.1    paulus 		if (ESCAPE_P(c)) {
    641  1.1    paulus 		    *p++ = PPP_ESCAPE;
    642  1.1    paulus 		    *p++ = c ^ PPP_TRANS;
    643  1.1    paulus 		} else
    644  1.1    paulus 		    *p++ = c;
    645  1.1    paulus 		c = (~sc->sc_outfcs >> 8) & 0xFF;
    646  1.1    paulus 		if (ESCAPE_P(c)) {
    647  1.1    paulus 		    *p++ = PPP_ESCAPE;
    648  1.1    paulus 		    *p++ = c ^ PPP_TRANS;
    649  1.1    paulus 		} else
    650  1.1    paulus 		    *p++ = c;
    651  1.1    paulus 		*p++ = PPP_FLAG;
    652  1.1    paulus 
    653  1.1    paulus 		/*
    654  1.1    paulus 		 * Try to output the FCS and flag.  If the bytes
    655  1.1    paulus 		 * don't all fit, back out.
    656  1.1    paulus 		 */
    657  1.1    paulus 		for (q = endseq; q < p; ++q)
    658  1.1    paulus 		    if (putc(*q, &tp->t_outq)) {
    659  1.1    paulus 			done = 0;
    660  1.1    paulus 			for (; q > endseq; --q)
    661  1.1    paulus 			    unputc(&tp->t_outq);
    662  1.1    paulus 			break;
    663  1.1    paulus 		    }
    664  1.1    paulus 		sc->sc_bytessent += q - endseq;
    665  1.1    paulus 	    }
    666  1.1    paulus 
    667  1.1    paulus 	    if (!done) {
    668  1.1    paulus 		/* remember where we got to */
    669  1.1    paulus 		m->m_data = start;
    670  1.1    paulus 		m->m_len = len;
    671  1.1    paulus 		break;
    672  1.1    paulus 	    }
    673  1.1    paulus 
    674  1.1    paulus 	    /* Finished with this mbuf; free it and move on. */
    675  1.1    paulus 	    MFREE(m, m2);
    676  1.1    paulus 	    m = m2;
    677  1.1    paulus 	    if (m == NULL) {
    678  1.1    paulus 		/* Finished a packet */
    679  1.1    paulus 		sc->sc_if.if_opackets++;
    680  1.1    paulus 		sc->sc_if.if_obytes = sc->sc_bytessent;
    681  1.1    paulus 		break;
    682  1.1    paulus 	    }
    683  1.1    paulus 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
    684  1.1    paulus 	}
    685  1.1    paulus 
    686  1.1    paulus 	/*
    687  1.1    paulus 	 * Here we have either finished a packet (m == NULL)
    688  1.1    paulus 	 * or filled up the output queue (m != NULL).
    689  1.1    paulus 	 */
    690  1.1    paulus 	sc->sc_outm = m;
    691  1.1    paulus 	if (m)
    692  1.1    paulus 	    break;
    693  1.1    paulus     }
    694  1.1    paulus 
    695  1.1    paulus     /*
    696  1.1    paulus      * If there is stuff in the output queue, send it now.
    697  1.1    paulus      * We are being called in lieu of ttstart and must do what it would.
    698  1.1    paulus      */
    699  1.1    paulus     if (tp->t_oproc != NULL)
    700  1.1    paulus 	(*tp->t_oproc)(tp);
    701  1.1    paulus 
    702  1.1    paulus     /*
    703  1.1    paulus      * This timeout is needed for operation on a pseudo-tty,
    704  1.1    paulus      * because the pty code doesn't call pppstart after it has
    705  1.1    paulus      * drained the t_outq.
    706  1.1    paulus      */
    707  1.1    paulus     if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
    708  1.1    paulus 	timeout(ppp_timeout, (void *) sc, 1);
    709  1.1    paulus 	sc->sc_flags |= SC_TIMEOUT;
    710  1.1    paulus     }
    711  1.1    paulus 
    712  1.1    paulus     return 0;
    713  1.1    paulus }
    714  1.1    paulus 
    715  1.1    paulus /*
    716  1.1    paulus  * Timeout routine - try to start some more output.
    717  1.1    paulus  */
    718  1.1    paulus static void
    719  1.1    paulus ppp_timeout(x)
    720  1.1    paulus     void *x;
    721  1.1    paulus {
    722  1.1    paulus     struct ppp_softc *sc = (struct ppp_softc *) x;
    723  1.1    paulus     struct tty *tp = (struct tty *) sc->sc_devp;
    724  1.1    paulus     int s;
    725  1.1    paulus 
    726  1.1    paulus     s = spltty();
    727  1.1    paulus     sc->sc_flags &= ~SC_TIMEOUT;
    728  1.1    paulus     pppstart(tp);
    729  1.1    paulus     splx(s);
    730  1.1    paulus }
    731  1.1    paulus 
    732  1.1    paulus /*
    733  1.1    paulus  * Allocate enough mbuf to handle current MRU.
    734  1.1    paulus  */
    735  1.1    paulus static void
    736  1.1    paulus pppgetm(sc)
    737  1.1    paulus     register struct ppp_softc *sc;
    738  1.1    paulus {
    739  1.1    paulus     struct mbuf *m, **mp;
    740  1.1    paulus     int len;
    741  1.1    paulus     int s;
    742  1.1    paulus 
    743  1.1    paulus     s = spltty();
    744  1.1    paulus     mp = &sc->sc_m;
    745  1.1    paulus     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
    746  1.1    paulus 	if ((m = *mp) == NULL) {
    747  1.1    paulus 	    MGETHDR(m, M_DONTWAIT, MT_DATA);
    748  1.1    paulus 	    if (m == NULL)
    749  1.1    paulus 		break;
    750  1.1    paulus 	    *mp = m;
    751  1.1    paulus 	    MCLGET(m, M_DONTWAIT);
    752  1.1    paulus 	}
    753  1.1    paulus 	len -= M_DATASIZE(m);
    754  1.1    paulus 	mp = &m->m_next;
    755  1.1    paulus     }
    756  1.1    paulus     splx(s);
    757  1.1    paulus }
    758  1.1    paulus 
    759  1.1    paulus /*
    760  1.1    paulus  * tty interface receiver interrupt.
    761  1.1    paulus  */
    762  1.1    paulus static unsigned paritytab[8] = {
    763  1.1    paulus     0x96696996, 0x69969669, 0x69969669, 0x96696996,
    764  1.1    paulus     0x69969669, 0x96696996, 0x96696996, 0x69969669
    765  1.1    paulus };
    766  1.1    paulus 
    767  1.1    paulus int
    768  1.1    paulus pppinput(c, tp)
    769  1.1    paulus     int c;
    770  1.1    paulus     register struct tty *tp;
    771  1.1    paulus {
    772  1.1    paulus     register struct ppp_softc *sc;
    773  1.1    paulus     struct mbuf *m;
    774  1.1    paulus     int ilen, s;
    775  1.1    paulus 
    776  1.1    paulus     sc = (struct ppp_softc *) tp->t_sc;
    777  1.1    paulus     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
    778  1.1    paulus 	return 0;
    779  1.1    paulus 
    780  1.1    paulus     s = spltty();		/* should be unnecessary */
    781  1.1    paulus     ++tk_nin;
    782  1.1    paulus     ++sc->sc_bytesrcvd;
    783  1.1    paulus 
    784  1.1    paulus     if (c & TTY_FE) {
    785  1.1    paulus 	/* framing error or overrun on this char - abort packet */
    786  1.1    paulus 	if (sc->sc_flags & SC_DEBUG)
    787  1.1    paulus 	    printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
    788  1.1    paulus 	goto flush;
    789  1.1    paulus     }
    790  1.1    paulus 
    791  1.1    paulus     c &= 0xff;
    792  1.1    paulus 
    793  1.1    paulus     if (c & 0x80)
    794  1.1    paulus 	sc->sc_flags |= SC_RCV_B7_1;
    795  1.1    paulus     else
    796  1.1    paulus 	sc->sc_flags |= SC_RCV_B7_0;
    797  1.1    paulus     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
    798  1.1    paulus 	sc->sc_flags |= SC_RCV_ODDP;
    799  1.1    paulus     else
    800  1.1    paulus 	sc->sc_flags |= SC_RCV_EVNP;
    801  1.1    paulus 
    802  1.1    paulus     if (sc->sc_flags & SC_LOG_RAWIN)
    803  1.1    paulus 	ppplogchar(sc, c);
    804  1.1    paulus 
    805  1.1    paulus     if (c == PPP_FLAG) {
    806  1.1    paulus 	ilen = sc->sc_ilen;
    807  1.1    paulus 	sc->sc_ilen = 0;
    808  1.1    paulus 	sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
    809  1.1    paulus 
    810  1.1    paulus 	if (sc->sc_rawin_count > 0)
    811  1.1    paulus 	    ppplogchar(sc, -1);
    812  1.1    paulus 
    813  1.1    paulus 	/*
    814  1.1    paulus 	 * If SC_ESCAPED is set, then we've seen the packet
    815  1.1    paulus 	 * abort sequence "}~".
    816  1.1    paulus 	 */
    817  1.1    paulus 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
    818  1.4  christos 	    || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
    819  1.1    paulus 	    sc->sc_flags |= SC_PKTLOST;	/* note the dropped packet */
    820  1.1    paulus 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
    821  1.1    paulus 		if (sc->sc_flags & SC_DEBUG)
    822  1.1    paulus 		    printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
    823  1.1    paulus 			   sc->sc_fcs);
    824  1.1    paulus 		sc->sc_if.if_ierrors++;
    825  1.1    paulus 	    } else
    826  1.1    paulus 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
    827  1.1    paulus 	    splx(s);
    828  1.1    paulus 	    return 0;
    829  1.1    paulus 	}
    830  1.1    paulus 
    831  1.1    paulus 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
    832  1.1    paulus 	    if (ilen) {
    833  1.1    paulus 		if (sc->sc_flags & SC_DEBUG)
    834  1.1    paulus 		    printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
    835  1.1    paulus 		sc->sc_if.if_ierrors++;
    836  1.1    paulus 		sc->sc_flags |= SC_PKTLOST;
    837  1.1    paulus 	    }
    838  1.1    paulus 	    splx(s);
    839  1.1    paulus 	    return 0;
    840  1.1    paulus 	}
    841  1.1    paulus 
    842  1.1    paulus 	/*
    843  1.1    paulus 	 * Remove FCS trailer.  Somewhat painful...
    844  1.1    paulus 	 */
    845  1.1    paulus 	ilen -= 2;
    846  1.1    paulus 	if (--sc->sc_mc->m_len == 0) {
    847  1.1    paulus 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
    848  1.1    paulus 		;
    849  1.1    paulus 	    sc->sc_mc = m;
    850  1.1    paulus 	}
    851  1.1    paulus 	sc->sc_mc->m_len--;
    852  1.1    paulus 
    853  1.1    paulus 	/* excise this mbuf chain */
    854  1.1    paulus 	m = sc->sc_m;
    855  1.1    paulus 	sc->sc_m = sc->sc_mc->m_next;
    856  1.1    paulus 	sc->sc_mc->m_next = NULL;
    857  1.1    paulus 
    858  1.1    paulus 	ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
    859  1.1    paulus 	sc->sc_flags &= ~SC_PKTLOST;
    860  1.1    paulus 
    861  1.1    paulus 	pppgetm(sc);
    862  1.1    paulus 	splx(s);
    863  1.1    paulus 	return 0;
    864  1.1    paulus     }
    865  1.1    paulus 
    866  1.1    paulus     if (sc->sc_flags & SC_FLUSH) {
    867  1.1    paulus 	if (sc->sc_flags & SC_LOG_FLUSH)
    868  1.1    paulus 	    ppplogchar(sc, c);
    869  1.1    paulus 	splx(s);
    870  1.1    paulus 	return 0;
    871  1.1    paulus     }
    872  1.1    paulus 
    873  1.1    paulus     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
    874  1.1    paulus 	splx(s);
    875  1.1    paulus 	return 0;
    876  1.1    paulus     }
    877  1.1    paulus 
    878  1.1    paulus     if (sc->sc_flags & SC_ESCAPED) {
    879  1.1    paulus 	sc->sc_flags &= ~SC_ESCAPED;
    880  1.1    paulus 	c ^= PPP_TRANS;
    881  1.1    paulus     } else if (c == PPP_ESCAPE) {
    882  1.1    paulus 	sc->sc_flags |= SC_ESCAPED;
    883  1.1    paulus 	splx(s);
    884  1.1    paulus 	return 0;
    885  1.1    paulus     }
    886  1.1    paulus 
    887  1.1    paulus     /*
    888  1.1    paulus      * Initialize buffer on first octet received.
    889  1.1    paulus      * First octet could be address or protocol (when compressing
    890  1.1    paulus      * address/control).
    891  1.1    paulus      * Second octet is control.
    892  1.1    paulus      * Third octet is first or second (when compressing protocol)
    893  1.1    paulus      * octet of protocol.
    894  1.1    paulus      * Fourth octet is second octet of protocol.
    895  1.1    paulus      */
    896  1.1    paulus     if (sc->sc_ilen == 0) {
    897  1.1    paulus 	/* reset the first input mbuf */
    898  1.1    paulus 	if (sc->sc_m == NULL) {
    899  1.1    paulus 	    pppgetm(sc);
    900  1.1    paulus 	    if (sc->sc_m == NULL) {
    901  1.1    paulus 		if (sc->sc_flags & SC_DEBUG)
    902  1.1    paulus 		    printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
    903  1.1    paulus 		goto flush;
    904  1.1    paulus 	    }
    905  1.1    paulus 	}
    906  1.1    paulus 	m = sc->sc_m;
    907  1.1    paulus 	m->m_len = 0;
    908  1.1    paulus 	m->m_data = M_DATASTART(sc->sc_m);
    909  1.1    paulus 	sc->sc_mc = m;
    910  1.1    paulus 	sc->sc_mp = mtod(m, char *);
    911  1.1    paulus 	sc->sc_fcs = PPP_INITFCS;
    912  1.1    paulus 	if (c != PPP_ALLSTATIONS) {
    913  1.1    paulus 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
    914  1.1    paulus 		if (sc->sc_flags & SC_DEBUG)
    915  1.1    paulus 		    printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
    916  1.1    paulus 			   sc->sc_if.if_unit, c);
    917  1.1    paulus 		goto flush;
    918  1.1    paulus 	    }
    919  1.1    paulus 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
    920  1.1    paulus 	    *sc->sc_mp++ = PPP_UI;
    921  1.1    paulus 	    sc->sc_ilen += 2;
    922  1.1    paulus 	    m->m_len += 2;
    923  1.1    paulus 	}
    924  1.1    paulus     }
    925  1.1    paulus     if (sc->sc_ilen == 1 && c != PPP_UI) {
    926  1.1    paulus 	if (sc->sc_flags & SC_DEBUG)
    927  1.1    paulus 	    printf("ppp%d: missing UI (0x3), got 0x%x\n",
    928  1.1    paulus 		   sc->sc_if.if_unit, c);
    929  1.1    paulus 	goto flush;
    930  1.1    paulus     }
    931  1.1    paulus     if (sc->sc_ilen == 2 && (c & 1) == 1) {
    932  1.1    paulus 	/* a compressed protocol */
    933  1.1    paulus 	*sc->sc_mp++ = 0;
    934  1.1    paulus 	sc->sc_ilen++;
    935  1.1    paulus 	sc->sc_mc->m_len++;
    936  1.1    paulus     }
    937  1.1    paulus     if (sc->sc_ilen == 3 && (c & 1) == 0) {
    938  1.1    paulus 	if (sc->sc_flags & SC_DEBUG)
    939  1.1    paulus 	    printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
    940  1.1    paulus 		   (sc->sc_mp[-1] << 8) + c);
    941  1.1    paulus 	goto flush;
    942  1.1    paulus     }
    943  1.1    paulus 
    944  1.1    paulus     /* packet beyond configured mru? */
    945  1.1    paulus     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
    946  1.1    paulus 	if (sc->sc_flags & SC_DEBUG)
    947  1.1    paulus 	    printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
    948  1.1    paulus 	goto flush;
    949  1.1    paulus     }
    950  1.1    paulus 
    951  1.1    paulus     /* is this mbuf full? */
    952  1.1    paulus     m = sc->sc_mc;
    953  1.1    paulus     if (M_TRAILINGSPACE(m) <= 0) {
    954  1.1    paulus 	if (m->m_next == NULL) {
    955  1.1    paulus 	    pppgetm(sc);
    956  1.1    paulus 	    if (m->m_next == NULL) {
    957  1.1    paulus 		if (sc->sc_flags & SC_DEBUG)
    958  1.1    paulus 		    printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
    959  1.1    paulus 		goto flush;
    960  1.1    paulus 	    }
    961  1.1    paulus 	}
    962  1.1    paulus 	sc->sc_mc = m = m->m_next;
    963  1.1    paulus 	m->m_len = 0;
    964  1.1    paulus 	m->m_data = M_DATASTART(m);
    965  1.1    paulus 	sc->sc_mp = mtod(m, char *);
    966  1.1    paulus     }
    967  1.1    paulus 
    968  1.1    paulus     ++m->m_len;
    969  1.1    paulus     *sc->sc_mp++ = c;
    970  1.1    paulus     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
    971  1.1    paulus     splx(s);
    972  1.1    paulus     return 0;
    973  1.1    paulus 
    974  1.1    paulus  flush:
    975  1.1    paulus     if (!(sc->sc_flags & SC_FLUSH)) {
    976  1.1    paulus 	sc->sc_if.if_ierrors++;
    977  1.1    paulus 	sc->sc_flags |= SC_FLUSH;
    978  1.1    paulus 	if (sc->sc_flags & SC_LOG_FLUSH)
    979  1.1    paulus 	    ppplogchar(sc, c);
    980  1.1    paulus     }
    981  1.1    paulus     splx(s);
    982  1.1    paulus     return 0;
    983  1.1    paulus }
    984  1.1    paulus 
    985  1.1    paulus #define MAX_DUMP_BYTES	128
    986  1.1    paulus 
    987  1.1    paulus static void
    988  1.1    paulus ppplogchar(sc, c)
    989  1.1    paulus     struct ppp_softc *sc;
    990  1.1    paulus     int c;
    991  1.1    paulus {
    992  1.1    paulus     if (c >= 0)
    993  1.1    paulus 	sc->sc_rawin[sc->sc_rawin_count++] = c;
    994  1.1    paulus     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
    995  1.4  christos 	|| (c < 0 && sc->sc_rawin_count > 0)) {
    996  1.1    paulus 	printf("ppp%d input: ", sc->sc_if.if_unit);
    997  1.1    paulus 	pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
    998  1.1    paulus 	sc->sc_rawin_count = 0;
    999  1.1    paulus     }
   1000  1.1    paulus }
   1001  1.1    paulus 
   1002  1.1    paulus static void
   1003  1.1    paulus pppdumpb(b, l)
   1004  1.1    paulus     u_char *b;
   1005  1.1    paulus     int l;
   1006  1.1    paulus {
   1007  1.1    paulus     char buf[3*MAX_DUMP_BYTES+4];
   1008  1.1    paulus     char *bp = buf;
   1009  1.1    paulus     static char digits[] = "0123456789abcdef";
   1010  1.1    paulus 
   1011  1.1    paulus     while (l--) {
   1012  1.1    paulus 	if (bp >= buf + sizeof(buf) - 3) {
   1013  1.1    paulus 	    *bp++ = '>';
   1014  1.1    paulus 	    break;
   1015  1.1    paulus 	}
   1016  1.1    paulus 	*bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
   1017  1.1    paulus 	*bp++ = digits[*b++ & 0xf];
   1018  1.1    paulus 	*bp++ = ' ';
   1019  1.1    paulus     }
   1020  1.1    paulus 
   1021  1.1    paulus     *bp = 0;
   1022  1.1    paulus     printf("%s\n", buf);
   1023  1.1    paulus }
   1024  1.1    paulus 
   1025  1.1    paulus #endif	/* NPPP > 0 */
   1026