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

📄 bgp_packet.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 4 页
字号:
/* BGP packet management routine.   Copyright (C) 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 "thread.h"#include "stream.h"#include "network.h"#include "prefix.h"#include "command.h"#include "log.h"#include "memory.h"#include "sockunion.h"		/* for inet_ntop () */#include "linklist.h"#include "plist.h"#include "bgpd/bgpd.h"#include "bgpd/bgp_table.h"#include "bgpd/bgp_dump.h"#include "bgpd/bgp_attr.h"#include "bgpd/bgp_debug.h"#include "bgpd/bgp_fsm.h"#include "bgpd/bgp_route.h"#include "bgpd/bgp_packet.h"#include "bgpd/bgp_open.h"#include "bgpd/bgp_aspath.h"#include "bgpd/bgp_community.h"#include "bgpd/bgp_ecommunity.h"#include "bgpd/bgp_network.h"#include "bgpd/bgp_mplsvpn.h"#include "bgpd/bgp_advertise.h"int stream_put_prefix (struct stream *, struct prefix *);/* Set up BGP packet marker and packet type. */static intbgp_packet_set_marker (struct stream *s, u_char type){  int i;  /* Fill in marker. */  for (i = 0; i < BGP_MARKER_SIZE; i++)    stream_putc (s, 0xff);  /* Dummy total length. This field is should be filled in later on. */  stream_putw (s, 0);  /* BGP packet type. */  stream_putc (s, type);  /* Return current stream size. */  return stream_get_putp (s);}/* Set BGP packet header size entry.  If size is zero then use current   stream size. */static intbgp_packet_set_size (struct stream *s){  int cp;  /* Preserve current pointer. */  cp = stream_get_putp (s);  stream_set_putp (s, BGP_MARKER_SIZE);  stream_putw (s, cp);  /* Write back current pointer. */  stream_set_putp (s, cp);  return cp;}/* Add new packet to the peer. */voidbgp_packet_add (struct peer *peer, struct stream *s){  /* Add packet to the end of list. */  stream_fifo_push (peer->obuf, s);}/* Free first packet. */voidbgp_packet_delete (struct peer *peer){  stream_free (stream_fifo_pop (peer->obuf));}/* Duplicate packet. */struct stream *bgp_packet_dup (struct stream *s){  struct stream *new;  new = stream_new (stream_get_endp (s));  new->endp = s->endp;  new->putp = s->putp;  new->getp = s->getp;  memcpy (new->data, s->data, stream_get_endp (s));  return new;}/* Check file descriptor whether connect is established. */static voidbgp_connect_check (struct peer *peer){  int status;  int slen;  int ret;  /* Anyway I have to reset read and write thread. */  BGP_READ_OFF (peer->t_read);  BGP_WRITE_OFF (peer->t_write);  /* Check file descriptor. */  slen = sizeof (status);  ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);  /* If getsockopt is fail, this is fatal error. */  if (ret < 0)    {      zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");      BGP_EVENT_ADD (peer, TCP_fatal_error);      return;    }        /* When status is 0 then TCP connection is established. */  if (status == 0)    {      BGP_EVENT_ADD (peer, TCP_connection_open);    }  else    {      if (BGP_DEBUG (events, EVENTS))	  plog_info (peer->log, "%s [Event] Connect failed (%s)",		     peer->host, strerror (errno));      BGP_EVENT_ADD (peer, TCP_connection_open_failed);    }}/* Make BGP update packet.  */struct stream *bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi){  struct stream *s;  struct bgp_adj_out *adj;  struct bgp_advertise *adv;  struct stream *packet;  struct bgp_node *rn = NULL;  struct bgp_info *binfo = NULL;  bgp_size_t total_attr_len = 0;  unsigned long pos;  char buf[BUFSIZ];  struct prefix_rd *prd = NULL;  char *tag = NULL;  s = peer->work;  stream_reset (s);  adv = FIFO_HEAD (&peer->sync[afi][safi]->update);  while (adv)    {      if (adv->rn)        rn = adv->rn;      adj = adv->adj;      if (adv->binfo)        binfo = adv->binfo;#ifdef MPLS_VPN      if (rn)        prd = (struct prefix_rd *) &rn->prn->p;      if (binfo)        tag = binfo->tag;#endif /* MPLS_VPN */      /* When remaining space can't include NLRI and it's length.  */      if (rn && STREAM_REMAIN (s) <= BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen))	break;      /* If packet is empty, set attribute. */      if (stream_empty (s))	{	  bgp_packet_set_marker (s, BGP_MSG_UPDATE);	  stream_putw (s, 0);			  pos = stream_get_putp (s);	  stream_putw (s, 0);	  total_attr_len = bgp_packet_attribute (NULL, peer, s,	                			 adv->baa->attr,						 &rn->p, afi, safi,						 binfo->peer, prd, tag);	  stream_putw_at (s, pos, total_attr_len);	}      if (afi == AFI_IP && safi == SAFI_UNICAST)	stream_put_prefix (s, &rn->p);            if (BGP_DEBUG (update, UPDATE_OUT))	zlog (peer->log, LOG_INFO, "%s send UPDATE %s/%d",	      peer->host,	      inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, BUFSIZ),	      rn->p.prefixlen);      /* Synchnorize attribute.  */      if (adj->attr)	bgp_attr_unintern (adj->attr);      else	peer->scount[afi][safi]++;      adj->attr = bgp_attr_intern (adv->baa->attr);      adv = bgp_advertise_clean (peer, adj, afi, safi);      if (! (afi == AFI_IP && safi == SAFI_UNICAST))	break;    }	   if (! stream_empty (s))    {      bgp_packet_set_size (s);      packet = bgp_packet_dup (s);      bgp_packet_add (peer, packet);      stream_reset (s);      return packet;    }  return NULL;}/* Make BGP withdraw packet.  */struct stream *bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi){  struct stream *s;  struct stream *packet;  struct bgp_adj_out *adj;  struct bgp_advertise *adv;  struct bgp_node *rn;  unsigned long pos;  bgp_size_t unfeasible_len;  bgp_size_t total_attr_len;  char buf[BUFSIZ];  struct prefix_rd *prd = NULL;  s = peer->work;  stream_reset (s);  while ((adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)    {      adj = adv->adj;      rn = adv->rn;#ifdef MPLS_VPN      prd = (struct prefix_rd *) &rn->prn->p;#endif /* MPLS_VPN */      if (STREAM_REMAIN (s) 	  <= (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))	break;      if (stream_empty (s))	{	  bgp_packet_set_marker (s, BGP_MSG_UPDATE);	  stream_putw (s, 0);	}      if (afi == AFI_IP && safi == SAFI_UNICAST)	stream_put_prefix (s, &rn->p);      else	{	  pos = stream_get_putp (s);	  stream_putw (s, 0);	  total_attr_len	    = bgp_packet_withdraw (peer, s, &rn->p, afi, safi, prd, NULL);      	  /* Set total path attribute length. */	  stream_putw_at (s, pos, total_attr_len);	}      if (BGP_DEBUG (update, UPDATE_OUT))	zlog (peer->log, LOG_INFO, "%s send UPDATE %s/%d -- unreachable",	      peer->host,	      inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, BUFSIZ),	      rn->p.prefixlen);      peer->scount[afi][safi]--;      bgp_adj_out_remove (rn, adj, peer, afi, safi);      bgp_unlock_node (rn);      if (! (afi == AFI_IP && safi == SAFI_UNICAST))	break;    }  if (! stream_empty (s))    {      if (afi == AFI_IP && safi == SAFI_UNICAST)	{	  unfeasible_len 	    = stream_get_putp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;	  stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);	  stream_putw (s, 0);	}      bgp_packet_set_size (s);      packet = bgp_packet_dup (s);      bgp_packet_add (peer, packet);      stream_reset (s);      return packet;    }  return NULL;}voidbgp_default_update_send (struct peer *peer, struct attr *attr,			 afi_t afi, safi_t safi, struct peer *from){  struct stream *s;  struct stream *packet;  struct prefix p;  unsigned long pos;  bgp_size_t total_attr_len;  char attrstr[BUFSIZ];  char buf[BUFSIZ];#ifdef DISABLE_BGP_ANNOUNCE  return;#endif /* DISABLE_BGP_ANNOUNCE */  if (afi == AFI_IP)    str2prefix ("0.0.0.0/0", &p);#ifdef HAVE_IPV6  else     str2prefix ("::/0", &p);#endif /* HAVE_IPV6 */  /* Logging the attribute. */  if (BGP_DEBUG (update, UPDATE_OUT))    {      bgp_dump_attr (peer, attr, attrstr, BUFSIZ);      zlog (peer->log, LOG_INFO, "%s send UPDATE %s/%d %s",	    peer->host, inet_ntop(p.family, &(p.u.prefix), buf, BUFSIZ),	    p.prefixlen, attrstr);    }  s = stream_new (BGP_MAX_PACKET_SIZE);  /* Make BGP update packet. */  bgp_packet_set_marker (s, BGP_MSG_UPDATE);  /* Unfeasible Routes Length. */  stream_putw (s, 0);  /* Make place for total attribute length.  */  pos = stream_get_putp (s);  stream_putw (s, 0);  total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);  /* Set Total Path Attribute Length. */  stream_putw_at (s, pos, total_attr_len);  /* NLRI set. */  if (p.family == AF_INET && safi == SAFI_UNICAST)    stream_put_prefix (s, &p);  /* Set size. */  bgp_packet_set_size (s);  packet = bgp_packet_dup (s);  stream_free (s);  /* Dump packet if debug option is set. */#ifdef DEBUG  bgp_packet_dump (packet);#endif /* DEBUG */  /* Add packet to the peer. */  bgp_packet_add (peer, packet);  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);}voidbgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi){  struct stream *s;  struct stream *packet;  struct prefix p;  unsigned long pos;  unsigned long cp;  bgp_size_t unfeasible_len;  bgp_size_t total_attr_len;  char buf[BUFSIZ];#ifdef DISABLE_BGP_ANNOUNCE  return;#endif /* DISABLE_BGP_ANNOUNCE */  if (afi == AFI_IP)    str2prefix ("0.0.0.0/0", &p);#ifdef HAVE_IPV6  else     str2prefix ("::/0", &p);#endif /* HAVE_IPV6 */  total_attr_len = 0;  pos = 0;  if (BGP_DEBUG (update, UPDATE_OUT))    zlog (peer->log, LOG_INFO, "%s send UPDATE %s/%d -- unreachable",          peer->host, inet_ntop(p.family, &(p.u.prefix), buf, BUFSIZ),          p.prefixlen);  s = stream_new (BGP_MAX_PACKET_SIZE);  /* Make BGP update packet. */  bgp_packet_set_marker (s, BGP_MSG_UPDATE);  /* 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)              s = bgp_update_packet (peer, afi, safi);	    if (s)	      return s;	  }      }  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)	  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.  */

⌨️ 快捷键说明

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