igmp.c (128019) | igmp.c (130333) |
---|---|
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 | 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 128019 2004-04-07 20:46:16Z imp $ | 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 | 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; |
|
83static SLIST_HEAD(, router_info) router_info_head; 84static int igmp_timers_are_running; | 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 */ |
|
85static u_long igmp_all_hosts_group; 86static u_long igmp_all_rtrs_group; | 99static u_long igmp_all_hosts_group; 100static u_long igmp_all_rtrs_group; |
101 |
|
87static struct mbuf *router_alert; 88static struct route igmprt; 89 90#ifdef IGMP_DEBUG 91#define IGMP_PRINTF(x) printf(x) 92#else 93#define IGMP_PRINTF(x) 94#endif --- 18 unchanged lines hidden (view full) --- 113 ra = mtod(router_alert, struct ipoption *); 114 ra->ipopt_dst.s_addr = 0; 115 ra->ipopt_list[0] = IPOPT_RA; /* Router Alert Option */ 116 ra->ipopt_list[1] = 0x04; /* 4 bytes long */ 117 ra->ipopt_list[2] = 0x00; 118 ra->ipopt_list[3] = 0x00; 119 router_alert->m_len = sizeof(ra->ipopt_dst) + ra->ipopt_list[1]; 120 | 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); |
|
121 SLIST_INIT(&router_info_head); 122} 123 124static struct router_info * 125find_rti(struct ifnet *ifp) 126{ 127 struct router_info *rti; 128 | 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); |
|
129 IGMP_PRINTF("[igmp.c, _find_rti] --> entering \n"); 130 SLIST_FOREACH(rti, &router_info_head, rti_list) { 131 if (rti->rti_ifp == ifp) { 132 IGMP_PRINTF( 133 "[igmp.c, _find_rti] --> found old entry \n"); 134 return rti; 135 } 136 } | 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 */ |
|
137 MALLOC(rti, struct router_info *, sizeof *rti, M_IGMP, M_NOWAIT); 138 rti->rti_ifp = ifp; 139 rti->rti_type = IGMP_V2_ROUTER; 140 rti->rti_time = 0; 141 SLIST_INSERT_HEAD(&router_info_head, rti, rti_list); 142 143 IGMP_PRINTF("[igmp.c, _find_rti] --> created an entry \n"); 144 return rti; --- 47 unchanged lines hidden (view full) --- 192 } 193 m->m_data -= iphlen; 194 m->m_len += iphlen; 195 196 ip = mtod(m, struct ip *); 197 timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE; 198 if (timer == 0) 199 timer = 1; | 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; |
200 rti = find_rti(ifp); | |
201 202 /* 203 * In the IGMPv2 specification, there are 3 states and a flag. 204 * 205 * In Non-Member state, we simply don't have a membership record. 206 * In Delaying Member state, our timer is running (inm->inm_timer) 207 * In Idle Member state, our timer is not running (inm->inm_timer==0) 208 * --- 10 unchanged lines hidden (view full) --- 219 220 if (igmp->igmp_code == 0) { 221 /* 222 * Old router. Remember that the querier on this 223 * interface is old, and set the timer to the 224 * value in RFC 1112. 225 */ 226 | 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); |
|
227 rti->rti_type = IGMP_V1_ROUTER; 228 rti->rti_time = 0; | 248 rti->rti_type = IGMP_V1_ROUTER; 249 rti->rti_time = 0; |
250 mtx_unlock(&igmp_mtx); |
|
229 230 timer = IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ; 231 232 if (ip->ip_dst.s_addr != igmp_all_hosts_group || 233 igmp->igmp_group.s_addr != 0) { 234 ++igmpstat.igps_rcv_badqueries; 235 m_freem(m); 236 return; --- 102 unchanged lines hidden (view full) --- 339{ 340 int s = splnet(); 341 342 if (inm->inm_addr.s_addr == igmp_all_hosts_group 343 || inm->inm_ifp->if_flags & IFF_LOOPBACK) { 344 inm->inm_timer = 0; 345 inm->inm_state = IGMP_OTHERMEMBER; 346 } else { | 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); |
|
347 inm->inm_rti = find_rti(inm->inm_ifp); | 370 inm->inm_rti = find_rti(inm->inm_ifp); |
371 mtx_unlock(&igmp_mtx); |
|
348 igmp_sendpkt(inm, inm->inm_rti->rti_type, 0); 349 inm->inm_timer = IGMP_RANDOM_DELAY( 350 IGMP_MAX_HOST_REPORT_DELAY*PR_FASTHZ); 351 inm->inm_state = IGMP_IREPORTEDLAST; 352 igmp_timers_are_running = 1; 353 } 354 splx(s); 355} --- 43 unchanged lines hidden (view full) --- 399 400void 401igmp_slowtimo(void) 402{ 403 int s = splnet(); 404 struct router_info *rti; 405 406 IGMP_PRINTF("[igmp.c,_slowtimo] -- > entering \n"); | 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); |
|
407 SLIST_FOREACH(rti, &router_info_head, rti_list) { 408 if (rti->rti_type == IGMP_V1_ROUTER) { 409 rti->rti_time++; 410 if (rti->rti_time >= IGMP_AGE_THRESHOLD) 411 rti->rti_type = IGMP_V2_ROUTER; 412 } 413 } | 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); |
|
414 IGMP_PRINTF("[igmp.c,_slowtimo] -- > exiting \n"); 415 splx(s); 416} 417 418static void 419igmp_sendpkt(struct in_multi *inm, int type, unsigned long addr) 420{ 421 struct mbuf *m; --- 50 unchanged lines hidden --- | 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 --- |