/* ** Adds the interface '*IfDp' as virtual interface to the mrouted API ** */ void addVIF( struct IfDesc *IfDp ) { struct vifctl VifCtl; struct VifDesc *VifDp; /* search free VifDesc */ for ( VifDp = VifDescVc; VifDp < VCEP( VifDescVc ); VifDp++ ) { if ( ! VifDp->IfDp ) break; } /* no more space */ if ( VifDp >= VCEP( VifDescVc ) ) my_log( LOG_ERR, ENOMEM, "addVIF, out of VIF space" ); VifDp->IfDp = IfDp; VifCtl.vifc_vifi = VifDp - VifDescVc; VifCtl.vifc_flags = 0; /* no tunnel, no source routing, register ? */ VifCtl.vifc_threshold = VifDp->IfDp->threshold; // Packet TTL must be at least 1 to pass them VifCtl.vifc_rate_limit = VifDp->IfDp->ratelimit; // Ratelimit VifCtl.vifc_lcl_addr.s_addr = VifDp->IfDp->InAdr.s_addr; VifCtl.vifc_rmt_addr.s_addr = INADDR_ANY; // Set the index... VifDp->IfDp->index = VifCtl.vifc_vifi; my_log( LOG_NOTICE, 0, "adding VIF, Ix %d Fl 0x%x IP 0x%08x %s, Threshold: %d, Ratelimit: %d", VifCtl.vifc_vifi, VifCtl.vifc_flags, VifCtl.vifc_lcl_addr.s_addr, VifDp->IfDp->Name, VifCtl.vifc_threshold, VifCtl.vifc_rate_limit); struct SubnetList *currSubnet; for(currSubnet = IfDp->allowednets; currSubnet; currSubnet = currSubnet->next) { my_log(LOG_DEBUG, 0, " Network for [%s] : %s", IfDp->Name, inetFmts(currSubnet->subnet_addr, currSubnet->subnet_mask, s1)); } if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_ADD_VIF, (char *)&VifCtl, sizeof( VifCtl ) ) ) my_log( LOG_ERR, errno, "MRT_ADD_VIF" ); }
/** * Parses a subnet address string on the format * a.b.c.d/n into a SubnetList entry. */ struct SubnetList *parseSubnetAddress(char *addrstr) { struct SubnetList *tmpSubnet; char *tmpStr; uint32 addr = 0x00000000; uint32 mask = 0xFFFFFFFF; // First get the network part of the address... tmpStr = strtok(addrstr, "/"); addr = inet_addr(tmpStr); tmpStr = strtok(NULL, "/"); if(tmpStr != NULL) { int bitcnt = atoi(tmpStr); if(bitcnt < 0 || bitcnt > 32) { log(LOG_WARNING, 0, "The bits part of the address is invalid : %d.", bitcnt); return NULL; } if (bitcnt) { mask <<= (32 - bitcnt); } else { mask = 0; } } if(addr == -1) { log(LOG_WARNING, 0, "Unable to parse address token '%s'.", addrstr); return NULL; } tmpSubnet = (struct SubnetList*) malloc(sizeof(struct SubnetList)); tmpSubnet->subnet_addr = addr; tmpSubnet->subnet_mask = ntohl(mask); tmpSubnet->next = NULL; IF_DEBUG log(LOG_DEBUG, 0, "Config: IF: Altnet: Parsed altnet to %s.", inetFmts(tmpSubnet->subnet_addr, tmpSubnet->subnet_mask,s1)); return tmpSubnet; }
/*************************************************** * 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 ); }
/* ** 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 ); }