]> git.ozlabs.org Git - ppp.git/commitdiff
updated for 2.3 from netbsd stuff
authorPaul Mackerras <paulus@samba.org>
Mon, 1 Jul 1996 01:00:31 +0000 (01:00 +0000)
committerPaul Mackerras <paulus@samba.org>
Mon, 1 Jul 1996 01:00:31 +0000 (01:00 +0000)
freebsd-2.0/files-2.2.patch [new file with mode: 0644]
freebsd-2.0/files.patch
freebsd-2.0/if_ppp.c
freebsd-2.0/if_pppvar.h
freebsd-2.0/kinstall.sh
freebsd-2.0/ppp-deflate.c [new file with mode: 0644]
freebsd-2.0/ppp_tty.c

diff --git a/freebsd-2.0/files-2.2.patch b/freebsd-2.0/files-2.2.patch
new file mode 100644 (file)
index 0000000..4ce538b
--- /dev/null
@@ -0,0 +1,13 @@
+*** files.orig Wed Dec 14 13:11:12 1994
+--- files      Wed Dec 14 13:13:56 1994
+***************
+*** 141,146 ****
+--- 141,148 ----
+  net/if_ppp.c         optional ppp
+  net/ppp_tty.c                optional ppp
+  net/bsd-comp.c               optional ppp
++ net/ppp-deflate.c    optional ppp
++ net/zlib.c           optional ppp
+  net/if_sl.c          optional sl
+  net/pppcompress.c    optional ppp
+  net/radix.c          standard
index 56fb2b7d84c5708ee6ea9d804af2eca16730d342..b9e9f683de97d3419fcb1d8d272473be23f3fcdf 100644 (file)
@@ -2,12 +2,14 @@
 --- files      Wed Dec 14 13:13:56 1994
 ***************
 *** 139,144 ****
---- 139,146 ----
+--- 139,148 ----
   net/if_ethersubr.c   optional ether
   net/if_loop.c                optional loop
   net/if_ppp.c         optional ppp
 + net/ppp_tty.c                optional ppp
 + net/bsd-comp.c               optional ppp
++ net/ppp-deflate.c    optional ppp
++ net/zlib.c           optional ppp
   net/if_sl.c          optional sl
   net/pppcompress.c    optional ppp
   net/radix.c          standard
index 702bcca74c538133e584c5558f40fd41059ad28e..23a95b4d064eedd5266889f8fa765deb86e133cd 100644 (file)
@@ -69,8 +69,9 @@
  * Paul Mackerras (paulus@cs.anu.edu.au).
  */
 
-/* $Id: if_ppp.c,v 1.6 1995/10/27 03:34:42 paulus Exp $ */
+/* $Id: if_ppp.c,v 1.7 1996/07/01 01:00:27 paulus Exp $ */
 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
+/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
 
 #include "ppp.h"
 #if NPPP > 0
@@ -85,6 +86,8 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <sys/kernel.h>
+#include <sys/time.h>
+#include <sys/malloc.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
 
 #include "bpfilter.h"
 #if NBPFILTER > 0
-#include <sys/time.h>
 #include <net/bpf.h>
 #endif
 
 #include <net/ppp-comp.h>
 #endif
 
-void   pppattach __P((void));
-int    pppioctl __P((struct ppp_softc *sc, u_long cmd, caddr_t data, int flag,
-                     struct proc *));
-int    pppoutput __P((struct ifnet *ifp, struct mbuf *m0,
-                      struct sockaddr *dst, struct rtentry *rtp));
-int    pppsioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data));
-void   pppintr __P((void));
-
 static void    ppp_requeue __P((struct ppp_softc *));
 static void    ppp_outpkt __P((struct ppp_softc *));
-static int     ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd));
+static void    ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd));
 static void    ppp_ccp_closed __P((struct ppp_softc *));
 static void    ppp_inproc __P((struct ppp_softc *, struct mbuf *));
 static void    pppdumpm __P((struct mbuf *m0));
@@ -166,10 +160,14 @@ static void       pppdumpm __P((struct mbuf *m0));
  */
 
 extern struct compressor ppp_bsd_compress;
+extern struct compressor ppp_deflate;
 
 struct compressor *ppp_compressors[8] = {
 #if DO_BSD_COMPRESS
     &ppp_bsd_compress,
+#endif
+#if DO_DEFLATE
+    &ppp_deflate,
 #endif
     NULL
 };
@@ -232,8 +230,12 @@ pppalloc(pid)
     sc->sc_flags = 0;
     sc->sc_mru = PPP_MRU;
     sc->sc_relinq = NULL;
+    bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));
 #ifdef VJC
-    vj_compress_init(&sc->sc_comp, -1);
+    MALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress),
+          M_DEVBUF, M_NOWAIT);
+    if (sc->sc_comp)
+       vj_compress_init(sc->sc_comp, -1);
 #endif
 #ifdef PPP_COMPRESS
     sc->sc_xc_state = NULL;
@@ -292,6 +294,12 @@ pppdealloc(sc)
     sc->sc_xc_state = NULL;
     sc->sc_rc_state = NULL;
 #endif /* PPP_COMPRESS */
+#ifdef VJC
+    if (sc->sc_comp != 0) {
+       FREE(sc->sc_comp, M_DEVBUF);
+       sc->sc_comp = 0;
+    }
+#endif
 }
 
 /*
@@ -328,7 +336,7 @@ pppioctl(sc, cmd, data, flag, p)
        break;
 
     case PPPIOCSFLAGS:
-       if (error = suser(p->p_ucred, &p->p_acflag))
+       if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
            return (error);
        flags = *(int *)data & SC_MASK;
        s = splnet();
@@ -342,7 +350,7 @@ pppioctl(sc, cmd, data, flag, p)
        break;
 
     case PPPIOCSMRU:
-       if (error = suser(p->p_ucred, &p->p_acflag))
+       if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
            return (error);
        mru = *(int *)data;
        if (mru >= PPP_MRU && mru <= PPP_MAXMRU)
@@ -355,29 +363,31 @@ pppioctl(sc, cmd, data, flag, p)
 
 #ifdef VJC
     case PPPIOCSMAXCID:
-       if (error = suser(p->p_ucred, &p->p_acflag))
+       if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
            return (error);
-       s = splnet();
-       vj_compress_init(&sc->sc_comp, *(int *)data);
-       splx(s);
+       if (sc->sc_comp) {
+           s = splnet();
+           vj_compress_init(sc->sc_comp, *(int *)data);
+           splx(s);
+       }
        break;
 #endif
 
     case PPPIOCXFERUNIT:
-       if (error = suser(p->p_ucred, &p->p_acflag))
+       if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
            return (error);
        sc->sc_xfer = p->p_pid;
        break;
 
 #ifdef PPP_COMPRESS
     case PPPIOCSCOMPRESS:
-       if (error = suser(p->p_ucred, &p->p_acflag))
+       if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
            return (error);
        odp = (struct ppp_option_data *) data;
        nb = odp->length;
        if (nb > sizeof(ccp_option))
            nb = sizeof(ccp_option);
-       if (error = copyin(odp->ptr, ccp_option, nb))
+       if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)
            return (error);
        if (ccp_option[1] < 2)  /* preliminary check on the length byte */
            return (EINVAL);
@@ -441,7 +451,7 @@ pppioctl(sc, cmd, data, flag, p)
        if (cmd == PPPIOCGNPMODE) {
            npi->mode = sc->sc_npmode[npx];
        } else {
-           if (error = suser(p->p_ucred, &p->p_acflag))
+           if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
                return (error);
            if (npi->mode != sc->sc_npmode[npx]) {
                s = splnet();
@@ -505,7 +515,7 @@ pppsioctl(ifp, cmd, data)
        break;
 
     case SIOCSIFMTU:
-       if (error = suser(p->p_ucred, &p->p_acflag))
+       if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
            break;
        sc->sc_if.if_mtu = ifr->ifr_mtu;
        break;
@@ -516,6 +526,10 @@ pppsioctl(ifp, cmd, data)
 
     case SIOCADDMULTI:
     case SIOCDELMULTI:
+       if (ifr == 0) {
+           error = EAFNOSUPPORT;
+           break;
+       }
        switch(ifr->ifr_addr.sa_family) {
 #ifdef INET
        case AF_INET:
@@ -530,21 +544,18 @@ pppsioctl(ifp, cmd, data)
     case SIOCGPPPSTATS:
        psp = &((struct ifpppstatsreq *) data)->stats;
        bzero(psp, sizeof(*psp));
-       psp->p.ppp_ibytes = sc->sc_bytesrcvd;
-       psp->p.ppp_ipackets = ifp->if_ipackets;
-       psp->p.ppp_ierrors = ifp->if_ierrors;
-       psp->p.ppp_obytes = sc->sc_bytessent;
-       psp->p.ppp_opackets = ifp->if_opackets;
-       psp->p.ppp_oerrors = ifp->if_oerrors;
-#ifdef VJC
-       psp->vj.vjs_packets = sc->sc_comp.sls_packets;
-       psp->vj.vjs_compressed = sc->sc_comp.sls_compressed;
-       psp->vj.vjs_searches = sc->sc_comp.sls_searches;
-       psp->vj.vjs_misses = sc->sc_comp.sls_misses;
-       psp->vj.vjs_uncompressedin = sc->sc_comp.sls_uncompressedin;
-       psp->vj.vjs_compressedin = sc->sc_comp.sls_compressedin;
-       psp->vj.vjs_errorin = sc->sc_comp.sls_errorin;
-       psp->vj.vjs_tossed = sc->sc_comp.sls_tossed;
+       psp->p = sc->sc_stats;
+#if defined(VJC) && !defined(SL_NO_STATS)
+       if (sc->sc_comp) {
+           psp->vj.vjs_packets = sc->sc_comp->sls_packets;
+           psp->vj.vjs_compressed = sc->sc_comp->sls_compressed;
+           psp->vj.vjs_searches = sc->sc_comp->sls_searches;
+           psp->vj.vjs_misses = sc->sc_comp->sls_misses;
+           psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin;
+           psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin;
+           psp->vj.vjs_errorin = sc->sc_comp->sls_errorin;
+           psp->vj.vjs_tossed = sc->sc_comp->sls_tossed;
+       }
 #endif /* VJC */
        break;
 
@@ -578,7 +589,6 @@ pppoutput(ifp, m0, dst, rtp)
     struct rtentry *rtp;
 {
     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
-    struct ppp_header *ph;
     int protocol, address, control;
     u_char *cp;
     int s, error;
@@ -587,7 +597,7 @@ pppoutput(ifp, m0, dst, rtp)
     enum NPmode mode;
 
     if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
-       || (ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC) {
+       || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
        error = ENETDOWN;       /* sort of */
        goto bad;
     }
@@ -663,6 +673,13 @@ pppoutput(ifp, m0, dst, rtp)
        pppdumpm(m0);
     }
 
+    if ((protocol & 0x8000) == 0) {
+       /*
+        * Update the time we sent the most recent data packet.
+        */
+       sc->sc_last_sent = time.tv_sec;
+    }
+
 #if NBPFILTER > 0
     /*
      * See if bpf wants to look at the packet.
@@ -686,12 +703,16 @@ pppoutput(ifp, m0, dst, rtp)
            IF_DROP(ifq);
            splx(s);
            sc->sc_if.if_oerrors++;
+           sc->sc_stats.ppp_oerrors++;
            error = ENOBUFS;
            goto bad;
        }
        IF_ENQUEUE(ifq, m0);
        (*sc->sc_start)(sc);
     }
+    ifp->if_lastchange = time;
+    ifp->if_opackets++;
+    ifp->if_obytes += len;
 
     splx(s);
     return (0);
@@ -734,6 +755,7 @@ ppp_requeue(sc)
            if (IF_QFULL(ifq)) {
                IF_DROP(ifq);
                sc->sc_if.if_oerrors++;
+               sc->sc_stats.ppp_oerrors++;
            } else
                IF_ENQUEUE(ifq, m);
            break;
@@ -753,80 +775,34 @@ ppp_requeue(sc)
 }
 
 /*
- * Get a packet to send.  This procedure is intended to be called at
- * spltty or splimp, so it takes little time.  If there isn't a packet
- * waiting to go out, it schedules a software interrupt to prepare a
- * new packet; the device start routine gets called again when a
- * packet is ready.
+ * Transmitter has finished outputting some stuff;
+ * remember to call sc->sc_start later at splnet.
  */
-struct mbuf *
-ppp_dequeue(sc)
+void
+ppp_restart(sc)
     struct ppp_softc *sc;
 {
-    struct mbuf *m;
     int s = splimp();
 
-    m = sc->sc_togo;
-    if (m) {
-       /*
-        * Had a packet waiting - send it.
-        */
-       sc->sc_togo = NULL;
-       sc->sc_flags |= SC_TBUSY;
-       splx(s);
-       return m;
-    }
-    /*
-     * Remember we wanted a packet and schedule a software interrupt.
-     */
     sc->sc_flags &= ~SC_TBUSY;
     schednetisr(NETISR_PPP);
     splx(s);
-    return NULL;
 }
 
 /*
- * Software interrupt routine, called at splnet().
- */
-void
-pppintr()
-{
-    struct ppp_softc *sc;
-    int i, s;
-    struct mbuf *m;
-
-    s = splnet();
-    sc = ppp_softc;
-    for (i = 0; i < NPPP; ++i, ++sc) {
-       if (!(sc->sc_flags & SC_TBUSY) && sc->sc_togo == NULL
-           && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head))
-           ppp_outpkt(sc);
-       for (;;) {
-           s = splimp();
-           IF_DEQUEUE(&sc->sc_rawq, m);
-           splx(s);
-           if (m == NULL)
-               break;
-           ppp_inproc(sc, m);
-       }
-    }
-    splx(s);
-}
-
-/*
- * Grab another packet off a queue and apply VJ compression,
- * packet compression, address/control and/or protocol compression
- * if enabled.  Should be called at splnet.
+ * Get a packet to send.  This procedure is intended to be called at
+ * splnet, since it may involve time-consuming operations such as
+ * applying VJ compression, packet compression, address/control and/or
+ * protocol field compression to the packet.
  */
-static void
-ppp_outpkt(sc)
+struct mbuf *
+ppp_dequeue(sc)
     struct ppp_softc *sc;
 {
-    int s;
     struct mbuf *m, *mp;
     u_char *cp;
     int address, control, protocol;
-    enum NPmode mode;
+    int s;
 
     /*
      * Grab a packet to send: first try the fast queue, then the
@@ -836,7 +812,9 @@ ppp_outpkt(sc)
     if (m == NULL)
        IF_DEQUEUE(&sc->sc_if.if_snd, m);
     if (m == NULL)
-       return;
+       return NULL;
+
+    ++sc->sc_stats.ppp_opackets;
 
     /*
      * Extract the ppp header of the new packet.
@@ -849,16 +827,11 @@ ppp_outpkt(sc)
 
     switch (protocol) {
     case PPP_IP:
-       /*
-        * Update the time we sent the most recent packet.
-        */
-       sc->sc_last_sent = time.tv_sec;
-
 #ifdef VJC
        /*
         * If the packet is a TCP/IP packet, see if we can compress it.
         */
-       if (sc->sc_flags & SC_COMP_TCP) {
+       if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) {
            struct ip *ip;
            int type;
 
@@ -872,7 +845,7 @@ ppp_outpkt(sc)
            }
            /* this code assumes the IP/TCP header is in one non-shared mbuf */
            if (ip->ip_p == IPPROTO_TCP) {
-               type = vj_compress_tcp(mp, ip, &sc->sc_comp,
+               type = vj_compress_tcp(mp, ip, sc->sc_comp,
                                       !(sc->sc_flags & SC_NO_TCP_CCID));
                switch (type) {
                case TYPE_UNCOMPRESSED_TCP:
@@ -940,8 +913,39 @@ ppp_outpkt(sc)
        --m->m_len;
     }
 
-    sc->sc_togo = m;
-    (*sc->sc_start)(sc);
+    return m;
+}
+
+/*
+ * Software interrupt routine, called at splnet.
+ */
+void
+pppintr()
+{
+    struct ppp_softc *sc;
+    int i, s, s2;
+    struct mbuf *m;
+
+    sc = ppp_softc;
+    s = splnet();
+    for (i = 0; i < NPPP; ++i, ++sc) {
+       if (!(sc->sc_flags & SC_TBUSY)
+           && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head)) {
+           s2 = splimp();
+           sc->sc_flags |= SC_TBUSY;
+           splx(s2);
+           (*sc->sc_start)(sc);
+       }
+       for (;;) {
+           s2 = splimp();
+           IF_DEQUEUE(&sc->sc_rawq, m);
+           splx(s2);
+           if (m == NULL)
+               break;
+           ppp_inproc(sc, m);
+       }
+    }
+    splx(s);
 }
 
 #ifdef PPP_COMPRESS
@@ -949,7 +953,7 @@ ppp_outpkt(sc)
  * Handle a CCP packet.  `rcvd' is 1 if the packet was received,
  * 0 if it is about to be transmitted.
  */
-static int
+static void
 ppp_ccp(sc, m, rcvd)
     struct ppp_softc *sc;
     struct mbuf *m;
@@ -978,7 +982,7 @@ ppp_ccp(sc, m, rcvd)
     slen = CCP_LENGTH(dp);
     if (dp + slen > ep) {
        if (sc->sc_flags & SC_DEBUG)
-           printf("if_ppp/ccp: not enough data in mbuf (%x+%x > %x+%x)\n",
+           printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n",
                   dp, slen, mtod(mp, u_char *), mp->m_len);
        return;
     }
@@ -1094,6 +1098,7 @@ ppp_inproc(sc, m)
     struct ppp_softc *sc;
     struct mbuf *m;
 {
+    struct ifnet *ifp = &sc->sc_if;
     struct ifqueue *inq;
     int s, ilen, xlen, proto, rv;
     u_char *cp, adrs, ctrl;
@@ -1101,13 +1106,13 @@ ppp_inproc(sc, m)
     u_char *iphdr;
     u_int hlen;
 
-    sc->sc_if.if_ipackets++;
+    sc->sc_stats.ppp_ipackets++;
 
     if (sc->sc_flags & SC_LOG_INPKT) {
        ilen = 0;
        for (mp = m; mp != NULL; mp = mp->m_next)
            ilen += mp->m_len;
-       printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen);
+       printf("ppp%d: got %d bytes\n", ifp->if_unit, ilen);
        pppdumpm(m);
     }
 
@@ -1149,7 +1154,7 @@ ppp_inproc(sc, m)
             * CCP down or issue a Reset-Req.
             */
            if (sc->sc_flags & SC_DEBUG)
-               printf("ppp%d: decompress failed %d\n", sc->sc_if.if_unit, rv);
+               printf("ppp%d: decompress failed %d\n", ifp->if_unit, rv);
            s = splimp();
            sc->sc_flags |= SC_VJ_RESET;
            if (rv == DECOMP_ERROR)
@@ -1179,7 +1184,8 @@ ppp_inproc(sc, m)
         * If we've missed a packet, we must toss subsequent compressed
         * packets which don't have an explicit connection ID.
         */
-       vj_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);
+       if (sc->sc_comp)
+           vj_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp);
        s = splimp();
        sc->sc_flags &= ~SC_VJ_RESET;
        splx(s);
@@ -1189,17 +1195,17 @@ ppp_inproc(sc, m)
      * See if we have a VJ-compressed packet to uncompress.
      */
     if (proto == PPP_VJC_COMP) {
-       if (sc->sc_flags & SC_REJ_COMP_TCP)
+       if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
            goto bad;
 
        xlen = vj_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
                                      ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP,
-                                     &sc->sc_comp, &iphdr, &hlen);
+                                     sc->sc_comp, &iphdr, &hlen);
 
        if (xlen <= 0) {
            if (sc->sc_flags & SC_DEBUG)
                printf("ppp%d: VJ uncompress failed on type comp\n",
-                       sc->sc_if.if_unit);
+                       ifp->if_unit);
            goto bad;
        }
 
@@ -1241,17 +1247,17 @@ ppp_inproc(sc, m)
        ilen += hlen - xlen;
 
     } else if (proto == PPP_VJC_UNCOMP) {
-       if (sc->sc_flags & SC_REJ_COMP_TCP)
+       if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
            goto bad;
 
        xlen = vj_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
                                      ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP,
-                                     &sc->sc_comp, &iphdr, &hlen);
+                                     sc->sc_comp, &iphdr, &hlen);
 
        if (xlen < 0) {
            if (sc->sc_flags & SC_DEBUG)
                printf("ppp%d: VJ uncompress failed on type uncomp\n",
-                       sc->sc_if.if_unit);
+                       ifp->if_unit);
            goto bad;
        }
 
@@ -1274,7 +1280,14 @@ ppp_inproc(sc, m)
        }
     }
     m->m_pkthdr.len = ilen;
-    m->m_pkthdr.rcvif = &sc->sc_if;
+    m->m_pkthdr.rcvif = ifp;
+
+    /*
+     * Record the time that we received this packet.
+     */
+    if ((proto & 0x8000) == 0) {
+       sc->sc_last_recv = time.tv_sec;
+    }
 
 #if NBPFILTER > 0
     /* See if bpf wants to look at the packet. */
@@ -1289,7 +1302,7 @@ ppp_inproc(sc, m)
        /*
         * IP packet - take off the ppp header and pass it up to IP.
         */
-       if ((sc->sc_if.if_flags & IFF_UP) == 0
+       if ((ifp->if_flags & IFF_UP) == 0
            || sc->sc_npmode[NP_IP] != NPMODE_PASS) {
            /* interface is down - drop the packet. */
            m_freem(m);
@@ -1300,7 +1313,6 @@ ppp_inproc(sc, m)
        m->m_len -= PPP_HDRLEN;
        schednetisr(NETISR_IP);
        inq = &ipintrq;
-       sc->sc_last_recv = time.tv_sec; /* update time of last pkt rcvd */
        break;
 #endif
 
@@ -1321,12 +1333,15 @@ ppp_inproc(sc, m)
        IF_DROP(inq);
        splx(s);
        if (sc->sc_flags & SC_DEBUG)
-           printf("ppp%d: input queue full\n", sc->sc_if.if_unit);
-       sc->sc_if.if_iqdrops++;
+           printf("ppp%d: input queue full\n", ifp->if_unit);
+       ifp->if_iqdrops++;
        goto bad;
     }
     IF_ENQUEUE(inq, m);
     splx(s);
+    ifp->if_ipackets++;
+    ifp->if_ibytes += ilen;
+    ifp->if_lastchange = time;
 
     if (rv)
        (*sc->sc_ctlp)(sc);
@@ -1336,6 +1351,7 @@ ppp_inproc(sc, m)
  bad:
     m_freem(m);
     sc->sc_if.if_ierrors++;
+    sc->sc_stats.ppp_ierrors++;
 }
 
 #define MAX_DUMP_BYTES 128
index 196e54bb7462f7a9abeabe0eee6f1b1ccead72c4..4673334b5c10e3e19723a4435d84ed4e0270be51 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: if_pppvar.h,v 1.1 1994/12/15 22:28:09 paulus Exp $ */
+/*     $Id: if_pppvar.h,v 1.2 1996/07/01 01:00:28 paulus Exp $ */
 /*
  * if_pppvar.h - private structures and declarations for PPP.
  *
@@ -66,11 +66,7 @@ struct ppp_softc {
        struct  mbuf *sc_togo;          /* output packet ready to go */
        struct  mbuf *sc_npqueue;       /* output packets not to be sent yet */
        struct  mbuf **sc_npqtail;      /* ptr to last next ptr in npqueue */
-#ifdef VJC
-       struct  vjcompress sc_comp;     /* vjc control buffer */
-#endif
-       u_int   sc_bytessent;           /* count of octets sent */
-       u_int   sc_bytesrcvd;           /* count of octets received */
+       struct  pppstat sc_stats;       /* count of bytes/pkts sent/rcvd */
        caddr_t sc_bpf;                 /* hook for BPF */
        enum    NPmode sc_npmode[NUM_NP]; /* what to do with each NP */
        struct  compressor *sc_xcomp;   /* transmit compressor */
@@ -79,7 +75,10 @@ struct ppp_softc {
        void    *sc_rc_state;           /* receive decompressor state */
        time_t  sc_last_sent;           /* time (secs) last NP pkt sent */
        time_t  sc_last_recv;           /* time (secs) last NP pkt rcvd */
-       
+#ifdef VJC
+       struct  slcompress *sc_comp;    /* vjc control buffer */
+#endif
+
        /* Device-dependent part for async lines. */
        ext_accm sc_asyncmap;           /* async control character map */
        u_long  sc_rasyncmap;           /* receive async control char map */
@@ -98,7 +97,8 @@ struct        ppp_softc ppp_softc[NPPP];
 
 struct ppp_softc *pppalloc __P((pid_t pid));
 void   pppdealloc __P((struct ppp_softc *sc));
-int    pppioctl __P((struct ppp_softc *sc, int cmd, caddr_t data,
+int    pppioctl __P((struct ppp_softc *sc, u_long cmd, caddr_t data,
                      int flag, struct proc *p));
+void   ppp_restart __P((struct ppp_softc *sc));
 void   ppppktin __P((struct ppp_softc *sc, struct mbuf *m, int lost));
 struct mbuf *ppp_dequeue __P((struct ppp_softc *sc));
index 727390229607739faea40f8fc876109ac3c01a61..bb0d88a9e424567be363c9b720fce557e03e6e24 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 # This script modifies the kernel sources in /sys to install
-# ppp-2.2.  It is intended to be run in the ppp-2.2 directory.
+# ppp-2.3.  It is intended to be run in the ppp-2.3 directory.
 #
 # Paul Mackerras       17-Mar-95
 
@@ -17,14 +17,13 @@ CONFIG=config
 # Copy new versions of files into /sys/net
 
 for f in net/if_ppp.h net/ppp-comp.h net/ppp_defs.h $SRC/bsd-comp.c \
-        $SRC/if_ppp.c $SRC/if_pppvar.h $SRC/ppp_tty.c \
-        $SRC/pppcompress.c $SRC/pppcompress.h; do
+        $SRC/ppp-deflate.c $SRC/if_ppp.c $SRC/if_pppvar.h $SRC/ppp_tty.c \
+        $SRC/pppcompress.c $SRC/pppcompress.h common/zlib.c common/zlib.h; do
   dest=$SYS/net/$(basename $f)
   if [ -f $dest ]; then
     if ! cmp -s $f $dest; then
       echo "Copying $f to $dest"
-      mv -f $dest $dest.orig
-      echo " (old version saved in $dest.orig)"
+      mv -f $dest $dest.orig && echo " (old version saved in $dest.orig)"
       cp $f $dest
       DOMAKE=yes
     fi
@@ -41,9 +40,11 @@ if [ -f $SYS/conf/files ]; then
   if ! grep -q ppp_tty $SYS/conf/files; then
     echo "Patching $SYS/conf/files"
     patch -p -N -d $SYS/conf <$SRC/files.patch
-    if [ $CONFIG = config ]; then
-      DOCONF=yes
-    fi
+    DOCONF=yes
+  elif ! grep -q ppp-deflate $SYS/conf/files; then
+    echo "Patching $SYS/conf/files"
+    patch -N $SYS/conf/$OLDFILES <$SRC/files-2.2.patch
+    DOCONF=yes
   fi
 fi
 
diff --git a/freebsd-2.0/ppp-deflate.c b/freebsd-2.0/ppp-deflate.c
new file mode 100644 (file)
index 0000000..2ba1c35
--- /dev/null
@@ -0,0 +1,653 @@
+/*     $Id: ppp-deflate.c,v 1.1 1996/07/01 01:00:30 paulus Exp $       */
+
+/*
+ * ppp_deflate.c - interface the zlib procedures for Deflate compression
+ * and decompression (as used by gzip) to the PPP code.
+ * This version is for use with mbufs on BSD-derived systems.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <net/ppp_defs.h>
+#include <net/zlib.h>
+
+#define PACKETPTR      struct mbuf *
+#include <net/ppp-comp.h>
+
+#if DO_DEFLATE
+
+/*
+ * State for a Deflate (de)compressor.
+ */
+struct deflate_state {
+    int                seqno;
+    int                w_size;
+    int                unit;
+    int                hdrlen;
+    int                mru;
+    int                debug;
+    z_stream   strm;
+    struct compstat stats;
+};
+
+#define DEFLATE_OVHD   2               /* Deflate overhead/packet */
+
+static void    *zalloc __P((void *, u_int items, u_int size));
+static void    zfree __P((void *, void *ptr, u_int nb));
+static void    *z_comp_alloc __P((u_char *options, int opt_len));
+static void    *z_decomp_alloc __P((u_char *options, int opt_len));
+static void    z_comp_free __P((void *state));
+static void    z_decomp_free __P((void *state));
+static int     z_comp_init __P((void *state, u_char *options, int opt_len,
+                                int unit, int hdrlen, int debug));
+static int     z_decomp_init __P((void *state, u_char *options, int opt_len,
+                                    int unit, int hdrlen, int mru, int debug));
+static int     z_compress __P((void *state, struct mbuf **mret,
+                                 struct mbuf *mp, int slen, int maxolen));
+static void    z_incomp __P((void *state, struct mbuf *dmsg));
+static int     z_decompress __P((void *state, struct mbuf *cmp,
+                                   struct mbuf **dmpp));
+static void    z_comp_reset __P((void *state));
+static void    z_decomp_reset __P((void *state));
+static void    z_comp_stats __P((void *state, struct compstat *stats));
+
+/*
+ * Procedures exported to if_ppp.c.
+ */
+struct compressor ppp_deflate = {
+    CI_DEFLATE,                        /* compress_proto */
+    z_comp_alloc,              /* comp_alloc */
+    z_comp_free,               /* comp_free */
+    z_comp_init,               /* comp_init */
+    z_comp_reset,              /* comp_reset */
+    z_compress,                        /* compress */
+    z_comp_stats,              /* comp_stat */
+    z_decomp_alloc,            /* decomp_alloc */
+    z_decomp_free,             /* decomp_free */
+    z_decomp_init,             /* decomp_init */
+    z_decomp_reset,            /* decomp_reset */
+    z_decompress,              /* decompress */
+    z_incomp,                  /* incomp */
+    z_comp_stats,              /* decomp_stat */
+};
+
+/*
+ * Space allocation and freeing routines for use by zlib routines.
+ */
+void *
+zalloc(notused, items, size)
+    void *notused;
+    u_int items, size;
+{
+    void *ptr;
+
+    MALLOC(ptr, void *, items * size, M_DEVBUF, M_NOWAIT);
+    return ptr;
+}
+
+void
+zfree(notused, ptr, nbytes)
+    void *notused;
+    void *ptr;
+    u_int nbytes;
+{
+    FREE(ptr, M_DEVBUF);
+}
+
+/*
+ * Allocate space for a compressor.
+ */
+static void *
+z_comp_alloc(options, opt_len)
+    u_char *options;
+    int opt_len;
+{
+    struct deflate_state *state;
+    int w_size;
+
+    if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return NULL;
+    w_size = DEFLATE_SIZE(options[2]);
+    if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+       return NULL;
+
+    MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
+          M_DEVBUF, M_NOWAIT);
+    if (state == NULL)
+       return NULL;
+
+    state->strm.next_in = NULL;
+    state->strm.zalloc = zalloc;
+    state->strm.zfree = zfree;
+    if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
+                    -w_size, 8, Z_DEFAULT_STRATEGY, DEFLATE_OVHD+2) != Z_OK) {
+       FREE(state, M_DEVBUF);
+       return NULL;
+    }
+
+    state->w_size = w_size;
+    bzero(&state->stats, sizeof(state->stats));
+    return (void *) state;
+}
+
+static void
+z_comp_free(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    deflateEnd(&state->strm);
+    FREE(state, M_DEVBUF);
+}
+
+static int
+z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
+    void *arg;
+    u_char *options;
+    int opt_len, unit, hdrlen, debug;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || DEFLATE_SIZE(options[2]) != state->w_size
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return 0;
+
+    state->seqno = 0;
+    state->unit = unit;
+    state->hdrlen = hdrlen;
+    state->debug = debug;
+
+    deflateReset(&state->strm);
+
+    return 1;
+}
+
+static void
+z_comp_reset(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    state->seqno = 0;
+    deflateReset(&state->strm);
+}
+
+int
+z_compress(arg, mret, mp, orig_len, maxolen)
+    void *arg;
+    struct mbuf **mret;                /* compressed packet (out) */
+    struct mbuf *mp;           /* uncompressed packet (in) */
+    int orig_len, maxolen;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    u_char *rptr, *wptr;
+    int proto, olen, wspace, r, flush;
+    struct mbuf *m;
+
+    /*
+     * Check that the protocol is in the range we handle.
+     */
+    rptr = mtod(mp, u_char *);
+    proto = PPP_PROTOCOL(rptr);
+    if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) {
+       *mret = NULL;
+       return orig_len;
+    }
+
+    /* Allocate one mbuf initially. */
+    if (maxolen > orig_len)
+       maxolen = orig_len;
+    MGET(m, M_DONTWAIT, MT_DATA);
+    *mret = m;
+    if (m != NULL) {
+       m->m_len = 0;
+       if (maxolen + state->hdrlen > MLEN)
+           MCLGET(m, M_DONTWAIT);
+       wspace = M_TRAILINGSPACE(m);
+       if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
+           m->m_data += state->hdrlen;
+           wspace -= state->hdrlen;
+       }
+       wptr = mtod(m, u_char *);
+
+       /*
+        * Copy over the PPP header and store the 2-byte sequence number.
+        */
+       wptr[0] = PPP_ADDRESS(rptr);
+       wptr[1] = PPP_CONTROL(rptr);
+       wptr[2] = PPP_COMP >> 8;
+       wptr[3] = PPP_COMP;
+       wptr += PPP_HDRLEN;
+       wptr[0] = state->seqno >> 8;
+       wptr[1] = state->seqno;
+       wptr += 2;
+       state->strm.next_out = wptr;
+       state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
+    } else {
+       state->strm.next_out = NULL;
+       state->strm.avail_out = 1000000;
+       wptr = NULL;
+       wspace = 0;
+    }
+    ++state->seqno;
+
+    rptr += (proto > 0xff)? 2: 3;      /* skip 1st proto byte if 0 */
+    state->strm.next_in = rptr;
+    state->strm.avail_in = mtod(mp, u_char *) + mp->m_len - rptr;
+    mp = mp->m_next;
+    flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
+    olen = 0;
+    for (;;) {
+       r = deflate(&state->strm, flush);
+       if (r != Z_OK) {
+           printf("z_compress: deflate returned %d (%s)\n",
+                  r, (state->strm.msg? state->strm.msg: ""));
+           break;
+       }
+       if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
+           break;              /* all done */
+       if (state->strm.avail_in == 0 && mp != NULL) {
+           state->strm.next_in = mtod(mp, u_char *);
+           state->strm.avail_in = mp->m_len;
+           mp = mp->m_next;
+           if (mp == NULL)
+               flush = Z_PACKET_FLUSH;
+       }
+       if (state->strm.avail_out == 0) {
+           if (m != NULL) {
+               m->m_len = wspace;
+               olen += wspace;
+               MGET(m->m_next, M_DONTWAIT, MT_DATA);
+               m = m->m_next;
+               if (m != NULL) {
+                   m->m_len = 0;
+                   if (maxolen - olen > MLEN)
+                       MCLGET(m, M_DONTWAIT);
+                   state->strm.next_out = mtod(m, u_char *);
+                   state->strm.avail_out = wspace = M_TRAILINGSPACE(m);
+               }
+           }
+           if (m == NULL) {
+               state->strm.next_out = NULL;
+               state->strm.avail_out = 1000000;
+           }
+       }
+    }
+    if (m != NULL)
+       olen += (m->m_len = wspace - state->strm.avail_out);
+
+    /*
+     * See if we managed to reduce the size of the packet.
+     * If the compressor just gave us a single zero byte, it means
+     * the packet was incompressible.
+     */
+    if (m != NULL && olen < orig_len
+       && !(olen == PPP_HDRLEN + 3 && *wptr == 0)) {
+       state->stats.comp_bytes += olen;
+       state->stats.comp_packets++;
+    } else {
+       if (*mret != NULL) {
+           m_freem(*mret);
+           *mret = NULL;
+       }
+       state->stats.inc_bytes += orig_len;
+       state->stats.inc_packets++;
+       olen = orig_len;
+    }
+    state->stats.unc_bytes += orig_len;
+    state->stats.unc_packets++;
+
+    return olen;
+}
+
+static void
+z_comp_stats(arg, stats)
+    void *arg;
+    struct compstat *stats;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    u_int out;
+
+    *stats = state->stats;
+    stats->ratio = stats->unc_bytes;
+    out = stats->comp_bytes + stats->inc_bytes;
+    if (stats->ratio <= 0x7ffffff)
+       stats->ratio <<= 8;
+    else
+       out >>= 8;
+    if (out != 0)
+       stats->ratio /= out;
+}
+
+/*
+ * Allocate space for a decompressor.
+ */
+static void *
+z_decomp_alloc(options, opt_len)
+    u_char *options;
+    int opt_len;
+{
+    struct deflate_state *state;
+    int w_size;
+
+    if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return NULL;
+    w_size = DEFLATE_SIZE(options[2]);
+    if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+       return NULL;
+
+    MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
+          M_DEVBUF, M_NOWAIT);
+    if (state == NULL)
+       return NULL;
+
+    state->strm.next_out = NULL;
+    state->strm.zalloc = zalloc;
+    state->strm.zfree = zfree;
+    if (inflateInit2(&state->strm, -w_size) != Z_OK) {
+       FREE(state, M_DEVBUF);
+       return NULL;
+    }
+
+    state->w_size = w_size;
+    bzero(&state->stats, sizeof(state->stats));
+    return (void *) state;
+}
+
+static void
+z_decomp_free(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    inflateEnd(&state->strm);
+    FREE(state, M_DEVBUF);
+}
+
+static int
+z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
+    void *arg;
+    u_char *options;
+    int opt_len, unit, hdrlen, mru, debug;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || DEFLATE_SIZE(options[2]) != state->w_size
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return 0;
+
+    state->seqno = 0;
+    state->unit = unit;
+    state->hdrlen = hdrlen;
+    state->debug = debug;
+    state->mru = mru;
+
+    inflateReset(&state->strm);
+
+    return 1;
+}
+
+static void
+z_decomp_reset(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    state->seqno = 0;
+    inflateReset(&state->strm);
+}
+
+/*
+ * Decompress a Deflate-compressed packet.
+ *
+ * Because of patent problems, we return DECOMP_ERROR for errors
+ * found by inspecting the input data and for system problems, but
+ * DECOMP_FATALERROR for any errors which could possibly be said to
+ * be being detected "after" decompression.  For DECOMP_ERROR,
+ * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
+ * infringing a patent of Motorola's if we do, so we take CCP down
+ * instead.
+ *
+ * Given that the frame has the correct sequence number and a good FCS,
+ * errors such as invalid codes in the input most likely indicate a
+ * bug, so we return DECOMP_FATALERROR for them in order to turn off
+ * compression, even though they are detected by inspecting the input.
+ */
+int
+z_decompress(arg, mi, mop)
+    void *arg;
+    struct mbuf *mi, **mop;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    struct mbuf *mo, *mo_head;
+    u_char *rptr, *wptr;
+    int rlen, olen, ospace;
+    int seq, i, flush, r, decode_proto;
+    u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
+
+    *mop = NULL;
+    rptr = mtod(mi, u_char *);
+    rlen = mi->m_len;
+    for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
+       while (rlen <= 0) {
+           mi = mi->m_next;
+           if (mi == NULL)
+               return DECOMP_ERROR;
+           rptr = mtod(mi, u_char *);
+           rlen = mi->m_len;
+       }
+       hdr[i] = *rptr++;
+       --rlen;
+    }
+
+    /* Check the sequence number. */
+    seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
+    if (seq != state->seqno) {
+       if (state->debug)
+           printf("z_decompress%d: bad seq # %d, expected %d\n",
+                  state->unit, seq, state->seqno);
+       return DECOMP_ERROR;
+    }
+    ++state->seqno;
+
+    /* Allocate an output mbuf. */
+    MGETHDR(mo, M_DONTWAIT, MT_DATA);
+    if (mo == NULL)
+       return DECOMP_ERROR;
+    mo_head = mo;
+    mo->m_len = 0;
+    mo->m_next = NULL;
+    MCLGET(mo, M_DONTWAIT);
+    ospace = M_TRAILINGSPACE(mo);
+    if (state->hdrlen + PPP_HDRLEN < ospace) {
+       mo->m_data += state->hdrlen;
+       ospace -= state->hdrlen;
+    }
+
+    /*
+     * Fill in the first part of the PPP header.  The protocol field
+     * comes from the decompressed data.
+     */
+    wptr = mtod(mo, u_char *);
+    wptr[0] = PPP_ADDRESS(hdr);
+    wptr[1] = PPP_CONTROL(hdr);
+    wptr[2] = 0;
+
+    /*
+     * Set up to call inflate.  We set avail_out to 1 initially so we can
+     * look at the first byte of the output and decide whether we have
+     * a 1-byte or 2-byte protocol field.
+     */
+    state->strm.next_in = rptr;
+    state->strm.avail_in = rlen;
+    mi = mi->m_next;
+    flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
+    rlen += PPP_HDRLEN + DEFLATE_OVHD;
+    state->strm.next_out = wptr + 3;
+    state->strm.avail_out = 1;
+    decode_proto = 1;
+    olen = PPP_HDRLEN;
+
+    /*
+     * Call inflate, supplying more input or output as needed.
+     */
+    for (;;) {
+       r = inflate(&state->strm, flush);
+       if (r != Z_OK) {
+           if (state->debug)
+               printf("z_decompress%d: inflate returned %d (%s)\n",
+                      state->unit, r, (state->strm.msg? state->strm.msg: ""));
+           m_freem(mo_head);
+           return DECOMP_FATALERROR;
+       }
+       if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
+           break;              /* all done */
+       if (state->strm.avail_in == 0 && mi != NULL) {
+           state->strm.next_in = mtod(mi, u_char *);
+           state->strm.avail_in = mi->m_len;
+           rlen += mi->m_len;
+           mi = mi->m_next;
+           if (mi == NULL)
+               flush = Z_PACKET_FLUSH;
+       }
+       if (state->strm.avail_out == 0) {
+           if (decode_proto) {
+               state->strm.avail_out = ospace - PPP_HDRLEN;
+               if ((wptr[3] & 1) == 0) {
+                   /* 2-byte protocol field */
+                   wptr[2] = wptr[3];
+                   --state->strm.next_out;
+                   ++state->strm.avail_out;
+                   --olen;
+               }
+               decode_proto = 0;
+           } else {
+               mo->m_len = ospace;
+               olen += ospace;
+               MGET(mo->m_next, M_DONTWAIT, MT_DATA);
+               mo = mo->m_next;
+               if (mo == NULL) {
+                   m_freem(mo_head);
+                   return DECOMP_ERROR;
+               }
+               MCLGET(mo, M_DONTWAIT);
+               state->strm.next_out = mtod(mo, u_char *);
+               state->strm.avail_out = ospace = M_TRAILINGSPACE(mo);
+           }
+       }
+    }
+    if (decode_proto) {
+       m_freem(mo_head);
+       return DECOMP_ERROR;
+    }
+    olen += (mo->m_len = ospace - state->strm.avail_out);
+
+    state->stats.unc_bytes += olen;
+    state->stats.unc_packets++;
+    state->stats.comp_bytes += rlen;
+    state->stats.comp_packets++;
+
+    *mop = mo_head;
+    return DECOMP_OK;
+}
+
+/*
+ * Incompressible data has arrived - add it to the history.
+ */
+static void
+z_incomp(arg, mi)
+    void *arg;
+    struct mbuf *mi;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    u_char *rptr;
+    int rlen, proto, r;
+
+    /*
+     * Check that the protocol is one we handle.
+     */
+    rptr = mtod(mi, u_char *);
+    proto = PPP_PROTOCOL(rptr);
+    if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
+       return;
+
+    ++state->seqno;
+
+    /*
+     * Iterate through the mbufs, adding the characters in them
+     * to the decompressor's history.  For the first mbuf, we start
+     * at the either the 1st or 2nd byte of the protocol field,
+     * depending on whether the protocol value is compressible.
+     */
+    rlen = mi->m_len;
+    state->strm.next_in = rptr + 3;
+    state->strm.avail_in = rlen - 3;
+    if (proto > 0xff) {
+       --state->strm.next_in;
+       ++state->strm.avail_in;
+    }
+    for (;;) {
+       r = inflateIncomp(&state->strm);
+       if (r != Z_OK) {
+           /* gak! */
+           if (state->debug) {
+               printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
+                      state->unit, r, (state->strm.msg? state->strm.msg: ""));
+           }
+           return;
+       }
+       mi = mi->m_next;
+       if (mi == NULL)
+           break;
+       state->strm.next_in = mtod(mi, u_char *);
+       state->strm.avail_in = mi->m_len;
+       rlen += mi->m_len;
+    }
+
+    /*
+     * Update stats.
+     */
+    state->stats.inc_bytes += rlen;
+    state->stats.inc_packets++;
+    state->stats.unc_bytes += rlen;
+    state->stats.unc_packets++;
+}
+
+#endif /* DO_DEFLATE */
index 81ffe925b97f4a1e7c3252bf7aaacb66e930507d..01040de4748b2cc67e73aadb439b1e12da67af4e 100644 (file)
@@ -62,7 +62,7 @@
  * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
  * Cleaned up a lot of the mbuf-related code to fix bugs that
  * caused system crashes and packet corruption.  Changed pppstart
- * so that it doesn't just give up with a collision if the whole
+ * so that it doesn't just give up with a "collision" if the whole
  * packet doesn't fit in the output ring buffer.
  *
  * Added priority queueing for interactive IP packets, following
@@ -70,8 +70,9 @@
  * Paul Mackerras (paulus@cs.anu.edu.au).
  */
 
-/* $Id: ppp_tty.c,v 1.4 1995/10/27 03:34:44 paulus Exp $ */
+/* $Id: ppp_tty.c,v 1.5 1996/07/01 01:00:31 paulus Exp $ */
 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
+/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
 
 #include "ppp.h"
 #if NPPP > 0
@@ -149,6 +150,7 @@ static void ppplogchar __P((struct ppp_softc *, int));
 
 /* This is a FreeBSD-2.0 kernel. */
 #define CCOUNT(q)      ((q)->c_cc)
+#define PPP_LOWAT      100     /* Process more output when < LOWAT on queue */
 #define        PPP_HIWAT       400     /* Don't start a new packet if HIWAT on que */
 
 /*
@@ -181,9 +183,9 @@ pppopen(dev, tp)
 {
     struct proc *p = curproc;          /* XXX */
     register struct ppp_softc *sc;
-    int error, s, i;
+    int error, s;
 
-    if (error = suser(p->p_ucred, &p->p_acflag))
+    if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
        return (error);
 
     s = spltty();
@@ -217,6 +219,7 @@ pppopen(dev, tp)
     sc->sc_outm = NULL;
     pppgetm(sc);
     sc->sc_if.if_flags |= IFF_RUNNING;
+    sc->sc_if.if_baudrate = tp->t_ospeed;
 
     tp->t_sc = (caddr_t) sc;
     ttyflush(tp, FREAD | FWRITE);
@@ -237,7 +240,6 @@ pppclose(tp, flag)
     int flag;
 {
     register struct ppp_softc *sc;
-    struct mbuf *m;
     int s;
 
     s = spltty();
@@ -332,7 +334,7 @@ pppread(tp, uio, flag)
     splx(s);
 
     for (m = m0; m && uio->uio_resid; m = m->m_next)
-       if (error = uiomove(mtod(m, u_char *), m->m_len, uio))
+       if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
            break;
     m_freem(m0);
     return (error);
@@ -373,7 +375,7 @@ pppwrite(tp, uio, flag)
        len = M_TRAILINGSPACE(m);
        if (len > uio->uio_resid)
            len = uio->uio_resid;
-       if (error = uiomove(mtod(m, u_char *), len, uio)) {
+       if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
            m_freem(m0);
            return (error);
        }
@@ -409,7 +411,7 @@ ppptioctl(tp, cmd, data, flag, p)
     error = 0;
     switch (cmd) {
     case PPPIOCSASYNCMAP:
-       if (error = suser(p->p_ucred, &p->p_acflag))
+       if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
            break;
        sc->sc_asyncmap[0] = *(u_int *)data;
        break;
@@ -419,7 +421,7 @@ ppptioctl(tp, cmd, data, flag, p)
        break;
 
     case PPPIOCSRASYNCMAP:
-       if (error = suser(p->p_ucred, &p->p_acflag))
+       if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
            break;
        sc->sc_rasyncmap = *(u_int *)data;
        break;
@@ -429,7 +431,7 @@ ppptioctl(tp, cmd, data, flag, p)
        break;
 
     case PPPIOCSXASYNCMAP:
-       if (error = suser(p->p_ucred, &p->p_acflag))
+       if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
            break;
        s = spltty();
        bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
@@ -505,62 +507,20 @@ pppfcs(fcs, cp, len)
 }
 
 /*
- * This gets called from pppoutput when a new packet is
- * put on a queue, at splnet.
+ * This gets called at splnet from if_ppp.c at various times
+ * when there is data ready to be sent.
  */
 static void
 pppasyncstart(sc)
     register struct ppp_softc *sc;
 {
     register struct tty *tp = (struct tty *) sc->sc_devp;
-    int s;
-
-    s = spltty();
-    pppstart(tp);
-    splx(s);
-}
-
-/*
- * This gets called when a received packet is placed on
- * the inq, at splnet.
- */
-static void
-pppasyncctlp(sc)
-    struct ppp_softc *sc;
-{
-    struct tty *tp;
-    int s;
-
-    /* Put a placeholder byte in canq for ttselect()/ttnread(). */
-    s = spltty();
-    tp = (struct tty *) sc->sc_devp;
-    putc(0, &tp->t_canq);
-    ttwakeup(tp);
-    splx(s);
-}
-
-/*
- * Start output on async tty interface.  Get another datagram
- * to send from the interface queue and start sending it.
- * Called at spltty or higher.
- */
-int
-pppstart(tp)
-    register struct tty *tp;
-{
-    register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
     register struct mbuf *m;
     register int len;
     register u_char *start, *stop, *cp;
-    int n, s, ndone, done, idle;
+    int n, ndone, done, idle;
     struct mbuf *m2;
-
-    if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
-       || sc == NULL || tp != (struct tty *) sc->sc_devp) {
-       if (tp->t_oproc != NULL)
-           (*tp->t_oproc)(tp);
-       return 0;
-    }
+    int s;
 
     idle = 0;
     while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
@@ -585,12 +545,13 @@ pppstart(tp)
             * the line may have been idle for some time.
             */
            if (CCOUNT(&tp->t_outq) == 0) {
-               ++sc->sc_bytessent;
+               ++sc->sc_stats.ppp_obytes;
                (void) putc(PPP_FLAG, &tp->t_outq);
            }
 
            /* Calculate the FCS for the first mbuf's worth. */
            sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
+           sc->sc_if.if_lastchange = time;
        }
 
        for (;;) {
@@ -611,24 +572,27 @@ pppstart(tp)
                    ndone = n - b_to_q(start, n, &tp->t_outq);
                    len -= ndone;
                    start += ndone;
-                   sc->sc_bytessent += ndone;
+                   sc->sc_stats.ppp_obytes += ndone;
 
                    if (ndone < n)
                        break;  /* packet doesn't fit */
                }
                /*
                 * If there are characters left in the mbuf,
-                * the first one must be special..
+                * the first one must be special.
                 * Put it out in a different form.
                 */
                if (len) {
+                   s = spltty();
                    if (putc(PPP_ESCAPE, &tp->t_outq))
                        break;
                    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
                        (void) unputc(&tp->t_outq);
+                       splx(s);
                        break;
                    }
-                   sc->sc_bytessent += 2;
+                   splx(s);
+                   sc->sc_stats.ppp_obytes += 2;
                    start++;
                    len--;
                }
@@ -668,6 +632,7 @@ pppstart(tp)
                 * Try to output the FCS and flag.  If the bytes
                 * don't all fit, back out.
                 */
+               s = spltty();
                for (q = endseq; q < p; ++q)
                    if (putc(*q, &tp->t_outq)) {
                        done = 0;
@@ -675,7 +640,9 @@ pppstart(tp)
                            unputc(&tp->t_outq);
                        break;
                    }
-               sc->sc_bytessent += q - endseq;
+               splx(s);
+               if (done)
+                   sc->sc_stats.ppp_obytes += q - endseq;
            }
 
            if (!done) {
@@ -690,28 +657,24 @@ pppstart(tp)
            m = m2;
            if (m == NULL) {
                /* Finished a packet */
-               sc->sc_if.if_opackets++;
-               sc->sc_if.if_obytes = sc->sc_bytessent;
                break;
            }
            sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
        }
 
        /*
-        * Here we have either finished a packet (m == NULL)
-        * or filled up the output queue (m != NULL).
+        * If m == NULL, we have finished a packet.
+        * If m != NULL, we've either done as much work this time
+        * as we need to, or else we've filled up the output queue.
         */
        sc->sc_outm = m;
        if (m)
            break;
     }
 
-    /*
-     * Send anything that may be in the output queue.
-     * We are being called in lieu of ttstart and must do what it would.
-     */
-    if (tp->t_oproc != NULL)
-       (*tp->t_oproc)(tp);
+    /* Call pppstart to start output again if necessary. */
+    s = spltty();
+    pppstart(tp);
 
     /*
      * This timeout is needed for operation on a pseudo-tty,
@@ -723,6 +686,58 @@ pppstart(tp)
        sc->sc_flags |= SC_TIMEOUT;
     }
 
+    splx(s);
+}
+
+/*
+ * This gets called when a received packet is placed on
+ * the inq, at splnet.
+ */
+static void
+pppasyncctlp(sc)
+    struct ppp_softc *sc;
+{
+    struct tty *tp;
+    int s;
+
+    /* Put a placeholder byte in canq for ttselect()/ttnread(). */
+    s = spltty();
+    tp = (struct tty *) sc->sc_devp;
+    putc(0, &tp->t_canq);
+    ttwakeup(tp);
+    splx(s);
+}
+
+/*
+ * Start output on async tty interface.  If the transmit queue
+ * has drained sufficiently, arrange for pppasyncstart to be
+ * called later at splnet.
+ * Called at spltty or higher.
+ */
+int
+pppstart(tp)
+    register struct tty *tp;
+{
+    register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
+
+    /*
+     * If there is stuff in the output queue, send it now.
+     * We are being called in lieu of ttstart and must do what it would.
+     */
+    if (tp->t_oproc != NULL)
+       (*tp->t_oproc)(tp);
+
+    /*
+     * If the transmit queue has drained and the tty has not hung up
+     * or been disconnected from the ppp unit, then tell if_ppp.c that
+     * we need more output.
+     */
+    if (CCOUNT(&tp->t_outq) < PPP_LOWAT
+       && !((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
+       && sc != NULL && tp == (struct tty *) sc->sc_devp) {
+       ppp_restart(sc);
+    }
+
     return 0;
 }
 
@@ -752,9 +767,7 @@ pppgetm(sc)
 {
     struct mbuf *m, **mp;
     int len;
-    int s;
 
-    s = spltty();
     mp = &sc->sc_m;
     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
        if ((m = *mp) == NULL) {
@@ -767,7 +780,6 @@ pppgetm(sc)
        len -= M_DATASIZE(m);
        mp = &m->m_next;
     }
-    splx(s);
 }
 
 /*
@@ -791,9 +803,8 @@ pppinput(c, tp)
     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
        return 0;
 
-    s = spltty();              /* should be unnecessary */
     ++tk_nin;
-    ++sc->sc_bytesrcvd;
+    ++sc->sc_stats.ppp_ibytes;
 
     if (c & TTY_FE) {
        /* framing error or overrun on this char - abort packet */
@@ -804,15 +815,18 @@ pppinput(c, tp)
 
     c &= 0xff;
 
-    if (sc->sc_flags & SC_XONXOFF) {
-       if (c == XOFF) {
+    /*
+     * Handle software flow control of output.
+     */
+    if (tp->t_iflag & IXON) {
+       if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
            if ((tp->t_state & TS_TTSTOP) == 0) {
                tp->t_state |= TS_TTSTOP;
                (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
            }
            return 0;
        }
-       if (c == XON) {
+       if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
            tp->t_state &= ~TS_TTSTOP;
            if (tp->t_oproc != NULL)
                (*tp->t_oproc)(tp);
@@ -820,6 +834,7 @@ pppinput(c, tp)
        }
     }
 
+    s = spltty();
     if (c & 0x80)
        sc->sc_flags |= SC_RCV_B7_1;
     else
@@ -828,6 +843,7 @@ pppinput(c, tp)
        sc->sc_flags |= SC_RCV_ODDP;
     else
        sc->sc_flags |= SC_RCV_EVNP;
+    splx(s);
 
     if (sc->sc_flags & SC_LOG_RAWIN)
        ppplogchar(sc, c);
@@ -835,7 +851,6 @@ pppinput(c, tp)
     if (c == PPP_FLAG) {
        ilen = sc->sc_ilen;
        sc->sc_ilen = 0;
-       sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
 
        if (sc->sc_rawin_count > 0) 
            ppplogchar(sc, -1);
@@ -845,13 +860,15 @@ pppinput(c, tp)
         * abort sequence "}~".
         */
        if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
-           || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
+           || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
+           s = spltty();
            sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
            if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
                if (sc->sc_flags & SC_DEBUG)
-                   printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
-                          sc->sc_fcs);
+                   printf("ppp%d: bad fcs %x, pkt len %d\n",
+                          sc->sc_if.if_unit, sc->sc_fcs, ilen);
                sc->sc_if.if_ierrors++;
+               sc->sc_stats.ppp_ierrors++;
            } else
                sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
            splx(s);
@@ -862,10 +879,12 @@ pppinput(c, tp)
            if (ilen) {
                if (sc->sc_flags & SC_DEBUG)
                    printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
+               s = spltty();
                sc->sc_if.if_ierrors++;
+               sc->sc_stats.ppp_ierrors++;
                sc->sc_flags |= SC_PKTLOST;
+               splx(s);
            }
-           splx(s);
            return 0;
        }
 
@@ -886,25 +905,26 @@ pppinput(c, tp)
        sc->sc_mc->m_next = NULL;
 
        ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
-       sc->sc_flags &= ~SC_PKTLOST;
+       if (sc->sc_flags & SC_PKTLOST) {
+           s = spltty();
+           sc->sc_flags &= ~SC_PKTLOST;
+           splx(s);
+       }
 
        pppgetm(sc);
-       splx(s);
        return 0;
     }
 
     if (sc->sc_flags & SC_FLUSH) {
        if (sc->sc_flags & SC_LOG_FLUSH)
            ppplogchar(sc, c);
-       splx(s);
        return 0;
     }
 
-    if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
-       splx(s);
+    if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
        return 0;
-    }
 
+    s = spltty();
     if (sc->sc_flags & SC_ESCAPED) {
        sc->sc_flags &= ~SC_ESCAPED;
        c ^= PPP_TRANS;
@@ -913,6 +933,7 @@ pppinput(c, tp)
        splx(s);
        return 0;
     }
+    splx(s);
 
     /*
      * Initialize buffer on first octet received.
@@ -998,17 +1019,18 @@ pppinput(c, tp)
     ++m->m_len;
     *sc->sc_mp++ = c;
     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
-    splx(s);
     return 0;
 
  flush:
     if (!(sc->sc_flags & SC_FLUSH)) {
+       s = spltty();
        sc->sc_if.if_ierrors++;
+       sc->sc_stats.ppp_ierrors++;
        sc->sc_flags |= SC_FLUSH;
+       splx(s);
        if (sc->sc_flags & SC_LOG_FLUSH)
            ppplogchar(sc, c);
     }
-    splx(s);
     return 0;
 }
 
@@ -1022,7 +1044,7 @@ ppplogchar(sc, c)
     if (c >= 0)
        sc->sc_rawin[sc->sc_rawin_count++] = c;
     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
-       || c < 0 && sc->sc_rawin_count > 0) {
+       || (c < 0 && sc->sc_rawin_count > 0)) {
        printf("ppp%d input: ", sc->sc_if.if_unit);
        pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
        sc->sc_rawin_count = 0;