/** * Handles incoming membership reports, and * appends them to the routing table. */ void acceptGroupReport(uint32_t src, uint32_t group, uint8_t type) { struct IfDesc *sourceVif; // Sanitycheck the group adress... if(!IN_MULTICAST( ntohl(group) )) { my_log(LOG_WARNING, 0, "The group address %s is not a valid Multicast group.", inetFmt(group, s1)); return; } // Find the interface on which the report was recieved. sourceVif = getIfByAddress( src ); if(sourceVif == NULL) { my_log(LOG_WARNING, 0, "No interfaces found for source %s", inetFmt(src,s1)); return; } if(sourceVif->InAdr.s_addr == src) { my_log(LOG_NOTICE, 0, "The IGMP message was from myself. Ignoring."); return; } // We have a IF so check that it's an downstream IF. if(sourceVif->state == IF_STATE_DOWNSTREAM) { my_log(LOG_DEBUG, 0, "Should insert group %s (from: %s) to route table. Vif Ix : %d", inetFmt(group,s1), inetFmt(src,s2), sourceVif->index); // If we don't have a whitelist we insertRoute and done if(sourceVif->allowedgroups == NULL) { #ifdef RALINK_ESW_SUPPORT insert_multicast_ip(ntohl(group), ntohl(src)); #endif insertRoute(group, sourceVif->index); return; } // Check if this Request is legit on this interface struct SubnetList *sn; for(sn = sourceVif->allowedgroups; sn != NULL; sn = sn->next) if((group & sn->subnet_mask) == sn->subnet_addr) { #ifdef RALINK_ESW_SUPPORT insert_multicast_ip(ntohl(group), ntohl(src)); #endif // The membership report was OK... Insert it into the route table.. insertRoute(group, sourceVif->index); return; } my_log(LOG_INFO, 0, "The group address %s may not be requested from this interface. Ignoring.", inetFmt(group, s1)); } else { // Log the state of the interface the report was recieved on. my_log(LOG_INFO, 0, "Mebership report was recieved on %s. Ignoring.", sourceVif->state==IF_STATE_UPSTREAM?"the upstream interface":"a disabled interface"); } }
/** * Activates a passive group. If the group is already * activated, it's reinstalled in the kernel. If * the route is activated, no originAddr is needed. */ int activateRoute(uint32_t group, uint32_t originAddr) { struct RouteTable* croute; int result = 0; // Find the requested route. croute = findRoute(group); if(croute == NULL) { my_log(LOG_DEBUG, 0, "No table entry for %s [From: %s]. Inserting route.", inetFmt(group, s1),inetFmt(originAddr, s2)); // Insert route, but no interfaces have yet requested it downstream. insertRoute(group, -1); // Retrieve the route from table... croute = findRoute(group); } if(croute != NULL) { // If the origin address is set, update the route data. if(originAddr > 0) { // find this origin, or an unused slot int i; for (i = 0; i < MAX_ORIGINS; i++) { // unused slots are at the bottom, so we can't miss this origin if (croute->originAddrs[i] == originAddr || croute->originAddrs[i] == 0) { break; } } if (i == MAX_ORIGINS) { i = MAX_ORIGINS - 1; my_log(LOG_WARNING, 0, "Too many origins for route %s; replacing %s with %s", inetFmt(croute->group, s1), inetFmt(croute->originAddrs[i], s2), inetFmt(originAddr, s3)); } // set origin croute->originAddrs[i] = originAddr; // move it to the top while (i > 0) { uint32_t t = croute->originAddrs[i - 1]; croute->originAddrs[i - 1] = croute->originAddrs[i]; croute->originAddrs[i] = t; i--; } } // Only update kernel table if there are listeners ! if(croute->vifBits > 0) { result = internUpdateKernelRoute(croute, 1); } } logRouteTable("Activate Route"); return result; }
/** * Handles incoming membership reports, and * appends them to the routing table. */ void acceptGroupReport(uint32_t src, uint32_t group, uint8_t type) { struct IfDesc *sourceVif; // Sanitycheck the group adress... if(!IN_MULTICAST( ntohl(group) )) { my_log(LOG_WARNING, 0, "The group address %s is not a valid Multicast group.", inetFmt(group, s1)); return; } // Find the interface on which the report was recieved. sourceVif = getIfByAddress( src ); if(sourceVif == NULL) { my_log(LOG_WARNING, 0, "No interfaces found for source %s", inetFmt(src,s1)); return; } if(sourceVif->InAdr.s_addr == src) { my_log(LOG_NOTICE, 0, "The IGMP message was from myself. Ignoring."); return; } // We have a IF so check that it's an downstream IF. if(sourceVif->state == IF_STATE_DOWNSTREAM) { my_log(LOG_DEBUG, 0, "Should insert group %s (from: %s) to route table. Vif Ix : %d", inetFmt(group,s1), inetFmt(src,s2), sourceVif->index); // The membership report was OK... Insert it into the route table.. insertRoute(group, sourceVif->index); } else { // Log the state of the interface the report was recieved on. my_log(LOG_INFO, 0, "Membership report was recieved on %s. Ignoring.", sourceVif->state==IF_STATE_UPSTREAM?"the upstream interface":"a disabled interface"); } }
/** * Accept a V3 Membership Report */ void acceptV3GroupReport(uint32_t src, uint8_t type, struct igmpv3_groupreport* igmpv3rep) { struct IfDesc *sourceVif; // Sanitycheck the group adress... if(!IN_MULTICAST( ntohl(group) )) { my_log(LOG_WARNING, 0, "The group address %s is not a valid Multicast group.", inetFmt(group, s1)); return; } // Find the interface on which the report was recieved. sourceVif = getIfByAddress( src ); if(sourceVif == NULL) { my_log(LOG_WARNING, 0, "No interfaces found for source %s", inetFmt(src,s1)); return; } if(sourceVif->InAdr.s_addr == src) { my_log(LOG_NOTICE, 0, "The IGMP message was from myself. Ignoring."); return; } // We have a IF so check that it's an downstream IF. if(sourceVif->state != IF_STATE_DOWNSTREAM) { // Log the state of the interface the report was recieved on. my_log(LOG_INFO, 0, "Membership report was recieved on %s. Ignoring.", sourceVif->state==IF_STATE_UPSTREAM?"the upstream interface":"a disabled interface"); } else { my_log(LOG_DEBUG, 0, "IGMPv3 Membership Report") // TODO: Can we batch-report here? uint16_t num_entries = ntohl(igmpv3rep->num_entries); uint16_t eix = 0; while ( eix < num_entries ) { struct igmpv3_groupreport_entry* e = (struct igmpv3_groupreport_entry* igmpv3rep->grec) + eix; uint16_t num_sources = ntohl(e->nsrcs); uint16_t six = 0; while ( six < num_sources ) { uint32_t* srcgroup = (uint32_t* e->sources) + six; group = ntohl(*srcgroup); switch ( e->type == 0x0 ) { case IGMPV3_GRE_MODE_INCLUDE: case IGMPV3_GRE_CHMODE_INCLUDE: case IGMPV3_GRE_ALLOW_NEW_SOURCES: my_log(LOG_DEBUG, 0, "IGMPv3 Subscribe to %s.", inetFmt(group, s1)); insertRoute(group, sourceVif->index); break; case IGMPV3_GRE_MODE_EXCLUDE: case IGMPV3_GRE_CHMODE_EXCLUDE: case IGMPV3_GRE_BLOCK_OLD_SOURCES: my_log(LOG_DEBUG, 0, "IGMPv3 Unsubscribe from %s.", inetFmt(group, s1)); deleteRoute(group, sourceVif->index); break; default: my_log(LOG_INFO, 0, "Membership V3 group report received with unknown type %d.", e->type); } }; eix++; }; return; } }