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

📄 bgpd.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 5 页
字号:
/* BGP-4, BGP-4+ daemon program   Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro IshiguroThis file is part of GNU Zebra.GNU Zebra is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 2, or (at your option) anylater version.GNU Zebra is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Zebra; see the file COPYING.  If not, write to the FreeSoftware Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA02111-1307, USA.  */#include <zebra.h>#include "prefix.h"#include "thread.h"#include "buffer.h"#include "stream.h"#include "command.h"#include "sockunion.h"#include "network.h"#include "memory.h"#include "filter.h"#include "routemap.h"#include "str.h"#include "log.h"#include "plist.h"#include "linklist.h"#include "bgpd/bgpd.h"#include "bgpd/bgp_table.h"#include "bgpd/bgp_aspath.h"#include "bgpd/bgp_route.h"#include "bgpd/bgp_dump.h"#include "bgpd/bgp_debug.h"#include "bgpd/bgp_community.h"#include "bgpd/bgp_attr.h"#include "bgpd/bgp_regex.h"#include "bgpd/bgp_clist.h"#include "bgpd/bgp_fsm.h"#include "bgpd/bgp_packet.h"#include "bgpd/bgp_zebra.h"#include "bgpd/bgp_open.h"#include "bgpd/bgp_filter.h"#include "bgpd/bgp_nexthop.h"#include "bgpd/bgp_damp.h"#include "bgpd/bgp_mplsvpn.h"#include "bgpd/bgp_advertise.h"#include "bgpd/bgp_network.h"#include "bgpd/bgp_vty.h"#ifdef HAVE_SNMP#include "bgpd/bgp_snmp.h"#endif /* HAVE_SNMP *//* BGP process wide configuration.  */static struct bgp_master bgp_master;/* BGP process wide configuration pointer to export.  */struct bgp_master *bm;/* BGP community-list.  */struct community_list_handler *bgp_clist;/* BGP global flag manipulation.  */intbgp_option_set (int flag){  switch (flag)    {    case BGP_OPT_NO_FIB:    case BGP_OPT_MULTIPLE_INSTANCE:    case BGP_OPT_CONFIG_CISCO:      SET_FLAG (bm->options, flag);      break;    default:      return BGP_ERR_INVALID_FLAG;      break;    }  return 0;}intbgp_option_unset (int flag){  switch (flag)    {    case BGP_OPT_MULTIPLE_INSTANCE:      if (listcount (bm->bgp) > 1)	return BGP_ERR_MULTIPLE_INSTANCE_USED;      /* Fall through.  */    case BGP_OPT_NO_FIB:    case BGP_OPT_CONFIG_CISCO:      UNSET_FLAG (bm->options, flag);      break;    default:      return BGP_ERR_INVALID_FLAG;      break;    }  return 0;}intbgp_option_check (int flag){  return CHECK_FLAG (bm->options, flag);}/* BGP flag manipulation.  */intbgp_flag_set (struct bgp *bgp, int flag){  SET_FLAG (bgp->flags, flag);  return 0;}intbgp_flag_unset (struct bgp *bgp, int flag){  UNSET_FLAG (bgp->flags, flag);  return 0;}intbgp_flag_check (struct bgp *bgp, int flag){  return CHECK_FLAG (bgp->flags, flag);}/* Internal function to set BGP structure configureation flag.  */static voidbgp_config_set (struct bgp *bgp, int config){  SET_FLAG (bgp->config, config);}static voidbgp_config_unset (struct bgp *bgp, int config){  UNSET_FLAG (bgp->config, config);}static intbgp_config_check (struct bgp *bgp, int config){  return CHECK_FLAG (bgp->config, config);}/* Set BGP router identifier. */intbgp_router_id_set (struct bgp *bgp, struct in_addr *id){  struct peer *peer;  struct listnode *nn;  if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)      && IPV4_ADDR_SAME (&bgp->router_id, id))    return 0;  IPV4_ADDR_COPY (&bgp->router_id, id);  bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);  /* Set all peer's local identifier with this value. */  LIST_LOOP (bgp->peer, peer, nn)    {      IPV4_ADDR_COPY (&peer->local_id, id);      if (peer->status == Established)	{	  peer->last_reset = PEER_DOWN_RID_CHANGE;	  bgp_notify_send (peer, BGP_NOTIFY_CEASE,			   BGP_NOTIFY_CEASE_CONFIG_CHANGE);	}    }  return 0;}/* Unset BGP router identifier. */intbgp_router_id_unset (struct bgp *bgp){  struct peer *peer;  struct listnode *nn;  if (! bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID))    return 0;  bgp->router_id.s_addr = 0;  bgp_config_unset (bgp, BGP_CONFIG_ROUTER_ID);  /* Clear peer router id configuration.  */  LIST_LOOP (bgp->peer, peer, nn)    {      peer->local_id.s_addr = 0;    }  /* Set router-id from interface's address. */  bgp_if_update_all ();  /* Reset all BGP sessions to use new router-id.  */  LIST_LOOP (bgp->peer, peer, nn)    {      if (peer->status == Established)	{	  peer->last_reset = PEER_DOWN_RID_CHANGE;	  bgp_notify_send (peer, BGP_NOTIFY_CEASE,			   BGP_NOTIFY_CEASE_CONFIG_CHANGE);	}    }  return 0;}/* BGP's cluster-id control. */intbgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id){  struct peer *peer;  struct listnode *nn;  if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)      && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))    return 0;  IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);  bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);  /* Clear all IBGP peer. */  LIST_LOOP (bgp->peer, peer, nn)    {      if (peer_sort (peer) != BGP_PEER_IBGP)	continue;      if (peer->status == Established)	{	  peer->last_reset = PEER_DOWN_CLID_CHANGE;	  bgp_notify_send (peer, BGP_NOTIFY_CEASE,			   BGP_NOTIFY_CEASE_CONFIG_CHANGE);	}    }  return 0;}intbgp_cluster_id_unset (struct bgp *bgp){  struct peer *peer;  struct listnode *nn;  if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))    return 0;  bgp->cluster_id.s_addr = 0;  bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);  /* Clear all IBGP peer. */  LIST_LOOP (bgp->peer, peer, nn)    {      if (peer_sort (peer) != BGP_PEER_IBGP)	continue;      if (peer->status == Established)	{	  peer->last_reset = PEER_DOWN_CLID_CHANGE;	  bgp_notify_send (peer, BGP_NOTIFY_CEASE,			   BGP_NOTIFY_CEASE_CONFIG_CHANGE);	}    }  return 0;}/* BGP timer configuration.  */intbgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime){  bgp->default_keepalive = (keepalive < holdtime / 3 			    ? keepalive : holdtime / 3);  bgp->default_holdtime = holdtime;  return 0;}intbgp_timers_unset (struct bgp *bgp){  bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;  bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;  return 0;}/* BGP confederation configuration.  */intbgp_confederation_id_set (struct bgp *bgp, as_t as){  struct peer *peer;  struct listnode *nn;  int already_confed;  if (as == 0)    return BGP_ERR_INVALID_AS;  /* Remember - were we doing confederation before? */  already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);  bgp->confed_id = as;  bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);  /* If we were doing confederation already, this is just an external     AS change.  Just Reset EBGP sessions, not CONFED sessions.  If we     were not doing confederation before, reset all EBGP sessions.  */  LIST_LOOP (bgp->peer, peer, nn)    {      /* We're looking for peers who's AS is not local or part of our	 confederation.  */      if (already_confed)	{	  if (peer_sort (peer) == BGP_PEER_EBGP)	    {	      peer->local_as = as;	      if (peer->status == Established)		{		  peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;		  bgp_notify_send (peer, BGP_NOTIFY_CEASE,			       BGP_NOTIFY_CEASE_CONFIG_CHANGE);		}	      else		BGP_EVENT_ADD (peer, BGP_Stop);	    }	}      else	{	  /* Not doign confederation before, so reset every non-local	     session */	  if (peer_sort (peer) != BGP_PEER_IBGP)	    {	      /* Reset the local_as to be our EBGP one */	      if (peer_sort (peer) == BGP_PEER_EBGP)		peer->local_as = as;	      if (peer->status == Established)		{		  peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;		  bgp_notify_send (peer, BGP_NOTIFY_CEASE,			       BGP_NOTIFY_CEASE_CONFIG_CHANGE);		}	      else		BGP_EVENT_ADD (peer, BGP_Stop);	    }	}    }  return 0;}intbgp_confederation_id_unset (struct bgp *bgp){  struct peer *peer;  struct listnode *nn;  bgp->confed_id = 0;  bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);        LIST_LOOP (bgp->peer, peer, nn)    {      /* We're looking for peers who's AS is not local */      if (peer_sort (peer) != BGP_PEER_IBGP)	{	  peer->local_as = bgp->as;	  if (peer->status == Established)	    {	      peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;	      bgp_notify_send (peer, BGP_NOTIFY_CEASE,			       BGP_NOTIFY_CEASE_CONFIG_CHANGE);	    }	  else	    BGP_EVENT_ADD (peer, BGP_Stop);	}    }  return 0;}/* Is an AS part of the confed or not? */intbgp_confederation_peers_check (struct bgp *bgp, as_t as){  int i;  if (! bgp)    return 0;  for (i = 0; i < bgp->confed_peers_cnt; i++)    if (bgp->confed_peers[i] == as)      return 1;    return 0;}/* Add an AS to the confederation set.  */intbgp_confederation_peers_add (struct bgp *bgp, as_t as){  struct peer *peer;  struct listnode *nn;  if (! bgp)    return BGP_ERR_INVALID_BGP;  if (bgp->as == as)    return BGP_ERR_INVALID_AS;  if (bgp_confederation_peers_check (bgp, as))    return -1;  if (bgp->confed_peers)    bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST, 				  bgp->confed_peers,				  (bgp->confed_peers_cnt + 1) * sizeof (as_t));  else    bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST, 				 (bgp->confed_peers_cnt + 1) * sizeof (as_t));  bgp->confed_peers[bgp->confed_peers_cnt] = as;  bgp->confed_peers_cnt++;  if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))    {      LIST_LOOP (bgp->peer, peer, nn)	{	  if (peer->as == as)	    {	      peer->local_as = bgp->as;	      if (peer->status == Established)		{		  peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;		  bgp_notify_send (peer, BGP_NOTIFY_CEASE,				   BGP_NOTIFY_CEASE_CONFIG_CHANGE);		}	      else	        BGP_EVENT_ADD (peer, BGP_Stop);	    }	}    }  return 0;}/* Delete an AS from the confederation set.  */intbgp_confederation_peers_remove (struct bgp *bgp, as_t as){  int i;  int j;  struct peer *peer;  struct listnode *nn;  if (! bgp)    return -1;  if (! bgp_confederation_peers_check (bgp, as))    return -1;  for (i = 0; i < bgp->confed_peers_cnt; i++)    if (bgp->confed_peers[i] == as)      for(j = i + 1; j < bgp->confed_peers_cnt; j++)	bgp->confed_peers[j - 1] = bgp->confed_peers[j];  bgp->confed_peers_cnt--;  if (bgp->confed_peers_cnt == 0)    {      if (bgp->confed_peers)	XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);      bgp->confed_peers = NULL;    }  else    bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,				  bgp->confed_peers,				  bgp->confed_peers_cnt * sizeof (as_t));  /* Now reset any peer who's remote AS has just been removed from the     CONFED */  if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))    {      LIST_LOOP (bgp->peer, peer, nn)	{	  if (peer->as == as)	    {	      peer->local_as = bgp->confed_id;	      if (peer->status == Established)		{		  peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;		  bgp_notify_send (peer, BGP_NOTIFY_CEASE,				   BGP_NOTIFY_CEASE_CONFIG_CHANGE);		}	      else		BGP_EVENT_ADD (peer, BGP_Stop);	    }	}    }  return 0;}/* Local preference configuration.  */intbgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref){  if (! bgp)    return -1;  bgp_config_set (bgp, BGP_CONFIG_DEFAULT_LOCAL_PREF);  bgp->default_local_pref = local_pref;  return 0;}intbgp_default_local_preference_unset (struct bgp *bgp){  if (! bgp)    return -1;  bgp_config_unset (bgp, BGP_CONFIG_DEFAULT_LOCAL_PREF);  bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;  return 0;}/* Peer comparison function for sorting.  */static intpeer_cmp (struct peer *p1, struct peer *p2){  return sockunion_cmp (&p1->su, &p2->su);}intpeer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag){  return CHECK_FLAG (peer->af_flags[afi][safi], flag);}/* Reset all address family specific configuration.  */static void

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -