static int imp_get_is_forward(imp_interface* p_if, pi_addr *pigp, pi_addr *pip) { imp_source *msp = NULL; imp_group* p_gp; struct timeval now; if (get_sysuptime(&now) == -1) { IMP_LOG_ERROR("can't get sysuptime\n"); return 0; } p_gp = imp_get_group_if_addr(p_if, pigp); if (p_gp == NULL) { return 0; } if (p_gp->type == GROUP_INCLUDE) { for (msp = LIST_FIRST(&p_gp->src_list);msp; msp = LIST_NEXT(msp, link)) { if (memcmp(&msp->src_addr, pip, sizeof(pi_addr)) == 0 && TIMEVAL_LT(now, msp->timer->tm)) return 1; } return 0; }else if (p_gp->type == GROUP_EXCLUDE) { for (msp = LIST_FIRST(&p_gp->src_list);msp; msp = LIST_NEXT(msp, link)) { if (memcmp(&msp->src_addr, pip, sizeof(pi_addr)) == 0 && TIMEVAL_LT(msp->timer->tm, now)) return 0; } return 1; } return 0; }
/*----------------------------------------------------------------------- * Name : imp_source_is_scheduled * * Brief : check if source member is scheduled to be inlcuded group source specific query * Params : [in] p_is -- source member [in] sflag -- 1:member's timer is greater than LMQT 0:member's timer is less than LMQT * Return : 1:exsit 0:not exsit *------------------------------------------------------------------------ */ int imp_source_is_scheduled(imp_source *p_is, int sflag) { struct timeval lmqt; if(TIMEVAL_ISZERO(p_is->timer->tm) || p_is->times == 0 ) return 0; imp_time_val(TIMER_LMQT, &lmqt); if(sflag == 1 && TIMEVAL_LT(lmqt, p_is->timer->tm)) return 1; else if (sflag == 0 && TIMEVAL_LEQ(p_is->timer->tm, lmqt)) { return 1; } return 0; }
static struct timeval * rtsol_check_timer(void) { static struct timeval returnval; struct timeval now, rtsol_timer; struct ifinfo *ifinfo; int flags; gettimeofday(&now, NULL); rtsol_timer = tm_max; for (ifinfo = iflist; ifinfo; ifinfo = ifinfo->next) { if (TIMEVAL_LEQ(ifinfo->expire, now)) { if (dflag > 1) warnmsg(LOG_DEBUG, __func__, "timer expiration on %s, " "state = %d", ifinfo->ifname, ifinfo->state); switch (ifinfo->state) { case IFS_DOWN: case IFS_TENTATIVE: /* interface_up returns 0 on success */ flags = interface_up(ifinfo->ifname); if (flags == 0) ifinfo->state = IFS_DELAY; else if (flags == IFS_TENTATIVE) ifinfo->state = IFS_TENTATIVE; else ifinfo->state = IFS_DOWN; break; case IFS_IDLE: { int oldstatus = ifinfo->active; int probe = 0; ifinfo->active = interface_status(ifinfo); if (oldstatus != ifinfo->active) { warnmsg(LOG_DEBUG, __func__, "%s status is changed" " from %d to %d", ifinfo->ifname, oldstatus, ifinfo->active); probe = 1; ifinfo->state = IFS_DELAY; } else if (ifinfo->probeinterval && (ifinfo->probetimer -= ifinfo->timer.tv_sec) <= 0) { /* probe timer expired */ ifinfo->probetimer = ifinfo->probeinterval; probe = 1; ifinfo->state = IFS_PROBE; } if (probe && mobile_node) defrouter_probe(ifinfo->sdl->sdl_index); break; } case IFS_DELAY: ifinfo->state = IFS_PROBE; sendpacket(ifinfo); break; case IFS_PROBE: if (ifinfo->probes < MAX_RTR_SOLICITATIONS) sendpacket(ifinfo); else { warnmsg(LOG_INFO, __func__, "No answer " "after sending %d RSs", ifinfo->probes); ifinfo->probes = 0; ifinfo->state = IFS_IDLE; } break; } rtsol_timer_update(ifinfo); } if (TIMEVAL_LT(ifinfo->expire, rtsol_timer)) rtsol_timer = ifinfo->expire; } if (TIMEVAL_EQ(rtsol_timer, tm_max)) { warnmsg(LOG_DEBUG, __func__, "there is no timer"); return(NULL); } else if (TIMEVAL_LT(rtsol_timer, now)) /* this may occur when the interval is too small */ returnval.tv_sec = returnval.tv_usec = 0; else TIMEVAL_SUB(&rtsol_timer, &now, &returnval); if (dflag > 1) warnmsg(LOG_DEBUG, __func__, "New timer is %ld:%08ld", (long)returnval.tv_sec, (long)returnval.tv_usec); return(&returnval); }
/*----------------------------------------------------------------------- * Name : group_source_specific_timer_handler * * Brief : timer handler to send Group-and-Source-Specific Query * Params : [in] data -- struct sch_event * Return : new timer *------------------------------------------------------------------------ */ imp_timer* group_source_specific_timer_handler(void *data) { IMP_LOG_DEBUG("Enter\n"); imp_group *p_gp = data; imp_interface *p_if = p_gp->parent_if; struct timeval lqmt; imp_source *p_is; /*When building a group and source specific query for a group G, two *separate query messages are sent for the group. The first one has *the "Suppress Router-Side Processing" bit set and contains all the *sources with retransmission state and timers greater than LMQT. The *second has the "Suppress Router-Side Processing" bit clear and *contains all the sources with retransmission state and timers lower *or equal to LMQT. If either of the two calculated messages does not *contain any sources, then its transmission is suppressed. *rfc 3376 Section 6.6.3.2 */ if(imp_source_find_scheduled(p_gp, TRUE) != NULL) {/*Suppress Router-Side Processing 1*/ send_igmp_mld_query(p_if, p_gp->version, &p_gp->group_addr, &p_gp->group_addr, LIST_FIRST(&p_gp->src_list), 1); } if(imp_source_find_scheduled(p_gp, FALSE) != NULL) { send_igmp_mld_query(p_if, p_gp->version, &p_gp->group_addr, &p_gp->group_addr, LIST_FIRST(&p_gp->src_list), 0); } for(p_is = LIST_FIRST(&p_gp->src_list); p_is; p_is = LIST_NEXT(p_is, link)){ if(p_is->times) p_is->times--; } /* When a table action "Send Q(G)" is encountered, then the group timer * must be lowered to LMQT. The router must then immediately send a * group specific query as well as schedule [Last Member Query Count - * 1] query retransmissions to be sent every [Last Member Query * Interval] over [Last Member Query Time]. * When transmitting a group specific query, if the group timer is * larger than LMQT, the "Suppress Router-Side Processing" bit is set in * the query message. * rfc 3376 Section 6.6.3.1 */ imp_time_val(TIMER_LMQT, &lqmt); if (p_gp->gs_sch_times != 0 ) { if(TIMEVAL_LT(lqmt, p_gp->timer->tm))/*Suppress Router-Side Processing 1*/ { IMP_LOG_DEBUG("TIMEVAL_LT %d %d\n", lqmt.tv_sec, p_gp->timer->tm.tv_sec); send_igmp_mld_query(p_if, p_gp->version, &p_gp->group_addr, &p_gp->group_addr, NULL, TRUE); } else send_igmp_mld_query(p_if, p_gp->version, &p_gp->group_addr, &p_gp->group_addr, NULL, FALSE); p_gp->gs_sch_times--; } /*update timer*/ if (p_gp->gs_sch_times == 0 && imp_source_find_scheduled(p_gp, FALSE) == NULL && imp_source_find_scheduled(p_gp, TRUE) == NULL) { IMP_LOG_DEBUG("REMOVE\n"); imp_remove_timer(&p_gp->sch_timer); } else imp_set_timer(TIMER_LMQI, p_gp->sch_timer); return p_gp->sch_timer; }
void mcast_block_handler(imp_interface *p_if, pi_addr *p_ga, pa_list* p_src_list, im_version version) { imp_group *p_gp = NULL; pa_list *p_node = NULL;; p_gp = imp_group_find(p_if, p_ga); if (p_gp != NULL) { imp_source *p_is = NULL, *p_is_next = NULL; int enable_sch = 0; struct timeval lmqt; imp_time_val(TIMER_LMQT, &lmqt); if (p_gp->version < version && version == IM_IGMPv3_MLDv2) { IMP_LOG_INFO("Group %s Group Compatibility Mode" \ "is lesser than IGMPV3\n", imp_pi_ntoa(&p_gp->group_addr)); return; } /*update version timer*/ imp_group_version_timer_update(p_gp, version); if(p_gp->type == GROUP_INCLUDE) { /*INCLUDE (A) BLOCK (B) INCLUDE (A) Send Q(G, A*B)*/ for(p_is = LIST_FIRST(&p_gp->src_list); p_is; p_is = p_is_next) { if (pa_list_find(p_src_list, &p_is->src_addr) != NULL && TIMEVAL_LT(lmqt, p_is->timer->tm)) { imp_set_timer(TIMER_LMQT, p_is->timer); p_is->times = DEFAULT_RV; enable_sch = 1; } } } else { /*EXCLUDE (X, Y) BLOCK (A) EXCLUDE (X+(A-Y), Y) (A-X-Y)=Group Timer Send Q(G, A-Y)*/ for (p_node = p_src_list ;p_node; p_node = p_node->next ){ if (imp_source_find(p_gp, &p_node->addr, BLOCKING) == NULL) { p_is = imp_source_find(p_gp, &p_node->addr, FORWARDING); if (p_is == NULL) { p_is = imp_source_create(p_gp, &p_node->addr, FORWARDING); /*(A-X-Y)=Group Timer*/ memcpy(&p_is->timer->tm, &p_gp->timer->tm, sizeof(struct timeval)); } /*Send Q(G, A-Y)*/ if(TIMEVAL_LT(lmqt, p_is->timer->tm)) { p_is->times = DEFAULT_RV; enable_sch = 1; imp_set_timer(TIMER_LMQT, p_is->timer); } } } } if(enable_sch && p_gp->sch_timer == NULL ) { p_gp->sch_timer = imp_add_timer(group_source_specific_timer_handler, p_gp); imp_set_timer(0, p_gp->sch_timer); } return; } }
void mcast_to_in_handler(imp_interface *p_if, pi_addr *p_ga, pa_list* p_src_list, im_version version) { imp_group *p_gp; pa_list *p_node = NULL; struct timeval lmqt; imp_time_val(TIMER_LMQT, &lmqt); p_gp = imp_group_find(p_if, p_ga); if (p_gp != NULL) { IMP_LOG_DEBUG("Leave Group %s\n", imp_pi_ntoa(p_ga)); if (p_gp->version < version) { IMP_LOG_WARNING("%s's Group Compatibility Mode is IGMPv1.\n", imp_pi_ntoa(p_ga)); return; } if (p_gp->type == GROUP_INCLUDE) { /*INCLUDE (A) TO_IN (B) INCLUDE (A+B) (B)=GMI Send Q(G, A-B) */ imp_source *p_is = NULL; for (p_is = LIST_FIRST(&p_gp->src_list); p_is; p_is = LIST_NEXT(p_is, link)) { if (pa_list_find(p_src_list, &p_is->src_addr) == NULL) { /* Send Q(G, A-B)*/ if(TIMEVAL_LT(lmqt, p_is->timer->tm)) { p_is->times = DEFAULT_RV; imp_set_timer(TIMER_LMQT, p_is->timer); } } else { imp_set_timer(TIMER_GMI, p_is->timer); } } for(p_node = p_src_list; p_node; p_node = p_node->next) { if (imp_source_find(p_gp, &p_node->addr, FORWARDING) == NULL){ imp_source_create(p_gp, &p_node->addr, FORWARDING);/*forward*/ } } } else { /*EXCLUDE (X, Y) TO_IN (A) EXCLUDE (X+A, Y-A) (A)=GMI * Send Q(G, X-A) * Send Q(G) */ imp_source *p_is = NULL, *p_is_next = NULL; /*Y-A*/ for (p_is = LIST_FIRST(&p_gp->src_list); p_is; p_is = p_is_next) { p_is_next = LIST_NEXT(p_is, link); if(!TIMEVAL_ISZERO(p_is->timer->tm)) continue; if (pa_list_find(p_src_list, &p_is->src_addr) != NULL) { imp_source_cleanup(p_is); } } for (p_is = LIST_FIRST(&p_gp->src_list); p_is; p_is = LIST_NEXT(p_is, link)) { if(TIMEVAL_ISZERO(p_is->timer->tm)) continue; if (pa_list_find(p_src_list, &p_is->src_addr) == NULL) { /*Send Q(G, X-A)*/ if(TIMEVAL_LT(lmqt, p_is->timer->tm)) { p_is->times = DEFAULT_RV; imp_set_timer(TIMER_LMQT, p_is->timer); } } else { imp_set_timer(TIMER_GMI, p_is->timer); } } for(p_node = p_src_list; p_node; p_node = p_node->next) { if (imp_source_find(p_gp, &p_node->addr, FORWARDING) == NULL){ imp_source_create(p_gp, &p_node->addr, FORWARDING);/*forward*/ } } /*Send Q(G)*/ if(p_gp->gs_sch_times == 0) { IMP_LOG_DEBUG("Send Q(G)\n"); p_gp->gs_sch_times = DEFAULT_RV; imp_set_timer(TIMER_LMQT, p_gp->timer); } } if(p_gp->sch_timer == NULL) { p_gp->sch_timer = imp_add_timer( group_source_specific_timer_handler, p_gp); imp_set_timer(0, p_gp->sch_timer); } return; } if(p_src_list == NULL) return; IMP_LOG_DEBUG("Can't find group %s, will create it\n", imp_pi_ntoa(p_ga)); p_gp = imp_group_create(p_if, p_ga, p_src_list, GROUP_INCLUDE, version); if (p_gp == NULL) { IMP_LOG_ERROR("imp_group_create failed"); return; } imp_group_print(p_if); }
void mcast_to_ex_hander(imp_interface *p_if, pi_addr *p_ga, pa_list* p_src_list, im_version version) { imp_group *p_gp = NULL; pa_list *p_node = NULL;; p_gp = imp_group_find(p_if, p_ga); if (p_gp != NULL) { imp_source *p_is = NULL, *p_is_next = NULL; int enable_sch = 0; struct timeval lmqt; imp_time_val(TIMER_LMQT, &lmqt); if (p_gp->version < version && version == IM_IGMPv3_MLDv2) { IMP_LOG_INFO("Group %s Group Compatibility Mode" \ "is lesser than IGMPV3\n", imp_pi_ntoa(&p_gp->group_addr)); return; } /*update version timer*/ imp_group_version_timer_update(p_gp, version); if(p_gp->type == GROUP_INCLUDE) { /* Router State Report Rec'd New Router State Actions * ------------ ------------ ---------------- ------- * INCLUDE (A) TO_EX (B) EXCLUDE (A*B, B-A) (B-A)=0 * Send Q(G, A*B) * Delete (A-B) * Group Timer=GMI */ for (p_is = LIST_FIRST(&p_gp->src_list); p_is ; p_is = p_is_next) { p_is_next = LIST_NEXT(p_is, link); if(pa_list_find(p_src_list, &p_is->src_addr) == NULL) { /*Delete (A-B)*/ imp_source_cleanup(p_is); } else if(TIMEVAL_LT(lmqt, p_is->timer->tm)) { /*Send Q(G, A*B)*/ imp_set_timer(TIMER_LMQT, p_is->timer); p_is->times = DEFAULT_RV; enable_sch = 1; } } for(p_node = p_src_list; p_node; p_node = p_node->next) { if (imp_source_find(p_gp, &p_node->addr, FORWARDING) == NULL){ /*(B-A)=0*/ imp_source_create(p_gp, &p_node->addr, BLOCKING);/*forward or not*/ } } p_gp->type = GROUP_EXCLUDE; p_gp->timer = imp_add_timer(group_timer_handler, p_gp); /*Group Timer=GMI*/ imp_set_timer(TIMER_GMI, p_gp->timer); } else { /* Router State Report Rec'd New Router State Actions * ------------ ------------ ---------------- ------- * EXCLUDE (X, Y) TO_EX (A) EXCLUDE (A-Y, Y*A) (A-X-Y)=Group Timer * Delete (X-A) * Delete (Y-A) * Send Q(G, A-Y) * Group Timer=GMI */ for (p_is = LIST_FIRST(&p_gp->src_list); p_is ; p_is = p_is_next) { p_is_next = LIST_NEXT(p_is, link); if(TIMEVAL_ISZERO(p_is->timer->tm)) continue; if(pa_list_find(p_src_list, &p_is->src_addr) == NULL) { /*Delete (X-A)*/ imp_source_cleanup(p_is); } else if(TIMEVAL_LT(lmqt, p_is->timer->tm)) { /*Send Q(G, A-Y)*/ imp_set_timer(TIMER_LMQT, p_is->timer); p_is->times = DEFAULT_RV; enable_sch = 1; } } for (p_is = LIST_FIRST(&p_gp->src_list); p_is ; p_is = p_is_next) { p_is_next = LIST_NEXT(p_is, link); if(!TIMEVAL_ISZERO(p_is->timer->tm)) continue; /*Delete (Y-A)*/ if(pa_list_find(p_src_list, &p_is->src_addr) == NULL) { imp_source_cleanup(p_is); } } for(p_node = p_src_list; p_node; p_node = p_node->next) { if (imp_source_find(p_gp, &p_node->addr, BLOCKING) == NULL && imp_source_find(p_gp, &p_node->addr, FORWARDING) == NULL){ /*(A-X-Y)=Group Timer*/ p_is = imp_source_create(p_gp, &p_node->addr, FORWARDING);/*forward or not*/ memcpy(&p_is->timer->tm, &p_gp->timer->tm, sizeof(struct timeval)); if(TIMEVAL_LT(lmqt, p_is->timer->tm)) { imp_set_timer(TIMER_LMQT, p_is->timer); p_is->times = DEFAULT_RV; enable_sch = 1; } } } /*Group Timer=GMI*/ imp_set_timer(TIMER_GMI, p_gp->timer); } if(enable_sch && p_gp->sch_timer == NULL) { p_gp->sch_timer = imp_add_timer(group_source_specific_timer_handler, p_gp); imp_set_timer(0, p_gp->sch_timer); } imp_membership_db_update(p_ga); return; } p_gp = imp_group_create(p_if, p_ga, p_src_list, GROUP_EXCLUDE, version); if (p_gp == NULL) { IMP_LOG_ERROR("imp_group_create failed"); return; } imp_membership_db_update(p_ga); imp_group_print(p_if); }