Ejemplo n.º 1
0
/**
*   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");
    }

}
Ejemplo n.º 2
0
/**
*   Recieves and handles a group leave message.
*/
void acceptLeaveMessage(uint32_t src, uint32_t group) {
    struct IfDesc   *sourceVif;

    my_log(LOG_DEBUG, 0,
	    "Got leave message from %s to %s. Starting last member detection.",
	    inetFmt(src, s1), inetFmt(group, s2));

    // 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;
    }


    // We have a IF so check that it's an downstream IF.
    if(sourceVif->state == IF_STATE_DOWNSTREAM) {

        GroupVifDesc   *gvDesc;
        gvDesc = (GroupVifDesc*) malloc(sizeof(GroupVifDesc));

        // Tell the route table that we are checking for remaining members...
        setRouteLastMemberMode(group);

        // Call the group spesific membership querier...
        gvDesc->group = group;
        gvDesc->vifAddr = sourceVif->InAdr.s_addr;
        gvDesc->started = 0;

        sendGroupSpecificMemberQuery(gvDesc);

#ifdef RALINK_ESW_SUPPORT
	remove_member(ntohl(group), ntohl(src));
#endif
    } else {
        // just ignore the leave request...
        my_log(LOG_DEBUG, 0, "The found if for %s was not downstream. Ignoring leave request.", inetFmt(src, s1));
    }
}
Ejemplo n.º 3
0
/**
*   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");
    }

}
Ejemplo n.º 4
0
/**
*   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;
    }
}
Ejemplo n.º 5
0
/**
 * Process a newly received IGMP packet that is sitting in the input
 * packet buffer.
 */
void acceptIgmp(int recvlen) {
    register uint32_t src, dst, group;
    struct ip *ip;
    struct igmp *igmp;
    int ipdatalen, iphdrlen, igmpdatalen;

    if (recvlen < sizeof(struct ip)) {
        my_log(LOG_WARNING, 0,
            "received packet too short (%u bytes) for IP header", recvlen);
        return;
    }

    ip        = (struct ip *)recv_buf;
    src       = ip->ip_src.s_addr;
    dst       = ip->ip_dst.s_addr;

    /* filter local multicast 239.255.255.250 */
    if (dst == htonl(0xEFFFFFFA))
    {
        my_log(LOG_NOTICE, 0, "The IGMP message was local multicast. Ignoring.");
        return;
    }

    /* 
     * this is most likely a message from the kernel indicating that
     * a new src grp pair message has arrived and so, it would be 
     * necessary to install a route into the kernel for this.
     */
    if (ip->ip_p == 0) {
        if (src == 0 || dst == 0) {
            my_log(LOG_WARNING, 0, "kernel request not accurate");
        }
        else {
            struct IfDesc *checkVIF;

            // Check if the source address matches a valid address on upstream vif.
            checkVIF = getIfByIx( upStreamVif );
            if(checkVIF == 0) {
                my_log(LOG_WARNING, 0, "Upstream VIF was null.");
                return;
            } 
            else if(src == checkVIF->InAdr.s_addr) {
                my_log(LOG_NOTICE, 0, "Route activation request from %s for %s is from myself. Ignoring.",
                    inetFmt(src, s1), inetFmt(dst, s2));
                return;
            }
            else if(!isAdressValidForIf(checkVIF, src)) {
                struct IfDesc *downVIF = getIfByAddress(src);
                if (downVIF && downVIF->state & IF_STATE_DOWNSTREAM) {
                    my_log(LOG_NOTICE, 0, "The source address %s for group %s is from downstream VIF. Ignoring.",
                        inetFmt(src, s1), inetFmt(dst, s2));
                } else {
                    my_log(LOG_WARNING, 0, "The source address %s for group %s, is not in any valid net for upstream VIF.",
                        inetFmt(src, s1), inetFmt(dst, s2));
                }
                return;
            }

            // Activate the route.
            my_log(LOG_DEBUG, 0, "Route activate request from %s to %s",
		    inetFmt(src,s1), inetFmt(dst,s2));
            activateRoute(dst, src);


        }
        return;
    }

    iphdrlen  = ip->ip_hl << 2;
    ipdatalen = ip_data_len(ip);

    if (iphdrlen + ipdatalen != recvlen) {
        my_log(LOG_WARNING, 0,
            "received packet from %s shorter (%u bytes) than hdr+data length (%u+%u)",
            inetFmt(src, s1), recvlen, iphdrlen, ipdatalen);
        return;
    }

    igmp        = (struct igmp *)(recv_buf + iphdrlen);
    group       = igmp->igmp_group.s_addr;
    igmpdatalen = ipdatalen - IGMP_MINLEN;
    if (igmpdatalen < 0) {
        my_log(LOG_WARNING, 0,
            "received IP data field too short (%u bytes) for IGMP, from %s",
            ipdatalen, inetFmt(src, s1));
        return;
    }

    my_log(LOG_NOTICE, 0, "RECV %s from %-15s to %s",
        igmpPacketKind(igmp->igmp_type, igmp->igmp_code),
        inetFmt(src, s1), inetFmt(dst, s2) );

    switch (igmp->igmp_type) {
    case IGMP_V1_MEMBERSHIP_REPORT:
    case IGMP_V2_MEMBERSHIP_REPORT:
        acceptGroupReport(src, group, igmp->igmp_type);
        return;
    
    case IGMP_V2_LEAVE_GROUP:
        acceptLeaveMessage(src, group);
        return;
    
    case IGMP_MEMBERSHIP_QUERY:
        return;

    default:
        my_log(LOG_INFO, 0,
            "ignoring unknown IGMP message type %x from %s to %s",
            igmp->igmp_type, inetFmt(src, s1),
            inetFmt(dst, s2));
        return;
    }
}