int delMRoute( struct MRouteDesc *Dp ) /* ** Removes the multicast routed '*Dp' from the kernel routes ** ** returns: - 0 if the function succeeds ** - the errno value for non-fatal failure condition */ { struct mfcctl CtlReq; CtlReq.mfcc_origin = Dp->OriginAdr; CtlReq.mfcc_mcastgrp = Dp->McAdr; CtlReq.mfcc_parent = Dp->InVif; /* clear the TTL vector */ memset( CtlReq.mfcc_ttls, 0, sizeof( CtlReq.mfcc_ttls ) ); { char FmtBuO[ 32 ], FmtBuM[ 32 ]; log( LOG_NOTICE, 0, "removing MFC: %s -> %s, InpVIf: %d", fmtInAdr( FmtBuO, CtlReq.mfcc_origin ), fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ), CtlReq.mfcc_parent == ALL_VIFS ? -1 : CtlReq.mfcc_parent ); } if( setsockopt( MRouterFD, IPPROTO_IP, MRT_DEL_MFC, (void *)&CtlReq, sizeof( CtlReq ) ) ) log( LOG_WARNING, errno, "MRT_DEL_MFC" ); }
/* ** Removes the multicast routed '*Dp' from the kernel routes ** ** returns: - 0 if the function succeeds ** - the errno value for non-fatal failure condition */ int delMRoute( struct MRouteDesc *Dp ) { struct mfcctl CtlReq; int rc; CtlReq.mfcc_origin = Dp->OriginAdr; CtlReq.mfcc_mcastgrp = Dp->McAdr; CtlReq.mfcc_parent = Dp->InVif; /* clear the TTL vector */ memset( CtlReq.mfcc_ttls, 0, sizeof( CtlReq.mfcc_ttls ) ); { char FmtBuO[ 32 ], FmtBuM[ 32 ]; my_log( LOG_NOTICE, 0, "Removing MFC: %s -> %s, InpVIf: %d", fmtInAdr( FmtBuO, CtlReq.mfcc_origin ), fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ), (int)CtlReq.mfcc_parent ); } rc = setsockopt( MRouterFD, IPPROTO_IP, MRT_DEL_MFC, (void *)&CtlReq, sizeof( CtlReq ) ); if (rc) my_log( LOG_DEBUG, errno, "MRT_DEL_MFC" ); return rc; }
/* ** Adds the multicast routed '*Dp' to the kernel routes ** ** returns: - 0 if the function succeeds ** - the errno value for non-fatal failure condition */ int addMRoute( struct MRouteDesc *Dp ) { struct mfcctl CtlReq; int rc; CtlReq.mfcc_origin = Dp->OriginAdr; CtlReq.mfcc_mcastgrp = Dp->McAdr; CtlReq.mfcc_parent = Dp->InVif; /* copy the TTL vector */ memcpy( CtlReq.mfcc_ttls, Dp->TtlVc, sizeof( CtlReq.mfcc_ttls ) ); { char FmtBuO[ 32 ], FmtBuM[ 32 ]; my_log( LOG_NOTICE, 0, "Adding MFC: %s -> %s, InpVIf: %d", fmtInAdr( FmtBuO, CtlReq.mfcc_origin ), fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ), (int)CtlReq.mfcc_parent ); } rc = setsockopt( MRouterFD, IPPROTO_IP, MRT_ADD_MFC, (void *)&CtlReq, sizeof( CtlReq ) ); if (rc) my_log( LOG_WARNING, errno, "MRT_ADD_MFC" ); return rc; }
int addMRoute( struct MRouteDesc *Dp ) /* ** Adds the multicast routed '*Dp' to the kernel routes ** ** returns: - 0 if the function succeeds ** - the errno value for non-fatal failure condition */ { struct mfcctl CtlReq; CtlReq.mfcc_origin = Dp->OriginAdr; // Kaohj // CtlReq.mfcc_subscriber = Dp->SubsAdr; CtlReq.mfcc_mcastgrp = Dp->McAdr; CtlReq.mfcc_parent = Dp->InVif; /* copy the TTL vector */ if( sizeof( CtlReq.mfcc_ttls ) != sizeof( Dp->TtlVc ) || VCMC( CtlReq.mfcc_ttls ) != VCMC( Dp->TtlVc ) ) log( LOG_ERR, 0, "data types doesn't match in " __FILE__ ", source adaption needed !" ); memcpy( CtlReq.mfcc_ttls, Dp->TtlVc, sizeof( CtlReq.mfcc_ttls ) ); { char FmtBuO[ 32 ], FmtBuM[ 32 ]; log( LOG_DEBUG, 0, "adding MFC: %s -> %s, InpVIf: %d", fmtInAdr( FmtBuO, CtlReq.mfcc_origin ), fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ), CtlReq.mfcc_parent == ALL_VIFS ? -1 : CtlReq.mfcc_parent ); } if( setsockopt( MRouterFD, IPPROTO_IP, MRT_ADD_MFC, (void *)&CtlReq, sizeof( CtlReq ) ) ) log( LOG_WARNING, errno, "MRT_ADD_MFC" ); return errno; }
/*************************************************** * 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 ); }