]> git.ozlabs.org Git - ppp.git/blobdiff - modules/ppp.c
Install Microsoft dictionaries (patch from Frank Cusack)
[ppp.git] / modules / ppp.c
index c99c1416c42d51caeec74df27546d40e5baf2d18..0ed435b9904404a888415698076fd640b14ea70f 100644 (file)
@@ -24,7 +24,7 @@
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ppp.c,v 1.16 1999/02/26 10:52:06 paulus Exp $
+ * $Id: ppp.c,v 1.25 1999/10/08 01:10:12 masputra Exp $
  */
 
 /*
@@ -54,6 +54,7 @@
 #include <sys/ksynch.h>
 #include <sys/kstat.h>
 #include <sys/sunddi.h>
+#include <sys/ethernet.h>
 #else
 #include <sys/socket.h>
 #include <sys/sockio.h>
  * interactive traffic, and are due to Marko Zec <zec@japa.tel.fer.hr>.
  */
 #ifdef PRIOQ
-#include <netinet/in.h>
 #endif /* PRIOQ */
 
+#include <netinet/in.h>        /* leave this outside of PRIOQ for htons */
+
 #ifdef __STDC__
 #define __P(x) x
 #else
 #define ETHERTYPE_IP   0x800
 #endif
 
+#if !defined(ETHERTYPE_IPV6) 
+#define ETHERTYPE_IPV6 0x86dd
+#endif /* !defined(ETHERTYPE_IPV6) */
+
+#if !defined(ETHERTYPE_ALLSAP) && defined(SOL2)
+#define ETHERTYPE_ALLSAP   0
+#endif /* !defined(ETHERTYPE_ALLSAP) && defined(SOL2) */
+
+#if !defined(PPP_ALLSAP) && defined(SOL2)
+#define PPP_ALLSAP  PPP_ALLSTATIONS
+#endif /* !defined(PPP_ALLSAP) && defined(SOL2) */
+
 extern time_t time;
 
 #ifdef SOL2
@@ -140,8 +154,8 @@ krwlock_t ppp_lower_lock;
 #define LOCK_LOWER_R   0
 #define TRYLOCK_LOWER_R        1
 #define UNLOCK_LOWER   0
-#define MUTEX_ENTER(x) 0
-#define MUTEX_EXIT(x)  0
+#define MT_ENTER(x)    0
+#define MT_EXIT(x)     0
 
 #endif /* SOL2 */
 
@@ -193,6 +207,12 @@ typedef struct upperstr {
 #define US_DBGLOG      0x10    /* log various occurrences */
 #define US_RBLOCKED    0x20    /* flow ctrl has blocked upper read stream */
 
+#if defined(SOL2)
+#if DL_CURRENT_VERSION >= 2
+#define US_PROMISC     0x40    /* stream is promiscuous */
+#endif /* DL_CURRENT_VERSION >= 2 */
+#define US_RAWDATA     0x80    /* raw M_DATA, no DLPI header */
+#endif /* defined(SOL2) */
 
 #ifdef PRIOQ
 static u_char max_band=0;
@@ -252,10 +272,18 @@ static void detach_ppa __P((queue_t *, mblk_t *));
 static void detach_lower __P((queue_t *, mblk_t *));
 static void debug_dump __P((queue_t *, mblk_t *));
 static upperstr_t *find_dest __P((upperstr_t *, int));
+#if defined(SOL2)
+static upperstr_t *find_promisc __P((upperstr_t *, int));
+static mblk_t *prepend_ether __P((upperstr_t *, mblk_t *, int));
+static mblk_t *prepend_udind __P((upperstr_t *, mblk_t *, int));
+static void promisc_sendup __P((upperstr_t *, mblk_t *, int, int));
+#endif /* defined(SOL2) */
 static int putctl2 __P((queue_t *, int, int, int));
 static int putctl4 __P((queue_t *, int, int, int));
 static int pass_packet __P((upperstr_t *ppa, mblk_t *mp, int outbound));
+#ifdef FILTER_PACKETS
 static int ip_hard_filter __P((upperstr_t *ppa, mblk_t *mp, int outbound));
+#endif /* FILTER_PACKETS */
 
 #define PPP_ID 0xb1a6
 static struct module_info ppp_info = {
@@ -468,7 +496,7 @@ pppclose(q, flag)
 #endif
        if (up->lowerq != 0) {
            /* Gack! the lower stream should have be unlinked earlier! */
-           cmn_err(CE_WARN, "ppp%d: lower stream still connected on close?\n",
+           DPRINT1("ppp%d: lower stream still connected on close?\n",
                    up->mn);
            LOCK_LOWER_W;
            up->lowerq->q_ptr = 0;
@@ -556,7 +584,7 @@ pppuwput(q, mp)
     queue_t *q;
     mblk_t *mp;
 {
-    upperstr_t *us, *usnext, *ppa, *os, *nps;
+    upperstr_t *us, *ppa, *nps;
     struct iocblk *iop;
     struct linkblk *lb;
 #ifdef LACHTCP
@@ -567,10 +595,12 @@ pppuwput(q, mp)
     int error, n, sap;
     mblk_t *mq;
     struct ppp_idle *pip;
-    int len;
 #ifdef PRIOQ
     queue_t *tlq;
 #endif /* PRIOQ */
+#ifdef NO_DLPI
+    upperstr_t *os;
+#endif
 
     us = (upperstr_t *) q->q_ptr;
     if (us == 0) {
@@ -621,6 +651,12 @@ pppuwput(q, mp)
            DPRINT3("ppp/%d: ioctl %x count=%d\n",
                    us->mn, iop->ioc_cmd, iop->ioc_count);
        switch (iop->ioc_cmd) {
+#if defined(SOL2)
+       case DLIOCRAW:      /* raw M_DATA mode */
+           us->flags |= US_RAWDATA;
+           error = 0;
+           break;
+#endif /* defined(SOL2) */
        case I_LINK:
            if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
                break;
@@ -809,7 +845,7 @@ pppuwput(q, mp)
            if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
                qwriter(q, NULL, debug_dump, PERIM_OUTER);
                iop->ioc_count = 0;
-               error = 0;
+               error = -1;
            } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) {
                DPRINT1("ppp/%d: debug log enabled\n", us->mn);
                us->flags |= US_DBGLOG;
@@ -833,9 +869,12 @@ pppuwput(q, mp)
                break;
            }
            sap = ((int *)mp->b_cont->b_rptr)[0];
-           for (nps = us->next; nps != 0; nps = nps->next)
+           for (nps = us->next; nps != 0; nps = nps->next) {
+               if (us->flags & US_DBGLOG)
+                   DPRINT2("us = 0x%x, us->next->sap = 0x%x\n", nps, nps->sap);
                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);
@@ -1042,9 +1081,13 @@ dlpi_request(q, mp, us)
     int size = mp->b_wptr - mp->b_rptr;
     mblk_t *reply, *np;
     upperstr_t *ppa, *os;
-    int sap, *ip, len;
+    int sap, len;
     dl_info_ack_t *info;
     dl_bind_ack_t *ackp;
+#if DL_CURRENT_VERSION >= 2
+    dl_phys_addr_ack_t *paddrack;
+    static struct ether_addr eaddr = {0};
+#endif
 
     if (us->flags & US_DBGLOG)
        DPRINT3("ppp/%d: dlpi prim %x len=%d\n", us->mn,
@@ -1063,15 +1106,7 @@ dlpi_request(q, mp, us)
        info->dl_max_sdu = us->ppa? us->ppa->mtu: PPP_MAXMTU;
        info->dl_min_sdu = 1;
        info->dl_addr_length = sizeof(uint);
-#if 0
-#ifdef DL_OTHER
-       info->dl_mac_type = DL_OTHER;
-#else
-       info->dl_mac_type = DL_HDLC;    /* a lie */
-#endif
-#else
        info->dl_mac_type = DL_ETHER;   /* a bigger lie */
-#endif
        info->dl_current_state = us->state;
        info->dl_service_mode = DL_CLDLS;
        info->dl_provider_style = DL_STYLE2;
@@ -1098,7 +1133,7 @@ dlpi_request(q, mp, us)
        }
        us->ppa = ppa;
        qwriter(q, mp, attach_ppa, PERIM_OUTER);
-       break;
+       return;
 
     case DL_DETACH_REQ:
        if (size < sizeof(dl_detach_req_t))
@@ -1108,7 +1143,7 @@ dlpi_request(q, mp, us)
            break;
        }
        qwriter(q, mp, detach_ppa, PERIM_OUTER);
-       break;
+       return;
 
     case DL_BIND_REQ:
        if (size < sizeof(dl_bind_req_t))
@@ -1129,12 +1164,30 @@ 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 defined(SOL2)
+       if (us->flags & US_DBGLOG)
+           DPRINT2("DL_BIND_REQ: ip gives sap = 0x%x, us = 0x%x", sap, us);
+
+       if (sap == ETHERTYPE_IP)            /* normal IFF_IPV4 */
+           sap = PPP_IP;
+       else if (sap == ETHERTYPE_IPV6)     /* when IFF_IPV6 is set */
+           sap = PPP_IPV6;
+       else if (sap == ETHERTYPE_ALLSAP)   /* snoop gives sap of 0 */
+           sap = PPP_ALLSAP;
+       else {
+           DPRINT2("DL_BIND_REQ: unrecognized sap = 0x%x, us = 0x%x", sap, us);
+           dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
+           break;
+       }
+#else
        if (sap == ETHERTYPE_IP)
            sap = PPP_IP;
        if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
            dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
            break;
        }
+#endif /* defined(SOL2) */
 
        /* check that no other stream is bound to this sap already. */
        for (os = us->ppa; os != 0; os = os->next)
@@ -1194,6 +1247,16 @@ dlpi_request(q, mp, us)
            DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);
            break;
        }
+
+#if defined(SOL2)
+       /*
+        * Should there be any promiscuous stream(s), send the data
+        * up for each promiscuous stream that we recognize.
+        */
+       if (mp->b_cont)
+           promisc_sendup(ppa, mp->b_cont, us->sap, 0);
+#endif /* defined(SOL2) */
+
        mp->b_band = 0;
 #ifdef PRIOQ
         /* Extract s_port & d_port from IP-packet, the code is a bit
@@ -1281,14 +1344,55 @@ dlpi_request(q, mp, us)
        return;
 
 #if DL_CURRENT_VERSION >= 2
+    case DL_PHYS_ADDR_REQ:
+       if (size < sizeof(dl_phys_addr_req_t))
+           goto badprim;
+
+       /*
+        * Don't check state because ifconfig sends this one down too
+        */
+
+       if ((reply = allocb(sizeof(dl_phys_addr_ack_t)+ETHERADDRL, 
+                       BPRI_HI)) == 0)
+           break;              /* should do bufcall */
+       reply->b_datap->db_type = M_PCPROTO;
+       paddrack = (dl_phys_addr_ack_t *) reply->b_wptr;
+       reply->b_wptr += sizeof(dl_phys_addr_ack_t);
+       bzero((caddr_t) paddrack, sizeof(dl_phys_addr_ack_t)+ETHERADDRL);
+       paddrack->dl_primitive = DL_PHYS_ADDR_ACK;
+       paddrack->dl_addr_length = ETHERADDRL;
+       paddrack->dl_addr_offset = sizeof(dl_phys_addr_ack_t);
+       bcopy(&eaddr, reply->b_wptr, ETHERADDRL);
+       reply->b_wptr += ETHERADDRL;
+       qreply(q, reply);
+       break;
+
+#if defined(SOL2)
+    case DL_PROMISCON_REQ:
+       if (size < sizeof(dl_promiscon_req_t))
+           goto badprim;
+       us->flags |= US_PROMISC;
+       dlpi_ok(q, DL_PROMISCON_REQ);
+       break;
+
+    case DL_PROMISCOFF_REQ:
+       if (size < sizeof(dl_promiscoff_req_t))
+           goto badprim;
+       us->flags &= ~US_PROMISC;
+       dlpi_ok(q, DL_PROMISCOFF_REQ);
+       break;
+#else
+    case DL_PROMISCON_REQ:         /* fall thru */
+    case DL_PROMISCOFF_REQ:        /* fall thru */
+#endif /* defined(SOL2) */
+#endif /* DL_CURRENT_VERSION >= 2 */
+
+#if DL_CURRENT_VERSION >= 2
+    case DL_SET_PHYS_ADDR_REQ:
     case DL_SUBS_BIND_REQ:
     case DL_SUBS_UNBIND_REQ:
     case DL_ENABMULTI_REQ:
     case DL_DISABMULTI_REQ:
-    case DL_PROMISCON_REQ:
-    case DL_PROMISCOFF_REQ:
-    case DL_PHYS_ADDR_REQ:
-    case DL_SET_PHYS_ADDR_REQ:
     case DL_XID_REQ:
     case DL_TEST_REQ:
     case DL_REPLY_UPDATE_REQ:
@@ -1423,7 +1527,6 @@ send_data(mp, us)
     mblk_t *mp;
     upperstr_t *us;
 {
-    queue_t *q;
     upperstr_t *ppa;
 
     if ((us->flags & US_BLOCKED) || us->npmode == NPMODE_QUEUE)
@@ -1435,7 +1538,7 @@ send_data(mp, us)
        freemsg(mp);
        return 1;
     }
-    if ((q = ppa->lowerq) == 0) {
+    if (ppa->lowerq == 0) {
        /* try to send it up the control stream */
         if (bcanputnext(ppa->q, mp->b_band)) {
            /*
@@ -1699,9 +1802,7 @@ pppurput(q, mp)
     mblk_t *mp;
 {
     upperstr_t *ppa, *us;
-    queue_t *uq;
     int proto, len;
-    mblk_t *np;
     struct iocblk *iop;
 
     ppa = (upperstr_t *) q->q_ptr;
@@ -1782,6 +1883,15 @@ pppurput(q, mp)
            MT_EXIT(&ppa->stats_lock);
 
            proto = PPP_PROTOCOL(mp->b_rptr);
+
+#if defined(SOL2)
+           /*
+            * Should there be any promiscuous stream(s), send the data
+            * up for each promiscuous stream that we recognize.
+            */
+           promisc_sendup(ppa, mp, proto, 1);
+#endif /* defined(SOL2) */
+
            if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
                /*
                 * A data packet for some network protocol.
@@ -1955,6 +2065,148 @@ find_dest(ppa, proto)
     return us;
 }
 
+#if defined (SOL2)
+/*
+ * Test upstream promiscuous conditions. As of now, only pass IPv4 and
+ * Ipv6 packets upstream (let PPP packets be decoded elsewhere).
+ */
+static upperstr_t *
+find_promisc(us, proto)
+    upperstr_t *us;
+    int proto;
+{
+
+    if ((proto != PPP_IP) && (proto != PPP_IPV6))
+       return (upperstr_t *)0;
+
+    for ( ; us; us = us->next) {
+       if ((us->flags & US_PROMISC) && (us->state == DL_IDLE))
+           return us;
+    }
+
+    return (upperstr_t *)0;
+}
+
+/*
+ * Prepend an empty Ethernet header to msg for snoop, et al.
+ */
+static mblk_t *
+prepend_ether(us, mp, proto)
+    upperstr_t *us;
+    mblk_t *mp;
+    int proto;
+{
+    mblk_t *eh;
+    int type;
+
+    if ((eh = allocb(sizeof(struct ether_header), BPRI_HI)) == 0) {
+       freemsg(mp);
+       return (mblk_t *)0;
+    }
+
+    if (proto == PPP_IP)
+       type = ETHERTYPE_IP;
+    else if (proto == PPP_IPV6)
+       type = ETHERTYPE_IPV6;
+    else 
+       type = proto;       /* What else? Let decoder decide */
+
+    eh->b_wptr += sizeof(struct ether_header);
+    bzero((caddr_t)eh->b_rptr, sizeof(struct ether_header));
+    ((struct ether_header *)eh->b_rptr)->ether_type = htons((short)type);
+    eh->b_cont = mp;
+    return (eh);
+}
+
+/*
+ * Prepend DL_UNITDATA_IND mblk to msg
+ */
+static mblk_t *
+prepend_udind(us, mp, proto)
+    upperstr_t *us;
+    mblk_t *mp;
+    int proto;
+{
+    dl_unitdata_ind_t *dlu;
+    mblk_t *dh;
+    size_t size;
+
+    size = sizeof(dl_unitdata_ind_t);
+    if ((dh = allocb(size, BPRI_MED)) == 0) {
+       freemsg(mp);
+       return (mblk_t *)0;
+    }
+
+    dh->b_datap->db_type = M_PROTO;
+    dh->b_wptr = dh->b_datap->db_lim;
+    dh->b_rptr = dh->b_wptr - size;
+
+    dlu = (dl_unitdata_ind_t *)dh->b_rptr;
+    dlu->dl_primitive = DL_UNITDATA_IND;
+    dlu->dl_dest_addr_length = 0;
+    dlu->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
+    dlu->dl_src_addr_length = 0;
+    dlu->dl_src_addr_offset = sizeof(dl_unitdata_ind_t);
+    dlu->dl_group_address = 0;
+
+    dh->b_cont = mp;
+    return (dh);
+}
+
+/*
+ * For any recognized promiscuous streams, send data upstream
+ */
+static void
+promisc_sendup(ppa, mp, proto, skip)
+    upperstr_t *ppa;
+    mblk_t *mp;
+    int proto, skip;
+{
+    mblk_t *dup_mp, *dup_dup_mp;
+    upperstr_t *prus, *nprus;
+
+    if ((prus = find_promisc(ppa, proto)) != 0) {
+       if (dup_mp = dupmsg(mp)) {
+
+           if (skip)
+               dup_mp->b_rptr += PPP_HDRLEN;
+
+           for ( ; nprus = find_promisc(prus->next, proto); 
+                   prus = nprus) {
+
+               if (dup_dup_mp = dupmsg(dup_mp)) {
+                   if (canputnext(prus->q)) {
+                       if (prus->flags & US_RAWDATA) {
+                           dup_dup_mp = prepend_ether(prus, dup_dup_mp, proto);
+                           putnext(prus->q, dup_dup_mp);
+                       } else {
+                           dup_dup_mp = prepend_udind(prus, dup_dup_mp, proto);
+                           putnext(prus->q, dup_dup_mp);
+                       }
+                   } else {
+                       DPRINT("ppp_urput: data to promisc q dropped\n");
+                       freemsg(dup_dup_mp);
+                   }
+               }
+           }
+
+           if (canputnext(prus->q)) {
+               if (prus->flags & US_RAWDATA) {
+                   dup_mp = prepend_ether(prus, dup_mp, proto);
+                   putnext(prus->q, dup_mp);
+               } else {
+                   dup_mp = prepend_udind(prus, dup_mp, proto);
+                   putnext(prus->q, dup_mp);
+               }
+           } else {
+               DPRINT("ppp_urput: data to promisc q dropped\n");
+               freemsg(dup_mp);
+           }
+       }
+    }
+}
+#endif /* defined(SOL2) */
+
 /*
  * We simply put the message on to the associated upper control stream
  * (either here or in ppplrsrv).  That way we enter the perimeters
@@ -1967,6 +2219,25 @@ ppplrput(q, mp)
     mblk_t *mp;
 {
     queue_t *uq;
+    struct iocblk *iop;
+
+    switch (mp->b_datap->db_type) {
+    case M_IOCTL:
+       iop = (struct iocblk *) mp->b_rptr;
+       iop->ioc_error = EINVAL;
+       mp->b_datap->db_type = M_IOCNAK;
+       qreply(q, mp);
+       return 0;
+    case M_FLUSH:
+       if (*mp->b_rptr & FLUSHR)
+           flushq(q, FLUSHDATA);
+       if (*mp->b_rptr & FLUSHW) {
+           *mp->b_rptr &= ~FLUSHR;
+           qreply(q, mp);
+       } else
+           freemsg(mp);
+       return 0;
+    }
 
     /*
      * If we can't get the lower lock straight away, queue this one
@@ -2073,8 +2344,8 @@ putctl4(q, type, code, val)
 
 static void
 debug_dump(q, mp)
-    queue_t *q;                        /* not used */
-    mblk_t *mp;                        /* not used either */
+    queue_t *q;
+    mblk_t *mp;
 {
     upperstr_t *us;
     queue_t *uq, *lq;
@@ -2100,6 +2371,8 @@ debug_dump(q, mp)
                    (lq? qsize(lq): 0), us->mru, us->mtu);
        }
     }
+    mp->b_datap->db_type = M_IOCACK;
+    qreply(q, mp);
 }
 
 #ifdef FILTER_PACKETS