Example #1
0
void sendJoinLeaveUpstream(struct RouteTable* route, int join) 
{  
    struct IfDesc*      upstrIf;
    // Get the upstream VIF...
    upstrIf = getIfByIx( upStreamVif );
    
    if(upstrIf == NULL) 
    {
        atlog(LOG_ERR, 0 ,"FATAL: Unable to get Upstream IF.");
    }

    // Send join or leave request...
    if(join) 
    {
        // Only join a group if there are listeners downstream...
        if(route->vifBits > 0) 
        {
            joinMcGroup( getMcGroupSock(), upstrIf, &route->group );
            route->upstrState = ROUTESTATE_JOINED;
        } 
    } 
    else 
    {
        // Only leave if group is not left already...
        if(route->upstrState != ROUTESTATE_NOTJOINED) 
        {
            leaveMcGroup( getMcGroupSock(), upstrIf, &route->group );
            route->upstrState = ROUTESTATE_NOTJOINED;
        }
    }
}
Example #2
0
/**
*   Internal function to send join or leave requests for
*   a specified route upstream...
*/
void sendJoinLeaveUpstream(struct RouteTable* route, int join) {
    struct IfDesc*      upstrIf;
    
    // Get the upstream VIF...
    upstrIf = getIfByIx( upStreamVif );
    if(upstrIf == NULL) {
        my_log(LOG_ERR, 0 ,"FATAL: Unable to get Upstream IF.");
    }

    // Check if there is a white list for the upstram VIF
    if (upstrIf->allowedgroups != NULL) {
      uint32_t           group = route->group;
        struct SubnetList* sn;

        // Check if this Request is legit to be forwarded to upstream
        for(sn = upstrIf->allowedgroups; sn != NULL; sn = sn->next)
            if((group & sn->subnet_mask) == sn->subnet_addr)
                // Forward is OK...
                break;

        if (sn == NULL) {
	    my_log(LOG_INFO, 0, "The group address %s may not be forwarded upstream. Ignoring.", inetFmt(group, s1));
            return;
        }
    }

    // Send join or leave request...
    if(join) {

        // Only join a group if there are listeners downstream...
        if(route->vifBits > 0) {
            my_log(LOG_DEBUG, 0, "Joining group %s upstream on IF address %s",
                         inetFmt(route->group, s1), 
                         inetFmt(upstrIf->InAdr.s_addr, s2));

            //k_join(route->group, upstrIf->InAdr.s_addr);
            joinMcGroup( getMcGroupSock(), upstrIf, route->group );

            route->upstrState = ROUTESTATE_JOINED;
        } else {
            my_log(LOG_DEBUG, 0, "No downstream listeners for group %s. No join sent.",
                inetFmt(route->group, s1));
        }

    } else {
        // Only leave if group is not left already...
        if(route->upstrState != ROUTESTATE_NOTJOINED) {
            my_log(LOG_DEBUG, 0, "Leaving group %s upstream on IF address %s",
                         inetFmt(route->group, s1), 
                         inetFmt(upstrIf->InAdr.s_addr, s2));
            
            //k_leave(route->group, upstrIf->InAdr.s_addr);
            leaveMcGroup( getMcGroupSock(), upstrIf, route->group );

            route->upstrState = ROUTESTATE_NOTJOINED;
        }
    }
}
Example #3
0
/**
*   Initializes the routing table.
*/
void initRouteTable() {
    unsigned Ix;
    struct IfDesc *Dp;

    // Clear routing table...
    routing_table = NULL;

    // Join the all routers group on downstream vifs...
    for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
        // If this is a downstream vif, we should join the All routers group...
        if( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) && Dp->state == IF_STATE_DOWNSTREAM) {
            my_log(LOG_DEBUG, 0, "Joining all-routers group %s on vif %s",
                         inetFmt(allrouters_group,s1),inetFmt(Dp->InAdr.s_addr,s2));
            
            //k_join(allrouters_group, Dp->InAdr.s_addr);
            joinMcGroup( getMcGroupSock(), Dp, allrouters_group );

            my_log(LOG_DEBUG, 0, "Joining all igmpv3 multicast routers group %s on vif %s",
                         inetFmt(alligmp3_group,s1),inetFmt(Dp->InAdr.s_addr,s2));
            joinMcGroup( getMcGroupSock(), Dp, alligmp3_group );
        }
    }
}
Example #4
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 );
}