LCOV - code coverage report
Current view: top level - net - ppp_tty.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 487 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ppp_tty.c,v 1.50 2018/05/15 09:21:52 mikeb Exp $      */
       2             : /*      $NetBSD: ppp_tty.c,v 1.12 1997/03/24 21:23:10 christos 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 "ppp.h"
      96             : #if NPPP > 0
      97             : 
      98             : #define VJC
      99             : #define PPP_COMPRESS
     100             : 
     101             : #include <sys/param.h>
     102             : #include <sys/proc.h>
     103             : #include <sys/mbuf.h>
     104             : #include <sys/socket.h>
     105             : #include <sys/timeout.h>
     106             : #include <sys/ioctl.h>
     107             : #include <sys/fcntl.h>
     108             : #include <sys/tty.h>
     109             : #include <sys/kernel.h>
     110             : #include <sys/conf.h>
     111             : #include <sys/vnode.h>
     112             : #include <sys/systm.h>
     113             : #include <sys/rwlock.h>
     114             : #include <sys/pool.h>
     115             : 
     116             : #include <net/if.h>
     117             : #include <net/if_var.h>
     118             : 
     119             : #ifdef VJC
     120             : #include <netinet/in.h>
     121             : #include <netinet/ip.h>
     122             : #include <net/slcompress.h>
     123             : #endif
     124             : 
     125             : #include <net/bpf.h>
     126             : #include <net/ppp_defs.h>
     127             : #include <net/if_ppp.h>
     128             : #include <net/if_pppvar.h>
     129             : 
     130             : int     pppstart_internal(struct tty *tp, int);
     131             : 
     132             : u_int16_t pppfcs(u_int16_t fcs, u_char *cp, int len);
     133             : void    pppasyncstart(struct ppp_softc *);
     134             : void    pppasyncctlp(struct ppp_softc *);
     135             : void    pppasyncrelinq(struct ppp_softc *);
     136             : void    ppp_timeout(void *);
     137             : void    ppppkt(struct ppp_softc *sc);
     138             : void    pppdumpb(u_char *b, int l);
     139             : void    ppplogchar(struct ppp_softc *, int);
     140             : 
     141             : struct rwlock ppp_pkt_init = RWLOCK_INITIALIZER("ppppktini");
     142             : struct pool ppp_pkts;
     143             : 
     144             : #define PKT_MAXLEN(_sc) ((_sc)->sc_mru + PPP_HDRLEN + PPP_FCSLEN)
     145             : 
     146             : /*
     147             :  * Does c need to be escaped?
     148             :  */
     149             : #define ESCAPE_P(c)     (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
     150             : 
     151             : /*
     152             :  * Procedures for using an async tty interface for PPP.
     153             :  */
     154             : 
     155             : /* This is a NetBSD-1.0 or later kernel. */
     156             : #define CCOUNT(q)       ((q)->c_cc)
     157             : 
     158             : /*
     159             :  * Line specific open routine for async tty devices.
     160             :  * Attach the given tty to the first available ppp unit.
     161             :  * Called from device open routine or ttioctl.
     162             :  */
     163             : int
     164           0 : pppopen(dev_t dev, struct tty *tp, struct proc *p)
     165             : {
     166             :     struct ppp_softc *sc;
     167             :     int error, s;
     168             : 
     169           0 :     if ((error = suser(p)) != 0)
     170           0 :         return (error);
     171             : 
     172           0 :     rw_enter_write(&ppp_pkt_init);
     173           0 :     if (ppp_pkts.pr_size == 0) {
     174             :         extern struct kmem_pa_mode kp_dma_contig;
     175             : 
     176           0 :         pool_init(&ppp_pkts, sizeof(struct ppp_pkt), 0,
     177             :           IPL_TTY, 0, "ppppkts", NULL); /* IPL_SOFTTTY */
     178           0 :         pool_set_constraints(&ppp_pkts, &kp_dma_contig);
     179           0 :     }
     180           0 :     rw_exit_write(&ppp_pkt_init);
     181             : 
     182           0 :     s = spltty();
     183             : 
     184           0 :     if (tp->t_line == PPPDISC) {
     185           0 :         sc = (struct ppp_softc *) tp->t_sc;
     186           0 :         if (sc != NULL && sc->sc_devp == (void *) tp) {
     187           0 :             splx(s);
     188           0 :             return (0);
     189             :         }
     190             :     }
     191             : 
     192           0 :     if ((sc = pppalloc(p->p_p->ps_pid)) == NULL) {
     193           0 :         splx(s);
     194           0 :         return ENXIO;
     195             :     }
     196             : 
     197           0 :     if (sc->sc_relinq)
     198           0 :         (*sc->sc_relinq)(sc);        /* get previous owner to relinquish the unit */
     199             : 
     200           0 :     timeout_set(&sc->sc_timo, ppp_timeout, sc);
     201           0 :     sc->sc_ilen = 0;
     202           0 :     sc->sc_pkt = NULL;
     203           0 :     bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
     204           0 :     sc->sc_asyncmap[0] = 0xffffffff;
     205           0 :     sc->sc_asyncmap[3] = 0x60000000;
     206           0 :     sc->sc_rasyncmap = 0;
     207           0 :     sc->sc_devp = (void *) tp;
     208           0 :     sc->sc_start = pppasyncstart;
     209           0 :     sc->sc_ctlp = pppasyncctlp;
     210           0 :     sc->sc_relinq = pppasyncrelinq;
     211           0 :     sc->sc_outm = NULL;
     212           0 :     ppppkt(sc);
     213           0 :     sc->sc_if.if_flags |= IFF_RUNNING;
     214           0 :     sc->sc_if.if_baudrate = tp->t_ospeed;
     215             : 
     216           0 :     tp->t_sc = (caddr_t) sc;
     217           0 :     ttyflush(tp, FREAD | FWRITE);
     218             : 
     219           0 :     splx(s);
     220           0 :     return (0);
     221           0 : }
     222             : 
     223             : /*
     224             :  * Line specific close routine, called from device close routine
     225             :  * and from ttioctl.
     226             :  * Detach the tty from the ppp unit.
     227             :  * Mimics part of ttyclose().
     228             :  */
     229             : int
     230           0 : pppclose(struct tty *tp, int flag, struct proc *p)
     231             : {
     232             :     struct ppp_softc *sc;
     233             :     int s;
     234             : 
     235           0 :     s = spltty();
     236           0 :     ttyflush(tp, FREAD|FWRITE);
     237           0 :     tp->t_line = 0;
     238           0 :     sc = (struct ppp_softc *) tp->t_sc;
     239           0 :     if (sc != NULL) {
     240           0 :         tp->t_sc = NULL;
     241           0 :         if (tp == (struct tty *) sc->sc_devp) {
     242           0 :             pppasyncrelinq(sc);
     243           0 :             pppdealloc(sc);
     244           0 :         }
     245             :     }
     246           0 :     splx(s);
     247           0 :     return 0;
     248             : }
     249             : 
     250             : /*
     251             :  * Relinquish the interface unit to another device.
     252             :  */
     253             : void
     254           0 : pppasyncrelinq(struct ppp_softc *sc)
     255             : {
     256             :     int s;
     257             : 
     258           0 :     KERNEL_LOCK();
     259           0 :     s = spltty();
     260           0 :     m_freem(sc->sc_outm);
     261           0 :     sc->sc_outm = NULL;
     262             : 
     263           0 :     if (sc->sc_pkt != NULL) {
     264           0 :         ppp_pkt_free(sc->sc_pkt);
     265           0 :         sc->sc_pkt = sc->sc_pktc = NULL;
     266           0 :     }
     267           0 :     if (sc->sc_flags & SC_TIMEOUT) {
     268           0 :         timeout_del(&sc->sc_timo);
     269           0 :         sc->sc_flags &= ~SC_TIMEOUT;
     270           0 :     }
     271           0 :     splx(s);
     272           0 :     KERNEL_UNLOCK();
     273           0 : }
     274             : 
     275             : /*
     276             :  * Line specific (tty) read routine.
     277             :  */
     278             : int
     279           0 : pppread(struct tty *tp, struct uio *uio, int flag)
     280             : {
     281           0 :     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
     282             :     struct mbuf *m, *m0;
     283             :     int s;
     284             :     int error = 0;
     285             : 
     286           0 :     if (sc == NULL)
     287           0 :         return 0;
     288             :     /*
     289             :      * Loop waiting for input, checking that nothing disasterous
     290             :      * happens in the meantime.
     291             :      */
     292           0 :     s = spltty();
     293           0 :     for (;;) {
     294           0 :         if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
     295           0 :             splx(s);
     296           0 :             return 0;
     297             :         }
     298             :         /* Get the packet from the input queue */
     299           0 :         m0 = mq_dequeue(&sc->sc_inq);
     300           0 :         if (m0 != NULL)
     301             :             break;
     302           0 :         if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
     303           0 :             && (tp->t_state & TS_ISOPEN)) {
     304           0 :             splx(s);
     305           0 :             return 0;           /* end of file */
     306             :         }
     307           0 :         if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
     308           0 :             splx(s);
     309           0 :             return (EWOULDBLOCK);
     310             :         }
     311           0 :         error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
     312           0 :         if (error) {
     313           0 :             splx(s);
     314           0 :             return error;
     315             :         }
     316             :     }
     317             : 
     318             :     /* Pull place-holder byte out of canonical queue */
     319           0 :     getc(&tp->t_canq);
     320           0 :     splx(s);
     321             : 
     322           0 :     for (m = m0; m && uio->uio_resid; m = m->m_next)
     323           0 :         if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
     324             :             break;
     325           0 :     m_freem(m0);
     326           0 :     return (error);
     327           0 : }
     328             : 
     329             : /*
     330             :  * Line specific (tty) write routine.
     331             :  */
     332             : int
     333           0 : pppwrite(struct tty *tp, struct uio *uio, int flag)
     334             : {
     335           0 :     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
     336           0 :     struct mbuf *m, *m0, **mp;
     337           0 :     struct sockaddr dst;
     338             :     u_int len;
     339             :     int error;
     340             : 
     341           0 :     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
     342           0 :         return 0;               /* wrote 0 bytes */
     343           0 :     if (tp->t_line != PPPDISC)
     344           0 :         return (EINVAL);
     345           0 :     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
     346           0 :         return EIO;
     347           0 :     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
     348           0 :         uio->uio_resid < PPP_HDRLEN)
     349           0 :         return (EMSGSIZE);
     350           0 :     for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
     351           0 :         if (mp == &m0) {
     352           0 :             MGETHDR(m, M_WAIT, MT_DATA);
     353           0 :             m->m_pkthdr.len = uio->uio_resid - PPP_HDRLEN;
     354           0 :             m->m_pkthdr.ph_ifidx = 0;
     355           0 :         } else
     356           0 :             MGET(m, M_WAIT, MT_DATA);
     357           0 :         *mp = m;
     358           0 :         m->m_len = 0;
     359           0 :         if (uio->uio_resid >= MCLBYTES / 2)
     360           0 :             MCLGET(m, M_DONTWAIT);
     361           0 :         len = M_TRAILINGSPACE(m);
     362           0 :         if (len > uio->uio_resid)
     363           0 :             len = uio->uio_resid;
     364           0 :         if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
     365           0 :             m_freem(m0);
     366           0 :             return (error);
     367             :         }
     368           0 :         m->m_len = len;
     369             :     }
     370           0 :     dst.sa_family = AF_UNSPEC;
     371           0 :     bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
     372           0 :     m0->m_data += PPP_HDRLEN;
     373           0 :     m0->m_len -= PPP_HDRLEN;
     374           0 :     return sc->sc_if.if_output(&sc->sc_if, m0, &dst, NULL);
     375           0 : }
     376             : 
     377             : /*
     378             :  * Line specific (tty) ioctl routine.
     379             :  * This discipline requires that tty device drivers call
     380             :  * the line specific l_ioctl routine from their ioctl routines.
     381             :  */
     382             : int
     383           0 : ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
     384             : {
     385           0 :     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
     386             :     int error, s;
     387             : 
     388           0 :     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
     389           0 :         return -1;
     390             : 
     391             :     error = 0;
     392           0 :     switch (cmd) {
     393             :     case PPPIOCSASYNCMAP:
     394           0 :         if ((error = suser(p)) != 0)
     395             :             break;
     396           0 :         sc->sc_asyncmap[0] = *(u_int *)data;
     397           0 :         break;
     398             : 
     399             :     case PPPIOCGASYNCMAP:
     400           0 :         *(u_int *)data = sc->sc_asyncmap[0];
     401           0 :         break;
     402             : 
     403             :     case PPPIOCSRASYNCMAP:
     404           0 :         if ((error = suser(p)) != 0)
     405             :             break;
     406           0 :         sc->sc_rasyncmap = *(u_int *)data;
     407           0 :         break;
     408             : 
     409             :     case PPPIOCGRASYNCMAP:
     410           0 :         *(u_int *)data = sc->sc_rasyncmap;
     411           0 :         break;
     412             : 
     413             :     case PPPIOCSXASYNCMAP:
     414           0 :         if ((error = suser(p)) != 0)
     415             :             break;
     416           0 :         s = spltty();
     417           0 :         bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
     418           0 :         sc->sc_asyncmap[1] = 0;                  /* mustn't escape 0x20 - 0x3f */
     419           0 :         sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
     420           0 :         sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
     421           0 :         splx(s);
     422           0 :         break;
     423             : 
     424             :     case PPPIOCGXASYNCMAP:
     425           0 :         bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
     426           0 :         break;
     427             : 
     428             :     default:
     429           0 :         NET_LOCK();
     430           0 :         error = pppioctl(sc, cmd, data, flag, p);
     431           0 :         NET_UNLOCK();
     432           0 :         if (error == 0 && cmd == PPPIOCSMRU)
     433           0 :             ppppkt(sc);
     434             :     }
     435             : 
     436           0 :     return error;
     437           0 : }
     438             : 
     439             : /*
     440             :  * FCS lookup table as calculated by genfcstab.
     441             :  */
     442             : static u_int16_t fcstab[256] = {
     443             :         0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
     444             :         0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
     445             :         0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
     446             :         0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
     447             :         0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
     448             :         0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
     449             :         0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
     450             :         0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
     451             :         0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
     452             :         0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
     453             :         0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
     454             :         0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
     455             :         0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
     456             :         0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
     457             :         0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
     458             :         0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
     459             :         0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
     460             :         0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
     461             :         0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
     462             :         0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
     463             :         0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
     464             :         0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
     465             :         0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
     466             :         0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
     467             :         0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
     468             :         0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
     469             :         0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
     470             :         0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
     471             :         0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
     472             :         0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
     473             :         0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
     474             :         0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
     475             : };
     476             : 
     477             : /*
     478             :  * Calculate a new FCS given the current FCS and the new data.
     479             :  */
     480             : u_int16_t
     481           0 : pppfcs(u_int16_t fcs, u_char *cp, int len)
     482             : {
     483           0 :     while (len--)
     484           0 :         fcs = PPP_FCS(fcs, *cp++);
     485           0 :     return (fcs);
     486             : }
     487             : 
     488             : /*
     489             :  * This gets called from pppoutput when a new packet is
     490             :  * put on a queue.
     491             :  */
     492             : void
     493           0 : pppasyncstart(struct ppp_softc *sc)
     494             : {
     495           0 :     struct tty *tp = (struct tty *) sc->sc_devp;
     496             :     struct mbuf *m;
     497             :     int len;
     498             :     u_char *start, *stop, *cp;
     499             :     int n, ndone, done, idle;
     500             :     struct mbuf *m2;
     501             :     int s;
     502             : 
     503           0 :     KERNEL_LOCK();
     504             :     idle = 0;
     505           0 :     while (CCOUNT(&tp->t_outq) < tp->t_hiwat) {
     506             :         /*
     507             :          * See if we have an existing packet partly sent.
     508             :          * If not, get a new packet and start sending it.
     509             :          */
     510           0 :         m = sc->sc_outm;
     511           0 :         if (m == NULL) {
     512             :             /*
     513             :              * Get another packet to be sent.
     514             :              */
     515           0 :             m = ppp_dequeue(sc);
     516           0 :             if (m == NULL) {
     517             :                 idle = 1;
     518           0 :                 break;
     519             :             }
     520             : 
     521             :             /*
     522             :              * The extra PPP_FLAG will start up a new packet, and thus
     523             :              * will flush any accumulated garbage.  We do this whenever
     524             :              * the line may have been idle for some time.
     525             :              */
     526           0 :             if (CCOUNT(&tp->t_outq) == 0) {
     527           0 :                 ++sc->sc_stats.ppp_obytes;
     528           0 :                 (void) putc(PPP_FLAG, &tp->t_outq);
     529           0 :             }
     530             : 
     531             :             /* Calculate the FCS for the first mbuf's worth. */
     532           0 :             sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
     533           0 :         }
     534             : 
     535           0 :         for (;;) {
     536           0 :             start = mtod(m, u_char *);
     537           0 :             len = m->m_len;
     538           0 :             stop = start + len;
     539           0 :             while (len > 0) {
     540             :                 /*
     541             :                  * Find out how many bytes in the string we can
     542             :                  * handle without doing something special.
     543             :                  */
     544           0 :                 for (cp = start; cp < stop; cp++)
     545           0 :                     if (ESCAPE_P(*cp))
     546             :                         break;
     547           0 :                 n = cp - start;
     548           0 :                 if (n) {
     549             :                     /* NetBSD (0.9 or later), 4.3-Reno or similar. */
     550           0 :                     ndone = n - b_to_q(start, n, &tp->t_outq);
     551           0 :                     len -= ndone;
     552           0 :                     start += ndone;
     553           0 :                     sc->sc_stats.ppp_obytes += ndone;
     554             : 
     555           0 :                     if (ndone < n)
     556             :                         break;  /* packet doesn't fit */
     557             :                 }
     558             :                 /*
     559             :                  * If there are characters left in the mbuf,
     560             :                  * the first one must be special.
     561             :                  * Put it out in a different form.
     562             :                  */
     563           0 :                 if (len) {
     564           0 :                     s = spltty();
     565           0 :                     if (putc(PPP_ESCAPE, &tp->t_outq)) {
     566           0 :                         splx(s);
     567           0 :                         break;
     568             :                     }
     569           0 :                     if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
     570           0 :                         (void) unputc(&tp->t_outq);
     571           0 :                         splx(s);
     572           0 :                         break;
     573             :                     }
     574           0 :                     splx(s);
     575           0 :                     sc->sc_stats.ppp_obytes += 2;
     576           0 :                     start++;
     577           0 :                     len--;
     578           0 :                 }
     579             :             }
     580             : 
     581             :             /*
     582             :              * If we didn't empty this mbuf, remember where we're up to.
     583             :              * If we emptied the last mbuf, try to add the FCS and closing
     584             :              * flag, and if we can't, leave sc_outm pointing to m, but with
     585             :              * m->m_len == 0, to remind us to output the FCS and flag later.
     586             :              */
     587           0 :             done = len == 0;
     588           0 :             if (done && m->m_next == NULL) {
     589             :                 u_char *p, *q;
     590             :                 int c;
     591           0 :                 u_char endseq[8];
     592             : 
     593             :                 /*
     594             :                  * We may have to escape the bytes in the FCS.
     595             :                  */
     596           0 :                 p = endseq;
     597           0 :                 c = ~sc->sc_outfcs & 0xFF;
     598           0 :                 if (ESCAPE_P(c)) {
     599           0 :                     *p++ = PPP_ESCAPE;
     600           0 :                     *p++ = c ^ PPP_TRANS;
     601           0 :                 } else
     602           0 :                     *p++ = c;
     603           0 :                 c = (~sc->sc_outfcs >> 8) & 0xFF;
     604           0 :                 if (ESCAPE_P(c)) {
     605           0 :                     *p++ = PPP_ESCAPE;
     606           0 :                     *p++ = c ^ PPP_TRANS;
     607           0 :                 } else
     608           0 :                     *p++ = c;
     609           0 :                 *p++ = PPP_FLAG;
     610             : 
     611             :                 /*
     612             :                  * Try to output the FCS and flag.  If the bytes
     613             :                  * don't all fit, back out.
     614             :                  */
     615           0 :                 s = spltty();
     616           0 :                 for (q = endseq; q < p; ++q)
     617           0 :                     if (putc(*q, &tp->t_outq)) {
     618             :                         done = 0;
     619           0 :                         for (; q > endseq; --q)
     620           0 :                             unputc(&tp->t_outq);
     621             :                         break;
     622             :                     }
     623           0 :                 splx(s);
     624           0 :                 if (done)
     625           0 :                     sc->sc_stats.ppp_obytes += q - endseq;
     626           0 :             }
     627             : 
     628           0 :             if (!done) {
     629             :                 /* remember where we got to */
     630           0 :                 m->m_data = start;
     631           0 :                 m->m_len = len;
     632           0 :                 break;
     633             :             }
     634             : 
     635             :             /* Finished with this mbuf; free it and move on. */
     636           0 :             m2 = m_free(m);
     637             :             m = m2;
     638           0 :             if (m == NULL) {
     639             :                 /* Finished a packet */
     640             :                 break;
     641             :             }
     642           0 :             sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
     643             :         }
     644             : 
     645             :         /*
     646             :          * If m == NULL, we have finished a packet.
     647             :          * If m != NULL, we've either done as much work this time
     648             :          * as we need to, or else we've filled up the output queue.
     649             :          */
     650           0 :         sc->sc_outm = m;
     651           0 :         if (m)
     652             :             break;
     653             :     }
     654             : 
     655             :     /* Call pppstart to start output again if necessary. */
     656           0 :     s = spltty();
     657           0 :     pppstart_internal(tp, 0);
     658             : 
     659             :     /*
     660             :      * This timeout is needed for operation on a pseudo-tty,
     661             :      * because the pty code doesn't call pppstart after it has
     662             :      * drained the t_outq.
     663             :      */
     664           0 :     if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
     665           0 :         timeout_add(&sc->sc_timo, 1);
     666           0 :         sc->sc_flags |= SC_TIMEOUT;
     667           0 :     }
     668             : 
     669           0 :     splx(s);
     670           0 :     KERNEL_UNLOCK();
     671           0 : }
     672             : 
     673             : /*
     674             :  * This gets called when a received packet is placed on
     675             :  * the inq.
     676             :  */
     677             : void
     678           0 : pppasyncctlp(struct ppp_softc *sc)
     679             : {
     680             :     struct tty *tp;
     681             :     int s;
     682             : 
     683           0 :     KERNEL_LOCK();
     684             :     /* Put a placeholder byte in canq for ttpoll()/ttnread(). */
     685           0 :     s = spltty();
     686           0 :     tp = (struct tty *) sc->sc_devp;
     687           0 :     putc(0, &tp->t_canq);
     688           0 :     ttwakeup(tp);
     689           0 :     splx(s);
     690           0 :     KERNEL_UNLOCK();
     691           0 : }
     692             : 
     693             : /*
     694             :  * Start output on async tty interface.  If the transmit queue
     695             :  * has drained sufficiently, arrange for pppasyncstart to be
     696             :  * called later.
     697             :  */
     698             : int
     699           0 : pppstart_internal(struct tty *tp, int force)
     700             : {
     701           0 :     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
     702             : 
     703             :     /*
     704             :      * If there is stuff in the output queue, send it now.
     705             :      * We are being called in lieu of ttstart and must do what it would.
     706             :      */
     707           0 :     if (tp->t_oproc != NULL)
     708           0 :         (*tp->t_oproc)(tp);
     709             : 
     710             :     /*
     711             :      * If the transmit queue has drained and the tty has not hung up
     712             :      * or been disconnected from the ppp unit, then tell if_ppp.c that
     713             :      * we need more output.
     714             :      */
     715           0 :     if ((CCOUNT(&tp->t_outq) < tp->t_lowat || force)
     716           0 :         && !((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
     717           0 :         && sc != NULL && tp == (struct tty *) sc->sc_devp) {
     718           0 :         ppp_restart(sc);
     719           0 :     }
     720             : 
     721           0 :     return 0;
     722             : }
     723             : 
     724             : int
     725           0 : pppstart(struct tty *tp)
     726             : {
     727           0 :         return pppstart_internal(tp, 0);
     728             : }
     729             : 
     730             : /*
     731             :  * Timeout routine - try to start some more output.
     732             :  */
     733             : void
     734           0 : ppp_timeout(void *x)
     735             : {
     736           0 :     struct ppp_softc *sc = (struct ppp_softc *) x;
     737           0 :     struct tty *tp = (struct tty *) sc->sc_devp;
     738             :     int s;
     739             : 
     740           0 :     s = spltty();
     741           0 :     sc->sc_flags &= ~SC_TIMEOUT;
     742           0 :     pppstart_internal(tp, 1);
     743           0 :     splx(s);
     744           0 : }
     745             : 
     746             : /*
     747             :  * Allocate enough mbuf to handle current MRU.
     748             :  */
     749             : void
     750           0 : ppppkt(struct ppp_softc *sc)
     751             : {
     752             :     struct ppp_pkt **pktp, *pkt;
     753             :     int len;
     754             :     int s;
     755             : 
     756           0 :     s = spltty();
     757           0 :     pktp = &sc->sc_pkt;
     758           0 :     for (len = PKT_MAXLEN(sc); len > 0; len -= sizeof(pkt->p_buf)) {
     759           0 :         pkt = *pktp;
     760           0 :         if (pkt == NULL) {
     761           0 :             pkt = pool_get(&ppp_pkts, PR_NOWAIT);
     762           0 :             if (pkt == NULL)
     763             :                 break;
     764           0 :             PKT_NEXT(pkt) = NULL;
     765           0 :             PKT_PREV(pkt) = *pktp;
     766           0 :             PKT_LEN(pkt) = 0;
     767           0 :             *pktp = pkt;
     768           0 :         }
     769           0 :         pktp = &PKT_NEXT(pkt);
     770             :     }
     771           0 :     splx(s);
     772           0 : }
     773             : 
     774             : void
     775           0 : ppp_pkt_free(struct ppp_pkt *pkt)
     776             : {
     777             :         struct ppp_pkt *next;
     778             : 
     779           0 :         while (pkt != NULL) {
     780           0 :                 next = PKT_NEXT(pkt);
     781           0 :                 pool_put(&ppp_pkts, pkt);
     782             :                 pkt = next;
     783             :         }
     784           0 : }
     785             : 
     786             : /*
     787             :  * tty interface receiver interrupt.
     788             :  */
     789             : static unsigned int paritytab[8] = {
     790             :     0x96696996, 0x69969669, 0x69969669, 0x96696996,
     791             :     0x69969669, 0x96696996, 0x96696996, 0x69969669
     792             : };
     793             : 
     794             : int
     795           0 : pppinput(int c, struct tty *tp)
     796             : {
     797             :     struct ppp_softc *sc;
     798             :     struct ppp_pkt *pkt;
     799             :     int ilen, s;
     800             : 
     801           0 :     sc = (struct ppp_softc *) tp->t_sc;
     802           0 :     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
     803           0 :         return 0;
     804             : 
     805           0 :     ++tk_nin;
     806           0 :     ++sc->sc_stats.ppp_ibytes;
     807             : 
     808           0 :     if (c & TTY_FE) {
     809             :         /* framing error or overrun on this char - abort packet */
     810           0 :         if (sc->sc_flags & SC_DEBUG)
     811           0 :             printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
     812             :         goto flush;
     813             :     }
     814             : 
     815           0 :     c &= 0xff;
     816             : 
     817             :     /*
     818             :      * Handle software flow control of output.
     819             :      */
     820           0 :     if (tp->t_iflag & IXON) {
     821           0 :         if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
     822           0 :             if ((tp->t_state & TS_TTSTOP) == 0) {
     823           0 :                 tp->t_state |= TS_TTSTOP;
     824           0 :                 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
     825           0 :             }
     826           0 :             return 0;
     827             :         }
     828           0 :         if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
     829           0 :             tp->t_state &= ~TS_TTSTOP;
     830           0 :             if (tp->t_oproc != NULL)
     831           0 :                 (*tp->t_oproc)(tp);
     832           0 :             return 0;
     833             :         }
     834             :     }
     835             : 
     836           0 :     s = spltty();
     837           0 :     if (c & 0x80)
     838           0 :         sc->sc_flags |= SC_RCV_B7_1;
     839             :     else
     840           0 :         sc->sc_flags |= SC_RCV_B7_0;
     841           0 :     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
     842           0 :         sc->sc_flags |= SC_RCV_ODDP;
     843             :     else
     844           0 :         sc->sc_flags |= SC_RCV_EVNP;
     845           0 :     splx(s);
     846             : 
     847           0 :     if (sc->sc_flags & SC_LOG_RAWIN)
     848           0 :         ppplogchar(sc, c);
     849             : 
     850           0 :     if (c == PPP_FLAG) {
     851           0 :         ilen = sc->sc_ilen;
     852           0 :         sc->sc_ilen = 0;
     853             : 
     854           0 :         if (sc->sc_rawin_count > 0)
     855           0 :             ppplogchar(sc, -1);
     856             : 
     857             :         /*
     858             :          * If SC_ESCAPED is set, then we've seen the packet
     859             :          * abort sequence "}~".
     860             :          */
     861           0 :         if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
     862           0 :             || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
     863           0 :             s = spltty();
     864           0 :             sc->sc_flags |= SC_PKTLOST;      /* note the dropped packet */
     865           0 :             if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
     866           0 :                 if (sc->sc_flags & SC_DEBUG)
     867           0 :                     printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
     868           0 :                         sc->sc_fcs);
     869           0 :                 sc->sc_if.if_ierrors++;
     870           0 :                 sc->sc_stats.ppp_ierrors++;
     871           0 :             } else
     872           0 :                 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
     873           0 :             splx(s);
     874           0 :             return 0;
     875             :         }
     876             : 
     877           0 :         if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
     878           0 :             if (ilen) {
     879           0 :                 if (sc->sc_flags & SC_DEBUG)
     880           0 :                     printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
     881           0 :                 s = spltty();
     882           0 :                 sc->sc_if.if_ierrors++;
     883           0 :                 sc->sc_stats.ppp_ierrors++;
     884           0 :                 sc->sc_flags |= SC_PKTLOST;
     885           0 :                 splx(s);
     886           0 :             }
     887           0 :             return 0;
     888             :         }
     889             : 
     890             :         /*
     891             :          * Remove FCS trailer.
     892             :          */
     893             :         ilen -= 2;
     894           0 :         pkt = sc->sc_pktc;
     895           0 :         if (--PKT_LEN(pkt) == 0) {
     896           0 :             pkt = PKT_PREV(pkt);
     897           0 :             sc->sc_pktc = pkt;
     898           0 :         }
     899           0 :         PKT_LEN(pkt)--;
     900             : 
     901             :         /* excise this mbuf chain */
     902           0 :         pkt = sc->sc_pkt;
     903           0 :         sc->sc_pkt = sc->sc_pktc = PKT_NEXT(sc->sc_pktc);
     904           0 :         PKT_NEXT(pkt) = NULL;
     905             : 
     906           0 :         ppppktin(sc, pkt, sc->sc_flags & SC_PKTLOST);
     907           0 :         if (sc->sc_flags & SC_PKTLOST) {
     908           0 :             s = spltty();
     909           0 :             sc->sc_flags &= ~SC_PKTLOST;
     910           0 :             splx(s);
     911           0 :         }
     912             : 
     913           0 :         ppppkt(sc);
     914           0 :         return 0;
     915             :     }
     916             : 
     917           0 :     if (sc->sc_flags & SC_FLUSH) {
     918           0 :         if (sc->sc_flags & SC_LOG_FLUSH)
     919           0 :             ppplogchar(sc, c);
     920           0 :         return 0;
     921             :     }
     922             : 
     923           0 :     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
     924           0 :         return 0;
     925             : 
     926           0 :     s = spltty();
     927           0 :     if (sc->sc_flags & SC_ESCAPED) {
     928           0 :         sc->sc_flags &= ~SC_ESCAPED;
     929           0 :         c ^= PPP_TRANS;
     930           0 :     } else if (c == PPP_ESCAPE) {
     931           0 :         sc->sc_flags |= SC_ESCAPED;
     932           0 :         splx(s);
     933           0 :         return 0;
     934             :     }
     935           0 :     splx(s);
     936             : 
     937             :     /*
     938             :      * Initialize buffer on first octet received.
     939             :      * First octet could be address or protocol (when compressing
     940             :      * address/control).
     941             :      * Second octet is control.
     942             :      * Third octet is first or second (when compressing protocol)
     943             :      * octet of protocol.
     944             :      * Fourth octet is second octet of protocol.
     945             :      */
     946           0 :     if (sc->sc_ilen == 0) {
     947             :         /* reset the first input mbuf */
     948           0 :         if (sc->sc_pkt == NULL) {
     949           0 :             ppppkt(sc);
     950           0 :             if (sc->sc_pkt == NULL) {
     951           0 :                 if (sc->sc_flags & SC_DEBUG)
     952           0 :                     printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
     953             :                 goto flush;
     954             :             }
     955             :         }
     956           0 :         pkt = sc->sc_pkt;
     957           0 :         PKT_LEN(pkt) = 0;
     958           0 :         sc->sc_pktc = pkt;
     959           0 :         sc->sc_pktp = pkt->p_buf;
     960           0 :         sc->sc_fcs = PPP_INITFCS;
     961           0 :         if (c != PPP_ALLSTATIONS) {
     962           0 :             if (sc->sc_flags & SC_REJ_COMP_AC) {
     963           0 :                 if (sc->sc_flags & SC_DEBUG)
     964           0 :                     printf("%s: garbage received: 0x%x (need 0xFF)\n",
     965           0 :                         sc->sc_if.if_xname, c);
     966             :                 goto flush;
     967             :             }
     968           0 :             *sc->sc_pktp++ = PPP_ALLSTATIONS;
     969           0 :             *sc->sc_pktp++ = PPP_UI;
     970           0 :             sc->sc_ilen += 2;
     971           0 :             PKT_LEN(pkt) += 2;
     972           0 :         }
     973             :     }
     974           0 :     if (sc->sc_ilen == 1 && c != PPP_UI) {
     975           0 :         if (sc->sc_flags & SC_DEBUG)
     976           0 :             printf("%s: missing UI (0x3), got 0x%x\n",
     977           0 :                 sc->sc_if.if_xname, c);
     978             :         goto flush;
     979             :     }
     980           0 :     if (sc->sc_ilen == 2 && (c & 1) == 1) {
     981             :         /* a compressed protocol */
     982           0 :         *sc->sc_pktp++ = 0;
     983           0 :         sc->sc_ilen++;
     984           0 :         PKT_LEN(sc->sc_pktc)++;
     985           0 :     }
     986           0 :     if (sc->sc_ilen == 3 && (c & 1) == 0) {
     987           0 :         if (sc->sc_flags & SC_DEBUG)
     988           0 :             printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
     989           0 :                 (sc->sc_pktp[-1] << 8) + c);
     990             :         goto flush;
     991             :     }
     992             : 
     993             :     /* packet beyond configured mru? */
     994           0 :     if (++sc->sc_ilen > PKT_MAXLEN(sc)) {
     995           0 :         if (sc->sc_flags & SC_DEBUG)
     996           0 :             printf("%s: packet too big\n", sc->sc_if.if_xname);
     997             :         goto flush;
     998             :     }
     999             : 
    1000             :     /* is this packet full? */
    1001           0 :     pkt = sc->sc_pktc;
    1002           0 :     if (PKT_LEN(pkt) >= sizeof(pkt->p_buf)) {
    1003           0 :         if (PKT_NEXT(pkt) == NULL) {
    1004           0 :             ppppkt(sc);
    1005           0 :             if (PKT_NEXT(pkt) == NULL) {
    1006           0 :                 if (sc->sc_flags & SC_DEBUG)
    1007           0 :                     printf("%s: too few input packets!\n", sc->sc_if.if_xname);
    1008             :                 goto flush;
    1009             :             }
    1010             :         }
    1011           0 :         sc->sc_pktc = pkt = PKT_NEXT(pkt);
    1012           0 :         PKT_LEN(pkt) = 0;
    1013           0 :         sc->sc_pktp = pkt->p_buf;
    1014           0 :     }
    1015             : 
    1016           0 :     ++PKT_LEN(pkt);
    1017           0 :     *sc->sc_pktp++ = c;
    1018           0 :     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
    1019           0 :     return 0;
    1020             : 
    1021             :  flush:
    1022           0 :     if (!(sc->sc_flags & SC_FLUSH)) {
    1023           0 :         s = spltty();
    1024           0 :         sc->sc_if.if_ierrors++;
    1025           0 :         sc->sc_stats.ppp_ierrors++;
    1026           0 :         sc->sc_flags |= SC_FLUSH;
    1027           0 :         splx(s);
    1028           0 :         if (sc->sc_flags & SC_LOG_FLUSH)
    1029           0 :             ppplogchar(sc, c);
    1030             :     }
    1031           0 :     return 0;
    1032           0 : }
    1033             : 
    1034             : #define MAX_DUMP_BYTES  128
    1035             : 
    1036             : void
    1037           0 : ppplogchar(struct ppp_softc *sc, int c)
    1038             : {
    1039           0 :     if (c >= 0)
    1040           0 :         sc->sc_rawin[sc->sc_rawin_count++] = c;
    1041           0 :     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
    1042           0 :         || (c < 0 && sc->sc_rawin_count > 0)) {
    1043           0 :         printf("%s input: ", sc->sc_if.if_xname);
    1044           0 :         pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
    1045           0 :         sc->sc_rawin_count = 0;
    1046           0 :     }
    1047           0 : }
    1048             : 
    1049             : void
    1050           0 : pppdumpb(u_char *b, int l)
    1051             : {
    1052           0 :     char buf[3*MAX_DUMP_BYTES+4];
    1053           0 :     char *bp = buf;
    1054             :     static char digits[] = "0123456789abcdef";
    1055             : 
    1056           0 :     while (l--) {
    1057           0 :         if (bp >= buf + sizeof(buf) - 3) {
    1058           0 :             *bp++ = '>';
    1059           0 :             break;
    1060             :         }
    1061           0 :         *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
    1062           0 :         *bp++ = digits[*b++ & 0xf];
    1063           0 :         *bp++ = ' ';
    1064             :     }
    1065             : 
    1066           0 :     *bp = 0;
    1067           0 :     printf("%s\n", buf);
    1068           0 : }
    1069             : 
    1070             : #endif  /* NPPP > 0 */

Generated by: LCOV version 1.13