1/* 2 * Copyright (c) 1988 Stephen Deering. 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Stephen Deering of Stanford University. 8 * --- 17 unchanged lines hidden (view full) --- 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)igmp.c 8.1 (Berkeley) 7/19/93 |
34 * $FreeBSD: head/sys/netinet/igmp.c 130333 2004-06-11 03:42:37Z rwatson $ |
35 */ 36 37/* 38 * Internet Group Management Protocol (IGMP) routines. 39 * 40 * Written by Steve Deering, Stanford, May 1988. 41 * Modified by Rosen Sharma, Stanford, Aug 1994. 42 * Modified by Bill Fenner, Xerox PARC, Feb 1995. --- 32 unchanged lines hidden (view full) --- 75static struct router_info *find_rti(struct ifnet *ifp); 76static void igmp_sendpkt(struct in_multi *, int, unsigned long); 77 78static struct igmpstat igmpstat; 79 80SYSCTL_STRUCT(_net_inet_igmp, IGMPCTL_STATS, stats, CTLFLAG_RW, &igmpstat, 81 igmpstat, ""); 82 |
83/* 84 * igmp_mtx protects all mutable global variables in igmp.c, as well as 85 * the data fields in struct router_info. In general, a router_info 86 * structure will be valid as long as the referencing struct in_multi is 87 * valid, so no reference counting is used. We allow unlocked reads of 88 * router_info data when accessed via an in_multi read-only. 89 */ 90static struct mtx igmp_mtx; |
91static SLIST_HEAD(, router_info) router_info_head; 92static int igmp_timers_are_running; |
93 94/* 95 * XXXRW: can we define these such that these can be made const? In any 96 * case, these shouldn't be changed after igmp_init() and therefore don't 97 * need locking. 98 */ |
99static u_long igmp_all_hosts_group; 100static u_long igmp_all_rtrs_group; |
101 |
102static struct mbuf *router_alert; 103static struct route igmprt; 104 105#ifdef IGMP_DEBUG 106#define IGMP_PRINTF(x) printf(x) 107#else 108#define IGMP_PRINTF(x) 109#endif --- 18 unchanged lines hidden (view full) --- 128 ra = mtod(router_alert, struct ipoption *); 129 ra->ipopt_dst.s_addr = 0; 130 ra->ipopt_list[0] = IPOPT_RA; /* Router Alert Option */ 131 ra->ipopt_list[1] = 0x04; /* 4 bytes long */ 132 ra->ipopt_list[2] = 0x00; 133 ra->ipopt_list[3] = 0x00; 134 router_alert->m_len = sizeof(ra->ipopt_dst) + ra->ipopt_list[1]; 135 |
136 mtx_init(&igmp_mtx, "igmp_mtx", NULL, MTX_DEF); |
137 SLIST_INIT(&router_info_head); 138} 139 140static struct router_info * 141find_rti(struct ifnet *ifp) 142{ 143 struct router_info *rti; 144 |
145 mtx_assert(&igmp_mtx, MA_OWNED); |
146 IGMP_PRINTF("[igmp.c, _find_rti] --> entering \n"); 147 SLIST_FOREACH(rti, &router_info_head, rti_list) { 148 if (rti->rti_ifp == ifp) { 149 IGMP_PRINTF( 150 "[igmp.c, _find_rti] --> found old entry \n"); 151 return rti; 152 } 153 } |
154 /* 155 * XXXRW: return value of malloc not checked, despite M_NOWAIT. 156 */ |
157 MALLOC(rti, struct router_info *, sizeof *rti, M_IGMP, M_NOWAIT); 158 rti->rti_ifp = ifp; 159 rti->rti_type = IGMP_V2_ROUTER; 160 rti->rti_time = 0; 161 SLIST_INSERT_HEAD(&router_info_head, rti, rti_list); 162 163 IGMP_PRINTF("[igmp.c, _find_rti] --> created an entry \n"); 164 return rti; --- 47 unchanged lines hidden (view full) --- 212 } 213 m->m_data -= iphlen; 214 m->m_len += iphlen; 215 216 ip = mtod(m, struct ip *); 217 timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE; 218 if (timer == 0) 219 timer = 1; |
220 221 /* 222 * In the IGMPv2 specification, there are 3 states and a flag. 223 * 224 * In Non-Member state, we simply don't have a membership record. 225 * In Delaying Member state, our timer is running (inm->inm_timer) 226 * In Idle Member state, our timer is not running (inm->inm_timer==0) 227 * --- 10 unchanged lines hidden (view full) --- 238 239 if (igmp->igmp_code == 0) { 240 /* 241 * Old router. Remember that the querier on this 242 * interface is old, and set the timer to the 243 * value in RFC 1112. 244 */ 245 |
246 mtx_lock(&igmp_mtx); 247 rti = find_rti(ifp); |
248 rti->rti_type = IGMP_V1_ROUTER; 249 rti->rti_time = 0; |
250 mtx_unlock(&igmp_mtx); |
251 252 timer = IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ; 253 254 if (ip->ip_dst.s_addr != igmp_all_hosts_group || 255 igmp->igmp_group.s_addr != 0) { 256 ++igmpstat.igps_rcv_badqueries; 257 m_freem(m); 258 return; --- 102 unchanged lines hidden (view full) --- 361{ 362 int s = splnet(); 363 364 if (inm->inm_addr.s_addr == igmp_all_hosts_group 365 || inm->inm_ifp->if_flags & IFF_LOOPBACK) { 366 inm->inm_timer = 0; 367 inm->inm_state = IGMP_OTHERMEMBER; 368 } else { |
369 mtx_lock(&igmp_mtx); |
370 inm->inm_rti = find_rti(inm->inm_ifp); |
371 mtx_unlock(&igmp_mtx); |
372 igmp_sendpkt(inm, inm->inm_rti->rti_type, 0); 373 inm->inm_timer = IGMP_RANDOM_DELAY( 374 IGMP_MAX_HOST_REPORT_DELAY*PR_FASTHZ); 375 inm->inm_state = IGMP_IREPORTEDLAST; 376 igmp_timers_are_running = 1; 377 } 378 splx(s); 379} --- 43 unchanged lines hidden (view full) --- 423 424void 425igmp_slowtimo(void) 426{ 427 int s = splnet(); 428 struct router_info *rti; 429 430 IGMP_PRINTF("[igmp.c,_slowtimo] -- > entering \n"); |
431 mtx_lock(&igmp_mtx); |
432 SLIST_FOREACH(rti, &router_info_head, rti_list) { 433 if (rti->rti_type == IGMP_V1_ROUTER) { 434 rti->rti_time++; 435 if (rti->rti_time >= IGMP_AGE_THRESHOLD) 436 rti->rti_type = IGMP_V2_ROUTER; 437 } 438 } |
439 mtx_unlock(&igmp_mtx); |
440 IGMP_PRINTF("[igmp.c,_slowtimo] -- > exiting \n"); 441 splx(s); 442} 443 444static void 445igmp_sendpkt(struct in_multi *inm, int type, unsigned long addr) 446{ 447 struct mbuf *m; --- 50 unchanged lines hidden --- |