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

📄 bgp_attr.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef HAVE_IPV6  attr.mp_nexthop_len = 16;#endif  new = bgp_attr_intern (&attr);  aspath_unintern (new->aspath);  return new;}struct attr *bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,			   struct aspath *aspath,			   struct community *community, int as_set){  struct attr attr;  struct attr *new;  memset (&attr, 0, sizeof (struct attr));  /* Origin attribute. */  attr.origin = origin;  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);  /* AS path attribute. */  if (aspath)    attr.aspath = aspath_intern (aspath);  else    attr.aspath = aspath_empty ();  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);  /* Next hop attribute.  */  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);  if (community)    {      attr.community = community;      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);    }  attr.weight = 32768;#ifdef HAVE_IPV6  attr.mp_nexthop_len = 16;#endif  if (! as_set)    attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);  if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))    attr.aggregator_as = bgp->confed_id;  else    attr.aggregator_as = bgp->as;  attr.aggregator_addr = bgp->router_id;  new = bgp_attr_intern (&attr);  aspath_unintern (new->aspath);  return new;}/* Free bgp attribute and aspath. */voidbgp_attr_unintern (struct attr *attr){  struct attr *ret;  struct aspath *aspath;  struct community *community;  struct ecommunity *ecommunity;  struct cluster_list *cluster;  struct transit *transit;  /* Decrement attribute reference. */  attr->refcnt--;  aspath = attr->aspath;  community = attr->community;  ecommunity = attr->ecommunity;  cluster = attr->cluster;  transit = attr->transit;  /* If reference becomes zero then free attribute object. */  if (attr->refcnt == 0)    {          ret = hash_release (attrhash, attr);      assert (ret != NULL);      XFREE (MTYPE_ATTR, attr);    }  /* aspath refcount shoud be decrement. */  if (aspath)    aspath_unintern (aspath);  if (community)    community_unintern (community);  if (ecommunity)    ecommunity_unintern (ecommunity);  if (cluster)    cluster_unintern (cluster);  if (transit)    transit_unintern (transit);}voidbgp_attr_flush (struct attr *attr){  if (attr->aspath && ! attr->aspath->refcnt)    aspath_free (attr->aspath);  if (attr->community && ! attr->community->refcnt)    community_free (attr->community);  if (attr->ecommunity && ! attr->ecommunity->refcnt)    ecommunity_free (attr->ecommunity);  if (attr->cluster && ! attr->cluster->refcnt)    cluster_free (attr->cluster);  if (attr->transit && ! attr->transit->refcnt)    transit_free (attr->transit);}/* Get origin attribute of the update message. */intbgp_attr_origin (struct peer *peer, bgp_size_t length, 		 struct attr *attr, u_char flag, u_char *startp){  bgp_size_t total;  /* total is entire attribute length include Attribute Flags (1),     Attribute Type code (1) and Attribute length (1 or 2).  */  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);  /* If any recognized attribute has Attribute Flags that conflict     with the Attribute Type Code, then the Error Subcode is set to     Attribute Flags Error.  The Data field contains the erroneous     attribute (type, length and value). */  if (flag != BGP_ATTR_FLAG_TRANS)    {      zlog (peer->log, LOG_ERR, 	    "Origin attribute flag isn't transitive %d", flag);      bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_UPDATE_ERR, 				 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,				 startp, total);      return -1;    }  /* If any recognized attribute has Attribute Length that conflicts     with the expected length (based on the attribute type code), then     the Error Subcode is set to Attribute Length Error.  The Data     field contains the erroneous attribute (type, length and     value). */  if (length != 1)    {      zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",	    length);      bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, 				 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,				 startp, total);      return -1;    }  /* Fetch origin attribute. */  attr->origin = stream_getc (BGP_INPUT (peer));  /* If the ORIGIN attribute has an undefined value, then the Error     Subcode is set to Invalid Origin Attribute.  The Data field     contains the unrecognized attribute (type, length and value). */  if ((attr->origin != BGP_ORIGIN_IGP)      && (attr->origin != BGP_ORIGIN_EGP)      && (attr->origin != BGP_ORIGIN_INCOMPLETE))    {      zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",	    attr->origin);      bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_UPDATE_ERR, 				 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,				 startp, total);      return -1;    }  /* Set oring attribute flag. */  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);  return 0;}/* Parse AS path information.  This function is wrapper of   aspath_parse. */intbgp_attr_aspath (struct peer *peer, bgp_size_t length, 		 struct attr *attr, u_char flag, u_char *startp){  struct bgp *bgp;  struct aspath *aspath;  bgp_size_t total;  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);  /* Flag check. */  if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)      || ! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))    {      zlog (peer->log, LOG_ERR, 	    "Origin attribute flag isn't transitive %d", flag);      bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_UPDATE_ERR, 				 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,				 startp, total);      return -1;    }  /* In case of IBGP, length will be zero. */  attr->aspath = aspath_parse (stream_pnt (peer->ibuf), length);  if (! attr->aspath)    {      zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length);      bgp_notify_send (peer, 		       BGP_NOTIFY_UPDATE_ERR, 		       BGP_NOTIFY_UPDATE_MAL_AS_PATH);      return -1;    }  bgp = peer->bgp;      /* First AS check for EBGP. */  if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))    {      if (peer_sort (peer) == BGP_PEER_EBGP 	  && ! aspath_firstas_check (attr->aspath, peer->as)) 	{ 	  zlog (peer->log, LOG_ERR, 		"%s incorrect first AS (must be %d)", peer->host, peer->as); 	  bgp_notify_send (peer, 			   BGP_NOTIFY_UPDATE_ERR, 			   BGP_NOTIFY_UPDATE_MAL_AS_PATH);	  return -1; 	}    }  /* local-as prepend */  if (peer->change_local_as &&      ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))    {      aspath = aspath_dup (attr->aspath);      aspath = aspath_add_seq (aspath, peer->change_local_as);      aspath_unintern (attr->aspath);      attr->aspath = aspath_intern (aspath);    }  /* Forward pointer. */  stream_forward (peer->ibuf, length);  /* Set aspath attribute flag. */  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);  return 0;}/* Nexthop attribute. */intbgp_attr_nexthop (struct peer *peer, bgp_size_t length, 		  struct attr *attr, u_char flag, u_char *startp){  bgp_size_t total;  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);  /* Flag check. */  if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)      || ! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))    {      zlog (peer->log, LOG_ERR, 	    "Origin attribute flag isn't transitive %d", flag);      bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_UPDATE_ERR, 				 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,				 startp, total);      return -1;    }  /* Check nexthop attribute length. */  if (length != 4)    {      zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",	    length);      bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_UPDATE_ERR, 				 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,				 startp, total);      return -1;    }  attr->nexthop.s_addr = stream_get_ipv4 (peer->ibuf);  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);  return 0;}/* MED atrribute. */intbgp_attr_med (struct peer *peer, bgp_size_t length, 	      struct attr *attr, u_char flag, u_char *startp){  bgp_size_t total;  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);  /* Length check. */  if (length != 4)    {      zlog (peer->log, LOG_ERR, 	    "MED attribute length isn't four [%d]", length);            bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_UPDATE_ERR, 				 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,				 startp, total);      return -1;    }  attr->med = stream_getl (peer->ibuf);  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);  return 0;}/* Local preference attribute. */intbgp_attr_local_pref (struct peer *peer, bgp_size_t length, 		     struct attr *attr, u_char flag){  /* If it is contained in an UPDATE message that is received from an     external peer, then this attribute MUST be ignored by the     receiving speaker. */  if (peer_sort (peer) == BGP_PEER_EBGP)    {      stream_forward (peer->ibuf, length);      return 0;    }  if (length == 4)     attr->local_pref = stream_getl (peer->ibuf);  else     attr->local_pref = 0;  /* Set atomic aggregate flag. */  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);  return 0;}/* Atomic aggregate. */intbgp_attr_atomic (struct peer *peer, bgp_size_t length, 		 struct attr *attr, u_char flag){  if (length != 0)    {      zlog (peer->log, LOG_ERR, "Bad atomic aggregate length %d", length);      bgp_notify_send (peer, 		       BGP_NOTIFY_UPDATE_ERR, 		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);      return -1;    }  /* Set atomic aggregate flag. */  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);  return 0;}/* Aggregator attribute */intbgp_attr_aggregator (struct peer *peer, bgp_size_t length,		     struct attr *attr, u_char flag){  if (length != 6)    {      zlog (peer->log, LOG_ERR, "Aggregator length is not 6 [%d]", length);      bgp_notify_send (peer,		       BGP_NOTIFY_UPDATE_ERR,		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);      return -1;    }  attr->aggregator_as = stream_getw (peer->ibuf);  attr->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);  /* Set atomic aggregate flag. */  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);  return 0;}/* Community attribute. */intbgp_attr_community (struct peer *peer, bgp_size_t length, 		    struct attr *attr, u_char flag){  if (length == 0)    attr->community = NULL;  else    {      attr->community = community_parse (stream_pnt (peer->ibuf), length);      stream_forward (peer->ibuf, length);    }  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);  return 0;}/* Originator ID attribute. */intbgp_attr_originator_id (struct peer *peer, bgp_size_t length, 			struct attr *attr, u_char flag){  if (length != 4)    {      zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);      bgp_notify_send (peer, 		       BGP_NOTIFY_UPDATE_ERR, 		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);      return -1;    }  attr->originator_id.s_addr = stream_get_ipv4 (peer->ibuf);  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);  return 0;}/* Cluster list attribute. */intbgp_attr_cluster_list (struct peer *peer, bgp_size_t length, 		       struct attr *attr, u_char flag){  /* Check length. */  if (length % 4)    {      zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);      bgp_notify_send (peer, 		       BGP_NOTIFY_UPDATE_ERR, 		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);      return -1;    }  attr->cluster = cluster_parse (stream_pnt (peer->ibuf), length);  stream_forward (peer->ibuf, length);;  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);  return 0;}/* Multiprotocol reachability information parse. */intbgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,		    struct bgp_nlri *mp_update){

⌨️ 快捷键说明

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