]> git.ozlabs.org Git - ppp.git/blobdiff - solaris/ppp.c
pppd: Fix variable reference syntax in Makefile.linux
[ppp.git] / solaris / ppp.c
index 123ade1c17c3539890f2d8092af745a4c73a0176..676bc2644f1a88113d1a3c16f2b0408814ca6926 100644 (file)
@@ -1,30 +1,38 @@
 /*
  * ppp.c - STREAMS multiplexing pseudo-device driver for PPP.
  *
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
+ * Copyright (c) 1994 Paul Mackerras. 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
  *
- * 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.
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
  *
- * 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.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
  *
- * $Id: ppp.c,v 1.1 2000/04/18 23:51:28 masputra Exp $
+ * 3. The name(s) of the authors of this software must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission.
+ *
+ * 4. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by Paul Mackerras
+ *     <paulus@samba.org>".
+ *
+ * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ppp.c,v 1.4 2005/06/27 00:59:57 carlsonj Exp $
  */
 
 /*
@@ -268,7 +276,9 @@ static void dlpi_ok __P((queue_t *, int));
 static int send_data __P((mblk_t *, upperstr_t *));
 static void new_ppa __P((queue_t *, mblk_t *));
 static void attach_ppa __P((queue_t *, mblk_t *));
+#ifndef NO_DLPI
 static void detach_ppa __P((queue_t *, mblk_t *));
+#endif
 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));
@@ -637,11 +647,12 @@ pppuwput(q, mp)
            break;
        }
 #ifdef NO_DLPI
+       /* pass_packet frees the packet on returning 0 */
        if ((us->flags & US_CONTROL) == 0 && !pass_packet(us, mp, 1))
            break;
 #endif
-       if (!send_data(mp, us))
-           putq(q, mp);
+       if (!send_data(mp, us) && !putq(q, mp))
+           freemsg(mp);
        break;
 
     case M_IOCTL:
@@ -714,6 +725,7 @@ pppuwput(q, mp)
 #endif
            iop->ioc_count = 0;
            qwriter(q, mp, detach_lower, PERIM_OUTER);
+           /* mp is now gone */
            error = -1;
            break;
 
@@ -740,6 +752,7 @@ pppuwput(q, mp)
            iop->ioc_count = sizeof(int);
            mq->b_wptr = mq->b_rptr + sizeof(int);
            qwriter(q, mp, new_ppa, PERIM_OUTER);
+           /* mp is now gone */
            error = -1;
            break;
 
@@ -761,6 +774,7 @@ pppuwput(q, mp)
            us->ppa = ppa;
            iop->ioc_count = 0;
            qwriter(q, mp, attach_ppa, PERIM_OUTER);
+           /* mp is now gone */
            error = -1;
            break;
 
@@ -843,8 +857,8 @@ pppuwput(q, mp)
            }
            n = *(int *)mp->b_cont->b_rptr;
            if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
-               qwriter(q, NULL, debug_dump, PERIM_OUTER);
-               iop->ioc_count = 0;
+               qwriter(q, mp, debug_dump, PERIM_OUTER);
+               /* mp is now gone */
                error = -1;
            } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) {
                DPRINT1("ppp/%d: debug log enabled\n", us->mn);
@@ -855,6 +869,7 @@ pppuwput(q, mp)
                if (us->ppa == 0 || us->ppa->lowerq == 0)
                    break;
                putnext(us->ppa->lowerq, mp);
+               /* mp is now gone */
                error = -1;
            }
            break;
@@ -1002,7 +1017,8 @@ pppuwput(q, mp)
            ((union DL_primitives *)mq->b_rptr)->dl_primitive = DL_INFO_REQ;
            mq->b_wptr = mq->b_rptr + sizeof(dl_info_req_t);
            dlpi_request(q, mq, us);
-           error = 0;
+           /* mp is now gone */
+           error = -1;
            break;
 
        case SIOCGIFNETMASK:
@@ -1337,9 +1353,10 @@ dlpi_request(q, mp, us)
        mp->b_rptr[1] = PPP_UI;
        mp->b_rptr[2] = us->sap >> 8;
        mp->b_rptr[3] = us->sap;
+       /* pass_packet frees the packet on returning 0 */
        if (pass_packet(us, mp, 1)) {
-           if (!send_data(mp, us))
-               putq(q, mp);
+           if (!send_data(mp, us) && !putq(q, mp))
+               freemsg(mp);
        }
        return;
 
@@ -1422,7 +1439,8 @@ dlpi_request(q, mp, us)
 #endif
 
     default:
-       cmn_err(CE_CONT, "ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
+       if (us->flags & US_DBGLOG)
+           DPRINT1("ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
        /* fall through */
     badprim:
        dlpi_error(q, us, d->dl_primitive, DL_BADPRIM, 0);
@@ -1475,6 +1493,9 @@ dlpi_ok(q, prim)
 }
 #endif /* NO_DLPI */
 
+/*
+ * If return value is 0, then the packet has already been freed.
+ */
 static int
 pass_packet(us, mp, outbound)
     upperstr_t *us;
@@ -1667,9 +1688,11 @@ attach_ppa(q, mp)
 #ifndef NO_DLPI
        dlpi_ok(q, DL_ATTACH_REQ);
 #endif
+       freemsg(mp);
     }
 }
 
+#ifndef NO_DLPI
 static void
 detach_ppa(q, mp)
     queue_t *q;
@@ -1690,11 +1713,11 @@ detach_ppa(q, mp)
        }
     us->next = 0;
     us->ppa = 0;
-#ifndef NO_DLPI
     us->state = DL_UNATTACHED;
     dlpi_ok(q, DL_DETACH_REQ);
-#endif
+    freemsg(mp);
 }
+#endif
 
 /*
  * We call this with qwriter in order to give the upper queue procedures
@@ -1864,53 +1887,54 @@ pppurput(q, mp)
        putnext(ppa->q, mp);
        break;
 
-    default:
-       if (mp->b_datap->db_type == M_DATA) {
-           len = msgdsize(mp);
-           if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {
-               PULLUP(mp, PPP_HDRLEN);
-               if (mp == 0) {
-                   DPRINT1("ppp_urput: msgpullup failed (len=%d)\n", len);
-                   break;
-               }
+    case M_DATA:
+       len = msgdsize(mp);
+       if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {
+           PULLUP(mp, PPP_HDRLEN);
+           if (mp == 0) {
+               DPRINT1("ppp_urput: msgpullup failed (len=%d)\n", len);
+               break;
            }
-           MT_ENTER(&ppa->stats_lock);
-           ppa->stats.ppp_ipackets++;
-           ppa->stats.ppp_ibytes += len;
+       }
+       MT_ENTER(&ppa->stats_lock);
+       ppa->stats.ppp_ipackets++;
+       ppa->stats.ppp_ibytes += len;
 #ifdef INCR_IPACKETS
-           INCR_IPACKETS(ppa);
+       INCR_IPACKETS(ppa);
 #endif
-           MT_EXIT(&ppa->stats_lock);
+       MT_EXIT(&ppa->stats_lock);
 
-           proto = PPP_PROTOCOL(mp->b_rptr);
+       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);
+       /*
+        * 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.
-                * Queue it on the upper stream for that protocol.
-                * XXX could we just putnext it?  (would require thought)
-                * The rblocked flag is there to ensure that we keep
-                * messages in order for each network protocol.
-                */
-               if (!pass_packet(us, mp, 0))
-                   break;
-               if (!us->rblocked && !canput(us->q))
-                   us->rblocked = 1;
-               if (!us->rblocked)
-                   putq(us->q, mp);
-               else
-                   putq(q, mp);
+       if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
+           /*
+            * A data packet for some network protocol.
+            * Queue it on the upper stream for that protocol.
+            * XXX could we just putnext it?  (would require thought)
+            * The rblocked flag is there to ensure that we keep
+            * messages in order for each network protocol.
+            */
+           /* pass_packet frees the packet on returning 0 */
+           if (!pass_packet(us, mp, 0))
                break;
-           }
+           if (!us->rblocked && !canput(us->q))
+               us->rblocked = 1;
+           if (!putq(us->rblocked ? q : us->q, mp))
+               freemsg(mp);
+           break;
        }
+
+       /* FALLTHROUGH */
+
+   default:
        /*
         * A control frame, a frame for an unknown protocol,
         * or some other message type.
@@ -1918,8 +1942,8 @@ pppurput(q, mp)
         */
        if (queclass(mp) == QPCTL || canputnext(ppa->q))
            putnext(ppa->q, mp);
-       else
-           putq(q, mp);
+       else if (!putq(q, mp))
+           freemsg(mp);
        break;
     }
 
@@ -1971,7 +1995,8 @@ pppursrv(q)
            if (proto < 0x8000 && (as = find_dest(us, proto)) != 0) {
                if (!canput(as->q))
                    break;
-               putq(as->q, mp);
+               if (!putq(as->q, mp))
+                   freemsg(mp);
            } else {
                if (!canputnext(q))
                    break;
@@ -2178,11 +2203,12 @@ promisc_sendup(ppa, mp, proto, skip)
                    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);
                        }
+                       if (dup_dup_mp == 0)
+                           continue;
+                       putnext(prus->q, dup_dup_mp);
                    } else {
                        DPRINT("ppp_urput: data to promisc q dropped\n");
                        freemsg(dup_dup_mp);
@@ -2193,11 +2219,11 @@ promisc_sendup(ppa, mp, proto, skip)
            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);
                }
+               if (dup_mp != 0)
+                   putnext(prus->q, dup_mp);
            } else {
                DPRINT("ppp_urput: data to promisc q dropped\n");
                freemsg(dup_mp);
@@ -2244,7 +2270,8 @@ ppplrput(q, mp)
      * rather than blocking, to avoid the possibility of deadlock.
      */
     if (!TRYLOCK_LOWER_R) {
-       putq(q, mp);
+       if (!putq(q, mp))
+           freemsg(mp);
        return 0;
     }
 
@@ -2267,8 +2294,8 @@ ppplrput(q, mp)
      */
     if (queclass(mp) == QPCTL || (qsize(q) == 0 && canput(uq)))
        put(uq, mp);
-    else
-       putq(q, mp);
+    else if (!putq(q, mp))
+       freemsg(mp);
 
     UNLOCK_LOWER;
     return 0;
@@ -2402,6 +2429,9 @@ static struct pktfilt_tab {
 };
 
 
+/*
+ * Packet has already been freed if return value is 0.
+ */
 static int
 ip_hard_filter(us, mp, outbound)
     upperstr_t *us;
@@ -2475,7 +2505,10 @@ ip_hard_filter(us, mp, outbound)
                                us->mn, pft->proto, pft->port);
            /* Discard if not connected, or if not pass_with_link_up */
            /* else, if link is up let go by, but don't update time */
-           return pft->ok_if_link_up? -1: 0;
+           if (pft->ok_if_link_up)
+               return -1;
+           freemsg(mp);
+           return 0;
        }
         break;
     } /* end switch (proto) */