]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet6/ip6_mroute.c
xnu-1699.22.81.tar.gz
[apple/xnu.git] / bsd / netinet6 / ip6_mroute.c
index 84e1a08ad4907466b7dd5c16e138f46d31c1a20b..39f14628426d8d84842995a02e51a2a55a31c077 100644 (file)
@@ -1,3 +1,30 @@
+/*
+ * Copyright (c) 2003-2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
 /*     $FreeBSD: src/sys/netinet6/ip6_mroute.c,v 1.16.2.1 2002/12/18 21:39:40 suz Exp $        */
 /*     $KAME: ip6_mroute.c,v 1.58 2001/12/18 02:36:31 itojun Exp $     */
 
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+/*
+ * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
+ * support for mandatory and extensible security protections.  This notice
+ * is included in support of clause 2.2 (b) of the Apple Public License,
+ * Version 2.0.
+ */
 
 /*     BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp     */
 
 #include <net/if.h>
 #include <net/route.h>
 #include <net/raw_cb.h>
+#include <net/dlil.h>
+#include <net/net_osdep.h>
 
 #include <netinet/in.h>
 #include <netinet/in_var.h>
 
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
+#include <netinet6/scope6_var.h>
 #include <netinet6/ip6_mroute.h>
+#include <netinet/icmp6.h>
 #include <netinet6/pim6.h>
 #include <netinet6/pim6_var.h>
 
+#if CONFIG_MACF_NET
+#include <security/mac.h>
+#endif /* MAC_NET */
+
 #ifndef __APPLE__
 static MALLOC_DEFINE(M_MRTABLE, "mf6c", "multicast forwarding cache entry");
 #endif
@@ -88,7 +129,6 @@ static int socket_send(struct socket *, struct mbuf *,
 static int register_send(struct ip6_hdr *, struct mif6 *,
                              struct mbuf *);
 
-extern lck_mtx_t *ip6_mutex;
 /*
  * Globals.  All but ip6_mrouter, ip6_mrtproto and mrt6stat could be static,
  * except for netstat or debugging purposes.
@@ -96,6 +136,9 @@ extern lck_mtx_t *ip6_mutex;
 struct socket  *ip6_mrouter  = NULL;
 int            ip6_mrouter_ver = 0;
 int            ip6_mrtproto = IPPROTO_PIM;    /* for netstat only */
+
+#if MROUTING
+
 struct mrt6stat        mrt6stat;
 
 #define NO_RTE_FOUND   0x1
@@ -204,21 +247,18 @@ static int pim6;
 
 #if UPCALL_TIMING
 #define UPCALL_MAX     50
-u_long upcall_data[UPCALL_MAX + 1];
+u_int32_t upcall_data[UPCALL_MAX + 1];
 static void collate();
 #endif /* UPCALL_TIMING */
 
 static int get_sg_cnt(struct sioc_sg_req6 *);
-static int get_mif6_cnt(struct sioc_mif_req6 *);
+static int get_mif6_cnt(void *, int);
 static int ip6_mrouter_init(struct socket *, int, int);
 static int add_m6if(struct mif6ctl *);
 static int del_m6if(mifi_t *);
 static int add_m6fc(struct mf6cctl *);
 static int del_m6fc(struct mf6cctl *);
 
-#ifndef __APPLE__
-static struct callout expire_upcalls_ch;
-#endif
 /*
  * Handle MRT setsockopt commands to modify the multicast routing tables.
  */
@@ -313,24 +353,25 @@ ip6_mrouter_get(so, sopt)
  * Handle ioctl commands to obtain information from the cache
  */
 int
-mrt6_ioctl(cmd, data)
-       int cmd;
-       caddr_t data;
+mrt6_ioctl(u_long cmd, caddr_t data)
 {
        int error = 0;
 
        switch (cmd) {
        case SIOCGETSGCNT_IN6:
-               return(get_sg_cnt((struct sioc_sg_req6 *)data));
-               break;          /* for safety */
-       case SIOCGETMIFCNT_IN6:
-               return(get_mif6_cnt((struct sioc_mif_req6 *)data));
-               break;          /* for safety */
+               return (get_sg_cnt((struct sioc_sg_req6 *)data));
+               /* NOTREACHED */
+
+       case SIOCGETMIFCNT_IN6_32:
+       case SIOCGETMIFCNT_IN6_64:
+               return (get_mif6_cnt(data, cmd == SIOCGETMIFCNT_IN6_64));
+               /* NOTREACHED */
+
        default:
-               return (EINVAL);
+               error = EINVAL;
                break;
        }
-       return error;
+       return (error);
 }
 
 /*
@@ -360,20 +401,34 @@ get_sg_cnt(req)
  * returns the input and output packet and byte counts on the mif provided
  */
 static int
-get_mif6_cnt(req)
-       struct sioc_mif_req6 *req;
+get_mif6_cnt(void *data, int p64)
 {
-       mifi_t mifi = req->mifi;
+       if (p64) {
+               struct sioc_mif_req6_64 *req = data;
 
-       if (mifi >= nummifs)
-               return EINVAL;
+               mifi_t mifi = req->mifi;
 
-       req->icount = mif6table[mifi].m6_pkt_in;
-       req->ocount = mif6table[mifi].m6_pkt_out;
-       req->ibytes = mif6table[mifi].m6_bytes_in;
-       req->obytes = mif6table[mifi].m6_bytes_out;
+               if (mifi >= nummifs)
+                       return (EINVAL);
 
-       return 0;
+               req->icount = mif6table[mifi].m6_pkt_in;
+               req->ocount = mif6table[mifi].m6_pkt_out;
+               req->ibytes = mif6table[mifi].m6_bytes_in;
+               req->obytes = mif6table[mifi].m6_bytes_out;
+       } else {
+               struct sioc_mif_req6_32 *req = data;
+
+               mifi_t mifi = req->mifi;
+
+               if (mifi >= nummifs)
+                       return (EINVAL);
+
+               req->icount = mif6table[mifi].m6_pkt_in;
+               req->ocount = mif6table[mifi].m6_pkt_out;
+               req->ibytes = mif6table[mifi].m6_bytes_in;
+               req->obytes = mif6table[mifi].m6_bytes_out;
+       }
+       return (0);
 }
 
 static int
@@ -421,12 +476,7 @@ ip6_mrouter_init(so, v, cmd)
 
        pim6 = 0;/* used for stubbing out/in pim stuff */
 
-#ifndef __APPLE__
-       callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
-           expire_upcalls, NULL);
-#else
        timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
-#endif
 
 #if MRT6DEBUG
        if (mrt6debug)
@@ -444,8 +494,6 @@ ip6_mrouter_done()
 {
        mifi_t mifi;
        int i;
-       struct ifnet *ifp;
-       struct in6_ifreq ifr;
        struct mf6c *rt;
        struct rtdetq *rte;
 
@@ -469,33 +517,28 @@ ip6_mrouter_done()
                for (mifi = 0; mifi < nummifs; mifi++) {
                        if (mif6table[mifi].m6_ifp &&
                            !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
-                               ifr.ifr_addr.sin6_family = AF_INET6;
-                               ifr.ifr_addr.sin6_addr= in6addr_any;
-                               ifp = mif6table[mifi].m6_ifp;
 #ifdef __APPLE__
-                               dlil_ioctl(0, ifp, SIOCDELMULTI,
-                                                (caddr_t)&ifr);
+                               if_allmulti(mif6table[mifi].m6_ifp, 0);
 #else
-                               (*ifp->if_ioctl)(ifp, SIOCDELMULTI,
-                                                (caddr_t)&ifr);
+                               {
+                                       struct ifnet *ifp;
+                                       struct in6_ifreq ifr;
+                       
+                                       ifr.ifr_addr.sin6_family = AF_INET6;
+                                       ifr.ifr_addr.sin6_addr= in6addr_any;
+                                       ifp = mif6table[mifi].m6_ifp;
+                                       ifnet_ioctl(ifp, 0, SIOCDELMULTI, &ifr);
+                               }
 #endif
                        }
                }
        }
-#if notyet
-       bzero((caddr_t)qtable, sizeof(qtable));
-       bzero((caddr_t)tbftable, sizeof(tbftable));
-#endif
        bzero((caddr_t)mif6table, sizeof(mif6table));
        nummifs = 0;
 
        pim6 = 0; /* used to stub out/in pim specific code */
 
-#ifndef __APPLE__
-       callout_stop(&expire_upcalls_ch);
-#else
        untimeout(expire_upcalls, (caddr_t)NULL);
-#endif
 
        /*
         * Free all multicast forwarding cache entries.
@@ -538,7 +581,8 @@ ip6_mrouter_done()
        return 0;
 }
 
-static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
+static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 ,
+                                     0, 0, IN6ADDR_ANY_INIT, 0};
 
 /*
  * Add a mif to the mif table
@@ -558,11 +602,21 @@ add_m6if(mifcp)
                return EINVAL;
        mifp = mif6table + mifcp->mif6c_mifi;
        if (mifp->m6_ifp)
-               return EADDRINUSE; /* XXX: is it appropriate? */
+               return (EADDRINUSE); /* XXX: is it appropriate? */
        if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > if_index)
+               return (ENXIO);
+
+       ifnet_head_lock_shared();
+       if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > if_index) {
+               ifnet_head_done();
                return ENXIO;
+       }
        ifp = ifindex2ifnet[mifcp->mif6c_pifi];
+       ifnet_head_done();
 
+       if (ifp == NULL) {
+               return ENXIO;
+       }
        if (mifcp->mif6c_flags & MIFF_REGISTER) {
                if (reg_mif_num == (mifi_t)-1) {
                        multicast_register_if.if_name = "register_mif";
@@ -586,10 +640,7 @@ add_m6if(mifcp)
 
        mifp->m6_flags     = mifcp->mif6c_flags;
        mifp->m6_ifp       = ifp;
-#if notyet
-       /* scaling up here allows division by 1024 in critical code */
-       mifp->m6_rate_limit = mifcp->mif6c_rate_limit * 1024 / 1000;
-#endif
+
        /* initialize per mif pkt counters */
        mifp->m6_pkt_in    = 0;
        mifp->m6_pkt_out   = 0;
@@ -638,10 +689,6 @@ del_m6if(mifip)
                if_allmulti(ifp, 0);
        }
 
-#if notyet
-       bzero((caddr_t)qtable[*mifip], sizeof(qtable[*mifip]));
-       bzero((caddr_t)mifp->m6_tbf, sizeof(*(mifp->m6_tbf)));
-#endif
        bzero((caddr_t)mifp, sizeof(*mifp));
 
        /* Adjust nummifs down */
@@ -667,10 +714,9 @@ add_m6fc(mfccp)
        struct mf6cctl *mfccp;
 {
        struct mf6c *rt;
-       u_long hash;
+       u_int32_t hash;
        struct rtdetq *rte;
        u_short nstl;
-       int s;
 
        MF6CFIND(mfccp->mf6cc_origin.sin6_addr,
                 mfccp->mf6cc_mcastgrp.sin6_addr, rt);
@@ -786,7 +832,6 @@ add_m6fc(mfccp)
                        rt = (struct mf6c *)_MALLOC(sizeof(*rt), M_MRTABLE,
                                                  M_NOWAIT);
                        if (rt == NULL) {
-                               splx(s);
                                return ENOBUFS;
                        }
        
@@ -818,9 +863,9 @@ static void
 collate(t)
        struct timeval *t;
 {
-       u_long d;
+       u_int32_t d;
        struct timeval tp;
-       u_long delta;
+       u_int32_t delta;
 
        GET_TIME(tp);
 
@@ -848,7 +893,7 @@ del_m6fc(mfccp)
        struct sockaddr_in6     mcastgrp;
        struct mf6c             *rt;
        struct mf6c             **nptr;
-       u_long          hash;
+       u_int32_t               hash;
 
        origin = mfccp->mf6cc_origin;
        mcastgrp = mfccp->mf6cc_mcastgrp;
@@ -923,7 +968,6 @@ ip6_mforward(ip6, ifp, m)
        struct mf6c *rt;
        struct mif6 *mifp;
        struct mbuf *mm;
-       int s;
        mifi_t mifi;
        struct timeval timenow;
 
@@ -969,12 +1013,10 @@ ip6_mforward(ip6, ifp, m)
        /*
         * Determine forwarding mifs from the forwarding cache table
         */
-       s = splnet();
        MF6CFIND(ip6->ip6_src, ip6->ip6_dst, rt);
 
        /* Entry exists, so forward if necessary */
        if (rt) {
-               splx(s);
                return (ip6_mdq(m, ifp, rt));
        } else {
                /*
@@ -985,7 +1027,7 @@ ip6_mforward(ip6, ifp, m)
 
                struct mbuf *mb0;
                struct rtdetq *rte;
-               u_long hash;
+               u_int32_t hash;
 /*             int i, npkts;*/
 #if UPCALL_TIMING
                struct timeval tp;
@@ -1008,7 +1050,6 @@ ip6_mforward(ip6, ifp, m)
                rte = (struct rtdetq *)_MALLOC(sizeof(*rte), M_MRTABLE,
                                              M_NOWAIT);
                if (rte == NULL) {
-                       splx(s);
                        return ENOBUFS;
                }
                mb0 = m_copy(m, 0, M_COPYALL);
@@ -1021,7 +1062,6 @@ ip6_mforward(ip6, ifp, m)
                        mb0 = m_pullup(mb0, sizeof(struct ip6_hdr));
                if (mb0 == NULL) {
                        FREE(rte, M_MRTABLE);
-                       splx(s);
                        return ENOBUFS;
                }
        
@@ -1048,7 +1088,6 @@ ip6_mforward(ip6, ifp, m)
                        if (rt == NULL) {
                                FREE(rte, M_MRTABLE);
                                m_freem(mb0);
-                               splx(s);
                                return ENOBUFS;
                        }
                        /*
@@ -1061,7 +1100,6 @@ ip6_mforward(ip6, ifp, m)
                                FREE(rte, M_MRTABLE);
                                m_freem(mb0);
                                FREE(rt, M_MRTABLE);
-                               splx(s);
                                return ENOBUFS;
                        }
 
@@ -1091,7 +1129,6 @@ ip6_mforward(ip6, ifp, m)
                                FREE(rte, M_MRTABLE);
                                m_freem(mb0);
                                FREE(rt, M_MRTABLE);
-                               splx(s);
                                return EINVAL;
                        }
 
@@ -1124,7 +1161,6 @@ ip6_mforward(ip6, ifp, m)
                                FREE(rte, M_MRTABLE);
                                m_freem(mb0);
                                FREE(rt, M_MRTABLE);
-                               splx(s);
                                return ENOBUFS;
                        }
 
@@ -1157,7 +1193,6 @@ ip6_mforward(ip6, ifp, m)
                                        mrt6stat.mrt6s_upq_ovflw++;
                                        FREE(rte, M_MRTABLE);
                                        m_freem(mb0);
-                                       splx(s);
                                        return 0;
                                }
 
@@ -1172,7 +1207,6 @@ ip6_mforward(ip6, ifp, m)
                rte->t = tp;
 #endif /* UPCALL_TIMING */
 
-               splx(s);
 
                return 0;
        }
@@ -1183,15 +1217,13 @@ ip6_mforward(ip6, ifp, m)
  * Call from the Slow Timeout mechanism, every half second.
  */
 static void
-expire_upcalls(unused)
-       void *unused;
+expire_upcalls(
+       __unused void *unused)
 {
        struct rtdetq *rte;
        struct mf6c *mfc, **nptr;
        int i;
-       int s;
 
-       s = splnet();
        for (i = 0; i < MF6CTBLSIZ; i++) {
                if (n6expire[i] == 0)
                        continue;
@@ -1232,14 +1264,8 @@ expire_upcalls(unused)
                        }
                }
        }
-       splx(s);
 
-#ifndef __APPLE__
-       callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
-           expire_upcalls, NULL);
-#else
        timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
-#endif
 }
 
 /*
@@ -1255,6 +1281,9 @@ ip6_mdq(m, ifp, rt)
        mifi_t mifi, iif;
        struct mif6 *mifp;
        int plen = m->m_pkthdr.len;
+       struct in6_addr src0, dst0; /* copies for local work */
+       u_int32_t iszone, idzone, oszone, odzone;
+       int error = 0;
 
 /*
  * Macro to send packet on mif.  Since RSVP packets don't get counted on
@@ -1298,8 +1327,8 @@ ip6_mdq(m, ifp, rt)
                                 * unnecessary PIM assert.
                                 * XXX: M_LOOP is an ad-hoc hack...
                                 */
-                               static struct sockaddr_in6 sin6 =
-                               { sizeof(sin6), AF_INET6 };
+                               static struct sockaddr_in6 addr =
+                               { sizeof(addr), AF_INET6 , 0, 0, IN6ADDR_ANY_INIT, 0};
 
                                struct mbuf *mm;
                                struct mrt6msg *im;
@@ -1347,18 +1376,18 @@ ip6_mdq(m, ifp, rt)
 #if MRT6_OINIT
                                case MRT6_OINIT:
                                        oim->im6_mif = iif;
-                                       sin6.sin6_addr = oim->im6_src;
+                                       addr.sin6_addr = oim->im6_src;
                                        break;
 #endif
                                case MRT6_INIT:
                                        im->im6_mif = iif;
-                                       sin6.sin6_addr = im->im6_src;
+                                       addr.sin6_addr = im->im6_src;
                                        break;
                                }
 
                                mrt6stat.mrt6s_upcalls++;
 
-                               if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
+                               if (socket_send(ip6_mrouter, mm, &addr) < 0) {
 #if MRT6DEBUG
                                        if (mrt6debug)
                                                log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n");
@@ -1386,7 +1415,14 @@ ip6_mdq(m, ifp, rt)
         * For each mif, forward a copy of the packet if there are group
         * members downstream on the interface.
         */
-       for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++)
+       src0 = ip6->ip6_src;
+       dst0 = ip6->ip6_dst;
+       if ((error = in6_setscope(&src0, ifp, &iszone)) != 0 ||
+           (error = in6_setscope(&dst0, ifp, &idzone)) != 0) {
+               ip6stat.ip6s_badscope++;
+               return (error);
+       }
+       for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) {
                if (IF_ISSET(mifi, &rt->mf6c_ifset)) {
                        /*
                         * check if the outgoing packet is going to break
@@ -1394,23 +1430,25 @@ ip6_mdq(m, ifp, rt)
                         * XXX For packets through PIM register tunnel
                         * interface, we believe a routing daemon.
                         */
-                       if ((mif6table[rt->mf6c_parent].m6_flags &
-                            MIFF_REGISTER) == 0 &&
-                           (mif6table[mifi].m6_flags & MIFF_REGISTER) == 0 &&
-                           (in6_addr2scopeid(ifp, &ip6->ip6_dst) !=
-                            in6_addr2scopeid(mif6table[mifi].m6_ifp,
-                                             &ip6->ip6_dst) ||
-                            in6_addr2scopeid(ifp, &ip6->ip6_src) !=
-                            in6_addr2scopeid(mif6table[mifi].m6_ifp,
-                                             &ip6->ip6_src))) {
-                               ip6stat.ip6s_badscope++;
-                               continue;
+                       if (!(mif6table[rt->mf6c_parent].m6_flags &
+                             MIFF_REGISTER) &&
+                           !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
+                               if (in6_setscope(&src0, mif6table[mifi].m6_ifp,
+                                   &oszone) ||
+                                   in6_setscope(&dst0, mif6table[mifi].m6_ifp,
+                                   &odzone) ||
+                                   iszone != oszone ||
+                                   idzone != odzone) {
+                                       ip6stat.ip6s_badscope++;
+                                       continue;
+                               }
                        }
 
                        mifp->m6_pkt_out++;
                        mifp->m6_bytes_out += plen;
                        MC6_SEND(ip6, mifp, m);
                }
+       }
        return 0;
 }
 
@@ -1423,7 +1461,6 @@ phyint_send(ip6, mifp, m)
        struct mbuf *mb_copy;
        struct ifnet *ifp = mifp->m6_ifp;
        int error = 0;
-       int s = splnet();       /* needs to protect static "ro" below. */
        static struct route_in6 ro;
        struct  in6_multi *in6m;
        struct sockaddr_in6 *dst6;
@@ -1438,7 +1475,6 @@ phyint_send(ip6, mifp, m)
            (M_HASCL(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr)))
                mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr));
        if (mb_copy == NULL) {
-               splx(s);
                return;
        }
        /* set MCAST flag to the outgoing packet */
@@ -1452,22 +1488,27 @@ phyint_send(ip6, mifp, m)
         * sending queue.
         */
        if (m->m_pkthdr.rcvif == NULL) {
-               struct ip6_moptions im6o;
+               struct ip6_moptions *im6o;
 
-               im6o.im6o_multicast_ifp = ifp;
-               /* XXX: ip6_output will override ip6->ip6_hlim */
-               im6o.im6o_multicast_hlim = ip6->ip6_hlim;
-               im6o.im6o_multicast_loop = 1;
-               error = ip6_output(mb_copy, NULL, &ro,
-                                  IPV6_FORWARDING, &im6o, NULL, 0);
+               im6o = ip6_allocmoptions(M_DONTWAIT);
+               if (im6o == NULL) {
+                       m_freem(mb_copy);
+                       return;
+               }
 
+               im6o->im6o_multicast_ifp = ifp;
+               /* XXX: ip6_output will override ip6->ip6_hlim */
+               im6o->im6o_multicast_hlim = ip6->ip6_hlim;
+               im6o->im6o_multicast_loop = 1;
+               error = ip6_output(mb_copy, NULL, &ro, IPV6_FORWARDING,
+                   im6o, NULL, NULL);
 
+               IM6O_REMREF(im6o);
 #if MRT6DEBUG
                if (mrt6debug & DEBUG_XMIT)
                        log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
                            mifp - mif6table, error);
 #endif
-               splx(s);
                return;
        }
 
@@ -1476,8 +1517,11 @@ phyint_send(ip6, mifp, m)
         * on the outgoing interface, loop back a copy.
         */
        dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
+       in6_multihead_lock_shared();
        IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
+       in6_multihead_lock_done();
        if (in6m != NULL) {
+               IN6M_REMREF(in6m);
                dst6->sin6_len = sizeof(struct sockaddr_in6);
                dst6->sin6_family = AF_INET6;
                dst6->sin6_addr = ip6->ip6_dst;
@@ -1502,10 +1546,8 @@ phyint_send(ip6, mifp, m)
                mb_copy->m_pkthdr.csum_data = 0;
                mb_copy->m_pkthdr.csum_flags = 0;
 
-               lck_mtx_unlock(ip6_mutex);
                error = dlil_output(ifp, PF_INET6, mb_copy,
                                NULL, (struct sockaddr *)&ro.ro_dst, 0);
-               lck_mtx_lock(ip6_mutex);
 #else
                error = (*ifp->if_output)(ifp, mb_copy,
                                          (struct sockaddr *)&ro.ro_dst,
@@ -1517,24 +1559,29 @@ phyint_send(ip6, mifp, m)
                            mifp - mif6table, error);
 #endif
        } else {
-#if MULTICAST_PMTUD
-               icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
-#else
+               /*
+                * pMTU discovery is intentionally disabled by default, since
+                * various router may notify pMTU in multicast, which can be
+                * a DDoS to a router
+                */
+               if (ip6_mcast_pmtu)
+                       icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
 #if MRT6DEBUG
-               if (mrt6debug & DEBUG_XMIT)
-                       log(LOG_DEBUG,
-                           "phyint_send: packet too big on %s o %s g %s"
-                           " size %d(discarded)\n",
-                           if_name(ifp),
-                           ip6_sprintf(&ip6->ip6_src),
-                           ip6_sprintf(&ip6->ip6_dst),
-                           mb_copy->m_pkthdr.len);
+               else {
+                       if (mrt6debug & DEBUG_XMIT) {
+                               log(LOG_DEBUG,
+                                   "phyint_send: packet too big on %s o %s "
+                                   "g %s size %d(discarded)\n",
+                                   if_name(ifp),
+                                   ip6_sprintf(&ip6->ip6_src),
+                                   ip6_sprintf(&ip6->ip6_dst),
+                                   mb_copy->m_pkthdr.len);
+                       }
+               }
 #endif /* MRT6DEBUG */
                m_freem(mb_copy); /* simply discard the packet */
-#endif
+               
        }
-
-       splx(s);
 }
 
 static int
@@ -1545,7 +1592,8 @@ register_send(ip6, mif, m)
 {
        struct mbuf *mm;
        int i, len = m->m_pkthdr.len;
-       static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
+       static struct sockaddr_in6 addr = { sizeof(addr), AF_INET6 ,
+                                     0, 0, IN6ADDR_ANY_INIT, 0};
        struct mrt6msg *im6;
 
 #if MRT6DEBUG
@@ -1559,6 +1607,11 @@ register_send(ip6, mif, m)
        MGETHDR(mm, M_DONTWAIT, MT_HEADER);
        if (mm == NULL)
                return ENOBUFS;
+#ifdef __darwin8_notyet
+#if CONFIG_MACF_NET
+       mac_create_mbuf_multicast_encap(m, mif->m6_ifp, mm);
+#endif
+#endif
        mm->m_pkthdr.rcvif = NULL;
        mm->m_data += max_linkhdr;
        mm->m_len = sizeof(struct ip6_hdr);
@@ -1581,7 +1634,7 @@ register_send(ip6, mif, m)
        /*
         * Send message to routing daemon
         */
-       sin6.sin6_addr = ip6->ip6_src;
+       addr.sin6_addr = ip6->ip6_src;
 
        im6 = mtod(mm, struct mrt6msg *);
        im6->im6_msgtype      = MRT6MSG_WHOLEPKT;
@@ -1592,7 +1645,7 @@ register_send(ip6, mif, m)
        /* iif info is not given for reg. encap.n */
        mrt6stat.mrt6s_upcalls++;
 
-       if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
+       if (socket_send(ip6_mrouter, mm, &addr) < 0) {
 #if MRT6DEBUG
                if (mrt6debug)
                        log(LOG_WARNING,
@@ -1612,9 +1665,7 @@ register_send(ip6, mif, m)
  * is stripped off, and the inner packet is passed to register_mforward.
  */
 int
-pim6_input(mp, offp)
-       struct mbuf **mp;
-       int *offp;
+pim6_input(struct mbuf **mp, int *offp, int proto)
 {
        struct pim *pim; /* pointer to a pim struct */
        struct ip6_hdr *ip6;
@@ -1622,13 +1673,11 @@ pim6_input(mp, offp)
        struct mbuf *m = *mp;
        int minlen;
        int off = *offp;
-       int proto;
 
        ++pim6stat.pim6s_rcv_total;
 
        ip6 = mtod(m, struct ip6_hdr *);
        pimlen = m->m_pkthdr.len - *offp;
-       proto = ip6->ip6_nxt;
 
        /*
         * Validate lengths
@@ -1717,12 +1766,12 @@ pim6_input(mp, offp)
                 * headers ip6+pim+u_int32_t+encap_ip6, to be passed up to the
                 * routing daemon.
                 */
-               static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 };
+               static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 , 
+                                                                                       0, 0, IN6ADDR_ANY_INIT, 0 };
 
                struct mbuf *mcp;
                struct ip6_hdr *eip6;
                u_int32_t *reghdr;
-               int rc;
        
                ++pim6stat.pim6s_rcv_registers;
 
@@ -1827,16 +1876,14 @@ pim6_input(mp, offp)
 #ifdef __APPLE__
 
                 if (lo_ifp) {
-                   lck_mtx_unlock(ip6_mutex);
                     dlil_output(lo_ifp, PF_INET6, m, 0, (struct sockaddr *)&dst, 0);
-                   lck_mtx_lock(ip6_mutex);
                }
                 else {
                     printf("Warning: pim6_input call to dlil_find_dltag failed!\n");
                     m_freem(m);
                 }
 #else
-               rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m,
+               (void) if_simloop(mif6table[reg_mif_num].m6_ifp, m,
                                dst.sin6_family, NULL);
 #endif
        
@@ -1854,3 +1901,4 @@ pim6_input(mp, offp)
        rip6_input(&m, offp);
        return(IPPROTO_DONE);
 }
+#endif