📄 bgp_attr.c
字号:
#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 + -