X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/e5568f75972dfc723778653c11cb6b4dc825716a..b0d623f7f2ae71ed96e60569f61f9a9a27016e80:/bsd/netinet/igmp.c?ds=sidebyside diff --git a/bsd/netinet/igmp.c b/bsd/netinet/igmp.c index 1430acc47..004ccc9c7 100644 --- a/bsd/netinet/igmp.c +++ b/bsd/netinet/igmp.c @@ -1,23 +1,29 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2008 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * 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. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * 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 OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * 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_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1988 Stephen Deering. @@ -57,6 +63,12 @@ * * @(#)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. @@ -89,12 +101,16 @@ #include #include +#if CONFIG_MACF_NET +#include +#endif + #ifndef __APPLE__ static MALLOC_DEFINE(M_IGMP, "igmp", "igmp state"); #endif static struct router_info * - find_rti __P((struct ifnet *ifp)); + find_rti(struct ifnet *ifp, int wait); static struct igmpstat igmpstat; @@ -102,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 __P((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; @@ -125,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 */ @@ -138,10 +154,10 @@ igmp_init() } static struct router_info * -find_rti(ifp) - struct ifnet *ifp; +find_rti( + struct ifnet *ifp, int wait) { - register struct router_info *rti = Head; + struct router_info *rti = Head; #if IGMP_DEBUG @@ -157,7 +173,7 @@ find_rti(ifp) 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; @@ -173,17 +189,17 @@ find_rti(ifp) } void -igmp_input(m, iphlen) - register struct mbuf *m; - register int iphlen; +igmp_input( + struct mbuf *m, + int iphlen) { - register struct igmp *igmp; - register struct ip *ip; - register int igmplen; - register struct ifnet *ifp = m->m_pkthdr.rcvif; - register int minlen; - register struct in_multi *inm; - register struct in_ifaddr *ia; + struct igmp *igmp; + struct ip *ip; + int igmplen; + struct ifnet *ifp = m->m_pkthdr.rcvif; + int minlen; + struct in_multi *inm; + struct in_ifaddr *ia; struct in_multistep step; struct router_info *rti; @@ -227,7 +243,7 @@ igmp_input(m, iphlen) 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; @@ -293,6 +309,7 @@ igmp_input(m, iphlen) * - Use the value specified in the query message as * the maximum timeout. */ + lck_mtx_lock(rnh_lock); IN_FIRST_MULTI(step, inm); while (inm != NULL) { if (inm->inm_ifp == ifp && @@ -308,6 +325,7 @@ igmp_input(m, iphlen) } IN_NEXT_MULTI(step, inm); } + lck_mtx_unlock(rnh_lock); break; @@ -320,17 +338,24 @@ igmp_input(m, iphlen) * 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; } @@ -350,7 +375,9 @@ igmp_input(m, iphlen) * If we belong to the group being reported, stop * our timer for that group. */ + ifnet_lock_shared(ifp); IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm); + ifnet_lock_done(ifp); if (inm != NULL) { inm->inm_timer = 0; @@ -359,6 +386,8 @@ igmp_input(m, iphlen) inm->inm_state = IGMP_OTHERMEMBER; } + if (ia != NULL) + ifafree(&ia->ia_ifa); break; } @@ -370,17 +399,15 @@ igmp_input(m, iphlen) } int -igmp_joingroup(inm) - struct in_multi *inm; +igmp_joingroup(struct in_multi *inm) { - int s = splnet(); if (inm->inm_addr.s_addr == igmp_all_hosts_group || inm->inm_ifp->if_flags & IFF_LOOPBACK) { 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( @@ -389,12 +416,10 @@ igmp_joingroup(inm) igmp_timers_are_running = 1; } return 0; - splx(s); } 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 && @@ -404,11 +429,10 @@ igmp_leavegroup(inm) } void -igmp_fasttimo() +igmp_fasttimo(void) { - register struct in_multi *inm; + struct in_multi *inm; struct in_multistep step; - int s; /* * Quick check to see if any work needs to be done, in order @@ -418,13 +442,12 @@ igmp_fasttimo() if (!igmp_timers_are_running) return; - s = splnet(); igmp_timers_are_running = 0; IN_FIRST_MULTI(step, inm); 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 { @@ -432,14 +455,12 @@ igmp_fasttimo() } IN_NEXT_MULTI(step, inm); } - splx(s); } void -igmp_slowtimo() +igmp_slowtimo(void) { - int s = splnet(); - register struct router_info *rti = Head; + struct router_info *rti = Head; #if IGMP_DEBUG printf("[igmp.c,_slowtimo] -- > entering \n"); @@ -456,27 +477,26 @@ igmp_slowtimo() #if IGMP_DEBUG printf("[igmp.c,_slowtimo] -- > exiting \n"); #endif - splx(s); } 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); @@ -502,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; } +