📄 bgp.c
字号:
__FUNCTION__, ip6str(&wdrte->rt_ripinfo.rip6_dest, 0), wdrte->rt_ripinfo.rip6_plen, bgp_peerstr(bnp));#endif bnp->rp_adj_ribs_in = rte_remove(drte, bnp->rp_adj_ribs_in); } } else { /* RTE not found */ syslog(LOG_NOTICE, "<%s>: MP_UNREACH_NLRI %s/%d: %s not origin (ignored): ", __FUNCTION__, ip6str(&wdrte->rt_ripinfo.rip6_dest, 0), wdrte->rt_ripinfo.rip6_plen, bgp_peerstr(bnp)); } } if (uprtehead.rt_next != &uprtehead) { struct rt_entry *head = uprtehead.rt_next; remque(&uprtehead); /* XXX: uprtehead would annoy redistribute() */ redistribute(head); insque(&uprtehead, head); /* XXX: restore link */ if (!bgp_rpcb_isvalid(bnp)) { syslog(LOG_NOTICE, "<%s>: rpcb %p was invalidated during a redistribution", __FUNCTION__, bnp); goto done; } } /* uprtehead */ task_timer_update(bnp->rp_hold_timer); done: if (asp) free_aspath(asp); { struct rt_entry *drte; for (drte = uprtehead.rt_next; drte != &uprtehead;) { struct rt_entry *nrte = drte->rt_next; remque(drte); free(drte); /* aspath has been already freed. */ drte = nrte; } for (drte = wdrtehead.rt_next; drte != &wdrtehead;) { struct rt_entry *nrte = drte->rt_next; remque(drte); free(drte); /* ditto. */ drte = nrte; } } /* End of bgp_process_update() */}static intbgp_selectroute(rte, bnp) struct rt_entry *rte; struct rpcb *bnp;{ struct rpcb *obnp; /* search for */ struct rt_entry *orte; extern struct ripif *ripifs; extern byte ripyes; /* * At first, check our own routes since possible propagation * might destory bnp...Ugh! */ if ((orte = find_rte(rte, bnp->rp_adj_ribs_in))) { struct rt_entry crte; /* local copy */ /* * i) If its Network Layer Reachability Information (NLRI) * is identical to the one of a route currently stored * in the Adj-RIB-In, then the new route shall replace the * older route in the Adj-RIB-In, thus implicitly withdrawing * the older route from service. The BGP speaker shall run * its Decision Process since the older route is no longer * available for use. * [BGP4+ 9. UPDATE Message Handling] */ if (orte->rt_flags & RTF_UP) {#ifdef DEBUG_BGP syslog(LOG_NOTICE, "<%s>: %s/%d from %s was overwritten " "nexthop=(old:%s, new:%s)", __FUNCTION__, ip6str(&orte->rt_ripinfo.rip6_dest, 0), orte->rt_ripinfo.rip6_plen, bgp_peerstr(bnp), ip6str(&orte->rt_bgw, 0), ip6str(&rte->rt_bgw, 0));#endif crte = *orte; crte.rt_next = crte.rt_prev = &crte; bgp_disable_rte(&crte); propagate(&crte); /* XXX: propagate might invalidate bnp */ if (!bgp_rpcb_isvalid(bnp)) { syslog(LOG_NOTICE, "<%s>: rpcb %p was invalidated during a " "propagation", __FUNCTION__, bnp); return(-1); } } bnp->rp_adj_ribs_in = rte_remove(orte, bnp->rp_adj_ribs_in); } obnp = bgb; while(obnp) { if (bnp != obnp && /* already done above */ (orte = find_rte(rte, obnp->rp_adj_ribs_in))) { /* same NLRI */ /* * Route Selection * take care of route flapping !! * comparison technique * (like RIPng metric) (1998/05/13) */ if (orte->rt_flags & RTF_UP) { if (bgp_preferred_rte(rte, orte)) { /* a new RTE may prefer */ bgp_disable_rte(orte); orte->rt_flags &= ~RTF_UP; } else { /* * Don't activate Kernel table */ rte->rt_flags &= ~RTF_UP; IFLOG(LOG_BGPINPUT) syslog(LOG_DEBUG, "<%s>: to be backup.", __FUNCTION__); } } } if ((obnp = obnp->rp_next) == bgb) break; } /* End of while(obnp) */ /** check RIPng routes **/ if (ripyes) { struct ripif *oripif; oripif = ripifs; while(oripif) { /* iw97 */ if ((orte = find_rte(rte, oripif->rip_adj_ribs_in)) && (orte->rt_flags & RTF_UP)) { /* fuckin' reversing BGP speker */ /* route synchronization(1998/06/20) */ if (orte->rt_ripinfo.rip6_tag == 0) { /* purely internal */ /* * Don't activate Kernel table */ rte->rt_flags &= ~RTF_UP; break; /* while(oripif) */ } if (bnp->rp_mode & BGPO_IGP){ /* IBGP */ if (rte->rt_ripinfo.rip6_tag == orte->rt_ripinfo.rip6_tag){ struct rt_entry *nrte; /* * If "rte" is backup, don't * install even if "rte" * becomes syncronized */ IFLOG(LOG_BGPINPUT) syslog(LOG_DEBUG, "<%s>: now synchronized.", __FUNCTION__); nrte = rip_disable_rte(orte); free(nrte); rte->rt_flags |= RTF_IGP_EGP_SYNC; orte->rt_flags |= RTF_IGP_EGP_SYNC; } else { /* tag differ */ if (orte->rt_flags & RTF_IGP_EGP_SYNC && rte->rt_flags & RTF_UP) { IFLOG(LOG_BGPINPUT) syslog(LOG_DEBUG, "<%s>: a new iBGP RTE prefered.", __FUNCTION__); rip_erase_rte(orte); } } } else { /* eBGP */ if (rte->rt_ripinfo.rip6_tag == orte->rt_ripinfo.rip6_tag) { IFLOG(LOG_BGPINPUT) syslog(LOG_DEBUG, "<%s>: fear.", __FUNCTION__); rip_erase_rte(orte); } else { /* tag differ */ if (orte->rt_flags & RTF_IGP_EGP_SYNC && rte->rt_flags & RTF_UP) { syslog(LOG_NOTICE, "<%s>: a new eBGP RTE prefered.", __FUNCTION__); rip_erase_rte(orte); } else { IFLOG(LOG_BGPINPUT) syslog(LOG_DEBUG, "<%s>: to be Backup.", __FUNCTION__); /* XXX long... */ rte->rt_flags &= ~RTF_UP; } } } /* End of eBGP */ } /* still I may get poison-reverse via RIP */ if ((oripif = oripif->rip_next) == ripifs) break; } /* while(oripif) */ } /* (ripyes) */ return(0); /* sucess */}/* * bgp_process_notification() * process received KEEPALIVE msg. */voidbgp_process_notification (struct rpcb *bnp) { char in6txt[INET6_ADDRSTRLEN]; struct bgphdr *bh = (struct bgphdr *)bnp->rp_inpkt; extern char *bgp_errstr[]; extern char *bgp_hdrerrstr[]; extern char *bgp_opnerrstr[]; extern char *bgp_upderrstr[]; memset(in6txt, 0, INET6_ADDRSTRLEN); syslog(LOG_NOTICE, "NOTIFICATION received from %s (%s AS %d): code %d (%s) data %s", inet_ntop(AF_INET6, &bnp->rp_addr.sin6_addr, in6txt, INET6_ADDRSTRLEN), ((bnp->rp_mode & BGPO_IGP) ? "Internal" : "External"), (int)bnp->rp_as, (int)bnp->rp_inpkt[BGP_HEADER_LEN], /* code */ bgp_errstr[(int)bnp->rp_inpkt[BGP_HEADER_LEN]], bgp_errdatastr(&bnp->rp_inpkt[BGP_HEADER_LEN + 2], ntohs(bh->bh_length) - (BGP_HEADER_LEN + 2))); switch ((int)bnp->rp_inpkt[BGP_HEADER_LEN]) { /* code */ case BGP_ERR_HEADER: if ((int)bnp->rp_inpkt[BGP_HEADER_LEN+1] <= BGP_ERRHDR_TYPE) syslog(LOG_NOTICE, "\t subcode (%d) %s", (int)bnp->rp_inpkt[BGP_HEADER_LEN+1], bgp_hdrerrstr[(int)bnp->rp_inpkt[BGP_HEADER_LEN+1]]); break; case BGP_ERR_OPEN: if ((int)bnp->rp_inpkt[BGP_HEADER_LEN+1] <= BGP_ERROPN_BADHOLDTIME) syslog(LOG_NOTICE, "\t subcode (%d) %s", (int)bnp->rp_inpkt[BGP_HEADER_LEN+1], bgp_opnerrstr[(int)bnp->rp_inpkt[BGP_HEADER_LEN+1]]); break; case BGP_ERR_UPDATE: if ((int)bnp->rp_inpkt[BGP_HEADER_LEN+1] <= BGP_ERRUPD_ASPATH) syslog(LOG_NOTICE, "\t subcode (%d) %s", (int)bnp->rp_inpkt[BGP_HEADER_LEN+1], bgp_upderrstr[(int)bnp->rp_inpkt[BGP_HEADER_LEN+1]]); break; default: break; } /* Update Hold Timer. XXX: connection will soon be released */ if (bnp->rp_state == BGPSTATE_ESTABLISHED) task_timer_update(bnp->rp_hold_timer); bgp_cease(bnp); /* no means of reporting error in NOTIFICATION msg */}/* * bgp_process_keepalive() * process received KEEPALIVE msg. */voidbgp_process_keepalive (struct rpcb *bnp){ int i; /* tracer */ struct bgphdr *bh; struct rt_entry *rtehead, *rte; /* advertising */ rtehead = rte = NULL; bh = (struct bgphdr *)bnp->rp_inpkt; BGP_MARKER_CHECK; switch (bnp->rp_state) { case BGPSTATE_OPENCONFIRM: bnp->rp_state = BGPSTATE_ESTABLISHED; IFLOG(LOG_BGPSTATE) syslog(LOG_NOTICE, "<%s>: BGP state shift[%s] peer: %s", __FUNCTION__, bgp_statestr[bnp->rp_state], bgp_peerstr(bnp)); if (bgpsbsize && setsockopt(bnp->rp_socket, SOL_SOCKET, SO_SNDBUF, &bgpsbsize, sizeof(bgpsbsize)) < 0) { fatal("bgp_process_keepalive>: setsockopt"); } bgp_update_stat(bnp, BGPS_ESTABLISHED); bgp_dump(bnp); if (bnp && bnp->rp_hold_timer) task_timer_update(bnp->rp_hold_timer); break; case BGPSTATE_ESTABLISHED: task_timer_update(bnp->rp_hold_timer); break; default: bgp_notify(bnp, BGP_ERR_FSM, BGP_ERR_UNSPEC, 0, NULL); break; };}/* * collision_resolv() */struct rpcb *collision_resolv(newconn, oldconn) struct rpcb *newconn; struct rpcb *oldconn;{ IFLOG(LOG_BGPSTATE) syslog(LOG_DEBUG, "<collision_resolv>: invoked."); if (newconn->rp_id > bgpIdentifier) { bgp_notify(oldconn, BGP_CEASE, BGP_ERR_UNSPEC, 0, NULL); /* use newconn */ return newconn; } else { bgp_notify(newconn, BGP_CEASE, BGP_ERR_UNSPEC, 0, NULL); /* use oldconn */ return oldconn; } IFLOG(LOG_BGPSTATE) syslog(LOG_DEBUG, "<collision_resolv>: end.");}/* * bgp_holdtimer_expired() */voidbgp_holdtimer_expired(task *t){ IFLOG(LOG_BGPSTATE) syslog(LOG_DEBUG, "<%s>: holdtime expired for %s (%s AS %d)", __FUNCTION__, ip6str2(&t->tsk_bgp->rp_addr), ((t->tsk_bgp->rp_mode & BGPO_IGP) ? "Internal" : "External"), (int)t->tsk_bgp->rp_as); bgp_notify(t->tsk_bgp, BGP_ERR_HOLDTIME, BGP_ERR_UNSPEC, 0, NULL);}/* * bgp_notify() */voidbgp_notify(struct rpcb *bnp, byte errcode, byte subcode, int len, byte *data){ bgp_send_notification(bnp, errcode, subcode, len, data); bgp_cease(bnp);}/* * bgp_cease() */voidbgp_cease(struct rpcb *bnp){ struct rpcb *abnp = NULL; /* another entry */ if (bnp == NULL) return; bgp_flush(bnp);#if 0 /* XXX: ad-hoc solution */ abnp = bgb; while(abnp) { if (abnp != bnp && abnp->rp_state == BGPSTATE_ESTABLISHED) bgp_dump(abnp); if ((abnp = abnp->rp_next) == bgb) break; }#endif /*** PASSIVEly opened Entry ***/ if (bnp->rp_mode & BGPO_PASSIVE) { /* Remove the Entry from global-list */ if (bgb->rp_next != bgb) { /* check solo ? */ if (bgb == bnp) bgb = bgb->rp_next; remque(bnp); } else { /* solo */ /* active entry should exist. */ fatalx("bgp_cease: no active entry(BUG !!)"); } /* * If there is an RPCB whose state is IDLE for the peer and * there is no other active peer, retry connecting to it * (after waiting for ConnectRetryTimer). * It must not be an already opened passive connection(should we check it?) */ if (!find_active_peer(bnp) && (abnp =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -