* Dispatch an IGMPv1/v2 host report or leave message. * These are always small enough to fit inside a single mbuf. */
| 2234 | * These are always small enough to fit inside a single mbuf. |
| 2235 | */ |
| 2236 | static int |
| 2237 | igmp_v1v2_queue_report(struct in_multi *inm, const int type) |
| 2238 | { |
| 2239 | struct epoch_tracker et; |
| 2240 | struct ifnet *ifp; |
| 2241 | struct igmp *igmp; |
| 2242 | struct ip *ip; |
| 2243 | struct mbuf *m; |
| 2244 | |
| 2245 | IN_MULTI_LIST_LOCK_ASSERT(); |
| 2246 | IGMP_LOCK_ASSERT(); |
| 2247 | |
| 2248 | ifp = inm->inm_ifp; |
| 2249 | |
| 2250 | m = m_gethdr(M_NOWAIT, MT_DATA); |
| 2251 | if (m == NULL) |
| 2252 | return (ENOMEM); |
| 2253 | M_ALIGN(m, sizeof(struct ip) + sizeof(struct igmp)); |
| 2254 | |
| 2255 | m->m_pkthdr.len = sizeof(struct ip) + sizeof(struct igmp); |
| 2256 | |
| 2257 | m->m_data += sizeof(struct ip); |
| 2258 | m->m_len = sizeof(struct igmp); |
| 2259 | |
| 2260 | igmp = mtod(m, struct igmp *); |
| 2261 | igmp->igmp_type = type; |
| 2262 | igmp->igmp_code = 0; |
| 2263 | igmp->igmp_group = inm->inm_addr; |
| 2264 | igmp->igmp_cksum = 0; |
| 2265 | igmp->igmp_cksum = in_cksum(m, sizeof(struct igmp)); |
| 2266 | |
| 2267 | m->m_data -= sizeof(struct ip); |
| 2268 | m->m_len += sizeof(struct ip); |
| 2269 | |
| 2270 | ip = mtod(m, struct ip *); |
| 2271 | ip->ip_tos = 0; |
| 2272 | ip->ip_len = htons(sizeof(struct ip) + sizeof(struct igmp)); |
| 2273 | ip->ip_off = 0; |
| 2274 | ip->ip_p = IPPROTO_IGMP; |
| 2275 | ip->ip_src.s_addr = INADDR_ANY; |
| 2276 | |
| 2277 | if (type == IGMP_HOST_LEAVE_MESSAGE) |
| 2278 | ip->ip_dst.s_addr = htonl(INADDR_ALLRTRS_GROUP); |
| 2279 | else |
| 2280 | ip->ip_dst = inm->inm_addr; |
| 2281 | |
| 2282 | igmp_save_context(m, ifp); |
| 2283 | |
| 2284 | m->m_flags |= M_IGMPV2; |
| 2285 | if (inm->inm_igi->igi_flags & IGIF_LOOPBACK) |
| 2286 | m->m_flags |= M_IGMP_LOOP; |
| 2287 | |
| 2288 | CTR2(KTR_IGMPV3, "%s: netisr_dispatch(NETISR_IGMP, %p)", __func__, m); |
| 2289 | NET_EPOCH_ENTER(et); |
| 2290 | netisr_dispatch(NETISR_IGMP, m); |
| 2291 | NET_EPOCH_EXIT(et); |
| 2292 | |
| 2293 | return (0); |
no test coverage detected