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

📄 bgp_attr.c

📁 linux 路由软件 可支持RIP OSPF BGP等
💻 C
📖 第 1 页 / 共 4 页
字号:
  u_char snpa_num;  u_char snpa_len;  u_char *lim;  bgp_size_t nlri_len;  int ret;  struct stream *s;    /* Set end of packet. */  s = peer->ibuf;  lim = stream_pnt (s) + length;  /* Load AFI, SAFI. */  afi = stream_getw (s);  safi = stream_getc (s);  /* Get nexthop length. */  attr->mp_nexthop_len = stream_getc (s);  /* Nexthop length check. */  switch (attr->mp_nexthop_len)    {    case 4:      stream_get (&attr->mp_nexthop_global_in, s, 4);      break;    case 12:      {	u_int32_t rd_high;	u_int32_t rd_low;	rd_high = stream_getl (s);	rd_low = stream_getl (s);	stream_get (&attr->mp_nexthop_global_in, s, 4);      }      break;#ifdef HAVE_IPV6    case 16:      stream_get (&attr->mp_nexthop_global, s, 16);      break;    case 32:      stream_get (&attr->mp_nexthop_global, s, 16);      stream_get (&attr->mp_nexthop_local, s, 16);      if (! IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local))	{	  char buf1[INET6_ADDRSTRLEN];	  char buf2[INET6_ADDRSTRLEN];	  if (BGP_DEBUG (update, UPDATE_IN))	    zlog_warn ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,		       inet_ntop (AF_INET6, &attr->mp_nexthop_global,				  buf1, INET6_ADDRSTRLEN),		       inet_ntop (AF_INET6, &attr->mp_nexthop_local,				  buf2, INET6_ADDRSTRLEN));	  attr->mp_nexthop_len = 16;	}      break;#endif /* HAVE_IPV6 */    default:      zlog_info ("Wrong multiprotocol next hop length: %d", 		 attr->mp_nexthop_len);      return -1;      break;    }  snpa_num = stream_getc (s);  while (snpa_num--)    {      snpa_len = stream_getc (s);      stream_forward (s, (snpa_len + 1) >> 1);    }    nlri_len = lim - stream_pnt (s);   if (safi != BGP_SAFI_VPNV4)    {      ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);      if (ret < 0)	return -1;    }  mp_update->afi = afi;  mp_update->safi = safi;  mp_update->nlri = stream_pnt (s);  mp_update->length = nlri_len;  stream_forward (s, nlri_len);  return 0;}/* Multiprotocol unreachable parse */intbgp_mp_unreach_parse (struct peer *peer, int length, 		      struct bgp_nlri *mp_withdraw){  struct stream *s;  u_int16_t afi;  u_char safi;  u_char *lim;  u_int16_t withdraw_len;  int ret;  s = peer->ibuf;  lim = stream_pnt (s) + length;  afi = stream_getw (s);  safi = stream_getc (s);  withdraw_len = lim - stream_pnt (s);  if (safi != BGP_SAFI_VPNV4)    {      ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);      if (ret < 0)	return -1;    }  mp_withdraw->afi = afi;  mp_withdraw->safi = safi;  mp_withdraw->nlri = stream_pnt (s);  mp_withdraw->length = withdraw_len;  stream_forward (s, withdraw_len);  return 0;}/* Extended Community attribute. */intbgp_attr_ext_communities (struct peer *peer, bgp_size_t length, 			  struct attr *attr, u_char flag){  if (length == 0)    attr->ecommunity = NULL;  else    {      attr->ecommunity = ecommunity_parse (stream_pnt (peer->ibuf), length);      stream_forward (peer->ibuf, length);    }  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);  return 0;}/* BGP unknown attribute treatment. */intbgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,		  u_char type, bgp_size_t length, u_char *startp){  bgp_size_t total;  struct transit *transit;  if (BGP_DEBUG (normal, NORMAL))    zlog_info ("%s Unknown attribute is received (type %d, length %d)",	       peer->host, type, length);   /* Forward read pointer of input stream. */  stream_forward (peer->ibuf, length);  /* Adjest total length to include type and length. */  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);  /* If any of the mandatory well-known attributes are not recognized,     then the Error Subcode is set to Unrecognized Well-known     Attribute.  The Data field contains the unrecognized attribute     (type, length and value). */  if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))    {      /* Adjust startp to do not include flag value. */      bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_UPDATE_ERR, 				 BGP_NOTIFY_UPDATE_UNREC_ATTR,				 startp, total);      return -1;    }  /* Unrecognized non-transitive optional attributes must be quietly     ignored and not passed along to other BGP peers. */  if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))    return 0;  /* If a path with recognized transitive optional attribute is     accepted and passed along to other BGP peers and the Partial bit     in the Attribute Flags octet is set to 1 by some previous AS, it     is not set back to 0 by the current AS. */  SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);  /* Store transitive attribute to the end of attr->transit. */  if (! attr->transit)    {      attr->transit = XMALLOC (MTYPE_TRANSIT, sizeof (struct transit));      memset (attr->transit, 0, sizeof (struct transit));    }  transit = attr->transit;  if (transit->val)    transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val, 			     transit->length + total);  else    transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);  memcpy (transit->val + transit->length, startp, total);  transit->length += total;  return 0;}/* Read attribute of update packet.  This function is called from   bgp_update() in bgpd.c.  */intbgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,		struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw){  int ret;  u_char flag;  u_char type;  bgp_size_t length;  u_char *startp, *endp;  u_char *attr_endp;  u_char seen[BGP_ATTR_BITMAP_SIZE];  /* Initialize bitmap. */  memset (seen, 0, BGP_ATTR_BITMAP_SIZE);  /* End pointer of BGP attribute. */  endp = BGP_INPUT_PNT (peer) + size;  /* Get attributes to the end of attribute length. */  while (BGP_INPUT_PNT (peer) < endp)    {      /* Check remaining length check.*/      if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)	{	  zlog (peer->log, LOG_WARNING, 		"%s error BGP attribute length %d is smaller than min len",		peer->host, endp - STREAM_PNT (BGP_INPUT (peer)));	  bgp_notify_send (peer, 			   BGP_NOTIFY_UPDATE_ERR, 			   BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);	  return -1;	}      /* Fetch attribute flag and type. */      startp = BGP_INPUT_PNT (peer);      flag = stream_getc (BGP_INPUT (peer));      type = stream_getc (BGP_INPUT (peer));      /* Check extended attribue length bit. */      if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))	length = stream_getw (BGP_INPUT (peer));      else	length = stream_getc (BGP_INPUT (peer));            /* If any attribute appears more than once in the UPDATE	 message, then the Error Subcode is set to Malformed Attribute	 List. */      if (CHECK_BITMAP (seen, type))	{	  zlog (peer->log, LOG_WARNING,		"%s error BGP attribute type %d appears twice in a message",		peer->host, type);	  bgp_notify_send (peer, 			   BGP_NOTIFY_UPDATE_ERR, 			   BGP_NOTIFY_UPDATE_MAL_ATTR);	  return -1;	}      /* Set type to bitmap to check duplicate attribute.  `type' is	 unsigned char so it never overflow bitmap range. */      SET_BITMAP (seen, type);      /* Overflow check. */      attr_endp =  BGP_INPUT_PNT (peer) + length;      if (attr_endp > endp)	{	  zlog (peer->log, LOG_WARNING, 		"%s BGP type %d length %d is too large, attribute total length is %d.  attr_endp is %p.  endp is %p", peer->host, type, length, size, attr_endp, endp);	  bgp_notify_send (peer, 			   BGP_NOTIFY_UPDATE_ERR, 			   BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);	  return -1;	}      /* OK check attribute and store it's value. */      switch (type)	{	case BGP_ATTR_ORIGIN:	  ret = bgp_attr_origin (peer, length, attr, flag, startp);	  break;	case BGP_ATTR_AS_PATH:	  ret = bgp_attr_aspath (peer, length, attr, flag, startp);	  break;	case BGP_ATTR_NEXT_HOP:		  ret = bgp_attr_nexthop (peer, length, attr, flag, startp);	  break;	case BGP_ATTR_MULTI_EXIT_DISC:	  ret = bgp_attr_med (peer, length, attr, flag, startp);	  break;	case BGP_ATTR_LOCAL_PREF:	  ret = bgp_attr_local_pref (peer, length, attr, flag);	  break;	case BGP_ATTR_ATOMIC_AGGREGATE:	  ret = bgp_attr_atomic (peer, length, attr, flag);	  break;	case BGP_ATTR_AGGREGATOR:	  ret = bgp_attr_aggregator (peer, length, attr, flag);	  break;	case BGP_ATTR_COMMUNITIES:	  ret = bgp_attr_community (peer, length, attr, flag);	  break;	case BGP_ATTR_ORIGINATOR_ID:	  ret = bgp_attr_originator_id (peer, length, attr, flag);	  break;	case BGP_ATTR_CLUSTER_LIST:	  ret = bgp_attr_cluster_list (peer, length, attr, flag);	  break;	case BGP_ATTR_MP_REACH_NLRI:	  ret = bgp_mp_reach_parse (peer, length, attr, mp_update);	  break;	case BGP_ATTR_MP_UNREACH_NLRI:	  ret = bgp_mp_unreach_parse (peer, length, mp_withdraw);	  break;	case BGP_ATTR_EXT_COMMUNITIES:	  ret = bgp_attr_ext_communities (peer, length, attr, flag);	  break;	default:	  ret = bgp_attr_unknown (peer, attr, flag, type, length, startp);	  break;	}      /* If error occured immediately return to the caller. */      if (ret < 0)	return ret;      /* Check the fetched length. */      if (BGP_INPUT_PNT (peer) != attr_endp)	{	  zlog (peer->log, LOG_WARNING, 		"%s BGP attribute fetch error", peer->host);	  bgp_notify_send (peer, 			   BGP_NOTIFY_UPDATE_ERR, 			   BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);	  return -1;	}    }  /* Check final read pointer is same as end pointer. */  if (BGP_INPUT_PNT (peer) != endp)    {      zlog (peer->log, LOG_WARNING, 	    "%s BGP attribute length mismatch", peer->host);      bgp_notify_send (peer, 		       BGP_NOTIFY_UPDATE_ERR, 		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);      return -1;    }  /* Finally intern unknown attribute. */  if (attr->transit)    attr->transit = transit_intern (attr->transit);  return 0;}/* Well-known attribute check. */intbgp_attr_check (struct peer *peer, struct attr *attr){  u_char type = 0;    if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))    type = BGP_ATTR_ORIGIN;  if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))    type = BGP_ATTR_AS_PATH;  if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))    type = BGP_ATTR_NEXT_HOP;  if (peer_sort (peer) == BGP_PEER_IBGP      && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))    type = BGP_ATTR_LOCAL_PREF;  if (type)    {      zlog (peer->log, LOG_WARNING, 	    "%s Missing well-known attribute %d.",	    peer->host, type);      bgp_notify_send_with_data (peer, 				 BGP_NOTIFY_UPDATE_ERR, 				 BGP_NOTIFY_UPDATE_MISS_ATTR,				 &type, 1);      return -1;    }  return 0;}int stream_put_prefix (struct stream *, struct prefix *);/* Make attribute packet. */bgp_size_tbgp_packet_attribute (struct bgp *bgp, struct peer *peer,		      struct stream *s, struct attr *attr, struct prefix *p,		      afi_t afi, safi_t safi, struct peer *from,		      struct prefix_rd *prd, u_char *tag){  unsigned long cp;  struct aspath *aspath;  if (! bgp)    bgp = bgp_get_default ();  /* Remember current pointer. */  cp = stream_get_putp (s);  /* Origin attribute. */  stream_putc (s, BGP_ATTR_FLAG_TRANS);  stream_putc (s, BGP_ATTR_ORIGIN);  stream_putc (s, 1);  stream_putc (s, attr->origin);  /* AS path attribute. */  /* If remote-peer is EBGP */  if (peer_sort (peer) == BGP_PEER_EBGP      && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)	  || attr->aspath->length == 0)      && ! (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)	    && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))    {          aspath = aspath_dup (attr->aspath);      if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))	{	  /* Strip the confed info, and then stuff our path CONFED_ID	     on the front */	  aspath = aspath_delete_confed_seq (aspath);	  aspath = aspath_add_seq (aspath, bgp->confed_id);	}      else	{	  aspath = aspath_add_seq (aspath, peer->local_as);	  if (peer->change_local_as)	    aspath = aspath_add_seq (aspath, peer->change_local_as);	}    }  else if (peer_sort (peer) == BGP_PEER_CONFED)    {      /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */      aspath = aspath_dup (attr->aspath);      aspath = aspath_add_confed_seq (aspath, peer->local_as);    }  else    aspath = attr->aspath;

⌨️ 快捷键说明

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