⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bgp_util.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 + -