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

📄 bgp_packet.c

📁 linux 路由软件 可支持RIP OSPF BGP等
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Send route refresh message to the peer. */voidbgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,			u_char orf_type, u_char when_to_refresh, int remove){  struct stream *s;  struct stream *packet;  int length;  struct bgp_filter *filter;  int orf_refresh = 0;#ifdef DISABLE_BGP_ANNOUNCE  return;#endif /* DISABLE_BGP_ANNOUNCE */  filter = &peer->filter[afi][safi];  /* Adjust safi code. */  if (safi == SAFI_MPLS_VPN)    safi = BGP_SAFI_VPNV4;    s = stream_new (BGP_MAX_PACKET_SIZE);  /* Make BGP update packet. */  if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))    bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);  else    bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);  /* Encode Route Refresh message. */  stream_putw (s, afi);  stream_putc (s, 0);  stream_putc (s, safi);   if (orf_type == ORF_TYPE_PREFIX      || orf_type == ORF_TYPE_PREFIX_OLD)    if (remove || filter->plist[FILTER_IN].plist)      {	u_int16_t orf_len;	unsigned long orfp;	orf_refresh = 1; 	stream_putc (s, when_to_refresh);	stream_putc (s, orf_type);	orfp = stream_get_putp (s);	stream_putw (s, 0);	if (remove)	  {	    UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);	    stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);	    if (BGP_DEBUG (normal, NORMAL))	      zlog_info ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d", 			 peer->host, orf_type,			 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),			 afi, safi);	  }	else	  {	    SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);	    prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,				  ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,				  ORF_COMMON_PART_DENY);	    if (BGP_DEBUG (normal, NORMAL))	      zlog_info ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d", 			 peer->host, orf_type,			 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),			 afi, safi);	  }	/* Total ORF Entry Len. */	orf_len = stream_get_putp (s) - orfp - 2;	stream_putw_at (s, orfp, orf_len);      }  /* Set packet size. */  length = bgp_packet_set_size (s);  if (BGP_DEBUG (normal, NORMAL))    {      if (! orf_refresh)	zlog_info ("%s sending REFRESH_REQ for afi/safi: %d/%d", 		   peer->host, afi, safi);      zlog_info ("%s send message type %d, length (incl. header) %d",		 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?		 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);    }  /* Make real packet. */  packet = bgp_packet_dup (s);  stream_free (s);  /* Add packet to the peer. */  bgp_packet_add (peer, packet);  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);}/* Send capability message to the peer. */voidbgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,		     int capability_code, int action){  struct stream *s;  struct stream *packet;  int length;  /* Adjust safi code. */  if (safi == SAFI_MPLS_VPN)    safi = BGP_SAFI_VPNV4;  s = stream_new (BGP_MAX_PACKET_SIZE);  /* Make BGP update packet. */  bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);  /* Encode MP_EXT capability. */  if (capability_code == CAPABILITY_CODE_MP)    {      stream_putc (s, action);      stream_putc (s, CAPABILITY_CODE_MP);      stream_putc (s, CAPABILITY_CODE_MP_LEN);      stream_putw (s, afi);      stream_putc (s, 0);      stream_putc (s, safi);      if (BGP_DEBUG (normal, NORMAL))        zlog_info ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",		   peer->host, action == CAPABILITY_ACTION_SET ?		   "Advertising" : "Removing", afi, safi);    }  /* Set packet size. */  length = bgp_packet_set_size (s);  /* Make real packet. */  packet = bgp_packet_dup (s);  stream_free (s);  /* Add packet to the peer. */  bgp_packet_add (peer, packet);  if (BGP_DEBUG (normal, NORMAL))    zlog_info ("%s send message type %d, length (incl. header) %d",	       peer->host, BGP_MSG_CAPABILITY, length);  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);}/* RFC1771 6.8 Connection collision detection. */intbgp_collision_detect (struct peer *new, struct in_addr remote_id){  struct peer *peer;  struct listnode *nn;  struct bgp *bgp;  bgp = bgp_get_default ();  if (! bgp)    return 0;    /* Upon receipt of an OPEN message, the local system must examine     all of its connections that are in the OpenConfirm state.  A BGP     speaker may also examine connections in an OpenSent state if it     knows the BGP Identifier of the peer by means outside of the     protocol.  If among these connections there is a connection to a     remote BGP speaker whose BGP Identifier equals the one in the     OPEN message, then the local system performs the following     collision resolution procedure: */  LIST_LOOP (bgp->peer, peer, nn)    {      /* Under OpenConfirm status, local peer structure already hold         remote router ID. */      if (peer != new	  && (peer->status == OpenConfirm || peer->status == OpenSent)	  && sockunion_same (&peer->su, &new->su))	{	  /* 1. The BGP Identifier of the local system is compared to	     the BGP Identifier of the remote system (as specified in	     the OPEN message). */	  if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))	    {	      /* 2. If the value of the local BGP Identifier is less		 than the remote one, the local system closes BGP		 connection that already exists (the one that is		 already in the OpenConfirm state), and accepts BGP		 connection initiated by the remote system. */	      if (peer->fd >= 0)		bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONNECT_COLLISION);	      return 1;	    }	  else	    {	      /* 3. Otherwise, the local system closes newly created		 BGP connection (the one associated with the newly		 received OPEN message), and continues to use the		 existing one (the one that is already in the		 OpenConfirm state). */	      if (new->fd >= 0)		bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONNECT_COLLISION);	      return -1;	    }	}    }  return 0;}intbgp_open_receive (struct peer *peer, bgp_size_t size){  int ret;  u_char version;  u_char optlen;  u_int16_t holdtime;  u_int16_t send_holdtime;  as_t remote_as;  struct peer *realpeer;  struct in_addr remote_id;  int capability;  char notify_data_remote_as[2];  char notify_data_remote_id[4];  realpeer = NULL;    /* Parse open packet. */  version = stream_getc (peer->ibuf);  memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);  remote_as  = stream_getw (peer->ibuf);  holdtime = stream_getw (peer->ibuf);  memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);  remote_id.s_addr = stream_get_ipv4 (peer->ibuf);  /* Receive OPEN message log  */  if (BGP_DEBUG (normal, NORMAL))    zlog_info ("%s rcv OPEN, version %d, remote-as %d, holdtime %d, id %s",	       peer->host, version, remote_as, holdtime,	       inet_ntoa (remote_id));	    /* Lookup peer from Open packet. */  if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))    {      int as = 0;      realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);      if (! realpeer)	{	  /* Peer's source IP address is check in bgp_accept(), so this	     must be AS number mismatch or remote-id configuration	     mismatch. */	  if (as)	    {	      if (BGP_DEBUG (normal, NORMAL))		zlog_info ("%s bad OPEN, wrong router identifier %s",			   peer->host, inet_ntoa (remote_id));	      bgp_notify_send_with_data (peer, 					 BGP_NOTIFY_OPEN_ERR, 					 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,					 notify_data_remote_id, 4);	    }	  else	    {	      if (BGP_DEBUG (normal, NORMAL))		zlog_info ("%s bad OPEN, remote AS is %d, expected %d",			   peer->host, remote_as, peer->as);	      bgp_notify_send_with_data (peer, 					 BGP_NOTIFY_OPEN_ERR, 					 BGP_NOTIFY_OPEN_BAD_PEER_AS,					 notify_data_remote_as, 2);	    }	  return -1;	}    }  /* When collision is detected and this peer is closed.  Retrun     immidiately. */  ret = bgp_collision_detect (peer, remote_id);  if (ret < 0)    return ret;  /* Hack part. */  if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))    {      if (CHECK_FLAG (realpeer->flags, PEER_FLAG_CONNECT_MODE_ACTIVE))	{ 	  if (BGP_DEBUG (normal, NORMAL)) 	    zlog_info ("%s passive open failed - TCP session must be opened actively",		       realpeer->host);	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONNECT_REJECT); 	  return -1;	}      if (realpeer->status == Established	  && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))	{	  realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;	  SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);	}      else if (ret == 0 && realpeer->status != Active	       && realpeer->status != OpenSent	       && realpeer->status != OpenConfirm) 	{ 	  if (BGP_DEBUG (events, EVENTS)) 	    zlog_info ("%s peer status is %s close connection",		       realpeer->host, LOOKUP (bgp_status_msg, realpeer->status));	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONNECT_REJECT); 	  return -1; 	}      if (BGP_DEBUG (events, EVENTS))	zlog_info ("%s [Event] Transfer temporary BGP peer to existing one",		   peer->host);      bgp_stop (realpeer);            /* Transfer file descriptor. */      realpeer->fd = peer->fd;      peer->fd = -1;      /* Transfer input buffer. */      stream_free (realpeer->ibuf);      realpeer->ibuf = peer->ibuf;      realpeer->packet_size = peer->packet_size;      peer->ibuf = NULL;      /* Transfer status. */      bgp_fsm_change_status (realpeer, peer->status);      bgp_stop (peer);      /* peer pointer change. Open packet send to neighbor. */      peer = realpeer;      bgp_open_send (peer);      if (peer->fd < 0)	{	  zlog_err ("bgp_open_receive peer's fd is negative value %d",		    peer->fd);	  return -1;	}      BGP_READ_ON (peer->t_read, bgp_read, peer->fd);    }  /* remote router-id check. */  if (remote_id.s_addr == 0      || ntohl (remote_id.s_addr) >= 0xe0000000      || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))    {      if (BGP_DEBUG (normal, NORMAL))	zlog_info ("%s bad OPEN, wrong router identifier %s",		   peer->host, inet_ntoa (remote_id));      bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_OPEN_ERR, 				 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,				 notify_data_remote_id, 4);      return -1;    }  /* Set remote router-id */  peer->remote_id = remote_id;  /* Peer BGP version check. */  if (version != BGP_VERSION_4)    {      if (BGP_DEBUG (normal, NORMAL))	zlog_info ("%s bad protocol version, remote requested %d, local request %d",		   peer->host, version, BGP_VERSION_4);      bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_OPEN_ERR, 				 BGP_NOTIFY_OPEN_UNSUP_VERSION,				 "\x04", 1);      return -1;    }  /* Check neighbor as number. */  if (remote_as != peer->as)    {      if (BGP_DEBUG (normal, NORMAL))	zlog_info ("%s bad OPEN, remote AS is %d, expected %d",		   peer->host, remote_as, peer->as);      bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_OPEN_ERR, 				 BGP_NOTIFY_OPEN_BAD_PEER_AS,				 notify_data_remote_as, 2);      return -1;    }  /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST     calculate the value of the Hold Timer by using the smaller of its     configured Hold Time and the Hold Time received in the OPEN message.     The Hold Time MUST be either zero or at least three seconds.  An     implementation may reject connections on the basis of the Hold Time. */  if (holdtime < 3 && holdtime != 0)    {      bgp_notify_send (peer,		       BGP_NOTIFY_OPEN_ERR, 		       BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);      return -1;    }      /* From the rfc: A reasonable maximum time between KEEPALIVE messages     would be one third of the Hold Time interval.  KEEPALIVE messages     MUST NOT be sent more frequently than one per second.  An     implementation MAY adjust the rate at which it sends KEEPALIVE     messages as a function of the Hold Time interval. */  if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))    send_holdtime = peer->holdtime;  else    send_holdtime = peer->bgp->default_holdtime;  if (holdtime < send_holdtime)    peer->v_holdtime = holdtime;  else    peer->v_holdtime = send_holdtime;  peer->v_keepalive = peer->v_holdtime / 3;  /* Open option part parse. */  capability = 0;  optlen = stream_getc (peer->ibuf);  if (optlen != 0)     {      ret = bgp_open_option_parse (peer, optlen, &capability);      if (ret < 0)	return ret;      stream_forward (peer->ibuf, optlen);    }  else    {      if (BGP_DEBUG (normal, NORMAL))	zlog_info ("%s rcvd OPEN w/ OPTION parameter len: 0",		   peer->host);    }  /* Override capability. */  if (! capability || CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))    {      peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];      peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];      peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];      peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];    }  /* Get sockname. */  bgp_getsockname (peer);  BGP_EVENT_ADD (peer, Receive_OPEN_message);  peer->packet_size = 0;  if (peer->ibuf)    stream_reset (peer->ibuf);  return 0;}/* Parse BGP Update packet and make attribute object. */intbgp_update_receive (struct peer *peer, bgp_size_t size){  int ret;  u_char *end;  struct stream *s;  struct attr attr;  bgp_size_t attribute_len;  bgp_size_t update_len;  bgp_size_t withdraw_len;  struct bgp_nlri update;  struct bgp_nlri withdraw;  struct bgp_nlri mp_update;  struct bgp_nlri mp_withdraw;  char attrstr[BUFSIZ] = "";  /* Status must be Established. */

⌨️ 快捷键说明

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