📄 ripng.c
字号:
syslog(LOG_DEBUG, "RIPng DUMP\t%d\t%s/%d (%d) on %s", nn, ip6str(&np->rip6_dest, 0), np->rip6_plen, np->rip6_metric, ripif->rip_ife->ifi_ifn->if_name); np++; /* nibbing */ nn++; /* count */ agg->rt_aggr.ag_flags |= AGGR_ADVDONE; } if (!((rte->rt_aggr.ag_flags & AGGR_NOADVD) && agg && agg->rt_aggr.ag_flags & AGGR_ADVDONE) && !rip_output_filter(ripif, &rte->rt_ripinfo)) { if ((ripif->rip_mode & IFS_DEFAULTORIGINATE) && IN6_IS_ADDR_UNSPECIFIED(&rte->rt_ripinfo.rip6_dest) && rte->rt_ripinfo.rip6_plen == 0) { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: ignore default route when originating", __FUNCTION__); goto nextroute; } memcpy(np, &rte->rt_ripinfo, sizeof(struct ripinfo6)); np->rip6_metric = MIN(np->rip6_metric+1, RIPNG_METRIC_UNREACHABLE); IFLOG(LOG_RIP) syslog(LOG_DEBUG, "RIPng DUMP\t%d\t%s/%d (%d) on %s", nn, ip6str(&np->rip6_dest, 0), np->rip6_plen, np->rip6_metric, ripif->rip_ife->ifi_ifn->if_name); np++; /* nibbing */ nn++; /* count */ } } nextroute: if ((rte = rte->rt_next) == base) break; } /* while(rte) */ if ((rtp = rtp->rtp_next) == ripif->rip_adj_ribs_out) break; } /* while(rtp) */ return nn; /* End of rip_make_dump() */}/* * rip_make_data() * DESCRIPTION: make a RIP data. (excluding RIP header) */intrip_make_data(rte, ripif, ripmode) struct rt_entry *rte; struct ripif *ripif; /* NULL case .... withdrawning. */ byte ripmode;{ struct ripinfo6 *np; /* RIPng RTE, nibbing "ripbuf" */ struct rt_entry *r, *agg; struct rtproto artp; int nn = 0; np = (struct ripinfo6 *)(ripbuf + sizeof(struct riphdr)); if (ripif) { memset(&artp, 0, sizeof(artp)); artp.rtp_type = RTPROTO_IF; artp.rtp_if = ripif->rip_ife; } r = rte; while(r) { agg = r->rt_aggr.ag_agg; if (ripif && aggr_advable(agg, &artp) && !rip_output_filter(ripif, &agg->rt_ripinfo)) { if ((ripmode & IFS_DEFAULTORIGINATE) && IN6_IS_ADDR_UNSPECIFIED(&agg->rt_ripinfo.rip6_dest) && agg->rt_ripinfo.rip6_plen) { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: ignore default route when originating", __FUNCTION__); goto nextroute; } memcpy(np, &agg->rt_ripinfo, sizeof(struct ripinfo6)); np->rip6_metric = MIN(np->rip6_metric+1, RIPNG_METRIC_UNREACHABLE); np++; /* nibbing */ nn++; /* count */ agg->rt_aggr.ag_flags |= AGGR_ADVDONE; } if (ripif == NULL || /* withdrawing or.. */ (((r->rt_flags & RTF_UP || (r->rt_proto.rtp_type == RTPROTO_RIP && (r->rt_flags & RTF_IGP_EGP_SYNC))) && !(r->rt_aggr.ag_flags & AGGR_NOADVD && agg && (agg->rt_aggr.ag_flags & AGGR_ADVDONE))) && !rip_output_filter(ripif, &r->rt_ripinfo))) { if ((ripmode & IFS_DEFAULTORIGINATE) && IN6_IS_ADDR_UNSPECIFIED(&r->rt_ripinfo.rip6_dest) && r->rt_ripinfo.rip6_plen) { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: ignore default route when originating", __FUNCTION__); goto nextroute; } memcpy(np, &r->rt_ripinfo, sizeof(struct ripinfo6)); np->rip6_metric = MIN(np->rip6_metric + 1, RIPNG_METRIC_UNREACHABLE); np++; /* nibbing */ nn++; /* count */ } nextroute: if ((r = r->rt_next) == rte) break; } return nn; /* End of rip_make_data() */}/* * find_rip_by_index() */struct ripif *find_rip_by_index(u_int index){ struct ripif *rip; extern struct ripif *ripifs; if ((rip = ripifs) == NULL) return NULL; while(rip) { if (rip->rip_ife == NULL || rip->rip_ife->ifi_ifn == NULL) fatalx("<find_rip_by_index>: BUG !"); if (rip->rip_ife->ifi_ifn->if_index == index) break; if ((rip = rip->rip_next) == ripifs) return NULL; } return rip;}/* * rip_disable_rte() * DESCRIPTION: called by rip_life_expired(), bgp_process_update(), * or, when received metric=16. */struct rt_entry *rip_disable_rte(rte) struct rt_entry *rte;{ struct rt_entry *crte; /* to be copied */ IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: delroute()...", __FUNCTION__); if (delroute(rte, &rte->rt_gw) != 0) { syslog(LOG_ERR, "<%s>: route couldn't be deleted.", __FUNCTION__); return NULL; rte->rt_flags &= ~RTF_UP; } rte->rt_flags &= ~RTF_UP; /* down */ rte->rt_ripinfo.rip6_metric = RIPNG_METRIC_UNREACHABLE; /* also disable BGP routes that use this route to resolve the nexthop */ bgp_disable_rte_by_igp(rte); MALLOC(crte, struct rt_entry); memcpy(crte, rte, sizeof(struct rt_entry)); return crte;}/* * rip_erase_rte() * DESCRIPTION: Kernel delroute(). * rip_adj_ribs_in is shorten. */voidrip_erase_rte(rte) struct rt_entry *rte;{ struct ripif *ripif; if (rte->rt_proto.rtp_type != RTPROTO_RIP) fatalx("<rip_erase_rte>: BUG !"); IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: delroute()...", __FUNCTION__); if (delroute(rte, &rte->rt_gw) != 0) syslog(LOG_ERR, "<%s>: route couldn't be deleted.", __FUNCTION__); /* also disable BGP routes that use this route to resolve the nexthop */ bgp_disable_rte_by_igp(rte); if ((ripif = rte->rt_proto.rtp_rip) == NULL) fatalx("<rip_erase_rte>: BUG !"); ripif->rip_adj_ribs_in = rte_remove(rte, ripif->rip_adj_ribs_in);}/* * rip_change_rte() */struct rt_entry *rip_change_rte(rte) struct rt_entry *rte;{ struct rt_entry *crte; /* to be copied */ if (chroute(rte, &rte->rt_gw, rte->rt_proto.rtp_rip->rip_ife) != 0) { syslog(LOG_ERR, "<rip_change_rte>: route couldn't be changed."); return NULL; } MALLOC(crte, struct rt_entry); memcpy(crte, rte, sizeof(struct rt_entry)); return crte;}/* * rip_dump() * triggered by SIGALRM. */voidrip_dump() { struct ripif *ripif; struct in6_pktinfo spktinfo; /* Adv. API */ struct riphdr *rp; int nn; extern task *taskhead; memset(ripbuf, 0, RIPNG_BUFSIZ); memset(rippkt, 0, RIPNG_MAXPKT); rp = (struct riphdr *)rippkt; /* outgoing RIPng header */ rp->riph_cmd = RIPNGCMD_RESPONSE; rp->riph_vers = RIPNG_VERSION; rp->riph_zero2 = 0; ripif = ripifs; /* global */ while(ripif) { if (!(ripif->rip_mode & IFS_NORIPOUT)) { nn = rip_make_dump(ripif); /* periodic DUMP */ spktinfo.ipi6_addr = ripif->rip_ife->ifi_laddr; /* copy */ spktinfo.ipi6_ifindex = ripif->rip_ife->ifi_ifn->if_index; if (nn > 0) { int mm; /* current */ int done; done = 0; while(1) { mm = MIN(nn - done, RIPNG_MAXRTES); memcpy(&rippkt[sizeof(struct riphdr)], &ripbuf[sizeof(struct riphdr) + done*sizeof(struct ripinfo6)], mm * sizeof(struct ripinfo6)); if (rip_sendmsg(&ripsin, /* ff02::9.RIPNG_PORT */ &spktinfo, /* source address, I/F */ sizeof(struct riphdr) + mm * sizeof(struct ripinfo6))) ripif->rip_respfail++; ripif->rip_responsesent++; done += mm; if (done == nn) break; } } } if ((ripif = ripif->rip_next) == ripifs) break; } taskhead->tsk_timefull.tv_sec = RIP_T_DUMP + (random()%(RIP_T_DUMPRAND*2)) - RIP_T_DUMPRAND; taskhead->tsk_timefull.tv_usec = 0; task_timer_update(taskhead); /* End of rip_dump() */}/* * rip_life_expired() */voidrip_life_expired() { struct ripif *ripif; task *garbage; byte garbageyes; struct rt_entry *rte; /* cursor */ struct rt_entry *dwnrte; extern task *taskhead; MALLOC(garbage, task); garbageyes = 0; garbage->tsk_timename = RIP_GARBAGE_TIMER; ripif = taskhead->tsk_rip; rte = ripif->rip_adj_ribs_in; while(rte) { dwnrte = NULL; if (rte->rt_riptime->tsk_next == NULL) /* safety check */ fatalx("<rip_life_expired>: BUG !"); if (rte->rt_riptime == taskhead) { rte->rt_riptime = garbage; garbageyes = 1; rte->rt_ripinfo.rip6_metric = RIPNG_METRIC_UNREACHABLE; IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: calling rip_disable_rte()...", __FUNCTION__); dwnrte = rip_disable_rte(rte); /* copied */ if (dwnrte) { dwnrte->rt_next = dwnrte->rt_prev = dwnrte; propagate(dwnrte); /* triggered update */ free(dwnrte); bgp_recover_rte(rte); } } if ((rte = rte->rt_next) == ripif->rip_adj_ribs_in) break; } /* while(rte) */ taskhead = task_remove(taskhead); /* erase lifetime */ if (garbageyes) { garbage->tsk_rip = ripif; garbage->tsk_timename = RIP_GARBAGE_TIMER; garbage->tsk_timefull.tv_sec = RIP_T_GARBAGE; insque(garbage, taskhead); /* taskhead exists. */ task_timer_update(garbage); } else { free(garbage); } return;}/* * rip_garbage_expired() */voidrip_garbage_expired() { struct ripif *ripif; struct rt_entry *rte; /* cursor */ extern task *taskhead; IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<rip_garbage_expired>: invoked."); ripif = taskhead->tsk_rip; rte = ripif->rip_adj_ribs_in; if (rte) while(rte) { if (rte->rt_riptime == taskhead) { ripif->rip_adj_ribs_in = rte_remove(rte, ripif->rip_adj_ribs_in); if ((rte = ripif->rip_adj_ribs_in)) continue; else break; } if ((rte = rte->rt_next) == ripif->rip_adj_ribs_in) break; } taskhead = task_remove(taskhead); IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<rip_garbage_expired>: done.");}/* * Detect if a specified outgoing RIPng route should be filtered on the given * interface. * 1. If we specify to restrict rotes to the default, all non default routes * should be filtered. * 2. If we specify the restiction list, filter the route unless it * matches at least one entry of the list. * 3. If we filter the default route on the interface, filter it. * 4. If we specify the filter list, the route that matches * at least one entry of the list should be filtered. */intrip_output_filter(struct ripif *ripif, struct ripinfo6 *ripinfo){ struct filterset *f = &ripif->rip_filterset; if (output_filter_check(f, rip_use_sitelocal, ripinfo)) { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: output route %s/%d on %s was filtered", __FUNCTION__, ip6str(&ripinfo->rip6_dest, 0), ripinfo->rip6_plen, ripif->rip_ife->ifi_ifn->if_name); return(1); } return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -