* Transmit the next pending IGMP message in the output queue. * * We get called from netisr_processqueue(). A mutex private to igmpoq * will be acquired and released around this routine. * * VIMAGE: Needs to store/restore vnet pointer on a per-mbuf-chain basis. * MRT: Nothing needs to be done, as IGMP traffic is always local to * a link and uses a link-scope multicast address. */
| 3437 | * a link and uses a link-scope multicast address. |
| 3438 | */ |
| 3439 | static void |
| 3440 | igmp_intr(struct mbuf *m) |
| 3441 | { |
| 3442 | struct ip_moptions imo; |
| 3443 | struct ifnet *ifp; |
| 3444 | struct mbuf *ipopts, *m0; |
| 3445 | int error; |
| 3446 | uint32_t ifindex; |
| 3447 | |
| 3448 | CTR2(KTR_IGMPV3, "%s: transmit %p", __func__, m); |
| 3449 | |
| 3450 | /* |
| 3451 | * Set VNET image pointer from enqueued mbuf chain |
| 3452 | * before doing anything else. Whilst we use interface |
| 3453 | * indexes to guard against interface detach, they are |
| 3454 | * unique to each VIMAGE and must be retrieved. |
| 3455 | */ |
| 3456 | CURVNET_SET((struct vnet *)(m->m_pkthdr.PH_loc.ptr)); |
| 3457 | ifindex = igmp_restore_context(m); |
| 3458 | |
| 3459 | /* |
| 3460 | * Check if the ifnet still exists. This limits the scope of |
| 3461 | * any race in the absence of a global ifp lock for low cost |
| 3462 | * (an array lookup). |
| 3463 | */ |
| 3464 | ifp = ifnet_byindex(ifindex); |
| 3465 | if (ifp == NULL) { |
| 3466 | CTR3(KTR_IGMPV3, "%s: dropped %p as ifindex %u went away.", |
| 3467 | __func__, m, ifindex); |
| 3468 | m_freem(m); |
| 3469 | IPSTAT_INC(ips_noroute); |
| 3470 | goto out; |
| 3471 | } |
| 3472 | |
| 3473 | ipopts = V_igmp_sendra ? m_raopt : NULL; |
| 3474 | |
| 3475 | imo.imo_multicast_ttl = 1; |
| 3476 | imo.imo_multicast_vif = -1; |
| 3477 | imo.imo_multicast_loop = (V_ip_mrouter != NULL); |
| 3478 | |
| 3479 | /* |
| 3480 | * If the user requested that IGMP traffic be explicitly |
| 3481 | * redirected to the loopback interface (e.g. they are running a |
| 3482 | * MANET interface and the routing protocol needs to see the |
| 3483 | * updates), handle this now. |
| 3484 | */ |
| 3485 | if (m->m_flags & M_IGMP_LOOP) |
| 3486 | imo.imo_multicast_ifp = V_loif; |
| 3487 | else |
| 3488 | imo.imo_multicast_ifp = ifp; |
| 3489 | |
| 3490 | if (m->m_flags & M_IGMPV2) { |
| 3491 | m0 = m; |
| 3492 | } else { |
| 3493 | m0 = igmp_v3_encap_report(ifp, m); |
| 3494 | if (m0 == NULL) { |
| 3495 | CTR2(KTR_IGMPV3, "%s: dropped %p", __func__, m); |
| 3496 | m_freem(m); |
nothing calls this directly
no test coverage detected