]> git.ozlabs.org Git - ppp.git/blobdiff - modules/ppp.c
fix counting bug
[ppp.git] / modules / ppp.c
index bbef69cf5e642bb90c2657da49555a96646cbbbe..3717afc59b75f1a4af20b212250dbd8923814164 100644 (file)
@@ -14,7 +14,7 @@
  * 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
  * 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 HAVE BEEN ADVISED OF THE POSSIBILITY
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  * OF SUCH DAMAGE.
  *
  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ppp.c,v 1.2 1995/12/18 03:57:27 paulus Exp $
+ * $Id: ppp.c,v 1.7 1996/08/28 06:35:30 paulus Exp $
  */
 
 /*
  */
 
 /*
- * This file is used under Solaris 2, SVR4, and SunOS 4.
+ * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
  */
 
 #include <sys/types.h>
  */
 
 #include <sys/types.h>
 #include <sys/stream.h>
 #include <sys/stropts.h>
 #include <sys/errno.h>
 #include <sys/stream.h>
 #include <sys/stropts.h>
 #include <sys/errno.h>
+#ifdef __osf__
+#include <sys/ioctl.h>
+#include <sys/cmn_err.h>
+#define queclass(mp)   ((mp)->b_band & QPCTL)
+#else
 #include <sys/ioccom.h>
 #include <sys/ioccom.h>
+#endif
 #include <sys/time.h>
 #ifdef SVR4
 #include <sys/cmn_err.h>
 #include <sys/time.h>
 #ifdef SVR4
 #include <sys/cmn_err.h>
@@ -93,6 +99,7 @@ typedef struct upperstr {
     struct upperstr *ppa;      /* control stream for our ppa */
     struct upperstr *next;     /* next stream for this ppa */
     uint ioc_id;               /* last ioctl ID for this stream */
     struct upperstr *ppa;      /* control stream for our ppa */
     struct upperstr *next;     /* next stream for this ppa */
     uint ioc_id;               /* last ioctl ID for this stream */
+    enum NPmode npmode;                /* what to do with packets on this SAP */
     /*
      * There is exactly one control stream for each PPA.
      * The following fields are only used for control streams.
     /*
      * There is exactly one control stream for each PPA.
      * The following fields are only used for control streams.
@@ -153,8 +160,9 @@ static upperstr_t *find_dest __P((upperstr_t *, int));
 static int putctl2 __P((queue_t *, int, int, int));
 static int putctl4 __P((queue_t *, int, int, int));
 
 static int putctl2 __P((queue_t *, int, int, int));
 static int putctl4 __P((queue_t *, int, int, int));
 
+#define PPP_ID 0xb1a6
 static struct module_info ppp_info = {
 static struct module_info ppp_info = {
-    0xb1a6, "ppp", 0, 512, 512, 128
+    PPP_ID, "ppp", 0, 512, 512, 128
 };
 
 static struct qinit pppurint = {
 };
 
 static struct qinit pppurint = {
@@ -288,6 +296,7 @@ pppopen(q, dev, oflag, sflag)
 #endif
     up->sap = -1;
     up->last_sent = up->last_recv = time;
 #endif
     up->sap = -1;
     up->last_sent = up->last_recv = time;
+    up->npmode = NPMODE_DROP;
     q->q_ptr = (caddr_t) up;
     WR(q)->q_ptr = (caddr_t) up;
     noenable(WR(q));
     q->q_ptr = (caddr_t) up;
     WR(q)->q_ptr = (caddr_t) up;
     noenable(WR(q));
@@ -385,7 +394,7 @@ pppclose(q, flag)
            break;
        }
     }
            break;
        }
     }
-    kmem_free(up, sizeof(upperstr_t));
+    FREE(up, sizeof(upperstr_t));
     --ppp_count;
 
     return 0;
     --ppp_count;
 
     return 0;
@@ -402,7 +411,7 @@ pppuwput(q, mp)
     queue_t *q;
     mblk_t *mp;
 {
     queue_t *q;
     mblk_t *mp;
 {
-    upperstr_t *us, *usnext, *ppa, *os;
+    upperstr_t *us, *usnext, *ppa, *os, *nps;
     struct iocblk *iop;
     struct linkblk *lb;
 #ifdef LACHTCP
     struct iocblk *iop;
     struct linkblk *lb;
 #ifdef LACHTCP
@@ -410,9 +419,10 @@ pppuwput(q, mp)
     int i;
 #endif
     queue_t *lq;
     int i;
 #endif
     queue_t *lq;
-    int error, n;
+    int error, n, sap;
     mblk_t *mq;
     struct ppp_idle *pip;
     mblk_t *mq;
     struct ppp_idle *pip;
+    int len;
 
     us = (upperstr_t *) q->q_ptr;
     switch (mp->b_datap->db_type) {
 
     us = (upperstr_t *) q->q_ptr;
     switch (mp->b_datap->db_type) {
@@ -437,8 +447,10 @@ pppuwput(q, mp)
            break;
        }
 #ifdef NO_DLPI
            break;
        }
 #ifdef NO_DLPI
-       if ((us->flags & US_CONTROL) == 0)
-           us->ppa->last_sent = time;
+       if (!pass_packet(us->ppa, mp, 1)) {
+           freemsg(mp);
+           break;
+       }
 #endif
        if (!send_data(mp, us))
            putq(q, mp);
 #endif
        if (!send_data(mp, us))
            putq(q, mp);
@@ -609,6 +621,30 @@ pppuwput(q, mp)
            }
            break;
 
            }
            break;
 
+       case PPPIO_NPMODE:
+           if (iop->ioc_count != 2 * sizeof(int))
+               break;
+           if ((us->flags & US_CONTROL) == 0)
+               break;
+           sap = ((int *)mp->b_cont->b_rptr)[0];
+           for (nps = us->next; nps != 0; nps = nps->next)
+               if (nps->sap == sap)
+                   break;
+           if (nps == 0) {
+               if (us->flags & US_DBGLOG)
+                   DPRINT2("ppp/%d: no stream for sap %x\n", us->mn, sap);
+               break;
+           }
+           nps->npmode = (enum NPmode) ((int *)mp->b_cont->b_rptr)[1];
+           if (nps->npmode == NPMODE_DROP || nps->npmode == NPMODE_ERROR)
+               flushq(WR(nps->q), FLUSHDATA);
+           else if (nps->npmode == NPMODE_PASS && qsize(WR(nps->q)) > 0
+                    && (nps->flags & US_BLOCKED) == 0)
+               qenable(WR(nps->q));
+           iop->ioc_count = 0;
+           error = 0;
+           break;
+
        case PPPIO_GIDLE:
            if ((ppa = us->ppa) == 0)
                break;
        case PPPIO_GIDLE:
            if ((ppa = us->ppa) == 0)
                break;
@@ -796,7 +832,7 @@ dlpi_request(q, mp, us)
     dl_bind_ack_t *ackp;
 
     if (us->flags & US_DBGLOG)
     dl_bind_ack_t *ackp;
 
     if (us->flags & US_DBGLOG)
-       cmn_err(CE_CONT, "ppp/%d: dlpi prim %x len=%d\n", us->mn,
+       DPRINT3("ppp/%d: dlpi prim %x len=%d\n", us->mn,
                d->dl_primitive, size);
     switch (d->dl_primitive) {
     case DL_INFO_REQ:
                d->dl_primitive, size);
     switch (d->dl_primitive) {
     case DL_INFO_REQ:
@@ -871,7 +907,6 @@ dlpi_request(q, mp, us)
           except that we accept ETHERTYPE_IP in place of PPP_IP. */
        sap = d->bind_req.dl_sap;
        us->req_sap = sap;
           except that we accept ETHERTYPE_IP in place of PPP_IP. */
        sap = d->bind_req.dl_sap;
        us->req_sap = sap;
-       DPRINT1("ppp bind %x\n", sap);
        if (sap == ETHERTYPE_IP)
            sap = PPP_IP;
        if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
        if (sap == ETHERTYPE_IP)
            sap = PPP_IP;
        if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
@@ -915,7 +950,7 @@ dlpi_request(q, mp, us)
        }
        us->sap = -1;
        us->state = DL_UNBOUND;
        }
        us->sap = -1;
        us->state = DL_UNBOUND;
-#ifndef sun
+#ifdef LACHTCP
        us->ppa->ifstats.ifs_active = 0;
 #endif
        dlpi_ok(q, DL_UNBIND_REQ);
        us->ppa->ifstats.ifs_active = 0;
 #endif
        dlpi_ok(q, DL_UNBIND_REQ);
@@ -937,7 +972,6 @@ dlpi_request(q, mp, us)
            DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);
            break;
        }
            DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);
            break;
        }
-       ppa->last_sent = time;
        /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
        if (mp->b_datap->db_ref > 1) {
            np = allocb(PPP_HDRLEN, BPRI_HI);
        /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
        if (mp->b_datap->db_ref > 1) {
            np = allocb(PPP_HDRLEN, BPRI_HI);
@@ -956,8 +990,12 @@ dlpi_request(q, mp, us)
        mp->b_rptr[1] = PPP_UI;
        mp->b_rptr[2] = us->sap >> 8;
        mp->b_rptr[3] = us->sap;
        mp->b_rptr[1] = PPP_UI;
        mp->b_rptr[2] = us->sap >> 8;
        mp->b_rptr[3] = us->sap;
-       if (!send_data(mp, us))
-           putq(q, mp);
+       if (!pass_packet(ppa, mp, 1)) {
+           freemsg(mp);
+       } else {
+           if (!send_data(mp, us))
+               putq(q, mp);
+       }
        return;
 
 #if DL_CURRENT_VERSION >= 2
        return;
 
 #if DL_CURRENT_VERSION >= 2
@@ -1048,6 +1086,23 @@ dlpi_ok(q, prim)
 }
 #endif /* NO_DLPI */
 
 }
 #endif /* NO_DLPI */
 
+static int
+pass_packet(ppa, mp, outbound)
+    upperstr_t *ppa;
+    mblk_t *mp;
+    int outbound;
+{
+    /*
+     * Here is where we might, in future, decide whether to pass
+     * or drop the packet, and whether it counts as link activity.
+     */
+    if (outbound)
+       ppa->last_sent = time;
+    else
+       ppa->last_recv = time;
+    return 1;
+}
+
 static int
 send_data(mp, us)
     mblk_t *mp;
 static int
 send_data(mp, us)
     mblk_t *mp;
@@ -1056,17 +1111,26 @@ send_data(mp, us)
     queue_t *q;
     upperstr_t *ppa;
 
     queue_t *q;
     upperstr_t *ppa;
 
-    if (us->flags & US_BLOCKED)
+    if ((us->flags & US_BLOCKED) || us->npmode == NPMODE_QUEUE)
        return 0;
     ppa = us->ppa;
        return 0;
     ppa = us->ppa;
-    if (ppa == 0) {
+    if (ppa == 0 || us->npmode == NPMODE_DROP || us->npmode == NPMODE_ERROR) {
+       if (us->flags & US_DBGLOG)
+           DPRINT2("ppp/%d: dropping pkt (npmode=%d)\n", us->mn, us->npmode);
        freemsg(mp);
        return 1;
     }
     if ((q = ppa->lowerq) == 0) {
        /* try to send it up the control stream */
        if (canputnext(ppa->q)) {
        freemsg(mp);
        return 1;
     }
     if ((q = ppa->lowerq) == 0) {
        /* try to send it up the control stream */
        if (canputnext(ppa->q)) {
-           putnext(ppa->q, mp);
+           /*
+            * The message seems to get corrupted for some reason if
+            * we just send the message up as it is, so we send a copy.
+            */
+           mblk_t *np = copymsg(mp);
+           freemsg(mp);
+           if (np != 0)
+               putnext(ppa->q, np);
            return 1;
        }
     } else {
            return 1;
        }
     } else {
@@ -1111,6 +1175,7 @@ new_ppa(q, mp)
     us->nextppa = *usp;
     *usp = us;
     us->flags |= US_CONTROL;
     us->nextppa = *usp;
     *usp = us;
     us->flags |= US_CONTROL;
+    us->npmode = NPMODE_PASS;
 
     us->mtu = PPP_MRU;
     us->mru = PPP_MRU;
 
     us->mtu = PPP_MRU;
     us->mru = PPP_MRU;
@@ -1405,6 +1470,22 @@ ppplrput(q, mp)
            putnext(us->q, mp);
        break;
 
            putnext(us->q, mp);
        break;
 
+    case M_HANGUP:
+       /*
+        * The serial device has hung up.  We don't want to send
+        * the M_HANGUP message up to pppd because that will stop
+        * us from using the control stream any more.  Instead we
+        * send a zero-length message as an end-of-file indication.
+        */
+       freemsg(mp);
+       mp = allocb(1, BPRI_HI);
+       if (mp == 0) {
+           DPRINT1("ppp/%d: couldn't allocate eof message!\n", ppa->mn);
+           break;
+       }
+       putnext(ppa->q, mp);
+       break;
+
     default:
        if (mp->b_datap->db_type == M_DATA) {
            len = msgdsize(mp);
     default:
        if (mp->b_datap->db_type == M_DATA) {
            len = msgdsize(mp);
@@ -1420,6 +1501,10 @@ ppplrput(q, mp)
 #ifdef INCR_IPACKETS
            INCR_IPACKETS(ppa);
 #endif
 #ifdef INCR_IPACKETS
            INCR_IPACKETS(ppa);
 #endif
+           if (!pass_packet(ppa, mp, 0)) {
+               freemsg(mp);
+               break;
+           }
            proto = PPP_PROTOCOL(mp->b_rptr);
            if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
                /*
            proto = PPP_PROTOCOL(mp->b_rptr);
            if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
                /*
@@ -1430,7 +1515,6 @@ ppplrput(q, mp)
                    putq(us->q, mp);
                else
                    putq(q, mp);
                    putq(us->q, mp);
                else
                    putq(q, mp);
-               ppa->last_recv = time;
                break;
            }
        }
                break;
            }
        }