]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/igmp.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / bsd / netinet / igmp.c
index 073cf1ae293c774b93d499e6cf325e32d13f8915..004ccc9c7a9898c367894d5698e9a3ab1cd91b30 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  *
  *     @(#)igmp.c      8.1 (Berkeley) 7/19/93
  */
+/*
+ * 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.
+ */
 
 /*
  * Internet Group Management Protocol (IGMP) routines.
 #include <netinet/igmp.h>
 #include <netinet/igmp_var.h>
 
+#if CONFIG_MACF_NET
+#include <security/mac_framework.h>
+#endif
+
 #ifndef __APPLE__
 static MALLOC_DEFINE(M_IGMP, "igmp", "igmp state");
 #endif
 
 static struct router_info *
-               find_rti(struct ifnet *ifp);
+               find_rti(struct ifnet *ifp, int wait);
 
 static struct igmpstat igmpstat;
 
@@ -108,15 +118,15 @@ SYSCTL_STRUCT(_net_inet_igmp, IGMPCTL_STATS, stats, CTLFLAG_RD,
        &igmpstat, igmpstat, "");
 
 static int igmp_timers_are_running;
-static u_long igmp_all_hosts_group;
-static u_long igmp_all_rtrs_group;
+static uint32_t igmp_all_hosts_group;
+static uint32_t igmp_all_rtrs_group;
 static struct mbuf *router_alert;
 static struct router_info *Head;
 
-static void igmp_sendpkt(struct in_multi *, int, unsigned long);
+static void igmp_sendpkt(struct in_multi *, int, uint32_t);
 
 void
-igmp_init()
+igmp_init(void)
 {
        struct ipoption *ra;
 
@@ -131,7 +141,7 @@ igmp_init()
        /*
         * Construct a Router Alert option to use in outgoing packets
         */
-       MGET(router_alert, M_DONTWAIT, MT_DATA);
+       MGET(router_alert, M_WAIT, MT_DATA);
        ra = mtod(router_alert, struct ipoption *);
        ra->ipopt_dst.s_addr = 0;
        ra->ipopt_list[0] = IPOPT_RA;   /* Router Alert Option */
@@ -145,7 +155,7 @@ igmp_init()
 
 static struct router_info *
 find_rti(
-       struct ifnet *ifp)
+       struct ifnet *ifp, int wait)
 {
        struct router_info *rti = Head;
        
@@ -163,7 +173,7 @@ find_rti(
                rti = rti->rti_next;
        }
        
-       MALLOC(rti, struct router_info *, sizeof *rti, M_IGMP, M_NOWAIT);
+       MALLOC(rti, struct router_info *, sizeof *rti, M_IGMP, wait);
        if (rti != NULL)
        {
                rti->rti_ifp = ifp;
@@ -233,7 +243,7 @@ igmp_input(
        timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE;
        if (timer == 0)
                timer = 1;
-       rti = find_rti(ifp);
+       rti = find_rti(ifp, M_NOWAIT);
        if (rti == NULL) {
                m_freem(m);
                return;
@@ -299,7 +309,7 @@ igmp_input(
                 * - Use the value specified in the query message as
                 *   the maximum timeout.
                 */
-               lck_mtx_lock(rt_mtx);
+               lck_mtx_lock(rnh_lock);
                IN_FIRST_MULTI(step, inm);
                while (inm != NULL) {
                        if (inm->inm_ifp == ifp &&
@@ -315,7 +325,7 @@ igmp_input(
                        }
                        IN_NEXT_MULTI(step, inm);
                }
-               lck_mtx_unlock(rt_mtx);
+               lck_mtx_unlock(rnh_lock);
 
                break;
 
@@ -328,17 +338,24 @@ igmp_input(
                 * router, so discard reports sourced by me.
                 */
                IFP_TO_IA(ifp, ia);
-               if (ia && ip->ip_src.s_addr == IA_SIN(ia)->sin_addr.s_addr)
+               if (ia && ip->ip_src.s_addr == IA_SIN(ia)->sin_addr.s_addr) {
+                       ifafree(&ia->ia_ifa);
                        break;
+               }
 
                ++igmpstat.igps_rcv_reports;
 
-               if (ifp->if_flags & IFF_LOOPBACK)
+               if (ifp->if_flags & IFF_LOOPBACK) {
+                       if (ia != NULL)
+                               ifafree(&ia->ia_ifa);
                        break;
+               }
 
                if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr))) {
                        ++igmpstat.igps_rcv_badreports;
                        m_freem(m);
+                       if (ia != NULL)
+                               ifafree(&ia->ia_ifa);
                        return;
                }
 
@@ -369,6 +386,8 @@ igmp_input(
                        inm->inm_state = IGMP_OTHERMEMBER;
                }
 
+               if (ia != NULL)
+                       ifafree(&ia->ia_ifa);
                break;
        }
 
@@ -380,8 +399,7 @@ igmp_input(
 }
 
 int
-igmp_joingroup(inm)
-       struct in_multi *inm;
+igmp_joingroup(struct in_multi *inm)
 {
 
        if (inm->inm_addr.s_addr == igmp_all_hosts_group
@@ -389,7 +407,7 @@ igmp_joingroup(inm)
                inm->inm_timer = 0;
                inm->inm_state = IGMP_OTHERMEMBER;
        } else {
-               inm->inm_rti = find_rti(inm->inm_ifp);
+               inm->inm_rti = find_rti(inm->inm_ifp, M_WAITOK);
                if (inm->inm_rti == NULL) return ENOMEM;
                igmp_sendpkt(inm, inm->inm_rti->rti_type, 0);
                inm->inm_timer = IGMP_RANDOM_DELAY(
@@ -401,8 +419,7 @@ igmp_joingroup(inm)
 }
 
 void
-igmp_leavegroup(inm)
-       struct in_multi *inm;
+igmp_leavegroup(struct in_multi *inm)
 {
        if (inm->inm_state == IGMP_IREPORTEDLAST &&
            inm->inm_addr.s_addr != igmp_all_hosts_group &&
@@ -412,7 +429,7 @@ igmp_leavegroup(inm)
 }
 
 void
-igmp_fasttimo()
+igmp_fasttimo(void)
 {
        struct in_multi *inm;
        struct in_multistep step;
@@ -430,7 +447,7 @@ igmp_fasttimo()
        while (inm != NULL) {
                if (inm->inm_timer == 0) {
                        /* do nothing */
-               } else if (--inm->inm_timer == 0) {
+               } else if ((--inm->inm_timer == 0) && (inm->inm_rti != NULL)) {
                        igmp_sendpkt(inm, inm->inm_rti->rti_type, 0);
                        inm->inm_state = IGMP_IREPORTEDLAST;
                } else {
@@ -441,7 +458,7 @@ igmp_fasttimo()
 }
 
 void
-igmp_slowtimo()
+igmp_slowtimo(void)
 {
        struct router_info *rti =  Head;
 
@@ -465,21 +482,21 @@ igmp_slowtimo()
 static struct route igmprt;
 
 static void
-igmp_sendpkt(inm, type, addr)
-       struct in_multi *inm;
-       int type;
-       unsigned long addr;
+igmp_sendpkt(struct in_multi *inm, int type, uint32_t addr)
 {
         struct mbuf *m;
         struct igmp *igmp;
         struct ip *ip;
         struct ip_moptions imo;
 
-        MGETHDR(m, M_DONTWAIT, MT_HEADER);
+        MGETHDR(m, M_DONTWAIT, MT_HEADER);     /* MAC-OK */
         if (m == NULL)
                 return;
 
-       m->m_pkthdr.rcvif = loif;
+       m->m_pkthdr.rcvif = lo_ifp;
+#if CONFIG_MACF_NET
+       mac_mbuf_label_associate_linklayer(inm->inm_ifp, m);
+#endif
        m->m_pkthdr.len = sizeof(struct ip) + IGMP_MINLEN;
        MH_ALIGN(m, IGMP_MINLEN + sizeof(struct ip));
        m->m_data += sizeof(struct ip);
@@ -505,18 +522,23 @@ igmp_sendpkt(inm, type, addr)
 
         imo.imo_multicast_ifp  = inm->inm_ifp;
         imo.imo_multicast_ttl  = 1;
-       imo.imo_multicast_vif  = -1;
+               imo.imo_multicast_vif  = -1;
+#if MROUTING
         /*
          * Request loopback of the report if we are acting as a multicast
          * router, so that the process-level routing demon can hear it.
          */
         imo.imo_multicast_loop = (ip_mrouter != NULL);
+#else
+        imo.imo_multicast_loop = 0;
+#endif
 
        /*
         * XXX
         * Do we have to worry about reentrancy here?  Don't think so.
         */
-        ip_output(m, router_alert, &igmprt, 0, &imo);
+        ip_output(m, router_alert, &igmprt, 0, &imo, NULL);
 
         ++igmpstat.igps_snd_reports;
 }
+