The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/ppp_tty.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ppp_tty.c,v 1.35 2005/02/26 22:45:09 perry Exp $       */
    2 /*      Id: ppp_tty.c,v 1.3 1996/07/01 01:04:11 paulus Exp      */
    3 
    4 /*
    5  * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
    6  *             tty devices.
    7  *
    8  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  *
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  *
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in
   19  *    the documentation and/or other materials provided with the
   20  *    distribution.
   21  *
   22  * 3. The name "Carnegie Mellon University" must not be used to
   23  *    endorse or promote products derived from this software without
   24  *    prior written permission. For permission or any legal
   25  *    details, please contact
   26  *      Office of Technology Transfer
   27  *      Carnegie Mellon University
   28  *      5000 Forbes Avenue
   29  *      Pittsburgh, PA  15213-3890
   30  *      (412) 268-4387, fax: (412) 268-7395
   31  *      tech-transfer@andrew.cmu.edu
   32  *
   33  * 4. Redistributions of any form whatsoever must retain the following
   34  *    acknowledgment:
   35  *    "This product includes software developed by Computing Services
   36  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
   37  *
   38  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
   39  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
   40  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
   41  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   42  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
   43  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
   44  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   45  *
   46  * Based on:
   47  *      @(#)if_sl.c     7.6.1.2 (Berkeley) 2/15/89
   48  *
   49  * Copyright (c) 1987 Regents of the University of California.
   50  * All rights reserved.
   51  *
   52  * Redistribution and use in source and binary forms are permitted
   53  * provided that the above copyright notice and this paragraph are
   54  * duplicated in all such forms and that any documentation,
   55  * advertising materials, and other materials related to such
   56  * distribution and use acknowledge that the software was developed
   57  * by the University of California, Berkeley.  The name of the
   58  * University may not be used to endorse or promote products derived
   59  * from this software without specific prior written permission.
   60  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
   61  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
   62  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   63  *
   64  * Serial Line interface
   65  *
   66  * Rick Adams
   67  * Center for Seismic Studies
   68  * 1300 N 17th Street, Suite 1450
   69  * Arlington, Virginia 22209
   70  * (703)276-7900
   71  * rick@seismo.ARPA
   72  * seismo!rick
   73  *
   74  * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
   75  * Converted to 4.3BSD Beta by Chris Torek.
   76  * Other changes made at Berkeley, based in part on code by Kirk Smith.
   77  *
   78  * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
   79  * Added VJ tcp header compression; more unified ioctls
   80  *
   81  * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
   82  * Cleaned up a lot of the mbuf-related code to fix bugs that
   83  * caused system crashes and packet corruption.  Changed pppstart
   84  * so that it doesn't just give up with a "collision" if the whole
   85  * packet doesn't fit in the output ring buffer.
   86  *
   87  * Added priority queueing for interactive IP packets, following
   88  * the model of if_sl.c, plus hooks for bpf.
   89  * Paul Mackerras (paulus@cs.anu.edu.au).
   90  */
   91 
   92 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
   93 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
   94 
   95 #include <sys/cdefs.h>
   96 __KERNEL_RCSID(0, "$NetBSD: ppp_tty.c,v 1.35 2005/02/26 22:45:09 perry Exp $");
   97 
   98 #include "ppp.h"
   99 
  100 #include "opt_ppp.h"
  101 #define VJC
  102 #define PPP_COMPRESS
  103 
  104 #include <sys/param.h>
  105 #include <sys/proc.h>
  106 #include <sys/mbuf.h>
  107 #include <sys/dkstat.h>
  108 #include <sys/socket.h>
  109 #include <sys/ioctl.h>
  110 #include <sys/file.h>
  111 #include <sys/tty.h>
  112 #include <sys/kernel.h>
  113 #include <sys/conf.h>
  114 #include <sys/vnode.h>
  115 #include <sys/systm.h>
  116 
  117 #include <net/if.h>
  118 #include <net/if_types.h>
  119 
  120 #ifdef VJC
  121 #include <netinet/in.h>
  122 #include <netinet/in_systm.h>
  123 #include <netinet/ip.h>
  124 #include <net/slcompress.h>
  125 #endif
  126 
  127 #include "bpfilter.h"
  128 #if NBPFILTER > 0 || defined(PPP_FILTER)
  129 #include <net/bpf.h>
  130 #endif
  131 #include <net/ppp_defs.h>
  132 #include <net/if_ppp.h>
  133 #include <net/if_pppvar.h>
  134 
  135 int     pppopen __P((dev_t dev, struct tty *tp));
  136 int     pppclose __P((struct tty *tp, int flag));
  137 int     pppread __P((struct tty *tp, struct uio *uio, int flag));
  138 int     pppwrite __P((struct tty *tp, struct uio *uio, int flag));
  139 int     ppptioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag,
  140                        struct proc *));
  141 int     pppinput __P((int c, struct tty *tp));
  142 int     pppstart __P((struct tty *tp));
  143 
  144 static void     ppprcvframe __P((struct ppp_softc *sc, struct mbuf *m));
  145 static u_int16_t pppfcs __P((u_int16_t fcs, u_char *cp, int len));
  146 static void     pppsyncstart __P((struct ppp_softc *sc));
  147 static void     pppasyncstart __P((struct ppp_softc *));
  148 static void     pppasyncctlp __P((struct ppp_softc *));
  149 static void     pppasyncrelinq __P((struct ppp_softc *));
  150 static void     ppp_timeout __P((void *));
  151 static void     pppgetm __P((struct ppp_softc *sc));
  152 static void     pppdumpb __P((u_char *b, int l));
  153 static void     ppplogchar __P((struct ppp_softc *, int));
  154 static void     pppdumpframe __P((struct ppp_softc *sc, struct mbuf* m,
  155     int xmit));
  156 
  157 /*
  158  * Some useful mbuf macros not in mbuf.h.
  159  */
  160 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
  161 
  162 #define M_DATASTART(m)  \
  163         (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
  164             (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
  165 
  166 #define M_DATASIZE(m)   \
  167         (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
  168             (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
  169 
  170 /*
  171  * Does c need to be escaped?
  172  */
  173 #define ESCAPE_P(c)     (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
  174 
  175 /*
  176  * Procedures for using an async tty interface for PPP.
  177  */
  178 
  179 /* This is a NetBSD-1.0 or later kernel. */
  180 #define CCOUNT(q)       ((q)->c_cc)
  181 
  182 #define PPP_LOWAT       100     /* Process more output when < LOWAT on queue */
  183 #define PPP_HIWAT       400     /* Don't start a new packet if HIWAT on que */
  184 
  185 /*
  186  * Line specific open routine for async tty devices.
  187  * Attach the given tty to the first available ppp unit.
  188  * Called from device open routine or ttioctl.
  189  */
  190 /* ARGSUSED */
  191 int
  192 pppopen(dev, tp)
  193     dev_t dev;
  194     struct tty *tp;
  195 {
  196     struct proc *p = curproc;           /* XXX */
  197     struct ppp_softc *sc;
  198     int error, s;
  199 
  200     if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  201         return (error);
  202 
  203     s = spltty();
  204 
  205     if (tp->t_linesw->l_no == PPPDISC) {
  206         sc = (struct ppp_softc *) tp->t_sc;
  207         if (sc != NULL && sc->sc_devp == (void *) tp) {
  208             splx(s);
  209             return (0);
  210         }
  211     }
  212 
  213     if ((sc = pppalloc(p->p_pid)) == NULL) {
  214         splx(s);
  215         return ENXIO;
  216     }
  217 
  218     if (sc->sc_relinq)
  219         (*sc->sc_relinq)(sc);   /* get previous owner to relinquish the unit */
  220 
  221 #if NBPFILTER > 0
  222     /* Switch DLT to PPP-over-serial. */
  223     bpf_change_type(&sc->sc_if, DLT_PPP_SERIAL, PPP_HDRLEN);
  224 #endif
  225 
  226     sc->sc_ilen = 0;
  227     sc->sc_m = NULL;
  228     memset(sc->sc_asyncmap, 0, sizeof(sc->sc_asyncmap));
  229     sc->sc_asyncmap[0] = 0xffffffff;
  230     sc->sc_asyncmap[3] = 0x60000000;
  231     sc->sc_rasyncmap = 0;
  232     sc->sc_devp = (void *) tp;
  233     sc->sc_start = pppasyncstart;
  234     sc->sc_ctlp = pppasyncctlp;
  235     sc->sc_relinq = pppasyncrelinq;
  236     sc->sc_outm = NULL;
  237     pppgetm(sc);
  238     sc->sc_if.if_flags |= IFF_RUNNING;
  239     sc->sc_if.if_baudrate = tp->t_ospeed;
  240 
  241     tp->t_sc = (caddr_t) sc;
  242     ttyflush(tp, FREAD | FWRITE);
  243 
  244     splx(s);
  245     return (0);
  246 }
  247 
  248 /*
  249  * Line specific close routine, called from device close routine
  250  * and from ttioctl.
  251  * Detach the tty from the ppp unit.
  252  * Mimics part of ttyclose().
  253  */
  254 int
  255 pppclose(tp, flag)
  256     struct tty *tp;
  257     int flag;
  258 {
  259     struct ppp_softc *sc;
  260     int s;
  261 
  262     s = spltty();
  263     ttyflush(tp, FREAD|FWRITE);
  264     tp->t_linesw = linesw[0]; /* default line discipline */
  265     sc = (struct ppp_softc *) tp->t_sc;
  266     if (sc != NULL) {
  267         tp->t_sc = NULL;
  268         if (tp == (struct tty *) sc->sc_devp) {
  269             pppasyncrelinq(sc);
  270             pppdealloc(sc);
  271         }
  272     }
  273     splx(s);
  274     return 0;
  275 }
  276 
  277 /*
  278  * Relinquish the interface unit to another device.
  279  */
  280 static void
  281 pppasyncrelinq(sc)
  282     struct ppp_softc *sc;
  283 {
  284     int s;
  285 
  286 #if NBPFILTER > 0
  287     /* Change DLT to back none. */
  288     bpf_change_type(&sc->sc_if, DLT_NULL, 0);
  289 #endif
  290 
  291     s = spltty();
  292     if (sc->sc_outm) {
  293         m_freem(sc->sc_outm);
  294         sc->sc_outm = NULL;
  295     }
  296     if (sc->sc_m) {
  297         m_freem(sc->sc_m);
  298         sc->sc_m = NULL;
  299     }
  300     if (sc->sc_flags & SC_TIMEOUT) {
  301         callout_stop(&sc->sc_timo_ch);
  302         sc->sc_flags &= ~SC_TIMEOUT;
  303     }
  304     splx(s);
  305 }
  306 
  307 /*
  308  * Line specific (tty) read routine.
  309  */
  310 int
  311 pppread(tp, uio, flag)
  312     struct tty *tp;
  313     struct uio *uio;
  314     int flag;
  315 {
  316     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
  317     struct mbuf *m, *m0;
  318     int s;
  319     int error = 0;
  320 
  321     if (sc == NULL)
  322         return 0;
  323     /*
  324      * Loop waiting for input, checking that nothing disasterous
  325      * happens in the meantime.
  326      */
  327     s = spltty();
  328     for (;;) {
  329         if (tp != (struct tty *) sc->sc_devp ||
  330             tp->t_linesw->l_no != PPPDISC) {
  331             splx(s);
  332             return 0;
  333         }
  334         if (sc->sc_inq.ifq_head != NULL)
  335             break;
  336         if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
  337             && (tp->t_state & TS_ISOPEN)) {
  338             splx(s);
  339             return 0;           /* end of file */
  340         }
  341         if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
  342             splx(s);
  343             return (EWOULDBLOCK);
  344         }
  345         error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
  346         if (error) {
  347             splx(s);
  348             return error;
  349         }
  350     }
  351 
  352     /* Pull place-holder byte out of canonical queue */
  353     getc(&tp->t_canq);
  354 
  355     /* Get the packet from the input queue */
  356     IF_DEQUEUE(&sc->sc_inq, m0);
  357     splx(s);
  358 
  359     for (m = m0; m && uio->uio_resid; m = m->m_next)
  360         if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
  361             break;
  362     m_freem(m0);
  363     return (error);
  364 }
  365 
  366 /*
  367  * Line specific (tty) write routine.
  368  */
  369 int
  370 pppwrite(tp, uio, flag)
  371     struct tty *tp;
  372     struct uio *uio;
  373     int flag;
  374 {
  375     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
  376     struct mbuf *m, *m0, **mp;
  377     struct sockaddr dst;
  378     int len, error;
  379 
  380     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
  381         return 0;               /* wrote 0 bytes */
  382     if (tp->t_linesw->l_no != PPPDISC)
  383         return (EINVAL);
  384     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
  385         return EIO;
  386     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
  387         uio->uio_resid < PPP_HDRLEN)
  388         return (EMSGSIZE);
  389     for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
  390         m = m_get(M_WAIT, MT_DATA);
  391         if ((*mp = m) == NULL) {
  392             m_freem(m0);
  393             return (ENOBUFS);
  394         }
  395         m->m_len = 0;
  396         if (uio->uio_resid >= MCLBYTES / 2)
  397             MCLGET(m, M_DONTWAIT);
  398         len = M_TRAILINGSPACE(m);
  399         if (len > uio->uio_resid)
  400             len = uio->uio_resid;
  401         if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
  402             m_freem(m0);
  403             return (error);
  404         }
  405         m->m_len = len;
  406     }
  407     dst.sa_family = AF_UNSPEC;
  408     bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
  409     m0->m_data += PPP_HDRLEN;
  410     m0->m_len -= PPP_HDRLEN;
  411     return ((*sc->sc_if.if_output)(&sc->sc_if, m0, &dst, (struct rtentry *)0));
  412 }
  413 
  414 /*
  415  * Line specific (tty) ioctl routine.
  416  * This discipline requires that tty device drivers call
  417  * the line specific l_ioctl routine from their ioctl routines.
  418  */
  419 /* ARGSUSED */
  420 int
  421 ppptioctl(tp, cmd, data, flag, p)
  422     struct tty *tp;
  423     u_long cmd;
  424     caddr_t data;
  425     int flag;
  426     struct proc *p;
  427 {
  428     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
  429     int error, s;
  430 
  431     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
  432         return (EPASSTHROUGH);
  433 
  434     error = 0;
  435     switch (cmd) {
  436     case TIOCRCVFRAME:
  437         ppprcvframe(sc,*((struct mbuf **)data));
  438         break;
  439 
  440     case PPPIOCSASYNCMAP:
  441         if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  442             break;
  443         sc->sc_asyncmap[0] = *(u_int *)data;
  444         break;
  445 
  446     case PPPIOCGASYNCMAP:
  447         *(u_int *)data = sc->sc_asyncmap[0];
  448         break;
  449 
  450     case PPPIOCSRASYNCMAP:
  451         if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  452             break;
  453         sc->sc_rasyncmap = *(u_int *)data;
  454         break;
  455 
  456     case PPPIOCGRASYNCMAP:
  457         *(u_int *)data = sc->sc_rasyncmap;
  458         break;
  459 
  460     case PPPIOCSXASYNCMAP:
  461         if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  462             break;
  463         s = spltty();
  464         bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
  465         sc->sc_asyncmap[1] = 0;             /* mustn't escape 0x20 - 0x3f */
  466         sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
  467         sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
  468         splx(s);
  469         break;
  470 
  471     case PPPIOCGXASYNCMAP:
  472         bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
  473         break;
  474 
  475     default:
  476         error = pppioctl(sc, cmd, data, flag, p);
  477         if (error == 0 && cmd == PPPIOCSMRU)
  478             pppgetm(sc);
  479     }
  480 
  481     return error;
  482 }
  483 
  484 /* receive a complete ppp frame from device in synchronous
  485  * hdlc mode. caller gives up ownership of mbuf
  486  */
  487 static void
  488 ppprcvframe(sc, m)
  489         struct ppp_softc *sc;
  490         struct mbuf *m;
  491 {
  492         int len, s;
  493         struct mbuf *n;
  494         u_char hdr[4];
  495         int hlen,count;
  496 
  497         for (n=m,len=0;n != NULL;n = n->m_next)
  498                 len += n->m_len;
  499         if (len==0) {
  500                 m_freem(m);
  501                 return;
  502         }
  503 
  504         /* extract PPP header from mbuf chain (1 to 4 bytes) */
  505         for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
  506                 count = (sizeof(hdr)-hlen) < n->m_len ?
  507                                 sizeof(hdr)-hlen : n->m_len;
  508                 bcopy(mtod(n,u_char*),&hdr[hlen],count);
  509                 hlen+=count;
  510         }
  511 
  512         s = spltty();
  513 
  514         /* if AFCF compressed then prepend AFCF */
  515         if (hdr[0] != PPP_ALLSTATIONS) {
  516                 if (sc->sc_flags & SC_REJ_COMP_AC) {
  517                         if (sc->sc_flags & SC_DEBUG)
  518                                 printf(
  519                                     "%s: garbage received: 0x%x (need 0xFF)\n",
  520                                     sc->sc_if.if_xname, hdr[0]);
  521                                 goto bail;
  522                         }
  523                 M_PREPEND(m,2,M_DONTWAIT);
  524                 if (m==NULL) {
  525                         splx(s);
  526                         return;
  527                 }
  528                 hdr[3] = hdr[1];
  529                 hdr[2] = hdr[0];
  530                 hdr[0] = PPP_ALLSTATIONS;
  531                 hdr[1] = PPP_UI;
  532                 len += 2;
  533         }
  534 
  535         /* if protocol field compressed, add MSB of protocol field = 0 */
  536         if (hdr[2] & 1) {
  537                 /* a compressed protocol */
  538                 M_PREPEND(m,1,M_DONTWAIT);
  539                 if (m==NULL) {
  540                         splx(s);
  541                         return;
  542                 }
  543                 hdr[3] = hdr[2];
  544                 hdr[2] = 0;
  545                 len++;
  546         }
  547 
  548         /* valid LSB of protocol field has bit0 set */
  549         if (!(hdr[3] & 1)) {
  550                 if (sc->sc_flags & SC_DEBUG)
  551                         printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
  552                                 (hdr[2] << 8) + hdr[3]);
  553                         goto bail;
  554         }
  555 
  556         /* packet beyond configured mru? */
  557         if (len > sc->sc_mru + PPP_HDRLEN) {
  558                 if (sc->sc_flags & SC_DEBUG)
  559                         printf("%s: packet too big\n", sc->sc_if.if_xname);
  560                 goto bail;
  561         }
  562 
  563         /* add expanded 4 byte header to mbuf chain */
  564         for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
  565                 count = (sizeof(hdr)-hlen) < n->m_len ?
  566                                 sizeof(hdr)-hlen : n->m_len;
  567                 bcopy(&hdr[hlen],mtod(n,u_char*),count);
  568                 hlen+=count;
  569         }
  570 
  571         /* if_ppp.c requires the PPP header and IP header */
  572         /* to be contiguous */
  573         count = len < MHLEN ? len : MHLEN;
  574         if (m->m_len < count) {
  575                 m = m_pullup(m,count);
  576                 if (m==NULL)
  577                         goto bail;
  578         }
  579 
  580         sc->sc_stats.ppp_ibytes += len;
  581 
  582         if (sc->sc_flags & SC_LOG_RAWIN)
  583                 pppdumpframe(sc,m,0);
  584 
  585         ppppktin(sc, m, 0);
  586         splx(s);
  587         return;
  588 bail:
  589         m_freem(m);
  590         splx(s);
  591 }
  592 
  593 /*
  594  * FCS lookup table as calculated by genfcstab.
  595  */
  596 static const u_int16_t fcstab[256] = {
  597         0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
  598         0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
  599         0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
  600         0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
  601         0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
  602         0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
  603         0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
  604         0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
  605         0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
  606         0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
  607         0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
  608         0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
  609         0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
  610         0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
  611         0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
  612         0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
  613         0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
  614         0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
  615         0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
  616         0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
  617         0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
  618         0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
  619         0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
  620         0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
  621         0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
  622         0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
  623         0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
  624         0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
  625         0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
  626         0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
  627         0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
  628         0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
  629 };
  630 
  631 /*
  632  * Calculate a new FCS given the current FCS and the new data.
  633  */
  634 static u_int16_t
  635 pppfcs(fcs, cp, len)
  636     u_int16_t fcs;
  637     u_char *cp;
  638     int len;
  639 {
  640     while (len--)
  641         fcs = PPP_FCS(fcs, *cp++);
  642     return (fcs);
  643 }
  644 
  645 /* This gets called at splsoftnet from pppasyncstart at various times
  646  * when there is data ready to be sent.
  647  */
  648 static void
  649 pppsyncstart(sc)
  650         struct ppp_softc *sc;
  651 {
  652         struct tty *tp = (struct tty *) sc->sc_devp;
  653         struct mbuf *m, *n;
  654         const struct cdevsw *cdev;
  655         int len;
  656 
  657         for(m = sc->sc_outm;;) {
  658                 if (m == NULL) {
  659                         m = ppp_dequeue(sc);    /* get new packet */
  660                         if (m == NULL)
  661                                 break;          /* no more packets */
  662                         if (sc->sc_flags & SC_DEBUG)
  663                                 pppdumpframe(sc,m,1);
  664                 }
  665                 for(n=m,len=0;n!=NULL;n=n->m_next)
  666                         len += n->m_len;
  667 
  668                 /* call device driver IOCTL to transmit a frame */
  669                 cdev = cdevsw_lookup(tp->t_dev);
  670                 if (cdev == NULL ||
  671                     (*cdev->d_ioctl)(tp->t_dev, TIOCXMTFRAME, (caddr_t)&m,
  672                                      0, 0)) {
  673                         /* busy or error, set as current packet */
  674                         sc->sc_outm = m;
  675                         break;
  676                 }
  677                 sc->sc_outm = m = NULL;
  678                 sc->sc_stats.ppp_obytes += len;
  679         }
  680 }
  681 
  682 /*
  683  * This gets called at splsoftnet from if_ppp.c at various times
  684  * when there is data ready to be sent.
  685  */
  686 static void
  687 pppasyncstart(sc)
  688     struct ppp_softc *sc;
  689 {
  690     struct tty *tp = (struct tty *) sc->sc_devp;
  691     struct mbuf *m;
  692     int len;
  693     u_char *start, *stop, *cp;
  694     int n, ndone, done, idle;
  695     struct mbuf *m2;
  696     int s;
  697 
  698     if (sc->sc_flags & SC_SYNC){
  699         pppsyncstart(sc);
  700         return;
  701     }
  702 
  703     idle = 0;
  704     while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
  705         /*
  706          * See if we have an existing packet partly sent.
  707          * If not, get a new packet and start sending it.
  708          */
  709         m = sc->sc_outm;
  710         if (m == NULL) {
  711             /*
  712              * Get another packet to be sent.
  713              */
  714             m = ppp_dequeue(sc);
  715             if (m == NULL) {
  716                 idle = 1;
  717                 break;
  718             }
  719 
  720             /*
  721              * The extra PPP_FLAG will start up a new packet, and thus
  722              * will flush any accumulated garbage.  We do this whenever
  723              * the line may have been idle for some time.
  724              */
  725             if (CCOUNT(&tp->t_outq) == 0) {
  726                 ++sc->sc_stats.ppp_obytes;
  727                 (void) putc(PPP_FLAG, &tp->t_outq);
  728             }
  729 
  730             /* Calculate the FCS for the first mbuf's worth. */
  731             sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
  732         }
  733 
  734         for (;;) {
  735             start = mtod(m, u_char *);
  736             len = m->m_len;
  737             stop = start + len;
  738             while (len > 0) {
  739                 /*
  740                  * Find out how many bytes in the string we can
  741                  * handle without doing something special.
  742                  */
  743                 for (cp = start; cp < stop; cp++)
  744                     if (ESCAPE_P(*cp))
  745                         break;
  746                 n = cp - start;
  747                 if (n) {
  748                     /* NetBSD (0.9 or later), 4.3-Reno or similar. */
  749                     ndone = n - b_to_q(start, n, &tp->t_outq);
  750                     len -= ndone;
  751                     start += ndone;
  752                     sc->sc_stats.ppp_obytes += ndone;
  753 
  754                     if (ndone < n)
  755                         break;  /* packet doesn't fit */
  756                 }
  757                 /*
  758                  * If there are characters left in the mbuf,
  759                  * the first one must be special.
  760                  * Put it out in a different form.
  761                  */
  762                 if (len) {
  763                     s = spltty();
  764                     if (putc(PPP_ESCAPE, &tp->t_outq)) {
  765                         splx(s);
  766                         break;
  767                     }
  768                     if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
  769                         (void) unputc(&tp->t_outq);
  770                         splx(s);
  771                         break;
  772                     }
  773                     splx(s);
  774                     sc->sc_stats.ppp_obytes += 2;
  775                     start++;
  776                     len--;
  777                 }
  778             }
  779 
  780             /*
  781              * If we didn't empty this mbuf, remember where we're up to.
  782              * If we emptied the last mbuf, try to add the FCS and closing
  783              * flag, and if we can't, leave sc_outm pointing to m, but with
  784              * m->m_len == 0, to remind us to output the FCS and flag later.
  785              */
  786             done = len == 0;
  787             if (done && m->m_next == NULL) {
  788                 u_char *p, *q;
  789                 int c;
  790                 u_char endseq[8];
  791 
  792                 /*
  793                  * We may have to escape the bytes in the FCS.
  794                  */
  795                 p = endseq;
  796                 c = ~sc->sc_outfcs & 0xFF;
  797                 if (ESCAPE_P(c)) {
  798                     *p++ = PPP_ESCAPE;
  799                     *p++ = c ^ PPP_TRANS;
  800                 } else
  801                     *p++ = c;
  802                 c = (~sc->sc_outfcs >> 8) & 0xFF;
  803                 if (ESCAPE_P(c)) {
  804                     *p++ = PPP_ESCAPE;
  805                     *p++ = c ^ PPP_TRANS;
  806                 } else
  807                     *p++ = c;
  808                 *p++ = PPP_FLAG;
  809 
  810                 /*
  811                  * Try to output the FCS and flag.  If the bytes
  812                  * don't all fit, back out.
  813                  */
  814                 s = spltty();
  815                 for (q = endseq; q < p; ++q)
  816                     if (putc(*q, &tp->t_outq)) {
  817                         done = 0;
  818                         for (; q > endseq; --q)
  819                             unputc(&tp->t_outq);
  820                         break;
  821                     }
  822                 splx(s);
  823                 if (done)
  824                     sc->sc_stats.ppp_obytes += q - endseq;
  825             }
  826 
  827             if (!done) {
  828                 /* remember where we got to */
  829                 m->m_data = start;
  830                 m->m_len = len;
  831                 break;
  832             }
  833 
  834             /* Finished with this mbuf; free it and move on. */
  835             MFREE(m, m2);
  836             m = m2;
  837             if (m == NULL) {
  838                 /* Finished a packet */
  839                 break;
  840             }
  841             sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
  842         }
  843 
  844         /*
  845          * If m == NULL, we have finished a packet.
  846          * If m != NULL, we've either done as much work this time
  847          * as we need to, or else we've filled up the output queue.
  848          */
  849         sc->sc_outm = m;
  850         if (m)
  851             break;
  852     }
  853 
  854     /* Call pppstart to start output again if necessary. */
  855     s = spltty();
  856     pppstart(tp);
  857 
  858     /*
  859      * This timeout is needed for operation on a pseudo-tty,
  860      * because the pty code doesn't call pppstart after it has
  861      * drained the t_outq.
  862      */
  863     if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
  864         callout_reset(&sc->sc_timo_ch, 1, ppp_timeout, sc);
  865         sc->sc_flags |= SC_TIMEOUT;
  866     }
  867 
  868     splx(s);
  869 }
  870 
  871 /*
  872  * This gets called when a received packet is placed on
  873  * the inq, at splsoftnet.
  874  */
  875 static void
  876 pppasyncctlp(sc)
  877     struct ppp_softc *sc;
  878 {
  879     struct tty *tp;
  880     int s;
  881 
  882     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
  883     s = spltty();
  884     tp = (struct tty *) sc->sc_devp;
  885     putc(0, &tp->t_canq);
  886     ttwakeup(tp);
  887     splx(s);
  888 }
  889 
  890 /*
  891  * Start output on async tty interface.  If the transmit queue
  892  * has drained sufficiently, arrange for pppasyncstart to be
  893  * called later at splsoftnet.
  894  * Called at spltty or higher.
  895  */
  896 int
  897 pppstart(tp)
  898     struct tty *tp;
  899 {
  900     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
  901 
  902     /*
  903      * If there is stuff in the output queue, send it now.
  904      * We are being called in lieu of ttstart and must do what it would.
  905      */
  906     if (tp->t_oproc != NULL)
  907         (*tp->t_oproc)(tp);
  908 
  909     /*
  910      * If the transmit queue has drained and the tty has not hung up
  911      * or been disconnected from the ppp unit, then tell if_ppp.c that
  912      * we need more output.
  913      */
  914     if ((CCOUNT(&tp->t_outq) >= PPP_LOWAT)
  915         && ((sc == NULL) || (sc->sc_flags & SC_TIMEOUT)))
  916         return 0;
  917 #ifdef ALTQ
  918     /*
  919      * if ALTQ is enabled, don't invoke NETISR_PPP.
  920      * pppintr() could loop without doing anything useful
  921      * under rate-limiting.
  922      */
  923     if (ALTQ_IS_ENABLED(&sc->sc_if.if_snd))
  924         return 0;
  925 #endif
  926     if (!((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
  927         && sc != NULL && tp == (struct tty *) sc->sc_devp) {
  928         ppp_restart(sc);
  929     }
  930 
  931     return 0;
  932 }
  933 
  934 /*
  935  * Timeout routine - try to start some more output.
  936  */
  937 static void
  938 ppp_timeout(x)
  939     void *x;
  940 {
  941     struct ppp_softc *sc = (struct ppp_softc *) x;
  942     struct tty *tp = (struct tty *) sc->sc_devp;
  943     int s;
  944 
  945     s = spltty();
  946     sc->sc_flags &= ~SC_TIMEOUT;
  947     pppstart(tp);
  948     splx(s);
  949 }
  950 
  951 /*
  952  * Allocate enough mbuf to handle current MRU.
  953  */
  954 static void
  955 pppgetm(sc)
  956     struct ppp_softc *sc;
  957 {
  958     struct mbuf *m, **mp;
  959     int len;
  960 
  961     mp = &sc->sc_m;
  962     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
  963         if ((m = *mp) == NULL) {
  964             MGETHDR(m, M_DONTWAIT, MT_DATA);
  965             if (m == NULL)
  966                 break;
  967             *mp = m;
  968             MCLGET(m, M_DONTWAIT);
  969         }
  970         len -= M_DATASIZE(m);
  971         mp = &m->m_next;
  972     }
  973 }
  974 
  975 /*
  976  * tty interface receiver interrupt.
  977  */
  978 static const unsigned paritytab[8] = {
  979     0x96696996, 0x69969669, 0x69969669, 0x96696996,
  980     0x69969669, 0x96696996, 0x96696996, 0x69969669
  981 };
  982 
  983 int
  984 pppinput(c, tp)
  985     int c;
  986     struct tty *tp;
  987 {
  988     struct ppp_softc *sc;
  989     struct mbuf *m;
  990     const struct cdevsw *cdev;
  991     int ilen, s;
  992 
  993     sc = (struct ppp_softc *) tp->t_sc;
  994     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
  995         return 0;
  996 
  997     ++tk_nin;
  998     ++sc->sc_stats.ppp_ibytes;
  999 
 1000     if (c & TTY_FE) {
 1001         /* framing error or overrun on this char - abort packet */
 1002         if (sc->sc_flags & SC_DEBUG)
 1003             printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
 1004         goto flush;
 1005     }
 1006 
 1007     c &= 0xff;
 1008 
 1009     /*
 1010      * Handle software flow control of output.
 1011      */
 1012     if (tp->t_iflag & IXON) {
 1013         if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
 1014             if ((tp->t_state & TS_TTSTOP) == 0) {
 1015                 tp->t_state |= TS_TTSTOP;
 1016                 cdev = cdevsw_lookup(tp->t_dev);
 1017                 if (cdev != NULL)
 1018                         (*cdev->d_stop)(tp, 0);
 1019             }
 1020             return 0;
 1021         }
 1022         if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
 1023             tp->t_state &= ~TS_TTSTOP;
 1024             if (tp->t_oproc != NULL)
 1025                 (*tp->t_oproc)(tp);
 1026             return 0;
 1027         }
 1028     }
 1029 
 1030     s = spltty();
 1031     if (c & 0x80)
 1032         sc->sc_flags |= SC_RCV_B7_1;
 1033     else
 1034         sc->sc_flags |= SC_RCV_B7_0;
 1035     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
 1036         sc->sc_flags |= SC_RCV_ODDP;
 1037     else
 1038         sc->sc_flags |= SC_RCV_EVNP;
 1039     splx(s);
 1040 
 1041     ppplogchar(sc, c);
 1042 
 1043     if (c == PPP_FLAG) {
 1044         ilen = sc->sc_ilen;
 1045         sc->sc_ilen = 0;
 1046 
 1047         if ((sc->sc_flags & SC_LOG_RAWIN) && sc->sc_rawin.count > 0)
 1048             ppplogchar(sc, -1);
 1049 
 1050         /*
 1051          * If SC_ESCAPED is set, then we've seen the packet
 1052          * abort sequence "}~".
 1053          */
 1054         if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
 1055             || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
 1056             s = spltty();
 1057             sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
 1058             if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
 1059                 if (sc->sc_flags & SC_DEBUG)
 1060                     printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
 1061                         sc->sc_fcs);
 1062                 sc->sc_if.if_ierrors++;
 1063                 sc->sc_stats.ppp_ierrors++;
 1064             } else
 1065                 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
 1066             splx(s);
 1067             return 0;
 1068         }
 1069 
 1070         if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
 1071             if (ilen) {
 1072                 if (sc->sc_flags & SC_DEBUG)
 1073                     printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
 1074                 s = spltty();
 1075                 sc->sc_if.if_ierrors++;
 1076                 sc->sc_stats.ppp_ierrors++;
 1077                 sc->sc_flags |= SC_PKTLOST;
 1078                 splx(s);
 1079             }
 1080             return 0;
 1081         }
 1082 
 1083         /*
 1084          * Remove FCS trailer.  Somewhat painful...
 1085          */
 1086         ilen -= 2;
 1087         if (--sc->sc_mc->m_len == 0) {
 1088             for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
 1089                 ;
 1090             sc->sc_mc = m;
 1091         }
 1092         sc->sc_mc->m_len--;
 1093 
 1094         /* excise this mbuf chain */
 1095         m = sc->sc_m;
 1096         sc->sc_m = sc->sc_mc->m_next;
 1097         sc->sc_mc->m_next = NULL;
 1098 
 1099         ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
 1100         if (sc->sc_flags & SC_PKTLOST) {
 1101             s = spltty();
 1102             sc->sc_flags &= ~SC_PKTLOST;
 1103             splx(s);
 1104         }
 1105 
 1106         pppgetm(sc);
 1107         return 0;
 1108     }
 1109 
 1110     if (sc->sc_flags & SC_FLUSH) {
 1111         if (sc->sc_flags & SC_LOG_FLUSH)
 1112             ppplogchar(sc, c);
 1113         return 0;
 1114     }
 1115 
 1116     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
 1117         return 0;
 1118 
 1119     s = spltty();
 1120     if (sc->sc_flags & SC_ESCAPED) {
 1121         sc->sc_flags &= ~SC_ESCAPED;
 1122         c ^= PPP_TRANS;
 1123     } else if (c == PPP_ESCAPE) {
 1124         sc->sc_flags |= SC_ESCAPED;
 1125         splx(s);
 1126         return 0;
 1127     }
 1128     splx(s);
 1129 
 1130     /*
 1131      * Initialize buffer on first octet received.
 1132      * First octet could be address or protocol (when compressing
 1133      * address/control).
 1134      * Second octet is control.
 1135      * Third octet is first or second (when compressing protocol)
 1136      * octet of protocol.
 1137      * Fourth octet is second octet of protocol.
 1138      */
 1139     if (sc->sc_ilen == 0) {
 1140         /* reset the first input mbuf */
 1141         if (sc->sc_m == NULL) {
 1142             pppgetm(sc);
 1143             if (sc->sc_m == NULL) {
 1144                 if (sc->sc_flags & SC_DEBUG)
 1145                     printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
 1146                 goto flush;
 1147             }
 1148         }
 1149         m = sc->sc_m;
 1150         m->m_len = 0;
 1151         m->m_data = M_DATASTART(sc->sc_m);
 1152         sc->sc_mc = m;
 1153         sc->sc_mp = mtod(m, char *);
 1154         sc->sc_fcs = PPP_INITFCS;
 1155         if (c != PPP_ALLSTATIONS) {
 1156             if (sc->sc_flags & SC_REJ_COMP_AC) {
 1157                 if (sc->sc_flags & SC_DEBUG)
 1158                     printf("%s: garbage received: 0x%x (need 0xFF)\n",
 1159                     sc->sc_if.if_xname, c);
 1160                 goto flush;
 1161             }
 1162             *sc->sc_mp++ = PPP_ALLSTATIONS;
 1163             *sc->sc_mp++ = PPP_UI;
 1164             sc->sc_ilen += 2;
 1165             m->m_len += 2;
 1166         }
 1167     }
 1168     if (sc->sc_ilen == 1 && c != PPP_UI) {
 1169         if (sc->sc_flags & SC_DEBUG)
 1170             printf("%s: missing UI (0x3), got 0x%x\n",
 1171                 sc->sc_if.if_xname, c);
 1172         goto flush;
 1173     }
 1174     if (sc->sc_ilen == 2 && (c & 1) == 1) {
 1175         /* a compressed protocol */
 1176         *sc->sc_mp++ = 0;
 1177         sc->sc_ilen++;
 1178         sc->sc_mc->m_len++;
 1179     }
 1180     if (sc->sc_ilen == 3 && (c & 1) == 0) {
 1181         if (sc->sc_flags & SC_DEBUG)
 1182             printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
 1183                 (sc->sc_mp[-1] << 8) + c);
 1184         goto flush;
 1185     }
 1186 
 1187     /* packet beyond configured mru? */
 1188     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
 1189         if (sc->sc_flags & SC_DEBUG)
 1190             printf("%s: packet too big\n", sc->sc_if.if_xname);
 1191         goto flush;
 1192     }
 1193 
 1194     /* is this mbuf full? */
 1195     m = sc->sc_mc;
 1196     if (M_TRAILINGSPACE(m) <= 0) {
 1197         if (m->m_next == NULL) {
 1198             pppgetm(sc);
 1199             if (m->m_next == NULL) {
 1200                 if (sc->sc_flags & SC_DEBUG)
 1201                     printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
 1202                 goto flush;
 1203             }
 1204         }
 1205         sc->sc_mc = m = m->m_next;
 1206         m->m_len = 0;
 1207         m->m_data = M_DATASTART(m);
 1208         sc->sc_mp = mtod(m, char *);
 1209     }
 1210 
 1211     ++m->m_len;
 1212     *sc->sc_mp++ = c;
 1213     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
 1214     return 0;
 1215 
 1216  flush:
 1217     if (!(sc->sc_flags & SC_FLUSH)) {
 1218         s = spltty();
 1219         sc->sc_if.if_ierrors++;
 1220         sc->sc_stats.ppp_ierrors++;
 1221         sc->sc_flags |= SC_FLUSH;
 1222         splx(s);
 1223         if (sc->sc_flags & SC_LOG_FLUSH)
 1224             ppplogchar(sc, c);
 1225     }
 1226     return 0;
 1227 }
 1228 
 1229 #define MAX_DUMP_BYTES  128
 1230 
 1231 static void
 1232 ppplogchar(sc, c)
 1233     struct ppp_softc *sc;
 1234     int c;
 1235 {
 1236     if (c >= 0) {
 1237         sc->sc_rawin.buf[sc->sc_rawin_start++] = c;
 1238         if (sc->sc_rawin.count < sizeof(sc->sc_rawin.buf))
 1239             sc->sc_rawin.count++;
 1240     }
 1241     if (sc->sc_rawin_start >= sizeof(sc->sc_rawin.buf)
 1242         || (c < 0 && sc->sc_rawin_start > 0)) {
 1243         if (sc->sc_flags & (SC_LOG_FLUSH|SC_LOG_RAWIN)) {
 1244             printf("%s input: ", sc->sc_if.if_xname);
 1245             pppdumpb(sc->sc_rawin.buf, sc->sc_rawin_start);
 1246         }
 1247         if (c < 0)
 1248             sc->sc_rawin.count = 0;
 1249         sc->sc_rawin_start = 0;
 1250     }
 1251 }
 1252 
 1253 static void
 1254 pppdumpb(b, l)
 1255     u_char *b;
 1256     int l;
 1257 {
 1258     char buf[3*MAX_DUMP_BYTES+4];
 1259     char *bp = buf;
 1260     static char digits[] = "0123456789abcdef";
 1261 
 1262     while (l--) {
 1263         if (bp >= buf + sizeof(buf) - 3) {
 1264             *bp++ = '>';
 1265             break;
 1266         }
 1267         *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
 1268         *bp++ = digits[*b++ & 0xf];
 1269         *bp++ = ' ';
 1270     }
 1271 
 1272     *bp = 0;
 1273     printf("%s\n", buf);
 1274 }
 1275 
 1276 static void
 1277 pppdumpframe(sc, m, xmit)
 1278         struct ppp_softc *sc;
 1279         struct mbuf* m;
 1280         int xmit;
 1281 {
 1282         int i,lcount,copycount,count;
 1283         char lbuf[16];
 1284         char *data;
 1285 
 1286         if (m == NULL)
 1287                 return;
 1288 
 1289         for(count=m->m_len,data=mtod(m,char*);m != NULL;) {
 1290                 /* build a line of output */
 1291                 for(lcount=0;lcount < sizeof(lbuf);lcount += copycount) {
 1292                         if (!count) {
 1293                                 m = m->m_next;
 1294                                 if (m == NULL)
 1295                                         break;
 1296                                 count = m->m_len;
 1297                                 data  = mtod(m,char*);
 1298                         }
 1299                         copycount = (count > sizeof(lbuf)-lcount) ?
 1300                                         sizeof(lbuf)-lcount : count;
 1301                         bcopy(data,&lbuf[lcount],copycount);
 1302                         data  += copycount;
 1303                         count -= copycount;
 1304                 }
 1305 
 1306                 /* output line (hex 1st, then ascii) */
 1307                 printf("%s %s:", sc->sc_if.if_xname,
 1308                     xmit ? "output" : "input ");
 1309                 for(i=0;i<lcount;i++)
 1310                         printf("%02x ",(u_char)lbuf[i]);
 1311                 for(;i<sizeof(lbuf);i++)
 1312                         printf("   ");
 1313                 for(i=0;i<lcount;i++)
 1314                         printf("%c",(lbuf[i] >= 040 &&
 1315                             lbuf[i] <= 0176) ? lbuf[i] : '.');
 1316                 printf("\n");
 1317         }
 1318 }

Cache object: b5e52007209e84c021c34542b2384b9b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.