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

📄 bgp_open.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 2 页
字号:
/* BGP open message handling   Copyright (C) 1998, 1999 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 "linklist.h"#include "prefix.h"#include "stream.h"#include "thread.h"#include "log.h"#include "command.h"#include "bgpd/bgpd.h"#include "bgpd/bgp_attr.h"#include "bgpd/bgp_debug.h"#include "bgpd/bgp_fsm.h"#include "bgpd/bgp_packet.h"#include "bgpd/bgp_open.h"/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can   negotiate remote peer supports extentions or not. But if   remote-peer doesn't supports negotiation process itself.  We would   like to do manual configuration.   So there is many configurable point.  First of all we want set each   peer whether we send capability negotiation to the peer or not.   Next, if we send capability to the peer we want to set my capabilty   inforation at each peer. */voidbgp_capability_vty_out (struct vty *vty, struct peer *peer){  u_char *pnt;  u_char *end;  struct capability cap;  pnt = peer->notify.data;  end = pnt + peer->notify.length;  while (pnt < end)    {      memcpy(&cap, pnt, sizeof(struct capability));      if (pnt + 2 > end)	return;      if (pnt + (cap.length + 2) > end)	return;      if (cap.code == CAPABILITY_CODE_MP)	{	  vty_out (vty, "  Capability error for: Multi protocol ");	  switch (ntohs (cap.mpc.afi))	    {	    case AFI_IP:	      vty_out (vty, "AFI IPv4, ");	      break;	    case AFI_IP6:	      vty_out (vty, "AFI IPv6, ");	      break;	    default:	      vty_out (vty, "AFI Unknown %d, ", ntohs (cap.mpc.afi));	      break;	    }	  switch (cap.mpc.safi)	    {	    case SAFI_UNICAST:	      vty_out (vty, "SAFI Unicast");	      break;	    case SAFI_MULTICAST:	      vty_out (vty, "SAFI Multicast");	      break;	    case SAFI_UNICAST_MULTICAST:	      vty_out (vty, "SAFI Unicast Multicast");	      break;	    case BGP_SAFI_VPNV4:	      vty_out (vty, "SAFI MPLS-VPN");	      break;	    default:	      vty_out (vty, "SAFI Unknown %d ", cap.mpc.safi);	      break;	    }	  vty_out (vty, "%s", VTY_NEWLINE);	}      else if (cap.code >= 128)	vty_out (vty, "  Capability error: vendor specific capability code %d",		 cap.code);      else	vty_out (vty, "  Capability error: unknown capability code %d", 		 cap.code);      pnt += cap.length + 2;    }}/* Set negotiated capability value. */intbgp_capability_mp (struct peer *peer, struct capability *cap){  if (ntohs (cap->mpc.afi) == AFI_IP)    {      if (cap->mpc.safi == SAFI_UNICAST)	{	  peer->afc_recv[AFI_IP][SAFI_UNICAST] = 1;	  if (peer->afc[AFI_IP][SAFI_UNICAST])	    peer->afc_nego[AFI_IP][SAFI_UNICAST] = 1;	  else	    return -1;	}      else if (cap->mpc.safi == SAFI_MULTICAST) 	{	  peer->afc_recv[AFI_IP][SAFI_MULTICAST] = 1;	  if (peer->afc[AFI_IP][SAFI_MULTICAST])	    peer->afc_nego[AFI_IP][SAFI_MULTICAST] = 1;	  else	    return -1;	}      else if (cap->mpc.safi == BGP_SAFI_VPNV4)	{	  peer->afc_recv[AFI_IP][SAFI_MPLS_VPN] = 1;	  if (peer->afc[AFI_IP][SAFI_MPLS_VPN])	    peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] = 1;	  else	    return -1;	}      else	return -1;    }#ifdef HAVE_IPV6  else if (ntohs (cap->mpc.afi) == AFI_IP6)    {      if (cap->mpc.safi == SAFI_UNICAST)	{	  peer->afc_recv[AFI_IP6][SAFI_UNICAST] = 1;	  if (peer->afc[AFI_IP6][SAFI_UNICAST])	    peer->afc_nego[AFI_IP6][SAFI_UNICAST] = 1;	  else	    return -1;	}      else if (cap->mpc.safi == SAFI_MULTICAST)	{	  peer->afc_recv[AFI_IP6][SAFI_MULTICAST] = 1;	  if (peer->afc[AFI_IP6][SAFI_MULTICAST])	    peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = 1;	  else	    return -1;	}      else	return -1;    }#endif /* HAVE_IPV6 */  else    {      /* Unknown Address Family. */      return -1;    }  return 0;}voidbgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,				u_char type, u_char mode){  if (BGP_DEBUG (normal, NORMAL))    zlog_info ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",	       peer->host, afi, safi, type, mode);}intbgp_capability_orf (struct peer *peer, struct capability *cap,		    u_char *pnt){  afi_t afi = ntohs(cap->mpc.afi);  safi_t safi = cap->mpc.safi;  u_char number_of_orfs;  u_char type;  u_char mode;  u_int16_t sm_cap = 0; /* capability send-mode receive */  u_int16_t rm_cap = 0; /* capability receive-mode receive */   int i;  /* Check length. */  if (cap->length < 7)    {      zlog_info ("%s ORF Capability length error %d",		 peer->host, cap->length);		 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);      return -1;    }  if (BGP_DEBUG (normal, NORMAL))    zlog_info ("%s OPEN has ORF CAP(%s) for afi/safi: %u/%u",	       peer->host, (cap->code == CAPABILITY_CODE_ORF ?                       "new" : "old"), afi, safi);  /* Check AFI and SAFI. */  if ((afi != AFI_IP && afi != AFI_IP6)      || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST	  && safi != BGP_SAFI_VPNV4))    {      zlog_info ("%s Addr-family %d/%d not supported. Ignoring the ORF capability",                 peer->host, afi, safi);      return -1;    }  number_of_orfs = *pnt++;  for (i = 0 ; i < number_of_orfs ; i++)    {      type = *pnt++;      mode = *pnt++;      /* ORF Mode error check */      if (mode != ORF_MODE_BOTH && mode != ORF_MODE_SEND	  && mode != ORF_MODE_RECEIVE)	{	  bgp_capability_orf_not_support (peer, afi, safi, type, mode);	  continue;	}      /* ORF Type and afi/safi error check */      if (cap->code == CAPABILITY_CODE_ORF)	{	  if (type == ORF_TYPE_PREFIX &&	      ((afi == AFI_IP && safi == SAFI_UNICAST)		|| (afi == AFI_IP && safi == SAFI_MULTICAST)		|| (afi == AFI_IP6 && safi == SAFI_UNICAST)))	    {	      sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;	      rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;	      if (BGP_DEBUG (normal, NORMAL))		zlog_info ("%s OPEN has Prefixlist ORF(%d) capability as %s for afi/safi: %d/%d",			   peer->host, ORF_TYPE_PREFIX, (mode == ORF_MODE_SEND ? "SEND" :			   mode == ORF_MODE_RECEIVE ? "RECEIVE" : "BOTH") , afi, safi);	    }	  else	    {	      bgp_capability_orf_not_support (peer, afi, safi, type, mode);	      continue;	    }	}      else if (cap->code == CAPABILITY_CODE_ORF_OLD)	{	  if (type == ORF_TYPE_PREFIX_OLD &&	      ((afi == AFI_IP && safi == SAFI_UNICAST)		|| (afi == AFI_IP && safi == SAFI_MULTICAST)		|| (afi == AFI_IP6 && safi == SAFI_UNICAST)))	    {	      sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;	      rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;	      if (BGP_DEBUG (normal, NORMAL))		zlog_info ("%s OPEN has Prefixlist ORF(%d) capability as %s for afi/safi: %d/%d",			   peer->host, ORF_TYPE_PREFIX_OLD, (mode == ORF_MODE_SEND ? "SEND" :			   mode == ORF_MODE_RECEIVE ? "RECEIVE" : "BOTH") , afi, safi);	    }	  else	    {	      bgp_capability_orf_not_support (peer, afi, safi, type, mode);	      continue;	    }	}      else	{	  bgp_capability_orf_not_support (peer, afi, safi, type, mode);	  continue;	}      switch (mode)	{	  case ORF_MODE_BOTH:	    SET_FLAG (peer->af_cap[afi][safi], sm_cap);	    SET_FLAG (peer->af_cap[afi][safi], rm_cap);	    break;	  case ORF_MODE_SEND:	    SET_FLAG (peer->af_cap[afi][safi], sm_cap);	    break;	  case ORF_MODE_RECEIVE:	    SET_FLAG (peer->af_cap[afi][safi], rm_cap);	    break;	}    }  return 0;}/* Parse given capability. */intbgp_capability_parse (struct peer *peer, u_char *pnt, u_char length,		      u_char **error){  int ret;  u_char *end;  struct capability cap;  end = pnt + length;  while (pnt < end)    {      afi_t afi;      safi_t safi;      /* Fetch structure to the byte stream. */      memcpy (&cap, pnt, sizeof (struct capability));      afi = ntohs(cap.mpc.afi);      safi = cap.mpc.safi;      if (BGP_DEBUG (normal, NORMAL))	zlog_info ("%s OPEN has CAPABILITY code: %d, length %d",		   peer->host, cap.code, cap.length);      /* We need at least capability code and capability length. */      if (pnt + 2 > end)	{	  zlog_info ("%s Capability length error", peer->host);	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);	  return -1;	}      /* Capability length check. */      if (pnt + (cap.length + 2) > end)	{	  zlog_info ("%s Capability length error", peer->host);	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);	  return -1;	}      /* We know MP Capability Code. */      if (cap.code == CAPABILITY_CODE_MP)	{	  if (BGP_DEBUG (normal, NORMAL))	    zlog_info ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",		       peer->host, afi, safi);	  /* Ignore capability when override-capability is set. */	  if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))	    {	      /* Set negotiated value. */	      ret = bgp_capability_mp (peer, &cap);	      /* Unsupported Capability. */	      if (ret < 0)		{		  /* Store return data. */		  memcpy (*error, &cap, cap.length + 2);		  *error += cap.length + 2;		}	    }	}      else if (cap.code == CAPABILITY_CODE_REFRESH	       || cap.code == CAPABILITY_CODE_REFRESH_OLD)	{	  /* Check length. */	  if (cap.length != 0)	    {	      zlog_info ("%s Route Refresh Capability length error %d",			 peer->host, cap.length);	      bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);	      return -1;	    }	  if (BGP_DEBUG (normal, NORMAL))	    zlog_info ("%s OPEN has ROUTE-REFRESH capability(%s) for all address-families",		       peer->host,		       cap.code == CAPABILITY_CODE_REFRESH_OLD ? "old" : "new");	  /* BGP refresh capability */	  if (cap.code == CAPABILITY_CODE_REFRESH_OLD)	    SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);	  else	    SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);	}      else if (cap.code == CAPABILITY_CODE_ORF	       || cap.code == CAPABILITY_CODE_ORF_OLD)	bgp_capability_orf (peer, &cap, pnt + sizeof (struct capability));

⌨️ 快捷键说明

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