* Process a received IGMPv1 host membership report. * * NOTE: 0.0.0.0 workaround breaks const correctness. */
| 1256 | * NOTE: 0.0.0.0 workaround breaks const correctness. |
| 1257 | */ |
| 1258 | static int |
| 1259 | igmp_input_v1_report(struct ifnet *ifp, /*const*/ struct ip *ip, |
| 1260 | /*const*/ struct igmp *igmp) |
| 1261 | { |
| 1262 | struct rm_priotracker in_ifa_tracker; |
| 1263 | struct in_ifaddr *ia; |
| 1264 | struct in_multi *inm; |
| 1265 | |
| 1266 | IGMPSTAT_INC(igps_rcv_reports); |
| 1267 | |
| 1268 | if (ifp->if_flags & IFF_LOOPBACK) |
| 1269 | return (0); |
| 1270 | |
| 1271 | if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr)) || |
| 1272 | !in_hosteq(igmp->igmp_group, ip->ip_dst)) { |
| 1273 | IGMPSTAT_INC(igps_rcv_badreports); |
| 1274 | return (EINVAL); |
| 1275 | } |
| 1276 | |
| 1277 | /* |
| 1278 | * RFC 3376, Section 4.2.13, 9.2, 9.3: |
| 1279 | * Booting clients may use the source address 0.0.0.0. Some |
| 1280 | * IGMP daemons may not know how to use IP_RECVIF to determine |
| 1281 | * the interface upon which this message was received. |
| 1282 | * Replace 0.0.0.0 with the subnet address if told to do so. |
| 1283 | */ |
| 1284 | if (V_igmp_recvifkludge && in_nullhost(ip->ip_src)) { |
| 1285 | IFP_TO_IA(ifp, ia, &in_ifa_tracker); |
| 1286 | if (ia != NULL) |
| 1287 | ip->ip_src.s_addr = htonl(ia->ia_subnet); |
| 1288 | } |
| 1289 | |
| 1290 | CTR3(KTR_IGMPV3, "process v1 report 0x%08x on ifp %p(%s)", |
| 1291 | ntohl(igmp->igmp_group.s_addr), ifp, ifp->if_xname); |
| 1292 | |
| 1293 | /* |
| 1294 | * IGMPv1 report suppression. |
| 1295 | * If we are a member of this group, and our membership should be |
| 1296 | * reported, stop our group timer and transition to the 'lazy' state. |
| 1297 | */ |
| 1298 | IN_MULTI_LIST_LOCK(); |
| 1299 | inm = inm_lookup(ifp, igmp->igmp_group); |
| 1300 | if (inm != NULL) { |
| 1301 | struct igmp_ifsoftc *igi; |
| 1302 | |
| 1303 | igi = inm->inm_igi; |
| 1304 | if (igi == NULL) { |
| 1305 | KASSERT(igi != NULL, |
| 1306 | ("%s: no igi for ifp %p", __func__, ifp)); |
| 1307 | goto out_locked; |
| 1308 | } |
| 1309 | |
| 1310 | IGMPSTAT_INC(igps_rcv_ourreports); |
| 1311 | |
| 1312 | /* |
| 1313 | * If we are in IGMPv3 host mode, do not allow the |
| 1314 | * other host's IGMPv1 report to suppress our reports |
| 1315 | * unless explicitly configured to do so. |
no test coverage detected