]> git.ozlabs.org Git - ppp.git/blobdiff - modules/ppp.c
describe new options, don't describe obsolete ones
[ppp.git] / modules / ppp.c
index b3d78a336c1694cafecedd0007dbe9283e9b61c0..97c40ddef5e407a28ee61901f99cb2a8ae62fe7f 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
- * 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,
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ppp.c,v 1.1 1995/12/11 05:06:40 paulus Exp $
+ * $Id: ppp.c,v 1.4 1996/04/04 02:45:29 paulus Exp $
  */
 
 /*
- * This file is used under Solaris 2 and SunOS 4.
+ * This file is used under Solaris 2, SVR4, and SunOS 4.
  */
 
 #include <sys/types.h>
@@ -38,6 +38,7 @@
 #include <sys/stropts.h>
 #include <sys/errno.h>
 #include <sys/ioccom.h>
+#include <sys/time.h>
 #ifdef SVR4
 #include <sys/cmn_err.h>
 #include <sys/conf.h>
@@ -57,6 +58,7 @@
 #endif /* SVR4 */
 #include <net/ppp_defs.h>
 #include <net/pppio.h>
+#include <net/bpf.h>
 #include "ppp_mod.h"
 
 #ifdef __STDC__
@@ -66,7 +68,7 @@
 #endif
 
 /*
- * The IP module uses this SAP value for IP packets.
+ * The IP module may use this SAP value for IP packets.
  */
 #ifndef ETHERTYPE_IP
 #define ETHERTYPE_IP   0x800
@@ -76,6 +78,8 @@
 #define PPP_MAXMTU     65535
 #endif
 
+extern time_t time;
+
 /*
  * Private information; one per upper stream.
  */
@@ -90,6 +94,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 */
+    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.
@@ -100,6 +105,10 @@ typedef struct upperstr {
     int mru;
     int mtu;
     struct pppstat stats;      /* statistics */
+    time_t last_sent;          /* time last NP packet sent */
+    time_t last_recv;          /* time last NP packet rcvd */
+    struct bpf_program active_f;/* filter for active packets */
+    struct bpf_program pass_f; /* filter for packets to pass */
 #ifdef SOL2
     kstat_t *kstats;           /* stats for netstat */
 #endif /* SOL2 */
@@ -282,6 +291,8 @@ pppopen(q, dev, oflag, sflag)
     up->ifflags = IFF_UP | IFF_POINTOPOINT;
 #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));
@@ -370,6 +381,15 @@ pppclose(q, flag)
        kstat_delete(up->kstats);
 #endif
 
+    if (up->active_f.bf_insns) {
+       kmem_free(up->active_f.bf_insns, up->active_f.bf_len);
+       up->active_f.bf_insns = 0;
+    }
+    if (up->pass_f.bf_insns) {
+       kmem_free(up->pass_f.bf_insns, up->pass_f.bf_len);
+       up->pass_f.bf_insns = 0;
+    }
+
     q->q_ptr = NULL;
     WR(q)->q_ptr = NULL;
 
@@ -396,7 +416,7 @@ pppuwput(q, 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
@@ -404,8 +424,12 @@ pppuwput(q, mp)
     int i;
 #endif
     queue_t *lq;
-    int error, n;
+    int error, n, sap;
     mblk_t *mq;
+    struct ppp_idle *pip;
+    int len;
+    struct bpf_insn *ip;
+    struct bpf_program *dest;
 
     us = (upperstr_t *) q->q_ptr;
     switch (mp->b_datap->db_type) {
@@ -429,6 +453,12 @@ pppuwput(q, mp)
            freemsg(mp);
            break;
        }
+#ifdef NO_DLPI
+       if (!pass_packet(us->ppa, mp, 1)) {
+           freemsg(mp);
+           break;
+       }
+#endif
        if (!send_data(mp, us))
            putq(q, mp);
        break;
@@ -598,6 +628,75 @@ pppuwput(q, mp)
            }
            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)
+               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;
+           mq = allocb(sizeof(struct ppp_idle), BPRI_HI);
+           if (mq == 0) {
+               error = ENOSR;
+               break;
+           }
+           if (mp->b_cont != 0)
+               freemsg(mp->b_cont);
+           mp->b_cont = mq;
+           mq->b_cont = 0;
+           pip = (struct ppp_idle *) mq->b_wptr;
+           pip->xmit_idle = time - ppa->last_sent;
+           pip->recv_idle = time - ppa->last_recv;
+           mq->b_wptr += sizeof(struct ppp_idle);
+           iop->ioc_count = sizeof(struct ppp_idle);
+           error = 0;
+           break;
+
+       case PPPIO_PASSFILT:
+       case PPPIO_ACTIVEFILT:
+           if ((us->flags & US_CONTROL) == 0)
+               break;
+           len = iop->ioc_count;
+           if (len > BPF_MAXINSNS * sizeof(struct bpf_insn)
+               || len % sizeof(struct bpf_insn) != 0)
+               break;
+           if (len > 0) {
+               if (!bpf_validate((struct bpf_insn *) mp->b_cont->b_rptr,
+                                 len / sizeof(struct bpf_insn)))
+                   break;
+               ip = (struct bpf_insn *) ALLOC_NOSLEEP(len);
+               if (ip == 0) {
+                   error = ENOSR;
+                   break;
+               }
+               bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)ip, len);
+           } else
+               ip = 0;
+           dest = iop->ioc_cmd == PPPIO_ACTIVEFILT?
+               &us->active_f: &us->pass_f;
+           if (dest->bf_insns != 0)
+               kmem_free((caddr_t) dest->bf_insns, dest->bf_len);
+           dest->bf_len = len;
+           dest->bf_insns = ip;
+           break;
+
 #ifdef LACHTCP
        case SIOCSIFNAME:
            printf("SIOCSIFNAME\n");
@@ -840,9 +939,7 @@ 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;
-#if DEBUG
-       cmn_err(CE_CONT, "ppp bind %x\n", sap);
-#endif
+       DPRINT1("ppp bind %x\n", sap);
        if (sap == ETHERTYPE_IP)
            sap = PPP_IP;
        if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
@@ -886,7 +983,7 @@ dlpi_request(q, mp, us)
        }
        us->sap = -1;
        us->state = DL_UNBOUND;
-#ifndef sun
+#ifdef LACHTCP
        us->ppa->ifstats.ifs_active = 0;
 #endif
        dlpi_ok(q, DL_UNBIND_REQ);
@@ -899,15 +996,13 @@ dlpi_request(q, mp, us)
            dlpi_error(q, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
            break;
        }
-       if (us->ppa == 0) {
+       if ((ppa = us->ppa) == 0) {
            cmn_err(CE_CONT, "ppp: in state dl_idle but ppa == 0?\n");
            break;
        }
        len = mp->b_cont == 0? 0: msgdsize(mp->b_cont);
-       if (len > us->ppa->mtu) {
-#if DEBUG
-           cmn_err(CE_CONT, "dlpi data too large (%d > %d)\n", len, us->mtu);
-#endif
+       if (len > ppa->mtu) {
+           DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);
            break;
        }
        /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
@@ -928,8 +1023,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;
-       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
@@ -1020,6 +1119,33 @@ dlpi_ok(q, prim)
 }
 #endif /* NO_DLPI */
 
+static int
+pass_packet(ppa, mp, outbound)
+    upperstr_t *ppa;
+    mblk_t *mp;
+    int outbound;
+{
+    int len, adr, pass;
+
+    if (PPP_PROTOCOL(mp->b_rptr) >= 0x8000
+       || (ppa->pass_f.bf_insns == 0 && ppa->active_f.bf_insns == 0))
+       return 1;
+    len = msgdsize(mp);
+    adr = *mp->b_rptr;
+    *mp->b_rptr = outbound;
+    pass = ppa->pass_f.bf_insns == 0
+       || bpf_filter(ppa->pass_f.bf_insns, mp, len, 0);
+    if (pass && (ppa->active_f.bf_insns == 0
+                || bpf_filter(ppa->active_f.bf_insns, mp, len, 0))) {
+       if (outbound)
+           ppa->last_sent = time;
+       else
+           ppa->last_recv = time;
+    }
+    *mp->b_rptr = adr;
+    return pass;
+}
+
 static int
 send_data(mp, us)
     mblk_t *mp;
@@ -1028,10 +1154,10 @@ send_data(mp, us)
     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;
-    if (ppa == 0) {
+    if (ppa == 0 || us->npmode == NPMODE_DROP || us->npmode == NPMODE_ERROR) {
        freemsg(mp);
        return 1;
     }
@@ -1083,6 +1209,7 @@ new_ppa(q, mp)
     us->nextppa = *usp;
     *usp = us;
     us->flags |= US_CONTROL;
+    us->npmode = NPMODE_PASS;
 
     us->mtu = PPP_MRU;
     us->mru = PPP_MRU;
@@ -1392,6 +1519,10 @@ ppplrput(q, mp)
 #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) {
                /*