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

📄 bgp_packet.c

📁 linux 路由软件 可支持RIP OSPF BGP等
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* Unfeasible Routes Length. */;  cp = stream_get_putp (s);  stream_putw (s, 0);  /* Withdrawn Routes. */  if (p.family == AF_INET && safi == SAFI_UNICAST)    {      stream_put_prefix (s, &p);      unfeasible_len = stream_get_putp (s) - cp - 2;      /* Set unfeasible len.  */      stream_putw_at (s, cp, unfeasible_len);      /* Set total path attribute length. */      stream_putw (s, 0);    }  else    {      pos = stream_get_putp (s);      stream_putw (s, 0);      total_attr_len = bgp_packet_withdraw (peer, s, &p, afi, safi, NULL, NULL);      /* Set total path attribute length. */      stream_putw_at (s, pos, total_attr_len);    }  bgp_packet_set_size (s);  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);}/* Get next packet to be written.  */struct stream *bgp_write_packet (struct peer *peer){  afi_t afi;  safi_t safi;  struct stream *s = NULL;  struct bgp_advertise *adv;  s = stream_fifo_head (peer->obuf);  if (s)    return s;  for (afi = AFI_IP; afi < AFI_MAX; afi++)    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)      {	adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw);	if (adv)	  {	    s = bgp_withdraw_packet (peer, afi, safi);	    if (s)	      return s;	  }      }      for (afi = AFI_IP; afi < AFI_MAX; afi++)    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)      {	adv = FIFO_HEAD (&peer->sync[afi][safi]->update);	if (adv)	  {            if (adv->binfo && adv->binfo->uptime < peer->synctime[afi][safi])	      {		if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)		    && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)		    && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)		    && safi != SAFI_MPLS_VPN)		  {		    if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],			PEER_STATUS_EOR_RECEIVED))		      s = bgp_update_packet (peer, afi, safi);		  }		else		  s = bgp_update_packet (peer, afi, safi);	      }	    if (s)	      return s;	  }	if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))	  {	    if (peer->afc_nego[afi][safi] && peer->synctime[afi][safi]		&& ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)		&& safi != SAFI_MPLS_VPN)	      {		SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);		return bgp_update_packet_eor (peer, afi, safi);	      }	  }      }  return NULL;}/* Is there partially written packet or updates we can send right   now.  */intbgp_write_proceed (struct peer *peer){  afi_t afi;  safi_t safi;  struct bgp_advertise *adv;  if (stream_fifo_head (peer->obuf))    return 1;  for (afi = AFI_IP; afi < AFI_MAX; afi++)    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)      if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))	return 1;  for (afi = AFI_IP; afi < AFI_MAX; afi++)    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)      if ((adv = FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)	if (adv->binfo->uptime < peer->synctime[afi][safi])	  return 1;  return 0;}/* Write packet to the peer. */intbgp_write (struct thread *thread){  struct peer *peer;  u_char type;  struct stream *s;   int num;  int count = 0;  int write_errno;  /* Yes first of all get peer pointer. */  peer = THREAD_ARG (thread);  peer->t_write = NULL;  /* For non-blocking IO check. */  if (peer->status == Connect)    {      bgp_connect_check (peer);      return 0;    }    /* Nonblocking write until TCP output buffer is full.  */  while (1)    {      int writenum;      s = bgp_write_packet (peer);      if (! s)	return 0;      /* Number of bytes to be sent.  */      writenum = stream_get_endp (s) - stream_get_getp (s);      /* Call write() system call.  */      num = write (peer->fd, STREAM_PNT (s), writenum);      write_errno = errno;      if (num <= 0)	{	  /* Partial write. */	  if (write_errno == EWOULDBLOCK || write_errno == EAGAIN)	      break;	  bgp_stop (peer);	  peer->status = Idle;	  bgp_timer_set (peer);	  return 0;	}      if (num != writenum)	{	  stream_forward (s, num);	  if (write_errno == EAGAIN)	    break;	  continue;	}      /* Retrieve BGP packet type. */      stream_set_getp (s, BGP_MARKER_SIZE + 2);      type = stream_getc (s);      switch (type)	{	case BGP_MSG_OPEN:	  peer->open_out++;	  break;	case BGP_MSG_UPDATE:	  peer->update_out++;	  break;	case BGP_MSG_NOTIFY:	  peer->notify_out++;	  /* BGP_EVENT_ADD (peer, BGP_Stop); */	  bgp_stop_with_error (peer);	  bgp_fsm_change_status (peer, Idle);	  bgp_timer_set (peer);	  return 0;	  break;	case BGP_MSG_KEEPALIVE:	  peer->keepalive_out++;	  break;	case BGP_MSG_ROUTE_REFRESH_NEW:	case BGP_MSG_ROUTE_REFRESH_OLD:	  peer->refresh_out++;	  break;	case BGP_MSG_CAPABILITY:	  peer->dynamic_cap_out++;	  break;	}      /* OK we send packet so delete it. */      bgp_packet_delete (peer);      if (++count >= BGP_WRITE_PACKET_MAX)	break;    }    if (bgp_write_proceed (peer))    BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);    return 0;}/* This is only for sending NOTIFICATION message to neighbor. */intbgp_write_notify (struct peer *peer){  int ret;  u_char type;  struct stream *s;   /* There should be at least one packet. */  s = stream_fifo_head (peer->obuf);  if (!s)    return 0;  assert (stream_get_endp (s) >= BGP_HEADER_SIZE);  /* I'm not sure fd is writable. */  ret = writen (peer->fd, STREAM_DATA (s), stream_get_endp (s));  if (ret <= 0)    {      bgp_stop (peer);      peer->status = Idle;      bgp_timer_set (peer);      return 0;    }  /* Retrieve BGP packet type. */  stream_set_getp (s, BGP_MARKER_SIZE + 2);  type = stream_getc (s);  assert (type == BGP_MSG_NOTIFY);  /* Type should be notify. */  peer->notify_out++;  /* We don't call event manager at here for avoiding other events. */  if (peer->status == Established)    bgp_stop (peer);  else    {      bgp_stop_with_error (peer);      bgp_fsm_change_status (peer, Idle);    }  bgp_timer_set (peer);  return 0;}/* Make keepalive packet and send it to the peer. */voidbgp_keepalive_send (struct peer *peer){  struct stream *s;  int length;  s = stream_new (BGP_MAX_PACKET_SIZE);  /* Make keepalive packet. */  bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);  /* Set packet size. */  length = bgp_packet_set_size (s);  /* Dump packet if debug option is set. */  /* bgp_packet_dump (s); */   if (BGP_DEBUG (keepalive, KEEPALIVE))      zlog_info ("%s sending KEEPALIVE", peer->host);   if (BGP_DEBUG (normal, NORMAL))    zlog_info ("%s send message type %d, length (incl. header) %d",               peer->host, BGP_MSG_KEEPALIVE, length);  /* Add packet to the peer. */  bgp_packet_add (peer, s);  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);}/* Make open packet and send it to the peer. */voidbgp_open_send (struct peer *peer){  struct stream *s;  int length;  u_int16_t send_holdtime;  as_t local_as;  if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))    send_holdtime = peer->holdtime;  else    send_holdtime = peer->bgp->default_holdtime;  /* local-as Change */  if (peer->change_local_as)    local_as = peer->change_local_as;   else    local_as = peer->local_as;   s = stream_new (BGP_MAX_PACKET_SIZE);  /* Make open packet. */  bgp_packet_set_marker (s, BGP_MSG_OPEN);  /* Set open packet values. */  stream_putc (s, BGP_VERSION_4);        /* BGP version */  stream_putw (s, local_as);		 /* My Autonomous System*/  stream_putw (s, send_holdtime);     	 /* Hold Time */  stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */  /* Set capability code. */  bgp_open_capability (s, peer);  /* Set BGP packet length. */  length = bgp_packet_set_size (s);  if (BGP_DEBUG (normal, NORMAL))    zlog_info ("%s sending OPEN, version %d, my as %d, holdtime %d, id %s", 	       peer->host, BGP_VERSION_4, local_as,	       send_holdtime, inet_ntoa (peer->local_id));  if (BGP_DEBUG (normal, NORMAL))    zlog_info ("%s send message type %d, length (incl. header) %d",	       peer->host, BGP_MSG_OPEN, length);  /* Dump packet if debug option is set. */  /* bgp_packet_dump (s); */  /* Add packet to the peer. */  bgp_packet_add (peer, s);  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);}/* Send BGP notify packet with data potion. */voidbgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,			   u_char *data, size_t datalen){  struct stream *s;  int length;  /* Allocate new stream. */  s = stream_new (BGP_MAX_PACKET_SIZE);  /* Make nitify packet. */  bgp_packet_set_marker (s, BGP_MSG_NOTIFY);  /* Set notify packet values. */  stream_putc (s, code);        /* BGP notify code */  stream_putc (s, sub_code);	/* BGP notify sub_code */  /* If notify data is present. */  if (data)    stream_write (s, data, datalen);    /* Set BGP packet length. */  length = bgp_packet_set_size (s);    /* Add packet to the peer. */  stream_fifo_clean (peer->obuf);  bgp_packet_add (peer, s);  /* For debug */  {    struct bgp_notify bgp_notify;    int first = 0;    int i;    char c[4];    bgp_notify.code = code;    bgp_notify.subcode = sub_code;    bgp_notify.data = NULL;    bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;        if (bgp_notify.length)      {	bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);	for (i = 0; i < bgp_notify.length; i++)	  if (first)	    {	      sprintf (c, " %02x", data[i]);	      strcat (bgp_notify.data, c);	    }	  else	    {	      first = 1;	      sprintf (c, "%02x", data[i]);	      strcpy (bgp_notify.data, c);	    }      }    bgp_notify_print (peer, &bgp_notify, "sending");    if (bgp_notify.data)      XFREE (MTYPE_TMP, bgp_notify.data);  }  if (BGP_DEBUG (normal, NORMAL))    zlog_info ("%s send message type %d, length (incl. header) %d",	       peer->host, BGP_MSG_NOTIFY, length);  /* peer reset cause */  if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)    {      if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)	peer->last_reset = PEER_DOWN_USER_RESET;      else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)	peer->last_reset = PEER_DOWN_USER_SHUTDOWN;      else if (sub_code == BGP_NOTIFY_CEASE_PEER_UNCONFIG)	peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;      else	peer->last_reset = PEER_DOWN_NOTIFY_SEND;    }  /* Call imidiately. */  BGP_WRITE_OFF (peer->t_write);  bgp_write_notify (peer);}/* Send BGP notify packet. */voidbgp_notify_send (struct peer *peer, u_char code, u_char sub_code){  bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);}char *afi2str (afi_t afi){  if (afi == AFI_IP)    return "AFI_IP";  else if (afi == AFI_IP6)    return "AFI_IP6";  else    return "Unknown AFI";}char *safi2str (safi_t safi){  if (safi == SAFI_UNICAST)    return "SAFI_UNICAST";  else if (safi == SAFI_MULTICAST)    return "SAFI_MULTICAST";  else if (safi == SAFI_MPLS_VPN || safi == BGP_SAFI_VPNV4)    return "SAFI_MPLS_VPN";  else    return "Unknown SAFI";}

⌨️ 快捷键说明

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