Example #1
0
/**
*   Sends a group specific member report query until the 
*   group times out...
*/
static void sendGroupSpecificMemberQuery(void *argument) {
    struct  Config  *conf = getCommonConfig();

    // Cast argument to correct type...
    GroupVifDesc   *gvDesc = (GroupVifDesc*) argument;

    if(gvDesc->started) {
        // If aging returns false, we don't do any further action...
        if(!lastMemberGroupAge(gvDesc->group)) {
            return;
        }
    } else {
        gvDesc->started = 1;
    }

    // Send a group specific membership query...
    sendIgmp(gvDesc->vifAddr, gvDesc->group, 
             IGMP_MEMBERSHIP_QUERY,
             conf->lastMemberQueryInterval * IGMP_TIMER_SCALE, 
             gvDesc->group, 0);

    my_log(LOG_DEBUG, 0, "Sent membership query from %s to %s. Delay: %d",
        inetFmt(gvDesc->vifAddr,s1), inetFmt(gvDesc->group,s2),
        conf->lastMemberQueryInterval);

    // Set timeout for next round...
    timer_setTimer(conf->lastMemberQueryInterval, sendGroupSpecificMemberQuery, gvDesc);

}
Example #2
0
/**
*   Remove a specified route. Returns 1 on success,
*   and 0 if route was not found.
*/
int removeRoute(struct RouteTable*  croute) {
    struct Config       *conf = getCommonConfig();
    int result = 1;
    
    // If croute is null, no routes was found.
    if(croute==NULL) {
        return 0;
    }

    // Log the cleanup in debugmode...
    my_log(LOG_DEBUG, 0, "Removed route entry for %s from table.",
                 inetFmt(croute->group, s1));

    //BIT_ZERO(croute->vifBits);

    // Uninstall current route from kernel
    if(!internUpdateKernelRoute(croute, 0)) {
        my_log(LOG_WARNING, 0, "The removal from Kernel failed.");
        result = 0;
    }

    // Send Leave request upstream if group is joined
    if(croute->upstrState == ROUTESTATE_JOINED || 
       (croute->upstrState == ROUTESTATE_CHECK_LAST_MEMBER && !conf->fastUpstreamLeave)) 
    {
        sendJoinLeaveUpstream(croute, 0);
    }

    // Update pointers...
    if(croute->prevroute == NULL) {
        // Topmost node...
        if(croute->nextroute != NULL) {
            croute->nextroute->prevroute = NULL;
        }
        routing_table = croute->nextroute;

    } else {
        croute->prevroute->nextroute = croute->nextroute;
        if(croute->nextroute != NULL) {
            croute->nextroute->prevroute = croute->prevroute;
        }
    }
    // Free the memory, and set the route to NULL...
    free(croute);
    croute = NULL;

    logRouteTable("Remove route");

    return result;
}
Example #3
0
/**
*   Ages groups in the last member check state. If the
*   route is not found, or not in this state, 0 is returned.
*/
int lastMemberGroupAge(struct in6_addr * group, struct in6_addr * src) 
{
    struct Config       *conf = NULL;
    struct RouteTable   *croute, *nroute;
    int i;
    
    conf = getCommonConfig();
/*
    printf("\nlastMemberGroupAge called, src = \n");
    for (i=0; i <16; i++)
        printf("%02x ",((char*)group)[i] & 255);
    printf("\n");  
    for (i=0; i <16; i++)
        printf("%02x ",((char*)src)[i] & 255);
    printf("\n");      
*/
    if( !IN6_ARE_ADDR_EQUAL( src, &allzero_addr ) ) 
    {
        croute = findRoute(group, src);
        if(croute!=NULL)
        {
            if(croute->upstrState == ROUTESTATE_CHECK_LAST_MEMBER) 
            {
                internAgeRoute(croute);
            }
        }
    }
    else
    {
        //showRoute();

        for( croute = routing_table; croute != NULL; croute = nroute )
        {        
            // Keep the next route (since current route may be removed)...
            nroute = croute->nextroute;

            // Run the aging round algorithm.
            if( croute->upstrState = ROUTESTATE_CHECK_LAST_MEMBER && 
                IN6_ARE_ADDR_EQUAL( &croute->group, group ) 
              )
            {
                // Only age routes if Last member probe is not active...
                internAgeRoute(croute);
            }
        }
    }    
    return 0;
}
Example #4
0
/**
*   Should be called when a leave message is recieved, to
*   mark a route for the last member probe state.
*/
void setRouteLastMemberMode(struct in6_addr * group, struct in6_addr * src) 
{
    struct Config       *conf = getCommonConfig();
    struct RouteTable   *croute, *tmpRoute;

    croute = findRoute(group, src);
    if(croute!=NULL) 
    {
        if( !IN6_ARE_ADDR_EQUAL( src, &allzero_addr) ) 
        {
            // Check for fast leave mode...
            /*
            if(croute->upstrState == ROUTESTATE_JOINED && conf->fastUpstreamLeave) 
            {
                // Send a leave message right away..
                sendJoinLeaveUpstream(croute, 0);
            }
            */
            // Set the routingstate to Last member check...
            croute->upstrState = ROUTESTATE_CHECK_LAST_MEMBER;
            // Set the count value for expiring... (-1 since first aging)
            croute->ageValue = conf->lastMemberQueryCount;
        }
        else
        {
            tmpRoute = findNextRoute(group, NULL);
            while(tmpRoute)
            {
                // Check for fast leave mode...
                /*
                if(tmpRoute->upstrState == ROUTESTATE_JOINED && conf->fastUpstreamLeave) 
                {
                    // Send a leave message right away..
                    sendJoinLeaveUpstream(tmpRoute, 0);
                }
                */
                // Set the routingstate to Last member check...
                tmpRoute->upstrState = ROUTESTATE_CHECK_LAST_MEMBER;
                // Set the count value for expiring... (-1 since first aging)
                tmpRoute->ageValue = conf->lastMemberQueryCount;  
                if (tmpRoute->nextroute)
                    tmpRoute = findNextRoute(group, tmpRoute->nextroute);            
                else
                    break;
            }
        }
    }
}
Example #5
0
/**
*   Should be called when a leave message is recieved, to
*   mark a route for the last member probe state.
*/
void setRouteLastMemberMode(uint32_t group) {
    struct Config       *conf = getCommonConfig();
    struct RouteTable   *croute;

    croute = findRoute(group);
    if(croute!=NULL) {
        // Check for fast leave mode...
        if(croute->upstrState == ROUTESTATE_JOINED && conf->fastUpstreamLeave) {
            // Send a leave message right away..
            sendJoinLeaveUpstream(croute, 0);
        }
        // Set the routingstate to Last member check...
        croute->upstrState = ROUTESTATE_CHECK_LAST_MEMBER;
        // Set the count value for expiring... (-1 since first aging)
        croute->ageValue = conf->lastMemberQueryCount;
    }
}
Example #6
0
/**
*   Sends a general membership query on downstream VIFs
*/
void sendGeneralMembershipQuery() {
    struct  Config  *conf = getCommonConfig();
    struct  IfDesc  *Dp;
    unsigned        Ix;

#ifdef RALINK_ESW_SUPPORT
    clear_all_entries_report();
#endif

    // Loop through all downstream vifs...
    for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
        if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
            if(Dp->state == IF_STATE_DOWNSTREAM) {
                // Send the membership query...
                sendIgmp(Dp->InAdr.s_addr, allhosts_group,
                         IGMP_MEMBERSHIP_QUERY,
                         conf->queryResponseInterval * IGMP_TIMER_SCALE, 0, 0);
                my_log(LOG_DEBUG, 0,
			"Sent membership query from %s to %s. Delay: %d",
			inetFmt(Dp->InAdr.s_addr,s1),
			inetFmt(allhosts_group,s2),
			conf->queryResponseInterval);
            }
        }
    }

    // Install timer for aging active routes.
    timer_setTimer(conf->queryResponseInterval, ageActiveRoutes, NULL);

    // Install timer for next general query...
    if(conf->startupQueryCount>0) {
        // Use quick timer...
        timer_setTimer(conf->startupQueryInterval, sendGeneralMembershipQuery, NULL);
        // Decrease startup counter...
        conf->startupQueryCount--;
    } 
    else {
        // Use slow timer...
        timer_setTimer(conf->queryInterval, sendGeneralMembershipQuery, NULL);
    }


}
Example #7
0
/**
*   Should be called when a leave message is received, to
*   mark a route for the last member probe state.
*/
void setRouteLastMemberMode(uint32_t group) {
    struct Config       *conf = getCommonConfig();
    struct RouteTable   *croute;

    croute = findRoute(group);
    if(croute!=NULL) {
        // Check for fast leave mode...
        if(croute->upstrState == ROUTESTATE_JOINED && conf->fastUpstreamLeave) {
            // Send a leave message right away only when the route has been active on only one interface
            if (numberOfInterfaces(croute) <= 1) {
                my_log(LOG_DEBUG, 0, "Leaving group %d now", group);
                sendJoinLeaveUpstream(croute, 0);
            }
        }

        // Set the routingstate to Last member check...
        croute->upstrState = ROUTESTATE_CHECK_LAST_MEMBER;

        // Set the count value for expiring... (-1 since first aging)
        croute->ageValue = conf->lastMemberQueryCount;
    }
}
Example #8
0
/***************************************************
 * TODO:    Only need run me when detect downstream changed.
 *          For example: /etc/ppp/ip-up & ip-down can touch a file /tmp/ppp_changed
 *          So I can check if the file exist then run me and delete the file.
 ***************************************************/
void rebuildIfVc () {
    struct ifreq IfVc[ sizeof( IfDescVc ) / sizeof( IfDescVc[ 0 ] )  ];
    struct ifreq *IfEp;
    struct ifconf IoCtlReq;
    struct IfDesc *Dp;
    struct ifreq  *IfPt, *IfNext;
    uint32_t addr, subnet, mask;
    int Sock, Ix;

    // Get the config.
    struct Config *config = getCommonConfig();

    if ( (Sock = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
        my_log( LOG_ERR, errno, "RAW socket open" );

    // aimwang: set all downstream IF as lost, for check IF exist or gone.
    for (Dp = IfDescVc; Dp < IfDescEp; Dp++) {
        if (Dp->state == IF_STATE_DOWNSTREAM) {
            Dp->state = IF_STATE_LOST;
        }
    }

    IoCtlReq.ifc_buf = (void *)IfVc;
    IoCtlReq.ifc_len = sizeof( IfVc );

    if ( ioctl( Sock, SIOCGIFCONF, &IoCtlReq ) < 0 )
        my_log( LOG_ERR, errno, "ioctl SIOCGIFCONF" );

    IfEp = (void *)((char *)IfVc + IoCtlReq.ifc_len);

    for ( IfPt = IfVc; IfPt < IfEp; IfPt = IfNext ) {
        struct ifreq IfReq;
        char FmtBu[ 32 ];

        IfNext = (struct ifreq *)((char *)&IfPt->ifr_addr +
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
                IfPt->ifr_addr.sa_len
#else
                sizeof(struct sockaddr_in)
#endif
        );
        if (IfNext < IfPt + 1)
            IfNext = IfPt + 1;

        for (Dp = IfDescVc; Dp < IfDescEp; Dp++) {
            if (0 == strcmp(Dp->Name, IfPt->ifr_name)) {
                break;
            }
        }

        if (Dp == IfDescEp) {
            strncpy( Dp->Name, IfPt->ifr_name, sizeof( IfDescEp->Name ) );
        }

        if ( IfPt->ifr_addr.sa_family != AF_INET ) {
            if (Dp == IfDescEp) {
                IfDescEp++;
            }
            Dp->InAdr.s_addr = 0;  /* mark as non-IP interface */
            continue;
        }

        // Get the interface adress...
        Dp->InAdr = ((struct sockaddr_in *)&IfPt->ifr_addr)->sin_addr;
        addr = Dp->InAdr.s_addr;

        memcpy( IfReq.ifr_name, Dp->Name, sizeof( IfReq.ifr_name ) );
        IfReq.ifr_addr.sa_family = AF_INET;
        ((struct sockaddr_in *)&IfReq.ifr_addr)->sin_addr.s_addr = addr;

        // Get the subnet mask...
        if (ioctl(Sock, SIOCGIFNETMASK, &IfReq ) < 0)
            my_log(LOG_ERR, errno, "ioctl SIOCGIFNETMASK for %s", IfReq.ifr_name);
        mask = ((struct sockaddr_in *)&IfReq.ifr_addr)->sin_addr.s_addr;
        subnet = addr & mask;

        if ( ioctl( Sock, SIOCGIFFLAGS, &IfReq ) < 0 )
            my_log( LOG_ERR, errno, "ioctl SIOCGIFFLAGS" );
        Dp->Flags = IfReq.ifr_flags;

        if (0x10d1 == Dp->Flags)
        {
            if ( ioctl( Sock, SIOCGIFDSTADDR, &IfReq ) < 0 )
                my_log(LOG_ERR, errno, "ioctl SIOCGIFDSTADDR for %s", IfReq.ifr_name);
            addr = ((struct sockaddr_in *)&IfReq.ifr_dstaddr)->sin_addr.s_addr;
            subnet = addr & mask;
        }

        if (Dp == IfDescEp) {
            // Insert the verified subnet as an allowed net...
            Dp->allowednets = (struct SubnetList *)malloc(sizeof(struct SubnetList));
            if(IfDescEp->allowednets == NULL) {
                my_log(LOG_ERR, 0, "Out of memory !");
            }
            Dp->allowednets->next = NULL;
            Dp->state         = IF_STATE_DOWNSTREAM;
            Dp->robustness    = DEFAULT_ROBUSTNESS;
            Dp->threshold     = DEFAULT_THRESHOLD;   /* ttl limit */
            Dp->ratelimit     = DEFAULT_RATELIMIT;
        }

        // Set the network address for the IF..
        Dp->allowednets->subnet_mask = mask;
        Dp->allowednets->subnet_addr = subnet;

        // Set the state for the IF...
        if (Dp->state == IF_STATE_LOST) {
            Dp->state         = IF_STATE_DOWNSTREAM;
        }

        // when IF become enabeld from downstream, addVIF to enable its VIF
        if (Dp->state == IF_STATE_HIDDEN) {
            my_log(LOG_NOTICE, 0, "%s [Hidden -> Downstream]", Dp->Name);
            Dp->state = IF_STATE_DOWNSTREAM;
            addVIF(Dp);
            joinMcGroup(getMcGroupSock(), Dp, allrouters_group);
        }

        // addVIF when found new IF
        if (Dp == IfDescEp) {
            my_log(LOG_NOTICE, 0, "%s [New]", Dp->Name);
            Dp->state = config->defaultInterfaceState;
            addVIF(Dp);
            joinMcGroup(getMcGroupSock(), Dp, allrouters_group);
            IfDescEp++;
        }

        // Debug log the result...
        my_log( LOG_DEBUG, 0, "rebuildIfVc: Interface %s Addr: %s, Flags: 0x%04x, Network: %s",
            Dp->Name,
            fmtInAdr( FmtBu, Dp->InAdr ),
            Dp->Flags,
            inetFmts(subnet, mask, s1));
    }

    // aimwang: search not longer exist IF, set as hidden and call delVIF
    for (Dp = IfDescVc; Dp < IfDescEp; Dp++) {
        if (IF_STATE_LOST == Dp->state) {
            my_log(LOG_NOTICE, 0, "%s [Downstream -> Hidden]", Dp->Name);
            Dp->state = IF_STATE_HIDDEN;
            leaveMcGroup( getMcGroupSock(), Dp, allrouters_group );
            delVIF(Dp);
        }
    }

    close( Sock );
}
Example #9
0
/*
** Builds up a vector with the interface of the machine. Calls to the other functions of
** the module will fail if they are called before the vector is build.
**
*/
void buildIfVc(void) {
    struct ifreq IfVc[ sizeof( IfDescVc ) / sizeof( IfDescVc[ 0 ] )  ];
    struct ifreq *IfEp;
    struct Config *config = getCommonConfig();

    int Sock;

    if ( (Sock = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
        my_log( LOG_ERR, errno, "RAW socket open" );

    /* get If vector
     */
    {
        struct ifconf IoCtlReq;

        IoCtlReq.ifc_buf = (void *)IfVc;
        IoCtlReq.ifc_len = sizeof( IfVc );

        if ( ioctl( Sock, SIOCGIFCONF, &IoCtlReq ) < 0 )
            my_log( LOG_ERR, errno, "ioctl SIOCGIFCONF" );

        IfEp = (void *)((char *)IfVc + IoCtlReq.ifc_len);
    }

    /* loop over interfaces and copy interface info to IfDescVc
     */
    {
        struct ifreq  *IfPt, *IfNext;

        // Temp keepers of interface params...
        uint32_t addr, subnet, mask;

        for ( IfPt = IfVc; IfPt < IfEp; IfPt = IfNext ) {
            struct ifreq IfReq;
            char FmtBu[ 32 ];

            IfNext = (struct ifreq *)((char *)&IfPt->ifr_addr +
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
                    IfPt->ifr_addr.sa_len
#else
                    sizeof(struct sockaddr_in)
#endif
            );
        if (IfNext < IfPt + 1)
            IfNext = IfPt + 1;

            strncpy( IfDescEp->Name, IfPt->ifr_name, sizeof( IfDescEp->Name ) );

            // Currently don't set any allowed nets...
            //IfDescEp->allowednets = NULL;

            // Set the index to -1 by default.
            IfDescEp->index = -1;

            /* don't retrieve more info for non-IP interfaces
             */
            if ( IfPt->ifr_addr.sa_family != AF_INET ) {
                IfDescEp->InAdr.s_addr = 0;  /* mark as non-IP interface */
                IfDescEp++;
                continue;
            }

            // Get the interface adress...
            IfDescEp->InAdr = ((struct sockaddr_in *)&IfPt->ifr_addr)->sin_addr;
            addr = IfDescEp->InAdr.s_addr;

            memcpy( IfReq.ifr_name, IfDescEp->Name, sizeof( IfReq.ifr_name ) );
            IfReq.ifr_addr.sa_family = AF_INET;
            ((struct sockaddr_in *)&IfReq.ifr_addr)->sin_addr.s_addr = addr;

            // Get the subnet mask...
            if (ioctl(Sock, SIOCGIFNETMASK, &IfReq ) < 0)
                my_log(LOG_ERR, errno, "ioctl SIOCGIFNETMASK for %s", IfReq.ifr_name);
            mask = ((struct sockaddr_in *)&IfReq.ifr_addr)->sin_addr.s_addr;
            subnet = addr & mask;

            /* get if flags
            **
            ** typical flags:
            ** lo    0x0049 -> Running, Loopback, Up
            ** ethx  0x1043 -> Multicast, Running, Broadcast, Up
            ** ipppx 0x0091 -> NoArp, PointToPoint, Up
            ** grex  0x00C1 -> NoArp, Running, Up
            ** ipipx 0x00C1 -> NoArp, Running, Up
            */
            if ( ioctl( Sock, SIOCGIFFLAGS, &IfReq ) < 0 )
                my_log( LOG_ERR, errno, "ioctl SIOCGIFFLAGS" );

            IfDescEp->Flags = IfReq.ifr_flags;

            // aimwang: when pppx get dstaddr for use
            if (0x10d1 == IfDescEp->Flags)
            {
                if ( ioctl( Sock, SIOCGIFDSTADDR, &IfReq ) < 0 )
                    my_log(LOG_ERR, errno, "ioctl SIOCGIFDSTADDR for %s", IfReq.ifr_name);
                addr = ((struct sockaddr_in *)&IfReq.ifr_dstaddr)->sin_addr.s_addr;
                subnet = addr & mask;
            }

            // Insert the verified subnet as an allowed net...
            IfDescEp->allowednets = (struct SubnetList *)malloc(sizeof(struct SubnetList));
            if(IfDescEp->allowednets == NULL) my_log(LOG_ERR, 0, "Out of memory !");

            // Create the network address for the IF..
            IfDescEp->allowednets->next = NULL;
            IfDescEp->allowednets->subnet_mask = mask;
            IfDescEp->allowednets->subnet_addr = subnet;

            // Set the default params for the IF...
            IfDescEp->state         = config->defaultInterfaceState;
            IfDescEp->robustness    = DEFAULT_ROBUSTNESS;
            IfDescEp->threshold     = DEFAULT_THRESHOLD;   /* ttl limit */
            IfDescEp->ratelimit     = DEFAULT_RATELIMIT;

            // Debug log the result...
            my_log( LOG_DEBUG, 0, "buildIfVc: Interface %s Addr: %s, Flags: 0x%04x, Network: %s",
                 IfDescEp->Name,
                 fmtInAdr( FmtBu, IfDescEp->InAdr ),
                 IfDescEp->Flags,
                 inetFmts(subnet,mask, s1));

            IfDescEp++;
        }
    }

    close( Sock );
}
Example #10
0
/**
*   Ages a specific route
*/
int internAgeRoute(struct RouteTable*  croute) {
    struct Config *conf = getCommonConfig();
    int result = 0;

    // Drop age by 1.
    croute->ageValue--;

    // Check if there has been any activity...
    if( croute->ageVifBits > 0 && croute->ageActivity == 0 ) {
        // There was some activity, check if all registered vifs responded.
        if(croute->vifBits == croute->ageVifBits) {
            // Everything is in perfect order, so we just update the route age.
            croute->ageValue = conf->robustnessValue;
            //croute->ageActivity = 0;
        } else {
            // One or more VIF has not gotten any response.
            croute->ageActivity++;

            // Update the actual bits for the route...
            croute->vifBits = croute->ageVifBits;
        }
    } 
    // Check if there have been activity in aging process...
    else if( croute->ageActivity > 0 ) {

        // If the bits are different in this round, we must
        if(croute->vifBits != croute->ageVifBits) {
            // Or the bits together to insure we don't lose any listeners.
            croute->vifBits |= croute->ageVifBits;

            // Register changes in this round as well..
            croute->ageActivity++;
        }
    }

    // If the aging counter has reached zero, its time for updating...
    if(croute->ageValue == 0) {
        // Check for activity in the aging process,
        if(croute->ageActivity>0) {
            
            my_log(LOG_DEBUG, 0, "Updating route after aging : %s",
                         inetFmt(croute->group,s1));
            
            // Just update the routing settings in kernel...
            internUpdateKernelRoute(croute, 1);
    
            // We append the activity counter to the age, and continue...
            croute->ageValue = croute->ageActivity;
            croute->ageActivity = 0;
        } else {

            my_log(LOG_DEBUG, 0, "Removing group %s. Died of old age.",
                         inetFmt(croute->group,s1));

            // No activity was registered within the timelimit, so remove the route.
            removeRoute(croute);
        }
        // Tell that the route was updated...
        result = 1;
    }

    // The aging vif bits must be reset for each round...
    BIT_ZERO(croute->ageVifBits);

    return result;
}
Example #11
0
/**
*   Adds a specified route to the routingtable.
*   If the route already exists, the existing route 
*   is updated...
*/
int insertRoute(uint32_t group, int ifx) {
    
    struct Config *conf = getCommonConfig();
    struct RouteTable*  croute;

    // Sanitycheck the group adress...
    if( ! IN_MULTICAST( ntohl(group) )) {
        my_log(LOG_WARNING, 0, "The group address %s is not a valid Multicast group. Table insert failed.",
            inetFmt(group, s1));
        return 0;
    }

    // Santiycheck the VIF index...
    //if(ifx < 0 || ifx >= MAX_MC_VIFS) {
    if(ifx >= MAX_MC_VIFS) {
        my_log(LOG_WARNING, 0, "The VIF Ix %d is out of range (0-%d). Table insert failed.",ifx,MAX_MC_VIFS);
        return 0;
    }

    // Try to find an existing route for this group...
    croute = findRoute(group);
    if(croute==NULL) {
        struct RouteTable*  newroute;

        my_log(LOG_DEBUG, 0, "No existing route for %s. Create new.",
                     inetFmt(group, s1));


        // Create and initialize the new route table entry..
        newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable));
        // Insert the route desc and clear all pointers...
        newroute->group      = group;
        memset(newroute->originAddrs, 0, MAX_ORIGINS * sizeof(newroute->originAddrs[0]));
        newroute->nextroute  = NULL;
        newroute->prevroute  = NULL;

        // The group is not joined initially.
        newroute->upstrState = ROUTESTATE_NOTJOINED;

        // The route is not active yet, so the age is unimportant.
        newroute->ageValue    = conf->robustnessValue;
        newroute->ageActivity = 0;
        
        BIT_ZERO(newroute->ageVifBits);     // Initially we assume no listeners.

        // Set the listener flag...
        BIT_ZERO(newroute->vifBits);    // Initially no listeners...
        if(ifx >= 0) {
            BIT_SET(newroute->vifBits, ifx);
        }

        // Check if there is a table already....
        if(routing_table == NULL) {
            // No location set, so insert in on the table top.
            routing_table = newroute;
            my_log(LOG_DEBUG, 0, "No routes in table. Insert at beginning.");
        } else {

            my_log(LOG_DEBUG, 0, "Found existing routes. Find insert location.");

            // Check if the route could be inserted at the beginning...
            if(routing_table->group > group) {
                my_log(LOG_DEBUG, 0, "Inserting at beginning, before route %s",inetFmt(routing_table->group,s1));

                // Insert at beginning...
                newroute->nextroute = routing_table;
                newroute->prevroute = NULL;
                routing_table = newroute;

                // If the route has a next node, the previous pointer must be updated.
                if(newroute->nextroute != NULL) {
                    newroute->nextroute->prevroute = newroute;
                }

            } else {

                // Find the location which is closest to the route.
                for( croute = routing_table; croute->nextroute != NULL; croute = croute->nextroute ) {
                    // Find insert position.
                    if(croute->nextroute->group > group) {
                        break;
                    }
                }

                my_log(LOG_DEBUG, 0, "Inserting after route %s",inetFmt(croute->group,s1));
                
                // Insert after current...
                newroute->nextroute = croute->nextroute;
                newroute->prevroute = croute;
                if(croute->nextroute != NULL) {
                    croute->nextroute->prevroute = newroute; 
                }
                croute->nextroute = newroute;
            }
        }

        // Set the new route as the current...
        croute = newroute;

        // Log the cleanup in debugmode...
        my_log(LOG_INFO, 0, "Inserted route table entry for %s on VIF #%d",
            inetFmt(croute->group, s1),ifx);

    } else if(ifx >= 0) {

        // The route exists already, so just update it.
        BIT_SET(croute->vifBits, ifx);
        
        // Register the VIF activity for the aging routine
        BIT_SET(croute->ageVifBits, ifx);

        // Log the cleanup in debugmode...
        my_log(LOG_INFO, 0, "Updated route entry for %s on VIF #%d",
            inetFmt(croute->group, s1), ifx);
        
        // Update route in kernel...
        if(!internUpdateKernelRoute(croute, 1)) {
            my_log(LOG_WARNING, 0, "The insertion into Kernel failed.");
            return 0;
        }
    }

    // Send join message upstream, if the route has no joined flag...
    if(croute->upstrState != ROUTESTATE_JOINED) {
        // Send Join request upstream
        sendJoinLeaveUpstream(croute, 1);
    }

    logRouteTable("Insert Route");

    return 1;
}
Example #12
0
/**
*   Remove a specified route. Returns 1 on success,
*   and 0 if route was not found.
*/
int removeRoute(struct RouteTable*  croute) 
{
    int result = 1;    
    struct RouteTable*  tmpRoute;
    struct Config       *conf = getCommonConfig();
    
    // If croute is null, no routes was found.
    if(croute==NULL) 
        return 0;

    //printf("removeRoute called\n");
    
   
    //BIT_ZERO(croute->vifBits);

    // Uninstall current route from kernel
    if(!internUpdateKernelRoute(croute, 0)) 
    {
        //printf("The removal from Kernel failed.\n");
        atlog(LOG_WARNING, 0, "The removal from Kernel failed.");
        result = 0;
    }

    // Send Leave request upstream if group is joined
    if(croute->upstrState == ROUTESTATE_JOINED || 
       (croute->upstrState == ROUTESTATE_CHECK_LAST_MEMBER && !conf->fastUpstreamLeave)) 
    {
        tmpRoute = findNextRoute( &(croute->group), NULL);
        if (tmpRoute && tmpRoute->nextroute)
            tmpRoute = findNextRoute( &(croute->group), tmpRoute->nextroute);

        // the group is not used by others
        if (tmpRoute == NULL)
            sendJoinLeaveUpstream(croute, 0);
    }

    // Update pointers...
    if(croute->prevroute == NULL)
    {
        // Topmost node...
        if(croute->nextroute != NULL) 
        {
            croute->nextroute->prevroute = NULL;
        }
        routing_table = croute->nextroute;

    } 
    else
    {
        croute->prevroute->nextroute = croute->nextroute;
        if(croute->nextroute != NULL) 
        {
            croute->nextroute->prevroute = croute->prevroute;
        }
    }
    // Free the memory, and set the route to NULL...
    free(croute);
    croute = NULL;

    IF_DEBUG atlogRouteTable("Remove route");
    return result;
}
Example #13
0
/**
*   Adds a specified route to the routingtable.
*   If the route already exists, the existing route 
*   is updated...
*/
int insertRoute(struct in6_addr *group, struct in6_addr *src, struct sockaddr_in6 *from) 
{
    struct Config *conf = getCommonConfig();
    struct RouteTable *croute, *tmpRoute;
    //int result = 1;
/*
    int i;
    printf("insertRoute called\n");

    for (i = 0; i < 16; i ++)
        printf("%02x ", ((char*)group)[i] & 255 );
    printf("\n");

    for (i = 0; i < 16; i ++)
        printf("%02x ", ((char*)src)[i] & 255 );
    printf("\n");
*/
    

    // Sanitycheck the group adress...
    if ( !IN6_IS_ADDR_MULTICAST(group) ) 
    {
        atlog( LOG_DEBUG, 0, "Not multicast group");    
        return 0;
    }

    // Santiycheck the VIF index...
    if(from->sin6_scope_id >= MAX_MC_VIFS) 
    {
        atlog(LOG_WARNING, 0, "The VIF Ix %d is out of range (0-%d). Table insert failed.",
              from->sin6_scope_id,MAX_MC_VIFS);
        return 0;
    }

    // Try to find an existing route for this group...
    croute = findRoute(group, src);
    
    if(croute==NULL)
    {
        struct RouteTable*  newroute;

        /*
        IF_DEBUG atlog(LOG_DEBUG, 0, "No existing route for %s. Create new.",
                     inetFmt(group, s1));
        */

        // Create and initialize the new route table entry..
        newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable));
        // Insert the route desc and clear all pointers...
        newroute->group = *group;
        newroute->originAddr = *src;
        
        newroute->nextroute  = NULL;
        newroute->prevroute  = NULL;

        // The group is not joined initially.
        newroute->upstrState = ROUTESTATE_NOTJOINED;

        // The route is not active yet, so the age is unimportant.
        newroute->ageValue    = conf->robustnessValue;
        newroute->ageActivity = 0;
        
        BIT_ZERO(newroute->ageVifBits);     // Initially we assume no listeners.

        // Set the listener flag...
        BIT_ZERO(newroute->vifBits);    // Initially no listeners...
        if(from->sin6_scope_id >= 0) 
        {
            BIT_SET(newroute->vifBits, from->sin6_scope_id);
        }

        // Check if there is a table already....
        if(routing_table == NULL) 
        {
            // No location set, so insert in on the table top.
            routing_table = newroute;
            IF_DEBUG atlog(LOG_DEBUG, 0, "No routes in table. Insert at beginning.");
        }
        else 
        {
            IF_DEBUG atlog(LOG_DEBUG, 0, "Found existing routes. Find insert location.");

            // Check if the route could be inserted at the beginning...
            if( memcmp(&routing_table->group, group, sizeof(struct in6_addr)) > 0 ) 
            {
                //IF_DEBUG atlog(LOG_DEBUG, 0, "Inserting at beginning, before route %s",inetFmt(routing_table->group,s1));

                // Insert at beginning...
                newroute->nextroute = routing_table;
                newroute->prevroute = NULL;
                routing_table = newroute;

                // If the route has a next node, the previous pointer must be updated.
                if(newroute->nextroute != NULL) 
                {
                    newroute->nextroute->prevroute = newroute;
                }

            } 
            else 
            {
                // Find the location which is closest to the route.
                for( croute = routing_table; croute->nextroute != NULL; croute = croute->nextroute ) 
                {
                    // Find insert position.
                    if( memcmp( &(croute->nextroute->group), group, sizeof(struct in6_addr) ) > 0 ) 
                        break;
                }

                //IF_DEBUG atlog(LOG_DEBUG, 0, "Inserting after route %s",inetFmt(croute->group,s1));
                
                // Insert after current...
                newroute->nextroute = croute->nextroute;
                newroute->prevroute = croute;
                if(croute->nextroute != NULL) 
                {
                    croute->nextroute->prevroute = newroute; 
                }
                croute->nextroute = newroute;
            }
        }

        // Set the new route as the current...
        croute = newroute;

     
        if( !IN6_ARE_ADDR_EQUAL( &croute->originAddr, &allzero_addr) ) 
        {
            // Update route in kernel...
            if( !internUpdateKernelRoute(croute, 1) ) 
            {
                atlog(LOG_WARNING, 0, "The insertion into Kernel failed.");
                return 0;
            }
        }    
    } 
    else if(from->sin6_scope_id >= 0) 
    {
        if( !IN6_ARE_ADDR_EQUAL( &croute->originAddr, &allzero_addr) ) 
        {
            // The route exists already, so just update it.
            BIT_SET(croute->vifBits, from->sin6_scope_id);
            
            // Register the VIF activity for the aging routine
            BIT_SET(croute->ageVifBits, from->sin6_scope_id);
        }
        else
        {
            tmpRoute = findNextRoute(group, NULL);
            while (tmpRoute != NULL)
            {
                // The route exists already, so just update it.
                BIT_SET(tmpRoute->vifBits, from->sin6_scope_id);
                
                // Register the VIF activity for the aging routine
                BIT_SET(tmpRoute->ageVifBits, from->sin6_scope_id);
                if (tmpRoute->nextroute)
                    tmpRoute = findNextRoute(group, tmpRoute->nextroute);  
                else
                    break;
            }
        }
    }

    // Send join message upstream, if the route has no joined flag...
    if(croute->upstrState != ROUTESTATE_JOINED)
    {
        // Send Join request upstream
        sendJoinLeaveUpstream(croute, 1);
    }

    IF_DEBUG atlogRouteTable("Insert Route");
    return 1;
}