📄 ripng.c
字号:
} } if ((obnp = obnp->rp_next) == bgb) break; } /* while(obnp) iBGP */ obnp = bgb; while(obnp) { if (!(obnp->rp_mode & BGPO_IGP) && /* eBGP */ (orte = find_rte(rte, obnp->rp_adj_ribs_in))) { if (rte->rt_ripinfo.rip6_tag == 0) { /* purely internal */ IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: %s/%d on %s is purely internal, tag=%u.", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, ifname, ntohs(rte->rt_ripinfo.rip6_tag)); bgp_disable_rte(orte); } else { if (rte->rt_ripinfo.rip6_tag == orte->rt_ripinfo.rip6_tag) { obnp = NULL; /* I mean "continue to next rte" */ break; } else if (srte) { /* tag differ */ if ((ntohl(srte->rt_aspath->asp_localpref) > ntohl(orte->rt_aspath->asp_localpref)) || ((ntohl(srte->rt_aspath->asp_localpref) == ntohl(orte->rt_aspath->asp_localpref)) && ((aspath2cost(srte->rt_aspath) < aspath2cost(orte->rt_aspath)) || (ntohl(srte->rt_aspath->asp_med) < ntohl(orte->rt_aspath->asp_med))))) { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: tag differ.", __FUNCTION__); bgp_disable_rte(orte); /* XXX: do not have to propagate? */ } else { /* don't touch srte's RTF_UP. No need. */ obnp = NULL; /* I mean "continue to next rte" */ break; } } } } if (obnp == NULL || (obnp = obnp->rp_next) == bgb) break; } /* while(obnp) eBGP */ if (obnp == NULL) { free(rte); IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: skip", __FUNCTION__); continue; /* to next rte */ } } /** check RIPng routes **/ oripif = ripifs; while(oripif) {#define ALTER_RTE { rte->rt_riptime = lifetime; lifeyes = 1;\ rip_erase_rte(orte);\ uprte = igp_enable_rte(rte);\ if (uprte) unn++; } if ((orte = find_rte(rte, oripif->rip_adj_ribs_in))) { /* If there is an existing route, compare the next hop address to the address of the router from which the datagram came. [rfc2080] */ if (ripif->rip_ife->ifi_ifn->if_index == oripif->rip_ife->ifi_ifn->if_index && IN6_ARE_ADDR_EQUAL(&orte->rt_gw, &fsock.sin6_addr)) { if (rte->rt_ripinfo.rip6_metric == RIPNG_METRIC_UNREACHABLE) { /* Note that the deletion process is started only when the metric is first set to infinity. If the metric was already infinity, then a new deletion process is not started. [rfc2080] */ if (orte->rt_ripinfo.rip6_metric == RIPNG_METRIC_UNREACHABLE) { oripif = NULL; /* I mean "continue to next rte" */ break; } else { orte->rt_riptime = garbage; garbageyes = 1; orte->rt_ripinfo.rip6_metric = RIPNG_METRIC_UNREACHABLE; dwnrte = rip_disable_rte(orte); /* copied */ if (dwnrte) { dnn++; dwnrte->rt_next = dwnrte->rt_prev = dwnrte; propagate(dwnrte); free(dwnrte); bgp_recover_rte(orte); oripif = NULL; } break; } } /* 0 < rte < 16 */ if (orte->rt_ripinfo.rip6_metric == RIPNG_METRIC_UNREACHABLE) { rte->rt_riptime = lifetime; lifeyes = 1; oripif->rip_adj_ribs_in = rte_remove(orte, oripif->rip_adj_ribs_in); uprte = igp_enable_rte(rte); /* copied */ if (uprte) unn++; break; /* while(oripif) */ } /* 0 < orte < 16 */ if (rte->rt_ripinfo.rip6_metric == orte->rt_ripinfo.rip6_metric) { /* If the new metric is the same as the old one, it is simplest to do nothing further (beyond reinitializing the timeout...) [rfc2080] */ orte->rt_riptime = lifetime; lifeyes = 1; oripif = NULL; /* I mean "continue to next rte" */ break; /* while(oripif) */ } if (rte->rt_ripinfo.rip6_metric != orte->rt_ripinfo.rip6_metric) { /** Metric Change **/ IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: metric for %s/%d on %s changes from %d to %d", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, ifname, orte->rt_ripinfo.rip6_metric, rte->rt_ripinfo.rip6_metric); ALTER_RTE; break; /* while(oripif) */ } } else { /* nexthop differ (maybe came from another router) */#if 0 /* there is a heuristic which could be applied. Normally, it is senseless to replace a route if the new route has the same metric as the existing route; this would cause the route to bounce back and forth, which would generate an intolerable number of triggered updates. However, if the existing route is showing signs of timing out, it may be better to switch to an equally-good alternative route immediately, rather than waiting for the timeout to happen. Therefore, if the new metric is the same as the old one, examine the timeout for the existing route. If it is at least halfway to the expiration point, switch to the new route. This heuristic is optional, but highly recommended. [rfc2080.txt] */#endif if (rte->rt_ripinfo.rip6_metric == RIPNG_METRIC_UNREACHABLE || orte->rt_ripinfo.rip6_metric <= rte->rt_ripinfo.rip6_metric) { oripif = NULL; /* I mean "continue to next rte" */ break; /* while(oripif) */ } else { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: nexthop for %s/%d changes " "from %s to %s on %s", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, ip6str(&orte->rt_gw, oripif->rip_ife->ifi_ifn->if_index), ip6str(&rte->rt_gw, ripif->rip_ife->ifi_ifn->if_index), ifname); ALTER_RTE; break; } } /* (nexthop differ) */ } else { /* couldn't find the same RTE */ } if ((oripif = oripif->rip_next) == ripifs) break;#undef ALTER_RTE } /* while(oripif) */ if (oripif == NULL) { free(rte); IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: skip", __FUNCTION__); continue; /* to next rte */ } if (!(uprte)) { /* Nothing matched in rp_adj_ribs_in */ if (rte->rt_ripinfo.rip6_metric == RIPNG_METRIC_UNREACHABLE) { free(rte); continue; /* to next rte */ } rte->rt_riptime = lifetime; lifeyes = 1; uprte = igp_enable_rte(rte); /* copied */ if (uprte) unn++; } if (srte) { struct rt_entry crte; bgp_enable_rte(srte); crte = *srte; crte.rt_next = crte.rt_prev = &crte; redistribute(&crte); /* newly synchronized iBGP rte */ } if (uprte) { if (uprtehead) { insque(uprte, uprtehead); } else { uprte->rt_next = uprte; uprte->rt_prev = uprte; uprtehead = uprte; } } } /* for (i<nn) */ /* triggerd update Go. */ if (uprtehead) { redistribute(uprtehead); while(uprtehead) { uprtehead = rte_remove(uprtehead, uprtehead); } } if (lifeyes) { lifetime->tsk_rip = ripif; lifetime->tsk_timename = RIP_LIFE_TIMER; lifetime->tsk_timefull.tv_sec = RIP_T_LIFE; insque(lifetime, taskhead); /* assume taskhead exists. */ task_timer_update(lifetime); } else { free(lifetime); } if (garbageyes) { garbage->tsk_rip = ripif; garbage->tsk_timename = RIP_GARBAGE_TIMER; garbage->tsk_timefull.tv_sec = RIP_T_GARBAGE; insque(garbage, taskhead); /* assume taskhead exists. */ task_timer_update(garbage); } else { free(garbage); } IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<rip_process_response>: done, i=%d", i); return (unn + dnn);}/* * rip_sendmsg() * Actually sendmsg. */intrip_sendmsg(sin, pktinfo, len) struct sockaddr_in6 *sin; /* dst addr.port */ struct in6_pktinfo *pktinfo; /* src addr, outgoing I/F */ int len; /* data */{ int tlen; /* sizeof To addr (for Adv. API) */ int slen; /* sent data len */ struct msghdr smsghdr; /* Adv. API */ struct iovec smsgiov; /* Adv. API */ static char *cmsg = NULL; /* buffer for ancillary data */ int cmsglen; struct cmsghdr *ch; /* Adv. API */ int shoplimit; /* Adv. API */ char ifname[IFNAMSIZ]; struct riphdr *rp; /* RIPng header */ cmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)); memset(ifname, 0, IFNAMSIZ); if (cmsg == NULL && (cmsg = malloc(cmsglen)) == NULL) fatalx("<rip_sendmsg>: malloc failed"); memset(cmsg, 0, cmsglen); shoplimit = RIPNG_HOPLIMIT;/*** Adv. API ***/ tlen = sizeof(struct sockaddr_in6); smsghdr.msg_name = (caddr_t)sin; /* dest addr.port */ smsghdr.msg_namelen = tlen; /* size of address */ smsgiov.iov_base = (void *)rippkt; /* buffer, base should be void */ smsgiov.iov_len = len; /* sending data len */ smsghdr.msg_iov = &smsgiov; smsghdr.msg_iovlen = 1; /* 1 iovec obj. */#ifdef ADVANCEDAPI smsghdr.msg_control = (caddr_t)cmsg; /* buffer for ancillary data */ smsghdr.msg_controllen = cmsglen;#endif smsghdr.msg_flags = 0; /* ? */ ch = CMSG_FIRSTHDR(&smsghdr);#ifdef ADVANCEDAPI ch->cmsg_level = IPPROTO_IPV6; ch->cmsg_type = IPV6_PKTINFO; ch->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); /* source address selection */ memcpy(CMSG_DATA(ch), pktinfo, sizeof(struct in6_pktinfo)); ch = CMSG_NXTHDR(&smsghdr, ch); ch->cmsg_level = IPPROTO_IPV6; ch->cmsg_type = IPV6_HOPLIMIT; /* may not be supported */ ch->cmsg_len = CMSG_LEN(sizeof(int)); memcpy(CMSG_DATA(ch), &shoplimit, sizeof(int));#else /* for hydranger */ if (IN6_IS_ADDR_MULTICAST(&sin->sin6_addr) && setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &pktinfo->ipi6_ifindex, sizeof(u_int)) < 0) { fatal("<rip_sendmsg>: IPV6_MULTICAST_IF"); }#endif /* ADVANCEDAPI */ if ((slen = sendmsg(ripsock, &smsghdr, 0)) != len) { syslog(LOG_ERR, /* spoofing or misconfig ? */ "<rip_sendmsg>: sendmsg on %s (src=%s): %s", if_indextoname(pktinfo->ipi6_ifindex, ifname), ip6str(&pktinfo->ipi6_addr, 0), strerror(errno)); return(-1); } IFLOG(LOG_RIP) { rp = (struct riphdr *)rippkt; /* RIPng header */ syslog(LOG_DEBUG, "RIPng SEND cmd %s, length %d", rip_msgstr[rp->riph_cmd], len); syslog(LOG_DEBUG, "RIPng SEND %s+%d -> %s+%d (%s)", ip6str(&pktinfo->ipi6_addr, 0), RIPNG_PORT, ip6str2(sin), ntohs(sin->sin6_port), if_indextoname(pktinfo->ipi6_ifindex, ifname)); } return(0); /* End of rip_sendmsg */}/* * rip_make_dump() * DESCRIPTION: make a RIP dump msg. * Split horizon applied. * Don't send the same I/F's direct route (metric = 0) * * RETURN VALUES: the number of RTEs */intrip_make_dump(ripif) struct ripif *ripif;{ struct ripinfo6 *np; /* RIPng RTE, nibbing to "ripbuf" */ struct rtproto *rtp, artp; struct rt_entry *rte, *base, *agg; int nn = 0; np = (struct ripinfo6 *)(ripbuf + sizeof(struct riphdr)); if (ripif->rip_mode & IFS_DEFAULTORIGINATE) { memset(np, 0, sizeof(struct ripinfo6)); np->rip6_metric = 1; np++; nn++; IFLOG(LOG_RIP) syslog(LOG_DEBUG, "RIPng DUMP\t%d\tdefault(originated) on %s", nn, ripif->rip_ife->ifi_ifn->if_name); } memset(&artp, 0, sizeof(artp)); artp.rtp_type = RTPROTO_IF; artp.rtp_if = ripif->rip_ife; aggr_flush(); rtp = ripif->rip_adj_ribs_out; while(rtp) { base = NULL; switch(rtp->rtp_type) { case RTPROTO_IF: base = rtp->rtp_if->ifi_rte; break; case RTPROTO_BGP: { struct rpcb *ebnp = find_epeer_by_rpcb(rtp->rtp_bgp); if (ebnp) base = ebnp->rp_adj_ribs_in; break; } case RTPROTO_RIP: if (rtp->rtp_rip != ripif) /* split horizon */ base = rtp->rtp_rip->rip_adj_ribs_in; break; default: fatalx("<rip_make_dump>: BUG !"); break; } rte = base; while(rte) { if ((rte->rt_flags & RTF_UP || /* iw97: avoid doublebooking */ (rtp->rtp_type == RTPROTO_RIP && rte->rt_flags & RTF_IGP_EGP_SYNC))) { if ((rte->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) != 0) { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: rejected route (%s/%d) not advertised on %s", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, ripif->rip_ife->ifi_ifn->if_name); goto nextroute; } agg = rte->rt_aggr.ag_agg; if (aggr_advable(agg, &artp) && !rip_output_filter(ripif, &agg->rt_ripinfo)) { if ((ripif->rip_mode & IFS_DEFAULTORIGINATE) && IN6_IS_ADDR_UNSPECIFIED(&agg->rt_ripinfo.rip6_dest) && agg->rt_ripinfo.rip6_plen == 0) { 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); IFLOG(LOG_RIP)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -