/** * Handles the initial startup of the daemon. */ int igmpProxyInit() { struct sigaction sa; int Err; sa.sa_handler = signalHandler; sa.sa_flags = 0; /* Interrupt system calls */ sigemptyset(&sa.sa_mask); sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); // Loads configuration for Physical interfaces... buildIfVc(); // Configures IF states and settings configureVifs(); switch ( Err = enableMRouter() ) { case 0: break; case EADDRINUSE: my_log( LOG_ERR, EADDRINUSE, "MC-Router API already in use" ); break; default: my_log( LOG_ERR, Err, "MRT_INIT failed" ); } /* create VIFs for all IP, non-loop interfaces */ { unsigned Ix; struct IfDesc *Dp; int vifcount = 0; upStreamVif = -1; for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) { if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) { if(Dp->state == IF_STATE_UPSTREAM) { if(upStreamVif == -1) { upStreamVif = Ix; } else { my_log(LOG_ERR, 0, "Vif #%d was already upstream. Cannot set VIF #%d as upstream as well.", upStreamVif, Ix); } } addVIF( Dp ); vifcount++; } } // If there is only one VIF, or no defined upstream VIF, we send an error. if(vifcount < 2 || upStreamVif < 0) { my_log(LOG_ERR, 0, "There must be at least 2 Vif's where one is upstream."); } } // Initialize IGMP initIgmp(); // Initialize Routing table initRouteTable(); // Initialize timer callout_init(); return 1; }
/*************************************************** * 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 ); }