📄 bgp_util.c
字号:
/* * Copyright (C) 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "include.h"#include "bgp.h"#include "router.h"#include "task.h"#include "rt_table.h"#include "aspath.h"#include "bgp_var.h"#include "in6.h"#include "ripng.h"/* * BGP message types */char *bgp_msgstr[] = { "", "Open", "Update", "Notify", "KeepAlive"};char *bgp_errstr[] = { "", "Message Header Error", "Open Message Error", "Update Message Error", "Hold Timer Expired Error", "Finite State Machine Error", "Cease"};char *bgp_hdrerrstr[] = { "", "Connection Not Synchronized", "Bad Message Length", "Bad Message Type"};char *bgp_opnerrstr[] = { "", "Unsupported Version number", "Bad peer AS", "Bad BGP Identifier", "Unsupported Optional Parameter", "Authentication Failure", "Unacceptabel Hold Time"};char *bgp_upderrstr[] = { "", "Malformed Attribute List", "Unrecognized Well-known Attribute", "Missing Well-known Attribute", "Attribute Flags Error", "Attribute Length Error", "Invalid ORIGIN Attribute", "AS Routing Loop", "Invalid NEXT_HOP Attribute", "Optional Attribute Error", "Invalid Network Field", "Malformed AS_PATH"};char *bgp_statestr[] = { "", "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established"};char *bgp_errdatastr(char *buf, int len){#define MAXDATALEN 64 int i = 0, n; static char errstr[(MAXDATALEN * 3) + 3]; if (len == 0) { strcpy(errstr, "(NONE)"); return(errstr); } /* traslate data buffer into a hex list */ for (n = 0; n < len && n < MAXDATALEN; n++) { i += sprintf(&errstr[i], "%s%02x", (i == 0) ? "" : " ", (unsigned char)buf[n]); } /* if there are remaining data, notify that */ if (len > MAXDATALEN) i += sprintf(&errstr[i], "%s", "..."); /* terminate the string buffer with NULL */ errstr[i] = '\0'; return(errstr);}/* * bgp_new_peer() * DESCRIPTION * Create & Initiate a peer * RETURN VALUES * pointer to new struct rpcb */struct rpcb *bgp_new_peer(){ struct rpcb *bnp; MALLOC(bnp, struct rpcb); bnp->rp_next = bnp; bnp->rp_prev = bnp; bnp->rp_state = BGPSTATE_IDLE; IFLOG(LOG_BGPSTATE) syslog(LOG_NOTICE, "<%s>: BGP state shift[%s] peer: %s", __FUNCTION__, bgp_statestr[bnp->rp_state], bgp_peerstr(bnp)); bnp->rp_socket = -1; /* none */ bnp->rp_prefer = htonl(BGP_DEF_LOCALPREF); bnp->rp_sfd[0] = -1; /* none */ bnp->rp_sfd[1] = -1; /* none */ bnp->rp_inputmode = BGP_READ_HEADER; return bnp;}/* * bgp_enable_rte() * RETURN VALUES: 1: succeed * 0: failed */intbgp_enable_rte(rte) struct rt_entry *rte;{ struct rpcb *bnp; struct ifinfo *ifep = NULL; bnp = rte->rt_proto.rtp_bgp; /* come from */ errno = 0; /* Add kernel table */ if (rte->rt_flags & RTF_UP) { if (!(bnp->rp_mode & BGPO_IGP)) { /* eBGP */ if (!in6_is_addr_onlink(&rte->rt_bgw, &ifep)) { /* currently we do not support multi-hop EBGP */ syslog(LOG_INFO, "<%s>: EBGP next hop %s is not on-link" "(not activated)", __FUNCTION__, ip6str(&rte->rt_bgw, 0)); rte->rt_flags &= ~RTF_UP; return 0; /* continue to next rte */ } rte->rt_gw = rte->rt_bgw; rte->rt_gwsrc_type = RTPROTO_BGP; if (ifep == NULL) ifep = bnp->rp_ife; if (addroute(rte, &rte->rt_bgw, ifep) != 0) { /* If the next hop is inaccessible, do not consider it. */ /* [cisco] */ return 0; } rte->rt_flags |= RTF_INSTALLED; } else { /* iBGP */ /* * In IBGP cases, try to resolve an on-link gateway to the * next-hop. It will succeed if an IGP(e.g. RIPng) works well. * If a gateway is resolved, try to install it. */ if (IN6_IS_ADDR_LINKLOCAL(&rte->rt_bgw)) { /* we reject link-local next hop for IBGP */ rte->rt_flags &= ~RTF_UP; return 0; } if (set_nexthop(&rte->rt_bgw, rte) == 1) { if (addroute(rte, &rte->rt_gw, rte->rt_gwif) == 0) { IFLOG(LOG_BGPROUTE) syslog(LOG_DEBUG, "<%s>:succeed (maybe third-party)", __FUNCTION__); rte->rt_flags |= RTF_INSTALLED; } else { syslog(LOG_ERR, "<%s>: failed to add a route dst: %s/%d, " "gw: %s if: %s", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, ip6str(&rte->rt_gw, rte->rt_gwif->ifi_ifn->if_index), rte->rt_gwif->ifi_ifn->if_name); } } else { syslog(LOG_ERR, "<%s>: failed to set a gateway for nexthop %s", __FUNCTION__, ip6str(&rte->rt_bgw, 0)); } } } if (!IN6_IS_ADDR_UNSPECIFIED(&rte->rt_gw) && !IN6_IS_ADDR_LINKLOCAL(&rte->rt_gw)) rte->rt_flags |= RTF_NH_NOT_LLADDR; return 1; /* succeed */}/* * bgp_disable_rte() */voidbgp_disable_rte(rte) struct rt_entry *rte;{ if (rte->rt_proto.rtp_type != RTPROTO_BGP) fatalx("<bgp_disable_rte>: BUG !"); if (rte->rt_flags & RTF_INSTALLED) { IFLOG(LOG_BGPROUTE) syslog(LOG_DEBUG, "<%s>: delroute()...", __FUNCTION__); if (delroute(rte, &rte->rt_gw) != 0) syslog(LOG_ERR, "<%s>: route couldn't be deleted: dst=%s/%d, " "gw=%s", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, ip6str(&rte->rt_gw, 0)); rte->rt_flags &= ~RTF_INSTALLED; /* down */ rte->rt_ripinfo.rip6_metric = RIPNG_METRIC_UNREACHABLE; }}/* * bgp_recover_rte() * DESCRIPTION: Find recoverable route. */voidbgp_recover_rte(drte) struct rt_entry *drte; /* already down */{ struct rpcb *obnp; /* other Peer */ struct rt_entry *orte, *rrte; /* recover RTE */ extern struct rpcb *bgb; orte = rrte = NULL; obnp = bgb; while(obnp) { if ((drte->rt_proto.rtp_type != RTPROTO_BGP || obnp != drte->rt_proto.rtp_bgp) && (orte = find_rte(drte, obnp->rp_adj_ribs_in))) { if (obnp->rp_mode & BGPO_IGP && drte->rt_ripinfo.rip6_tag == orte->rt_ripinfo.rip6_tag) orte->rt_flags &= ~RTF_IGP_EGP_SYNC; /* XXX: de-synchronize */ if (!(obnp->rp_mode & BGPO_IGP) || obnp->rp_mode & BGPO_NOSYNC || orte->rt_flags & RTF_IGP_EGP_SYNC) { if (rrte == NULL) rrte = orte; /* the first candidate */ else { if (bgp_preferred_rte(orte, rrte)) rrte = orte; /* More preferable candidate */ } } } if ((obnp = obnp->rp_next) == bgb) break; } if (rrte) { struct rt_entry crte; rrte->rt_flags |= RTF_UP; rrte->rt_ripinfo.rip6_metric = 1; if (bgp_enable_rte(rrte) == 0) { struct rpcb *obnp = rrte->rt_proto.rtp_bgp; IFLOG(LOG_BGPROUTE) syslog(LOG_DEBUG, "<%s>: failed route recovery for %s/%d, origin: %s(deleted)", __FUNCTION__, ip6str(&drte->rt_ripinfo.rip6_dest, 0), drte->rt_ripinfo.rip6_plen, bgp_peerstr(rrte->rt_proto.rtp_bgp)); obnp->rp_adj_ribs_in = rte_remove(rrte, obnp->rp_adj_ribs_in); } else if (!(rrte->rt_flags & RTF_INSTALLED)) { IFLOG(LOG_BGPROUTE) syslog(LOG_DEBUG, "<%s>: route recover for %s/%d, origin: %s (not installed)", __FUNCTION__, ip6str(&drte->rt_ripinfo.rip6_dest, 0), drte->rt_ripinfo.rip6_plen, bgp_peerstr(rrte->rt_proto.rtp_bgp)); } else { IFLOG(LOG_BGPROUTE) syslog(LOG_DEBUG, "<%s>: route recover for %s/%d, origin: %s", __FUNCTION__, ip6str(&drte->rt_ripinfo.rip6_dest, 0), drte->rt_ripinfo.rip6_plen, bgp_peerstr(rrte->rt_proto.rtp_bgp)); crte = *rrte; crte.rt_next = crte.rt_prev = &crte; redistribute(&crte); /* XXX: this might hevily modify the peer list */ } } else { IFLOG(LOG_BGPROUTE) syslog(LOG_DEBUG, "<%s>: no recover for %s/%d", __FUNCTION__, ip6str(&drte->rt_ripinfo.rip6_dest, 0), drte->rt_ripinfo.rip6_plen); } return;}/* * Detect if RTE is preferred to ORTE. */intbgp_preferred_rte(rte, orte) struct rt_entry *rte, *orte;{ u_int32_t lp, olp, med, omed; lp = ntohl(rte->rt_aspath->asp_localpref); olp = ntohl(orte->rt_aspath->asp_localpref); if (lp > olp) return(1); if (lp < olp) return(0); /* then lp == olp */ if (aspath2cost(rte->rt_aspath) < aspath2cost(orte->rt_aspath)) return(1); if (aspath2cost(rte->rt_aspath) > aspath2cost(orte->rt_aspath)) return(0); /* * now lp == olp && pathlen(rte) == pathlen(orte) * XXX: Cisco convention */ med = ntohl(rte->rt_aspath->asp_med); omed = ntohl(orte->rt_aspath->asp_med); if (med < omed) return(1); if (med > omed) return(0); return(0);}/* * If an IGP route (including an interface route) is being newly installed, * check each BGP routes that is up but does not have a proper gateway. * If the IGP route can be used as a gateway for a BGP route, enable the * BGP route. */voidbgp_enable_rte_by_igp(rte) struct rt_entry *rte;{ struct rpcb *bnp; struct rt_entry *brte; struct bgpcblist *bgpcb, *bgpcb_head; extern byte bgpyes; if (!bgpyes) return; switch(rte->rt_proto.rtp_type) { case RTPROTO_RIP: case RTPROTO_IF:#ifdef notyet case RTPROTO_OSPF:#endif bgpcb_head = make_bgpcb_list(); for (bgpcb = bgpcb_head; bgpcb; bgpcb = bgpcb->next) { bnp = bgpcb->bnp; /* * XXX: bnp might be closed or even freed during the loop, * so the validity check is necessary. */ if (!bgp_rpcb_isvalid(bnp)) continue; brte = bnp->rp_adj_ribs_in; while(brte) { if ((brte->rt_flags & (RTF_UP|RTF_INSTALLED)) == RTF_UP) { /* try to enable */ if (bgp_enable_rte(brte) == 1 && (brte->rt_flags & RTF_INSTALLED)) { struct rt_entry crte; /* XXX long line... */ IFLOG(LOG_BGPROUTE) syslog(LOG_DEBUG, "<%s>: BGP route(%s/%d) " "was enabled", __FUNCTION__, ip6str(&brte->rt_ripinfo.rip6_dest, 0), brte->rt_ripinfo.rip6_plen); /* redistribute this route */ crte = *brte; crte.rt_next = crte.rt_prev = &crte; redistribute(&crte); /* * XXX: redistrib might * invalidate bnp */ if (!bgp_rpcb_isvalid(bnp)) { syslog(LOG_NOTICE, "<%s>: rpcb %p was " "invalidated during a " "redistribution", __FUNCTION__, bnp); break; } } } if ((brte = brte->rt_next) == bnp->rp_adj_ribs_in) break; } } free_bgpcb_list(bgpcb_head); break; default: fatalx("<bgp_enable_rte_by_igp>: rt_proto.rtp_type corrupted"); /* NOTREACHED */ }}/* * If an IGP route (including an interface route) is being removed, * all BGP routes that refer to the IGP route should also be disabled. * XXX: The routes are withdrawn even when an alternative IGP route are * soon avaiable... */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -