📄 ripng.c
字号:
} if (ripif->rip_mode & IFS_NORIPIN) return; /* discard */ nn = (len - sizeof(struct riphdr)) / sizeof(struct ripinfo6); if (nn == 0) return; /* number of RTEs */ rp = (struct riphdr *)ripbuf; /* RIPng header */ if (rp->riph_vers != RIPNG_VERSION) { syslog(LOG_ERR, "<rip_input>: Unknown RIPng version %d", rp->riph_vers); return; } rp->riph_zero2 = 0; /* must be ignored, and must be zero */ switch (rp->riph_cmd) { /* received cmd */ case RIPNGCMD_REQUEST: ripif->rip_requestrcvd++; IFLOG(LOG_RIP) syslog(LOG_DEBUG, "RIPng RECV cmd=%s, length=%d, nn=%d", rip_msgstr[rp->riph_cmd], len, nn); if (ripif->rip_mode & IFS_NORIPOUT) return; ife = ifentry; while(ife) { /* from myself ? */ if (ife->ifi_ifn->if_index == rpktinfo->ipi6_ifindex && IN6_ARE_ADDR_EQUAL(&ife->ifi_laddr, &fsock.sin6_addr) && ripsin.sin6_port == fsock.sin6_port) { return; } if ((ife = ife->ifi_next) == ifentry) break; /* while */ } nn = rip_process_request(ripif, nn); if (nn > 0) { int mm; /* current */ int done; done = 0; if (fsock.sin6_port != ripsin.sin6_port && /* RIPNG_PORT */ !IN6_ARE_ADDR_EQUAL(&rpktinfo->ipi6_addr, &ripsin.sin6_addr) && !IN6_IS_ADDR_UNSPECIFIED(&ripif->rip_ife->ifi_gaddr)) spktinfo.ipi6_addr = ripif->rip_ife->ifi_gaddr; /* copy */ else spktinfo.ipi6_addr = ripif->rip_ife->ifi_laddr; /* copy */ spktinfo.ipi6_ifindex = rpktinfo->ipi6_ifindex; 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(&fsock, /* sender's addr.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; } } break; case RIPNGCMD_RESPONSE: ripif->rip_responsercvd++; if (ntohs(fsock.sin6_port) != RIPNG_PORT) { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<rip_input>: Response from non RIPng port: %s+%d on %s", ip6str2(&fsock), ntohs(fsock.sin6_port), if_indextoname(rpktinfo->ipi6_ifindex, ifname)); return; /* The Response must be ignored if it is not from the RIPng port. [rfc2080] */ } if (!IN6_IS_ADDR_LINKLOCAL(&fsock.sin6_addr)) { IFLOG(LOG_RIP) syslog(LOG_ERR, "<rip_input>: Response from non-linklocal addr: %s on %s", ip6str2(&fsock), if_indextoname(rpktinfo->ipi6_ifindex, ifname)); return; /* Ignore response msg from non-link-local address [rfc2080] */ } /* It is also worth checking to see whether the response is from one of the router's own addresses [rfc2080] */ ife = ifentry; while(ife) { if (ife->ifi_ifn->if_index == rpktinfo->ipi6_ifindex && IN6_ARE_ADDR_EQUAL(&ife->ifi_laddr, &fsock.sin6_addr)) { return; } if ((ife = ife->ifi_next) == ifentry) break; /* while */ }#ifdef ADVANCEDAPI /* multicast packets sent from the RIPng port (i.e. periodic advertisement or triggered update packets) must be examined to ensure that the hop count is 255. [rfc2080] */ if (rhoplimit != NULL && *rhoplimit != RIPNG_HOPLIMIT && rpktinfo != NULL && IN6_IS_ADDR_MULTICAST(&rpktinfo->ipi6_addr)) { IFLOG(LOG_RIP) syslog(LOG_ERR, "<%s>: Response from non-neighbor: %s on %s, hoplimit=%d", __FUNCTION__, ip6str2(&fsock), if_indextoname(rpktinfo->ipi6_ifindex, ifname), *rhoplimit); return; }#endif IFLOG(LOG_RIP) syslog(LOG_DEBUG, "RIPng RECV cmd=%s, length=%d, nn=%d", rip_msgstr[rp->riph_cmd], len, nn); nn = rip_process_response(ripif, nn); IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<rip_input>: rip_process_response() returned. (nn=%d)", nn); break; default: syslog(LOG_ERR, "<rip_input>: Unknow RIPng command %d", rp->riph_cmd); break; } return; }/* * rip_process_request() */intrip_process_request(ripif, nn) struct ripif *ripif; int nn; /* the Number of ripinfo6 */{ int i; struct ripinfo6 *np; /* RIPng RTE */ struct rt_entry key; struct rt_entry *base, *rte; struct rtproto *rtp; struct riphdr *rp; rp = (struct riphdr *)rippkt; /* outgoing RIPng header */ rp->riph_cmd = RIPNGCMD_RESPONSE; rp->riph_vers = RIPNG_VERSION; rp->riph_zero2 = 0; np = (struct ripinfo6 *)(ripbuf + sizeof(struct riphdr)); /* DUMP request */ if (nn == 1 && IN6_IS_ADDR_UNSPECIFIED(&np->rip6_dest) && np->rip6_plen == 0 && np->rip6_metric == RIPNG_METRIC_UNREACHABLE) { nn = rip_make_dump(ripif); return nn; } /* If the request is for specific entries, they are looked up in the routing table and the information is returned as is; no Split Horizon processing is done. [rfc2080 2.4.1] */ for (i = 0 ; i < nn ; i++, np++ ) { rte = NULL; memset(&key, 0, sizeof(key)); key.rt_ripinfo.rip6_dest = np->rip6_dest; key.rt_ripinfo.rip6_plen = np->rip6_plen; rtp = ripif->rip_adj_ribs_out; while(rtp) { switch(rtp->rtp_type) { case RTPROTO_IF: base = rtp->rtp_if->ifi_rte; break; case RTPROTO_BGP: base = rtp->rtp_bgp->rp_adj_ribs_in; break; case RTPROTO_RIP: base = rtp->rtp_rip->rip_adj_ribs_in; break; default: fatalx("<rip_process_request>: BUG !"); base = NULL; /*pacify gcc*/ break; /* NOTREACHED */ } rte = find_rte(&key, base); if (rte) break; /* while */ if ((rtp = rtp->rtp_next) == ripif->rip_adj_ribs_out) break; /* while */ } if (rte) { /* advertizing via RIP */ np->rip6_metric = MIN(rte->rt_ripinfo.rip6_metric + 1, RIPNG_METRIC_UNREACHABLE); np->rip6_tag = rte->rt_ripinfo.rip6_tag; /* AS number (net byte) */ } else { np->rip6_metric = RIPNG_METRIC_UNREACHABLE; np->rip6_tag = 0; /* no info */ } } /* for */ return nn; /* End of rip_process_request() */}/* * * rip_process_response() * DESCRIPTION: install RTE. and redistribute, if needed. * RETURN VALUES: the number of "triggered updated" RTEs. (ad-hoc) */intrip_process_response(ripif, nn) struct ripif *ripif; int nn; /* the Number of ripinfo6 */{ int i; int unn, dnn; /* return. (no use) */ struct ripinfo6 *np; /* nibbing */ struct in6_addr *nhaddr; /* "nexthop" address */ struct ripif *oripif; struct rt_entry *uprtehead, *uprte; /* copied object by igp_enable_rte() */ struct rt_entry *dwnrte;/* copied object by rip_disable_rte() */ task *lifetime, *garbage; /* may be registered */ byte lifeyes, garbageyes; char *ifname = ripif->rip_ife->ifi_ifn->if_name; /* for debugging use */ extern struct ifinfo *ifentry; extern task *taskhead; extern byte bgpyes; extern struct rt_entry *aggregations; IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<rip_process_response>: invoked, nn=%d", nn); uprtehead = NULL; unn = dnn = 0; MALLOC(lifetime, task); lifeyes = 0; MALLOC(garbage, task); garbageyes = 0; nhaddr = &fsock.sin6_addr; /* sender's address (normally) */ np = (struct ripinfo6 *)&(ripbuf[sizeof(struct riphdr)]); for (i = 0 ; i < nn ; i++, np++ ) { struct rt_entry *rte; /* to be installed */ struct rt_entry *srte = NULL; /* newly synchronized */ struct ifinfo *ife; /* search for */ struct rt_entry *orte = NULL; /* old RTE */ uprte = NULL; IFLOG(LOG_RIP) syslog(LOG_DEBUG, "RIPng RECV\t%d\t%s/%d (%d) on %s", i, ip6str(&np->rip6_dest, 0), np->rip6_plen, np->rip6_metric, ifname); if (np->rip6_metric == RIPNG_METRIC_NEXTHOP) { /* "nexthop" address */ if (IN6_IS_ADDR_LINKLOCAL(&np->rip6_dest)) nhaddr = &np->rip6_dest; else nhaddr = &fsock.sin6_addr; /* sender's */ continue; } if (!IN6_IS_ADDR_ROUTABLE(&np->rip6_dest)) { syslog(LOG_NOTICE, "<%s>: non-routable address(%s/%d) on %s", __FUNCTION__, ip6str(&np->rip6_dest, 0), np->rip6_plen, ripif->rip_ife->ifi_ifn->if_name); continue; /* ignore */ } /* * Check route filter and restriction. */ if (input_filter_check(&ripif->rip_filterset, rip_use_sitelocal, np)) { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: incoming route %s/%d on %s was filtered", __FUNCTION__, ip6str(&np->rip6_dest, 0), np->rip6_plen, ripif->rip_ife->ifi_ifn->if_name); continue; } if (np->rip6_metric == 0 || np->rip6_metric > RIPNG_METRIC_UNREACHABLE) { syslog(LOG_NOTICE, "<%s>: invaid metric(%d) for %s/%d on %s", __FUNCTION__, np->rip6_metric, ip6str(&np->rip6_dest, 0), np->rip6_plen, ripif->rip_ife->ifi_ifn->if_name); continue; /* ignore */ } else { /* incoming metric addition(if specified) */ if (ripif->rip_metricin) { np->rip6_metric += ripif->rip_metricin; if (np->rip6_metric > RIPNG_METRIC_UNREACHABLE) np->rip6_metric = RIPNG_METRIC_UNREACHABLE; IFLOG(LOG_RIP) syslog(LOG_DEBUG, "RIPng METRIC ADD\t%d\t%s/%d (%d) on %s", i, ip6str(&np->rip6_dest, 0), np->rip6_plen, np->rip6_metric, ifname); } } if (np->rip6_plen > 128) { syslog(LOG_ERR, "<rip_process_response>: invaid plefix length(%d)", np->rip6_plen); continue; /* ignore */ } if (np->rip6_plen == 128) { ife = ifentry; while(ife) { /* check I/F addrs */ if (IN6_ARE_ADDR_EQUAL(&np->rip6_dest, &ife->ifi_gaddr)) { ife = NULL; break; } if ((ife = ife->ifi_next) == ifentry) break; } if (ife == NULL) { continue; /* ignore */ } } MALLOC(rte, struct rt_entry); rte->rt_gw = *nhaddr; /* copy */ rte->rt_flags = RTF_UP|RTF_GATEWAY; rte->rt_ripinfo = *np; /* tag must be preserved and readvd */ mask_nclear(&rte->rt_ripinfo.rip6_dest, rte->rt_ripinfo.rip6_plen); if (rte->rt_ripinfo.rip6_plen == 128) rte->rt_flags |= RTF_HOST; rte->rt_proto.rtp_type = RTPROTO_RIP; rte->rt_proto.rtp_rip = ripif; /* for each RTE, each RTP exists. */ rte->rt_riptime = NULL; rte->rt_aspath = NULL;/* rte->rt_aggr = 0; */ /** check I/F routes **/ ife = ifentry; while(ife) { if ((orte = find_rte(rte, ife->ifi_rte))) break; if ((ife = ife->ifi_next) == ifentry) break; } if (orte != NULL) { /* I/F direct route (most preferable) */ IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: I/F direct route(%s/%d on %s) cannot overwritten", __FUNCTION__, ip6str(&orte->rt_ripinfo.rip6_dest, 0), orte->rt_ripinfo.rip6_plen, ifname); free(rte); continue; /* to next rte */ } /** check aggregate routes **/ if (find_rte(rte, aggregations)) { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: aggregate route %s/%d on %s cannot overwritten", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, ifname); free(rte); continue; /* to next rte */ } /** check BGP routes **/ /** exclude Poisoned Reverse **/ if (bgpyes && rte->rt_ripinfo.rip6_metric != RIPNG_METRIC_UNREACHABLE) { struct rpcb *obnp; extern struct rpcb *bgb; obnp = bgb; while(obnp) { if (obnp->rp_mode & BGPO_IGP && (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.", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, ifname); bgp_disable_rte(orte); /* XXX: do not have to propagate? */ } else { /** route synchronization (1998/06/27) **/ if (rte->rt_ripinfo.rip6_tag == orte->rt_ripinfo.rip6_tag) { rte->rt_flags |= RTF_IGP_EGP_SYNC; rte->rt_flags &= ~RTF_UP; if (!(orte->rt_flags & RTF_IGP_EGP_SYNC)) { IFLOG(LOG_RIP) syslog(LOG_DEBUG, "<%s>: synchronized...%s/%d on %s, tag=%u", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, ifname, ntohs(rte->rt_ripinfo.rip6_tag)); orte->rt_flags |= RTF_IGP_EGP_SYNC; /* don't touch RTF_UP, for backup-route */ srte = orte; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -