1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_aspath.h"
40 #include "bgpd/bgp_community.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_errors.h"
43 #include "bgpd/bgp_label.h"
44 #include "bgpd/bgp_packet.h"
45 #include "bgpd/bgp_ecommunity.h"
46 #include "bgpd/bgp_lcommunity.h"
47 #include "bgpd/bgp_updgrp.h"
48 #include "bgpd/bgp_encap_types.h"
50 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
51 #include "bgp_encap_types.h"
52 #include "bgp_vnc_types.h"
55 #include "bgp_flowspec_private.h"
58 /* Attribute strings for logging. */
59 static const struct message attr_str
[] = {
60 {BGP_ATTR_ORIGIN
, "ORIGIN"},
61 {BGP_ATTR_AS_PATH
, "AS_PATH"},
62 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
63 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
64 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
65 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
66 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
67 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
68 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
69 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
70 {BGP_ATTR_DPA
, "DPA"},
71 {BGP_ATTR_ADVERTISER
, "ADVERTISER"},
72 {BGP_ATTR_RCID_PATH
, "RCID_PATH"},
73 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
74 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
75 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
76 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
77 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
78 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
79 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
80 {BGP_ATTR_ENCAP
, "ENCAP"},
81 #if ENABLE_BGP_VNC_ATTR
82 {BGP_ATTR_VNC
, "VNC"},
84 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
85 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
88 static const struct message attr_flag_str
[] = {
89 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
90 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
91 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
92 /* bgp_attr_flags_diagnose() relies on this bit being last in
94 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
97 static struct hash
*cluster_hash
;
99 static void *cluster_hash_alloc(void *p
)
101 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
102 struct cluster_list
*cluster
;
104 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
105 cluster
->length
= val
->length
;
107 if (cluster
->length
) {
108 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
109 memcpy(cluster
->list
, val
->list
, val
->length
);
111 cluster
->list
= NULL
;
118 /* Cluster list related functions. */
119 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
121 struct cluster_list tmp
;
122 struct cluster_list
*cluster
;
127 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
132 int cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
136 for (i
= 0; i
< cluster
->length
/ 4; i
++)
137 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
142 static unsigned int cluster_hash_key_make(const void *p
)
144 const struct cluster_list
*cluster
= p
;
146 return jhash(cluster
->list
, cluster
->length
, 0);
149 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
151 const struct cluster_list
*cluster1
= p1
;
152 const struct cluster_list
*cluster2
= p2
;
154 return (cluster1
->length
== cluster2
->length
155 && memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
)
159 static void cluster_free(struct cluster_list
*cluster
)
161 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
162 XFREE(MTYPE_CLUSTER
, cluster
);
165 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
167 struct cluster_list
*find
;
169 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
175 void cluster_unintern(struct cluster_list
*cluster
)
180 if (cluster
->refcnt
== 0) {
181 hash_release(cluster_hash
, cluster
);
182 cluster_free(cluster
);
186 static void cluster_init(void)
188 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
192 static void cluster_finish(void)
194 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
195 hash_free(cluster_hash
);
199 static struct hash
*encap_hash
= NULL
;
201 static struct hash
*vnc_hash
= NULL
;
204 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
206 struct bgp_attr_encap_subtlv
*new;
207 struct bgp_attr_encap_subtlv
*tail
;
208 struct bgp_attr_encap_subtlv
*p
;
210 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
211 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
213 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
216 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
219 memcpy(tail
, p
, size
);
226 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
228 struct bgp_attr_encap_subtlv
*next
;
232 XFREE(MTYPE_ENCAP_TLV
, p
);
237 void bgp_attr_flush_encap(struct attr
*attr
)
242 if (attr
->encap_subtlvs
) {
243 encap_free(attr
->encap_subtlvs
);
244 attr
->encap_subtlvs
= NULL
;
247 if (attr
->vnc_subtlvs
) {
248 encap_free(attr
->vnc_subtlvs
);
249 attr
->vnc_subtlvs
= NULL
;
255 * Compare encap sub-tlv chains
260 * This algorithm could be made faster if needed
262 static int encap_same(const struct bgp_attr_encap_subtlv
*h1
,
263 const struct bgp_attr_encap_subtlv
*h2
)
265 const struct bgp_attr_encap_subtlv
*p
;
266 const struct bgp_attr_encap_subtlv
*q
;
270 if (h1
== NULL
|| h2
== NULL
)
273 for (p
= h1
; p
; p
= p
->next
) {
274 for (q
= h2
; q
; q
= q
->next
) {
275 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
276 && !memcmp(p
->value
, q
->value
, p
->length
)) {
285 for (p
= h2
; p
; p
= p
->next
) {
286 for (q
= h1
; q
; q
= q
->next
) {
287 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
288 && !memcmp(p
->value
, q
->value
, p
->length
)) {
300 static void *encap_hash_alloc(void *p
)
302 /* Encap structure is already allocated. */
313 static struct bgp_attr_encap_subtlv
*
314 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
316 struct bgp_attr_encap_subtlv
*find
;
317 struct hash
*hash
= encap_hash
;
319 if (type
== VNC_SUBTLV_TYPE
)
323 find
= hash_get(hash
, encap
, encap_hash_alloc
);
331 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
332 encap_subtlv_type type
)
334 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
338 if (encap
->refcnt
== 0) {
339 struct hash
*hash
= encap_hash
;
341 if (type
== VNC_SUBTLV_TYPE
)
344 hash_release(hash
, encap
);
350 static unsigned int encap_hash_key_make(const void *p
)
352 const struct bgp_attr_encap_subtlv
*encap
= p
;
354 return jhash(encap
->value
, encap
->length
, 0);
357 static bool encap_hash_cmp(const void *p1
, const void *p2
)
359 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
360 (const struct bgp_attr_encap_subtlv
*)p2
);
363 static void encap_init(void)
365 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
368 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
373 static void encap_finish(void)
375 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
376 hash_free(encap_hash
);
379 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
385 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
393 return !memcmp(&(a1
->evpn_overlay
), &(a2
->evpn_overlay
),
394 sizeof(struct bgp_route_evpn
));
397 /* Unknown transit attribute. */
398 static struct hash
*transit_hash
;
400 static void transit_free(struct transit
*transit
)
402 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
403 XFREE(MTYPE_TRANSIT
, transit
);
406 static void *transit_hash_alloc(void *p
)
408 /* Transit structure is already allocated. */
412 static struct transit
*transit_intern(struct transit
*transit
)
414 struct transit
*find
;
416 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
418 transit_free(transit
);
424 void transit_unintern(struct transit
*transit
)
429 if (transit
->refcnt
== 0) {
430 hash_release(transit_hash
, transit
);
431 transit_free(transit
);
435 static unsigned int transit_hash_key_make(const void *p
)
437 const struct transit
*transit
= p
;
439 return jhash(transit
->val
, transit
->length
, 0);
442 static bool transit_hash_cmp(const void *p1
, const void *p2
)
444 const struct transit
*transit1
= p1
;
445 const struct transit
*transit2
= p2
;
447 return (transit1
->length
== transit2
->length
448 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
451 static void transit_init(void)
453 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
457 static void transit_finish(void)
459 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
460 hash_free(transit_hash
);
464 /* Attribute hash routines. */
465 static struct hash
*attrhash
;
467 unsigned long int attr_count(void)
469 return attrhash
->count
;
472 unsigned long int attr_unknown_count(void)
474 return transit_hash
->count
;
477 unsigned int attrhash_key_make(const void *p
)
479 const struct attr
*attr
= (struct attr
*)p
;
481 #define MIX(val) key = jhash_1word(val, key)
482 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
484 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
485 MIX3(attr
->local_pref
, attr
->aggregator_as
,
486 attr
->aggregator_addr
.s_addr
);
487 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
488 attr
->originator_id
.s_addr
);
489 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
492 MIX(aspath_key_make(attr
->aspath
));
494 MIX(community_hash_make(attr
->community
));
496 if (attr
->lcommunity
)
497 MIX(lcommunity_hash_make(attr
->lcommunity
));
498 if (attr
->ecommunity
)
499 MIX(ecommunity_hash_make(attr
->ecommunity
));
501 MIX(cluster_hash_key_make(attr
->cluster
));
503 MIX(transit_hash_key_make(attr
->transit
));
504 if (attr
->encap_subtlvs
)
505 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
507 if (attr
->vnc_subtlvs
)
508 MIX(encap_hash_key_make(attr
->vnc_subtlvs
));
510 MIX(attr
->mp_nexthop_len
);
511 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
512 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
513 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
514 MIX(attr
->rmap_table_id
);
519 bool attrhash_cmp(const void *p1
, const void *p2
)
521 const struct attr
*attr1
= p1
;
522 const struct attr
*attr2
= p2
;
524 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
525 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
526 && attr1
->aspath
== attr2
->aspath
527 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
528 && attr1
->local_pref
== attr2
->local_pref
529 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
530 if (attr1
->aggregator_as
== attr2
->aggregator_as
531 && attr1
->aggregator_addr
.s_addr
532 == attr2
->aggregator_addr
.s_addr
533 && attr1
->weight
== attr2
->weight
534 && attr1
->tag
== attr2
->tag
535 && attr1
->label_index
== attr2
->label_index
536 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
537 && attr1
->ecommunity
== attr2
->ecommunity
538 && attr1
->lcommunity
== attr2
->lcommunity
539 && attr1
->cluster
== attr2
->cluster
540 && attr1
->transit
== attr2
->transit
541 && attr1
->rmap_table_id
== attr2
->rmap_table_id
542 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
543 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
545 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
547 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
548 &attr2
->mp_nexthop_global
)
549 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
550 &attr2
->mp_nexthop_local
)
551 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
552 &attr2
->mp_nexthop_global_in
)
553 && IPV4_ADDR_SAME(&attr1
->originator_id
,
554 &attr2
->originator_id
)
555 && overlay_index_same(attr1
, attr2
)
556 && attr1
->nh_ifindex
== attr2
->nh_ifindex
557 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
558 && attr1
->distance
== attr2
->distance
)
565 static void attrhash_init(void)
568 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
572 * special for hash_clean below
574 static void attr_vfree(void *attr
)
576 XFREE(MTYPE_ATTR
, attr
);
579 static void attrhash_finish(void)
581 hash_clean(attrhash
, attr_vfree
);
586 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
588 struct attr
*attr
= bucket
->data
;
590 vty_out(vty
, "attr[%ld] nexthop %s\n", attr
->refcnt
,
591 inet_ntoa(attr
->nexthop
));
592 vty_out(vty
, "\tflags: %" PRIu64
" med: %u local_pref: %u origin: %u weight: %u label: %u\n",
593 attr
->flag
, attr
->med
, attr
->local_pref
, attr
->origin
,
594 attr
->weight
, attr
->label
);
597 void attr_show_all(struct vty
*vty
)
599 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
600 void *))attr_show_all_iterator
,
604 static void *bgp_attr_hash_alloc(void *p
)
606 struct attr
*val
= (struct attr
*)p
;
609 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
611 if (val
->encap_subtlvs
) {
612 val
->encap_subtlvs
= NULL
;
615 if (val
->vnc_subtlvs
) {
616 val
->vnc_subtlvs
= NULL
;
623 /* Internet argument attribute. */
624 struct attr
*bgp_attr_intern(struct attr
*attr
)
628 /* Intern referenced strucutre. */
630 if (!attr
->aspath
->refcnt
)
631 attr
->aspath
= aspath_intern(attr
->aspath
);
633 attr
->aspath
->refcnt
++;
635 if (attr
->community
) {
636 if (!attr
->community
->refcnt
)
637 attr
->community
= community_intern(attr
->community
);
639 attr
->community
->refcnt
++;
642 if (attr
->ecommunity
) {
643 if (!attr
->ecommunity
->refcnt
)
644 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
646 attr
->ecommunity
->refcnt
++;
648 if (attr
->lcommunity
) {
649 if (!attr
->lcommunity
->refcnt
)
650 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
652 attr
->lcommunity
->refcnt
++;
655 if (!attr
->cluster
->refcnt
)
656 attr
->cluster
= cluster_intern(attr
->cluster
);
658 attr
->cluster
->refcnt
++;
661 if (!attr
->transit
->refcnt
)
662 attr
->transit
= transit_intern(attr
->transit
);
664 attr
->transit
->refcnt
++;
666 if (attr
->encap_subtlvs
) {
667 if (!attr
->encap_subtlvs
->refcnt
)
668 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
671 attr
->encap_subtlvs
->refcnt
++;
674 if (attr
->vnc_subtlvs
) {
675 if (!attr
->vnc_subtlvs
->refcnt
)
676 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
679 attr
->vnc_subtlvs
->refcnt
++;
683 /* At this point, attr only contains intern'd pointers. that means
684 * if we find it in attrhash, it has all the same pointers and we
685 * correctly updated the refcounts on these.
686 * If we don't find it, we need to allocate a one because in all
687 * cases this returns a new reference to a hashed attr, but the input
689 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
695 /* Make network statement's attribute. */
696 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
698 memset(attr
, 0, sizeof(struct attr
));
700 attr
->origin
= origin
;
701 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
702 attr
->aspath
= aspath_empty();
703 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
704 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
706 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
707 attr
->label
= MPLS_INVALID_LABEL
;
708 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
709 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
714 /* Create the attributes for an aggregate */
715 struct attr
*bgp_attr_aggregate_intern(struct bgp
*bgp
, uint8_t origin
,
716 struct aspath
*aspath
,
717 struct community
*community
,
718 struct ecommunity
*ecommunity
,
719 struct lcommunity
*lcommunity
,
720 struct bgp_aggregate
*aggregate
,
721 uint8_t atomic_aggregate
,
728 memset(&attr
, 0, sizeof(struct attr
));
730 /* Origin attribute. */
731 attr
.origin
= origin
;
732 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
734 /* AS path attribute. */
736 attr
.aspath
= aspath_intern(aspath
);
738 attr
.aspath
= aspath_empty();
739 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
741 /* Next hop attribute. */
742 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
745 uint32_t gshut
= COMMUNITY_GSHUT
;
747 /* If we are not shutting down ourselves and we are
748 * aggregating a route that contains the GSHUT community we
749 * need to remove that community when creating the aggregate */
750 if (!bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)
751 && community_include(community
, gshut
)) {
752 community_del_val(community
, &gshut
);
755 attr
.community
= community
;
756 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
760 attr
.ecommunity
= ecommunity
;
761 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
765 attr
.lcommunity
= lcommunity
;
766 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
769 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
770 bgp_attr_add_gshut_community(&attr
);
773 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
774 attr
.label
= MPLS_INVALID_LABEL
;
775 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
776 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
777 if (!aggregate
->as_set
|| atomic_aggregate
)
778 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
779 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
780 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
781 attr
.aggregator_as
= bgp
->confed_id
;
783 attr
.aggregator_as
= bgp
->as
;
784 attr
.aggregator_addr
= bgp
->router_id
;
785 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
786 attr
.label
= MPLS_INVALID_LABEL
;
788 /* Apply route-map */
789 if (aggregate
->rmap
.name
) {
790 struct attr attr_tmp
= attr
;
791 struct bgp_path_info rmap_path
;
793 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
794 rmap_path
.peer
= bgp
->peer_self
;
795 rmap_path
.attr
= &attr_tmp
;
797 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
799 ret
= route_map_apply(aggregate
->rmap
.map
, p
, RMAP_BGP
,
802 bgp
->peer_self
->rmap_type
= 0;
804 if (ret
== RMAP_DENYMATCH
) {
805 /* Free uninterned attribute. */
806 bgp_attr_flush(&attr_tmp
);
808 /* Unintern original. */
809 aspath_unintern(&attr
.aspath
);
813 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
814 bgp_attr_add_gshut_community(&attr_tmp
);
816 new = bgp_attr_intern(&attr_tmp
);
819 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
820 bgp_attr_add_gshut_community(&attr
);
822 new = bgp_attr_intern(&attr
);
825 aspath_unintern(&new->aspath
);
829 /* Unintern just the sub-components of the attr, but not the attr */
830 void bgp_attr_unintern_sub(struct attr
*attr
)
832 /* aspath refcount shoud be decrement. */
834 aspath_unintern(&attr
->aspath
);
835 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
838 community_unintern(&attr
->community
);
839 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
841 if (attr
->ecommunity
)
842 ecommunity_unintern(&attr
->ecommunity
);
843 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
845 if (attr
->lcommunity
)
846 lcommunity_unintern(&attr
->lcommunity
);
847 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
850 cluster_unintern(attr
->cluster
);
851 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
854 transit_unintern(attr
->transit
);
856 if (attr
->encap_subtlvs
)
857 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
860 if (attr
->vnc_subtlvs
)
861 encap_unintern(&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
866 * We have some show commands that let you experimentally
867 * apply a route-map. When we apply the route-map
868 * we are reseting values but not saving them for
869 * posterity via intern'ing( because route-maps don't
870 * do that) but at this point in time we need
871 * to compare the new attr to the old and if the
872 * routemap has changed it we need to, as Snoop Dog says,
873 * Drop it like it's hot
875 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
877 if (new->aspath
!= old
->aspath
)
878 aspath_free(new->aspath
);
880 if (new->community
!= old
->community
)
881 community_free(&new->community
);
883 if (new->ecommunity
!= old
->ecommunity
)
884 ecommunity_free(&new->ecommunity
);
886 if (new->lcommunity
!= old
->lcommunity
)
887 lcommunity_free(&new->lcommunity
);
890 /* Free bgp attribute and aspath. */
891 void bgp_attr_unintern(struct attr
**pattr
)
893 struct attr
*attr
= *pattr
;
897 /* Decrement attribute reference. */
902 /* If reference becomes zero then free attribute object. */
903 if (attr
->refcnt
== 0) {
904 ret
= hash_release(attrhash
, attr
);
906 XFREE(MTYPE_ATTR
, attr
);
910 bgp_attr_unintern_sub(&tmp
);
913 void bgp_attr_flush(struct attr
*attr
)
915 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
916 aspath_free(attr
->aspath
);
919 if (attr
->community
&& !attr
->community
->refcnt
)
920 community_free(&attr
->community
);
921 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
922 ecommunity_free(&attr
->ecommunity
);
923 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
924 lcommunity_free(&attr
->lcommunity
);
925 if (attr
->cluster
&& !attr
->cluster
->refcnt
) {
926 cluster_free(attr
->cluster
);
927 attr
->cluster
= NULL
;
929 if (attr
->transit
&& !attr
->transit
->refcnt
) {
930 transit_free(attr
->transit
);
931 attr
->transit
= NULL
;
933 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
934 encap_free(attr
->encap_subtlvs
);
935 attr
->encap_subtlvs
= NULL
;
938 if (attr
->vnc_subtlvs
&& !attr
->vnc_subtlvs
->refcnt
) {
939 encap_free(attr
->vnc_subtlvs
);
940 attr
->vnc_subtlvs
= NULL
;
945 /* Implement draft-scudder-idr-optional-transitive behaviour and
946 * avoid resetting sessions for malformed attributes which are
947 * are partial/optional and hence where the error likely was not
948 * introduced by the sending neighbour.
950 static bgp_attr_parse_ret_t
951 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
954 struct peer
*const peer
= args
->peer
;
955 const uint8_t flags
= args
->flags
;
956 /* startp and length must be special-cased, as whether or not to
957 * send the attribute data with the NOTIFY depends on the error,
958 * the caller therefore signals this with the seperate length argument
960 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
962 /* Only relax error handling for eBGP peers */
963 if (peer
->sort
!= BGP_PEER_EBGP
) {
964 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
965 notify_datap
, length
);
966 return BGP_ATTR_PARSE_ERROR
;
969 /* Adjust the stream getp to the end of the attribute, in case we can
970 * still proceed but the caller hasn't read all the attribute.
972 stream_set_getp(BGP_INPUT(peer
),
973 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
976 switch (args
->type
) {
977 /* where an attribute is relatively inconsequential, e.g. it does not
978 * affect route selection, and can be safely ignored, then any such
979 * attributes which are malformed should just be ignored and the route
980 * processed as normal.
982 case BGP_ATTR_AS4_AGGREGATOR
:
983 case BGP_ATTR_AGGREGATOR
:
984 case BGP_ATTR_ATOMIC_AGGREGATE
:
985 return BGP_ATTR_PARSE_PROCEED
;
987 /* Core attributes, particularly ones which may influence route
988 * selection, should always cause session resets
990 case BGP_ATTR_ORIGIN
:
991 case BGP_ATTR_AS_PATH
:
992 case BGP_ATTR_NEXT_HOP
:
993 case BGP_ATTR_MULTI_EXIT_DISC
:
994 case BGP_ATTR_LOCAL_PREF
:
995 case BGP_ATTR_COMMUNITIES
:
996 case BGP_ATTR_ORIGINATOR_ID
:
997 case BGP_ATTR_CLUSTER_LIST
:
998 case BGP_ATTR_MP_REACH_NLRI
:
999 case BGP_ATTR_MP_UNREACH_NLRI
:
1000 case BGP_ATTR_EXT_COMMUNITIES
:
1001 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1002 notify_datap
, length
);
1003 return BGP_ATTR_PARSE_ERROR
;
1006 /* Partial optional attributes that are malformed should not cause
1007 * the whole session to be reset. Instead treat it as a withdrawal
1008 * of the routes, if possible.
1010 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1011 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1012 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1013 return BGP_ATTR_PARSE_WITHDRAW
;
1015 /* default to reset */
1016 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1019 /* Find out what is wrong with the path attribute flag bits and log the error.
1020 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1021 Extended Length. Checking O/T/P bits at once implies, that the attribute
1022 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1023 non-transitive" attribute. */
1025 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1026 uint8_t desired_flags
/* how RFC says it must be */
1029 uint8_t seen
= 0, i
;
1030 uint8_t real_flags
= args
->flags
;
1031 const uint8_t attr_code
= args
->type
;
1033 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1034 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1035 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1036 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1037 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1038 flog_err(EC_BGP_ATTR_FLAG
,
1039 "%s attribute must%s be flagged as \"%s\"",
1040 lookup_msg(attr_str
, attr_code
, NULL
),
1041 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1044 attr_flag_str
[i
].str
);
1049 "Strange, %s called for attr %s, but no problem found with flags"
1050 " (real flags 0x%x, desired 0x%x)",
1051 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1052 real_flags
, desired_flags
);
1056 /* Required flags for attributes. EXTLEN will be masked off when testing,
1057 * as will PARTIAL for optional+transitive attributes.
1059 const uint8_t attr_flags_values
[] = {
1060 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1061 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1062 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1063 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1064 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1065 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1066 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1067 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1068 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1069 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1070 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1071 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1072 [BGP_ATTR_EXT_COMMUNITIES
] =
1073 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1074 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1075 [BGP_ATTR_AS4_AGGREGATOR
] =
1076 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1077 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1078 [BGP_ATTR_LARGE_COMMUNITIES
] =
1079 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1080 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1082 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1084 static int bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1086 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1087 const uint8_t flags
= args
->flags
;
1088 const uint8_t attr_code
= args
->type
;
1090 /* there may be attributes we don't know about */
1091 if (attr_code
> attr_flags_values_max
)
1093 if (attr_flags_values
[attr_code
] == 0)
1096 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1100 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1101 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1104 "%s well-known attributes must have transitive flag set (%x)",
1105 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1109 /* "For well-known attributes and for optional non-transitive
1111 * the Partial bit MUST be set to 0."
1113 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1114 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1115 flog_err(EC_BGP_ATTR_FLAG
,
1116 "%s well-known attribute "
1117 "must NOT have the partial flag set (%x)",
1118 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1121 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1122 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1123 flog_err(EC_BGP_ATTR_FLAG
,
1124 "%s optional + transitive attribute "
1125 "must NOT have the partial flag set (%x)",
1126 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1131 /* Optional transitive attributes may go through speakers that don't
1132 * reocgnise them and set the Partial bit.
1134 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1135 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1136 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1138 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1141 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1145 /* Get origin attribute of the update message. */
1146 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1148 struct peer
*const peer
= args
->peer
;
1149 struct attr
*const attr
= args
->attr
;
1150 const bgp_size_t length
= args
->length
;
1152 /* If any recognized attribute has Attribute Length that conflicts
1153 with the expected length (based on the attribute type code), then
1154 the Error Subcode is set to Attribute Length Error. The Data
1155 field contains the erroneous attribute (type, length and
1158 flog_err(EC_BGP_ATTR_LEN
,
1159 "Origin attribute length is not one %d", length
);
1160 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1164 /* Fetch origin attribute. */
1165 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1167 /* If the ORIGIN attribute has an undefined value, then the Error
1168 Subcode is set to Invalid Origin Attribute. The Data field
1169 contains the unrecognized attribute (type, length and value). */
1170 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1171 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1172 flog_err(EC_BGP_ATTR_ORIGIN
,
1173 "Origin attribute value is invalid %d", attr
->origin
);
1174 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1178 /* Set oring attribute flag. */
1179 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1184 /* Parse AS path information. This function is wrapper of
1186 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1188 struct attr
*const attr
= args
->attr
;
1189 struct peer
*const peer
= args
->peer
;
1190 const bgp_size_t length
= args
->length
;
1193 * peer with AS4 => will get 4Byte ASnums
1194 * otherwise, will get 16 Bit
1196 attr
->aspath
= aspath_parse(peer
->curr
, length
,
1197 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1199 /* In case of IBGP, length will be zero. */
1200 if (!attr
->aspath
) {
1201 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1202 "Malformed AS path from %s, length is %d", peer
->host
,
1204 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1208 /* Set aspath attribute flag. */
1209 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1211 return BGP_ATTR_PARSE_PROCEED
;
1214 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1215 struct attr
*const attr
)
1217 /* These checks were part of bgp_attr_aspath, but with
1218 * as4 we should to check aspath things when
1219 * aspath synthesizing with as4_path has already taken place.
1220 * Otherwise we check ASPATH and use the synthesized thing, and that is
1222 * So do the checks later, i.e. here
1224 struct aspath
*aspath
;
1226 /* Confederation sanity check. */
1227 if ((peer
->sort
== BGP_PEER_CONFED
1228 && !aspath_left_confed_check(attr
->aspath
))
1229 || (peer
->sort
== BGP_PEER_EBGP
1230 && aspath_confed_check(attr
->aspath
))) {
1231 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1233 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1234 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1235 return BGP_ATTR_PARSE_ERROR
;
1238 /* First AS check for EBGP. */
1239 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1240 if (peer
->sort
== BGP_PEER_EBGP
1241 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1242 flog_err(EC_BGP_ATTR_FIRST_AS
,
1243 "%s incorrect first AS (must be %u)",
1244 peer
->host
, peer
->as
);
1245 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1246 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1247 return BGP_ATTR_PARSE_ERROR
;
1251 /* local-as prepend */
1252 if (peer
->change_local_as
1253 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1254 aspath
= aspath_dup(attr
->aspath
);
1255 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1256 aspath_unintern(&attr
->aspath
);
1257 attr
->aspath
= aspath_intern(aspath
);
1260 return BGP_ATTR_PARSE_PROCEED
;
1263 /* Parse AS4 path information. This function is another wrapper of
1265 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1266 struct aspath
**as4_path
)
1268 struct peer
*const peer
= args
->peer
;
1269 struct attr
*const attr
= args
->attr
;
1270 const bgp_size_t length
= args
->length
;
1272 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1274 /* In case of IBGP, length will be zero. */
1276 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1277 "Malformed AS4 path from %s, length is %d", peer
->host
,
1279 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1283 /* Set aspath attribute flag. */
1284 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1286 return BGP_ATTR_PARSE_PROCEED
;
1290 * Check that the nexthop attribute is valid.
1292 bgp_attr_parse_ret_t
1293 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1295 in_addr_t nexthop_h
;
1297 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1298 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1299 || IPV4_CLASS_DE(nexthop_h
))
1300 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1301 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1302 char buf
[INET_ADDRSTRLEN
];
1304 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1306 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1308 data
[0] = BGP_ATTR_FLAG_TRANS
;
1309 data
[1] = BGP_ATTR_NEXT_HOP
;
1310 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1311 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1312 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1313 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1315 return BGP_ATTR_PARSE_ERROR
;
1318 return BGP_ATTR_PARSE_PROCEED
;
1321 /* Nexthop attribute. */
1322 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1324 struct peer
*const peer
= args
->peer
;
1325 struct attr
*const attr
= args
->attr
;
1326 const bgp_size_t length
= args
->length
;
1328 /* Check nexthop attribute length. */
1330 flog_err(EC_BGP_ATTR_LEN
,
1331 "Nexthop attribute length isn't four [%d]", length
);
1333 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1337 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1338 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1340 return BGP_ATTR_PARSE_PROCEED
;
1343 /* MED atrribute. */
1344 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1346 struct peer
*const peer
= args
->peer
;
1347 struct attr
*const attr
= args
->attr
;
1348 const bgp_size_t length
= args
->length
;
1352 flog_err(EC_BGP_ATTR_LEN
,
1353 "MED attribute length isn't four [%d]", length
);
1355 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1359 attr
->med
= stream_getl(peer
->curr
);
1361 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1363 return BGP_ATTR_PARSE_PROCEED
;
1366 /* Local preference attribute. */
1367 static bgp_attr_parse_ret_t
1368 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1370 struct peer
*const peer
= args
->peer
;
1371 struct attr
*const attr
= args
->attr
;
1372 const bgp_size_t length
= args
->length
;
1376 flog_err(EC_BGP_ATTR_LEN
,
1377 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1378 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1382 /* If it is contained in an UPDATE message that is received from an
1383 external peer, then this attribute MUST be ignored by the
1384 receiving speaker. */
1385 if (peer
->sort
== BGP_PEER_EBGP
) {
1386 stream_forward_getp(peer
->curr
, length
);
1387 return BGP_ATTR_PARSE_PROCEED
;
1390 attr
->local_pref
= stream_getl(peer
->curr
);
1392 /* Set the local-pref flag. */
1393 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1395 return BGP_ATTR_PARSE_PROCEED
;
1398 /* Atomic aggregate. */
1399 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1401 struct attr
*const attr
= args
->attr
;
1402 const bgp_size_t length
= args
->length
;
1406 flog_err(EC_BGP_ATTR_LEN
,
1407 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1409 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1413 /* Set atomic aggregate flag. */
1414 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1416 return BGP_ATTR_PARSE_PROCEED
;
1419 /* Aggregator attribute */
1420 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1422 struct peer
*const peer
= args
->peer
;
1423 struct attr
*const attr
= args
->attr
;
1424 const bgp_size_t length
= args
->length
;
1428 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1429 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1432 if (length
!= wantedlen
) {
1433 flog_err(EC_BGP_ATTR_LEN
,
1434 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1436 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1440 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1441 attr
->aggregator_as
= stream_getl(peer
->curr
);
1443 attr
->aggregator_as
= stream_getw(peer
->curr
);
1444 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1446 /* Set atomic aggregate flag. */
1447 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1449 return BGP_ATTR_PARSE_PROCEED
;
1452 /* New Aggregator attribute */
1453 static bgp_attr_parse_ret_t
1454 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1455 as_t
*as4_aggregator_as
,
1456 struct in_addr
*as4_aggregator_addr
)
1458 struct peer
*const peer
= args
->peer
;
1459 struct attr
*const attr
= args
->attr
;
1460 const bgp_size_t length
= args
->length
;
1463 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1465 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1469 *as4_aggregator_as
= stream_getl(peer
->curr
);
1470 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1472 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1474 return BGP_ATTR_PARSE_PROCEED
;
1477 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1479 static bgp_attr_parse_ret_t
1480 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1481 struct aspath
*as4_path
, as_t as4_aggregator
,
1482 struct in_addr
*as4_aggregator_addr
)
1484 int ignore_as4_path
= 0;
1485 struct aspath
*newpath
;
1487 if (!attr
->aspath
) {
1488 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1490 * checked that all well-known, mandatory attributes were
1493 * Can only be a problem with peer itself - hard error
1495 return BGP_ATTR_PARSE_ERROR
;
1498 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1499 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1501 * It is worth a warning though, because the peer really
1502 * should not send them
1504 if (BGP_DEBUG(as4
, AS4
)) {
1505 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1506 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1507 "AS4 capable peer, yet it sent");
1510 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1511 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1513 "AS4 capable peer, yet it sent");
1516 return BGP_ATTR_PARSE_PROCEED
;
1519 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1520 * because that may override AS4_PATH
1522 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1523 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1525 * if the as_number in aggregator is not AS_TRANS,
1526 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1527 * and the Aggregator shall be taken as
1528 * info on the aggregating node, and the AS_PATH
1529 * shall be taken as the AS_PATH
1531 * the Aggregator shall be ignored and the
1532 * AS4_AGGREGATOR shall be taken as the
1533 * Aggregating node and the AS_PATH is to be
1534 * constructed "as in all other cases"
1536 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1538 if (BGP_DEBUG(as4
, AS4
))
1540 "[AS4] %s BGP not AS4 capable peer"
1541 " send AGGREGATOR != AS_TRANS and"
1542 " AS4_AGGREGATOR, so ignore"
1543 " AS4_AGGREGATOR and AS4_PATH",
1545 ignore_as4_path
= 1;
1547 /* "New_aggregator shall be taken as aggregator"
1549 attr
->aggregator_as
= as4_aggregator
;
1550 attr
->aggregator_addr
.s_addr
=
1551 as4_aggregator_addr
->s_addr
;
1554 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1555 * That is bogus - but reading the conditions
1556 * we have to handle AS4_AGGREGATOR as if it were
1557 * AGGREGATOR in that case
1559 if (BGP_DEBUG(as4
, AS4
))
1561 "[AS4] %s BGP not AS4 capable peer send"
1562 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1563 " it as if AGGREGATOR with AS_TRANS had been there",
1565 attr
->aggregator_as
= as4_aggregator
;
1566 /* sweep it under the carpet and simulate a "good"
1568 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1572 /* need to reconcile NEW_AS_PATH and AS_PATH */
1573 if (!ignore_as4_path
1574 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1575 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1577 return BGP_ATTR_PARSE_ERROR
;
1579 aspath_unintern(&attr
->aspath
);
1580 attr
->aspath
= aspath_intern(newpath
);
1582 return BGP_ATTR_PARSE_PROCEED
;
1585 /* Community attribute. */
1586 static bgp_attr_parse_ret_t
1587 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1589 struct peer
*const peer
= args
->peer
;
1590 struct attr
*const attr
= args
->attr
;
1591 const bgp_size_t length
= args
->length
;
1594 attr
->community
= NULL
;
1595 return BGP_ATTR_PARSE_PROCEED
;
1599 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1601 /* XXX: fix community_parse to use stream API and remove this */
1602 stream_forward_getp(peer
->curr
, length
);
1604 if (!attr
->community
)
1605 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1608 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1610 return BGP_ATTR_PARSE_PROCEED
;
1613 /* Originator ID attribute. */
1614 static bgp_attr_parse_ret_t
1615 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1617 struct peer
*const peer
= args
->peer
;
1618 struct attr
*const attr
= args
->attr
;
1619 const bgp_size_t length
= args
->length
;
1623 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1626 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1630 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1632 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1634 return BGP_ATTR_PARSE_PROCEED
;
1637 /* Cluster list attribute. */
1638 static bgp_attr_parse_ret_t
1639 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1641 struct peer
*const peer
= args
->peer
;
1642 struct attr
*const attr
= args
->attr
;
1643 const bgp_size_t length
= args
->length
;
1647 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
1649 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1654 cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
), length
);
1656 /* XXX: Fix cluster_parse to use stream API and then remove this */
1657 stream_forward_getp(peer
->curr
, length
);
1659 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1661 return BGP_ATTR_PARSE_PROCEED
;
1664 /* Multiprotocol reachability information parse. */
1665 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1666 struct bgp_nlri
*mp_update
)
1670 iana_safi_t pkt_safi
;
1672 bgp_size_t nlri_len
;
1675 struct peer
*const peer
= args
->peer
;
1676 struct attr
*const attr
= args
->attr
;
1677 const bgp_size_t length
= args
->length
;
1679 /* Set end of packet. */
1680 s
= BGP_INPUT(peer
);
1681 start
= stream_get_getp(s
);
1683 /* safe to read statically sized header? */
1684 #define BGP_MP_REACH_MIN_SIZE 5
1685 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1686 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1687 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
1688 __func__
, peer
->host
, (unsigned long)length
);
1689 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1692 /* Load AFI, SAFI. */
1693 pkt_afi
= stream_getw(s
);
1694 pkt_safi
= stream_getc(s
);
1696 /* Convert AFI, SAFI to internal values, check. */
1697 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1698 /* Log if AFI or SAFI is unrecognized. This is not an error
1700 * the attribute is otherwise malformed.
1702 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1704 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
1705 peer
->host
, iana_afi2str(pkt_afi
),
1706 iana_safi2str(pkt_safi
));
1707 return BGP_ATTR_PARSE_ERROR
;
1710 /* Get nexthop length. */
1711 attr
->mp_nexthop_len
= stream_getc(s
);
1713 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
1715 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
1716 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1717 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1720 /* Nexthop length check. */
1721 switch (attr
->mp_nexthop_len
) {
1723 if (safi
!= SAFI_FLOWSPEC
) {
1724 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
1725 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1726 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1729 case BGP_ATTR_NHLEN_VPNV4
:
1730 stream_getl(s
); /* RD high */
1731 stream_getl(s
); /* RD low */
1733 * NOTE: intentional fall through
1734 * - for consistency in rx processing
1736 * The following comment is to signal GCC this intention
1737 * and suppress the warning
1740 case BGP_ATTR_NHLEN_IPV4
:
1741 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1742 /* Probably needed for RFC 2283 */
1743 if (attr
->nexthop
.s_addr
== 0)
1744 memcpy(&attr
->nexthop
.s_addr
,
1745 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1747 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1748 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1749 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
1750 stream_getl(s
); /* RD high */
1751 stream_getl(s
); /* RD low */
1753 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1754 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1755 if (!peer
->nexthop
.ifp
) {
1756 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
1758 return BGP_ATTR_PARSE_WITHDRAW
;
1760 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1763 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1764 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1765 if (attr
->mp_nexthop_len
1766 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1767 stream_getl(s
); /* RD high */
1768 stream_getl(s
); /* RD low */
1770 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1771 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1772 if (!peer
->nexthop
.ifp
) {
1773 zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
1775 return BGP_ATTR_PARSE_WITHDRAW
;
1777 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1779 if (attr
->mp_nexthop_len
1780 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1781 stream_getl(s
); /* RD high */
1782 stream_getl(s
); /* RD low */
1784 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1785 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
1786 char buf1
[INET6_ADDRSTRLEN
];
1787 char buf2
[INET6_ADDRSTRLEN
];
1789 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1791 "%s sent next-hops %s and %s. Ignoring non-LL value",
1794 &attr
->mp_nexthop_global
,
1795 buf1
, INET6_ADDRSTRLEN
),
1797 &attr
->mp_nexthop_local
, buf2
,
1800 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1802 if (!peer
->nexthop
.ifp
) {
1803 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
1805 return BGP_ATTR_PARSE_WITHDRAW
;
1807 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1810 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
1811 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1812 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1816 zlog_info("%s: %s sent SNPA which couldn't be read",
1817 __func__
, peer
->host
);
1818 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1823 if ((val
= stream_getc(s
)))
1825 EC_BGP_DEFUNCT_SNPA_LEN
,
1826 "%s sent non-zero value, %u, for defunct SNPA-length field",
1830 /* must have nrli_len, what is left of the attribute */
1831 nlri_len
= LEN_LEFT
;
1832 if (nlri_len
> STREAM_READABLE(s
)) {
1833 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
1834 __func__
, peer
->host
);
1835 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1839 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
1840 __func__
, peer
->host
);
1842 mp_update
->afi
= afi
;
1843 mp_update
->safi
= safi
;
1844 return BGP_ATTR_PARSE_EOR
;
1847 mp_update
->afi
= afi
;
1848 mp_update
->safi
= safi
;
1849 mp_update
->nlri
= stream_pnt(s
);
1850 mp_update
->length
= nlri_len
;
1852 stream_forward_getp(s
, nlri_len
);
1854 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
1856 return BGP_ATTR_PARSE_PROCEED
;
1860 /* Multiprotocol unreachable parse */
1861 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
1862 struct bgp_nlri
*mp_withdraw
)
1867 iana_safi_t pkt_safi
;
1869 uint16_t withdraw_len
;
1870 struct peer
*const peer
= args
->peer
;
1871 struct attr
*const attr
= args
->attr
;
1872 const bgp_size_t length
= args
->length
;
1876 #define BGP_MP_UNREACH_MIN_SIZE 3
1877 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1878 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1880 pkt_afi
= stream_getw(s
);
1881 pkt_safi
= stream_getc(s
);
1883 /* Convert AFI, SAFI to internal values, check. */
1884 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1885 /* Log if AFI or SAFI is unrecognized. This is not an error
1887 * the attribute is otherwise malformed.
1889 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1891 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
1892 peer
->host
, iana_afi2str(pkt_afi
),
1893 iana_safi2str(pkt_safi
));
1894 return BGP_ATTR_PARSE_ERROR
;
1897 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1899 mp_withdraw
->afi
= afi
;
1900 mp_withdraw
->safi
= safi
;
1901 mp_withdraw
->nlri
= stream_pnt(s
);
1902 mp_withdraw
->length
= withdraw_len
;
1904 stream_forward_getp(s
, withdraw_len
);
1906 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
1908 return BGP_ATTR_PARSE_PROCEED
;
1911 /* Large Community attribute. */
1912 static bgp_attr_parse_ret_t
1913 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
1915 struct peer
*const peer
= args
->peer
;
1916 struct attr
*const attr
= args
->attr
;
1917 const bgp_size_t length
= args
->length
;
1920 * Large community follows new attribute format.
1923 attr
->lcommunity
= NULL
;
1924 /* Empty extcomm doesn't seem to be invalid per se */
1925 return BGP_ATTR_PARSE_PROCEED
;
1929 lcommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1930 /* XXX: fix ecommunity_parse to use stream API */
1931 stream_forward_getp(peer
->curr
, length
);
1933 if (!attr
->lcommunity
)
1934 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1937 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1939 return BGP_ATTR_PARSE_PROCEED
;
1942 /* Extended Community attribute. */
1943 static bgp_attr_parse_ret_t
1944 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
1946 struct peer
*const peer
= args
->peer
;
1947 struct attr
*const attr
= args
->attr
;
1948 const bgp_size_t length
= args
->length
;
1952 attr
->ecommunity
= NULL
;
1953 /* Empty extcomm doesn't seem to be invalid per se */
1954 return BGP_ATTR_PARSE_PROCEED
;
1958 ecommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1959 /* XXX: fix ecommunity_parse to use stream API */
1960 stream_forward_getp(peer
->curr
, length
);
1962 if (!attr
->ecommunity
)
1963 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1966 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1968 /* Extract MAC mobility sequence number, if any. */
1969 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
1970 attr
->sticky
= sticky
;
1972 /* Check if this is a Gateway MAC-IP advertisement */
1973 attr
->default_gw
= bgp_attr_default_gw(attr
);
1975 /* Handle scenario where router flag ecommunity is not
1976 * set but default gw ext community is present.
1977 * Use default gateway, set and propogate R-bit.
1979 if (attr
->default_gw
)
1980 attr
->router_flag
= 1;
1982 /* Check EVPN Neighbor advertisement flags, R-bit */
1983 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
);
1985 /* Extract the Rmac, if any */
1986 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
1987 if (bgp_debug_update(peer
, NULL
, NULL
, 1) &&
1988 bgp_mac_exist(&attr
->rmac
)) {
1989 char buf1
[ETHER_ADDR_STRLEN
];
1991 zlog_debug("%s: router mac %s is self mac",
1993 prefix_mac2str(&attr
->rmac
, buf1
,
1999 /* Get the tunnel type from encap extended community */
2000 bgp_attr_extcom_tunnel_type(attr
,
2001 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2003 return BGP_ATTR_PARSE_PROCEED
;
2006 /* Parse Tunnel Encap attribute in an UPDATE */
2007 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2008 bgp_size_t length
, /* IN: attr's length field */
2009 struct attr
*attr
, /* IN: caller already allocated */
2010 uint8_t flag
, /* IN: attr's flags field */
2014 uint16_t tunneltype
= 0;
2016 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2018 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2019 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2021 "Tunnel Encap attribute flag isn't optional and transitive %d",
2023 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2024 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2029 if (BGP_ATTR_ENCAP
== type
) {
2030 /* read outer TLV type and length */
2031 uint16_t tlv_length
;
2035 "Tunnel Encap attribute not long enough to contain outer T,L");
2036 bgp_notify_send_with_data(
2037 peer
, BGP_NOTIFY_UPDATE_ERR
,
2038 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2041 tunneltype
= stream_getw(BGP_INPUT(peer
));
2042 tlv_length
= stream_getw(BGP_INPUT(peer
));
2045 if (tlv_length
!= length
) {
2046 zlog_info("%s: tlv_length(%d) != length(%d)",
2047 __func__
, tlv_length
, length
);
2051 while (length
>= 4) {
2052 uint16_t subtype
= 0;
2053 uint16_t sublength
= 0;
2054 struct bgp_attr_encap_subtlv
*tlv
;
2056 if (BGP_ATTR_ENCAP
== type
) {
2057 subtype
= stream_getc(BGP_INPUT(peer
));
2058 sublength
= stream_getc(BGP_INPUT(peer
));
2062 subtype
= stream_getw(BGP_INPUT(peer
));
2063 sublength
= stream_getw(BGP_INPUT(peer
));
2068 if (sublength
> length
) {
2070 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2072 bgp_notify_send_with_data(
2073 peer
, BGP_NOTIFY_UPDATE_ERR
,
2074 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2078 /* alloc and copy sub-tlv */
2079 /* TBD make sure these are freed when attributes are released */
2080 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2081 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2082 tlv
->type
= subtype
;
2083 tlv
->length
= sublength
;
2084 stream_get(tlv
->value
, peer
->curr
, sublength
);
2085 length
-= sublength
;
2087 /* attach tlv to encap chain */
2088 if (BGP_ATTR_ENCAP
== type
) {
2089 struct bgp_attr_encap_subtlv
*stlv_last
;
2090 for (stlv_last
= attr
->encap_subtlvs
;
2091 stlv_last
&& stlv_last
->next
;
2092 stlv_last
= stlv_last
->next
)
2095 stlv_last
->next
= tlv
;
2097 attr
->encap_subtlvs
= tlv
;
2101 struct bgp_attr_encap_subtlv
*stlv_last
;
2102 for (stlv_last
= attr
->vnc_subtlvs
;
2103 stlv_last
&& stlv_last
->next
;
2104 stlv_last
= stlv_last
->next
)
2107 stlv_last
->next
= tlv
;
2109 attr
->vnc_subtlvs
= tlv
;
2115 if (BGP_ATTR_ENCAP
== type
) {
2116 attr
->encap_tunneltype
= tunneltype
;
2120 /* spurious leftover data */
2122 "Tunnel Encap attribute length is bad: %d leftover octets",
2124 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2125 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2134 * Read an individual SID value returning how much data we have read
2135 * Returns 0 if there was an error that needs to be passed up the stack
2137 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(int32_t type
,
2139 struct bgp_attr_parser_args
*args
,
2140 struct bgp_nlri
*mp_update
)
2142 struct peer
*const peer
= args
->peer
;
2143 struct attr
*const attr
= args
->attr
;
2144 uint32_t label_index
;
2145 struct in6_addr ipv6_sid
;
2147 uint32_t srgb_range
;
2150 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2151 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2154 "Prefix SID label index length is %d instead of %d",
2155 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2156 return bgp_attr_malformed(args
,
2157 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2161 /* Ignore flags and reserved */
2162 stream_getc(peer
->curr
);
2163 stream_getw(peer
->curr
);
2165 /* Fetch the label index and see if it is valid. */
2166 label_index
= stream_getl(peer
->curr
);
2167 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2168 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2171 /* Store label index; subsequently, we'll check on
2173 attr
->label_index
= label_index
;
2176 * Ignore the Label index attribute unless received for
2180 if (!mp_update
->length
2181 || mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2182 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
2185 /* Placeholder code for the IPv6 SID type */
2186 else if (type
== BGP_PREFIX_SID_IPV6
) {
2187 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2188 flog_err(EC_BGP_ATTR_LEN
,
2189 "Prefix SID IPv6 length is %d instead of %d",
2190 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2191 return bgp_attr_malformed(args
,
2192 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2196 /* Ignore reserved */
2197 stream_getc(peer
->curr
);
2198 stream_getw(peer
->curr
);
2200 stream_get(&ipv6_sid
, peer
->curr
, 16);
2203 /* Placeholder code for the Originator SRGB type */
2204 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2206 stream_getw(peer
->curr
);
2210 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2213 "Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2214 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2215 return bgp_attr_malformed(
2216 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2220 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2222 for (int i
= 0; i
< srgb_count
; i
++) {
2223 stream_get(&srgb_base
, peer
->curr
, 3);
2224 stream_get(&srgb_range
, peer
->curr
, 3);
2229 * Placeholder code for Unsupported TLV
2230 * - SRv6 L3 Service TLV (type5)
2231 * - SRv6 L2 Service TLV (type6)
2233 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
2234 || type
== BGP_PREFIX_SID_SRV6_L2_SERVICE
) {
2235 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2237 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2239 for (int i
= 0; i
< length
; i
++)
2240 stream_getc(peer
->curr
);
2243 return BGP_ATTR_PARSE_PROCEED
;
2246 /* Prefix SID attribute
2247 * draft-ietf-idr-bgp-prefix-sid-05
2249 bgp_attr_parse_ret_t
2250 bgp_attr_prefix_sid(int32_t tlength
, struct bgp_attr_parser_args
*args
,
2251 struct bgp_nlri
*mp_update
)
2253 struct peer
*const peer
= args
->peer
;
2254 struct attr
*const attr
= args
->attr
;
2255 bgp_attr_parse_ret_t ret
;
2257 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2260 int32_t type
, length
;
2262 type
= stream_getc(peer
->curr
);
2263 length
= stream_getw(peer
->curr
);
2265 ret
= bgp_attr_psid_sub(type
, length
, args
, mp_update
);
2267 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2270 * Subtract length + the T and the L
2271 * since length is the Vector portion
2273 tlength
-= length
+ 3;
2278 "Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
2280 return bgp_attr_malformed(args
,
2281 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2286 return BGP_ATTR_PARSE_PROCEED
;
2289 /* PMSI tunnel attribute (RFC 6514)
2290 * Basic validation checks done here.
2292 static bgp_attr_parse_ret_t
2293 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2295 struct peer
*const peer
= args
->peer
;
2296 struct attr
*const attr
= args
->attr
;
2297 const bgp_size_t length
= args
->length
;
2299 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2301 /* Verify that the receiver is expecting "ingress replication" as we
2302 * can only support that.
2304 if (length
< attr_parse_len
) {
2305 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2307 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2310 stream_getc(peer
->curr
); /* Flags */
2311 tnl_type
= stream_getc(peer
->curr
);
2312 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2313 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2314 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2315 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2318 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2320 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2321 "Bad PMSI tunnel attribute length %d for IR",
2323 return bgp_attr_malformed(
2324 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2329 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2330 attr
->pmsi_tnl_type
= tnl_type
;
2331 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2333 /* Forward read pointer of input stream. */
2334 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2336 return BGP_ATTR_PARSE_PROCEED
;
2339 /* BGP unknown attribute treatment. */
2340 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2342 bgp_size_t total
= args
->total
;
2343 struct transit
*transit
;
2344 struct peer
*const peer
= args
->peer
;
2345 struct attr
*const attr
= args
->attr
;
2346 uint8_t *const startp
= args
->startp
;
2347 const uint8_t type
= args
->type
;
2348 const uint8_t flag
= args
->flags
;
2349 const bgp_size_t length
= args
->length
;
2351 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2353 "%s Unknown attribute is received (type %d, length %d)",
2354 peer
->host
, type
, length
);
2356 /* Forward read pointer of input stream. */
2357 stream_forward_getp(peer
->curr
, length
);
2359 /* If any of the mandatory well-known attributes are not recognized,
2360 then the Error Subcode is set to Unrecognized Well-known
2361 Attribute. The Data field contains the unrecognized attribute
2362 (type, length and value). */
2363 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2364 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2368 /* Unrecognized non-transitive optional attributes must be quietly
2369 ignored and not passed along to other BGP peers. */
2370 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2371 return BGP_ATTR_PARSE_PROCEED
;
2373 /* If a path with recognized transitive optional attribute is
2374 accepted and passed along to other BGP peers and the Partial bit
2375 in the Attribute Flags octet is set to 1 by some previous AS, it
2376 is not set back to 0 by the current AS. */
2377 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2379 /* Store transitive attribute to the end of attr->transit. */
2381 attr
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2383 transit
= attr
->transit
;
2386 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2387 transit
->length
+ total
);
2389 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2391 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2392 transit
->length
+= total
;
2394 return BGP_ATTR_PARSE_PROCEED
;
2397 /* Well-known attribute check. */
2398 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2402 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2404 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2405 return BGP_ATTR_PARSE_PROCEED
;
2407 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2408 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2409 are present, it should. Check for any other attribute being present
2412 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2413 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2414 return BGP_ATTR_PARSE_PROCEED
;
2416 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2417 type
= BGP_ATTR_ORIGIN
;
2419 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2420 type
= BGP_ATTR_AS_PATH
;
2422 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2424 * NLRI is empty. We can't easily check NLRI empty here though.
2426 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2427 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2428 type
= BGP_ATTR_NEXT_HOP
;
2430 if (peer
->sort
== BGP_PEER_IBGP
2431 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2432 type
= BGP_ATTR_LOCAL_PREF
;
2435 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2436 "%s Missing well-known attribute %s.", peer
->host
,
2437 lookup_msg(attr_str
, type
, NULL
));
2438 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2439 BGP_NOTIFY_UPDATE_MISS_ATTR
, &type
,
2441 return BGP_ATTR_PARSE_ERROR
;
2443 return BGP_ATTR_PARSE_PROCEED
;
2446 /* Read attribute of update packet. This function is called from
2447 bgp_update_receive() in bgp_packet.c. */
2448 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2449 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2450 struct bgp_nlri
*mp_withdraw
)
2452 bgp_attr_parse_ret_t ret
;
2456 uint8_t *startp
, *endp
;
2458 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2459 /* we need the as4_path only until we have synthesized the as_path with
2461 /* same goes for as4_aggregator */
2462 struct aspath
*as4_path
= NULL
;
2463 as_t as4_aggregator
= 0;
2464 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2466 /* Initialize bitmap. */
2467 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2469 /* End pointer of BGP attribute. */
2470 endp
= BGP_INPUT_PNT(peer
) + size
;
2472 /* Get attributes to the end of attribute length. */
2473 while (BGP_INPUT_PNT(peer
) < endp
) {
2474 /* Check remaining length check.*/
2475 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2476 /* XXX warning: long int format, int arg (arg 5) */
2478 EC_BGP_ATTRIBUTE_TOO_SMALL
,
2479 "%s: error BGP attribute length %lu is smaller than min len",
2481 (unsigned long)(endp
2482 - stream_pnt(BGP_INPUT(peer
))));
2484 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2485 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2486 return BGP_ATTR_PARSE_ERROR
;
2489 /* Fetch attribute flag and type. */
2490 startp
= BGP_INPUT_PNT(peer
);
2491 /* "The lower-order four bits of the Attribute Flags octet are
2492 unused. They MUST be zero when sent and MUST be ignored when
2494 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2495 type
= stream_getc(BGP_INPUT(peer
));
2497 /* Check whether Extended-Length applies and is in bounds */
2498 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2499 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2501 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
2502 "%s: Extended length set, but just %lu bytes of attr header",
2504 (unsigned long)(endp
2505 - stream_pnt(BGP_INPUT(peer
))));
2507 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2508 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2509 return BGP_ATTR_PARSE_ERROR
;
2512 /* Check extended attribue length bit. */
2513 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2514 length
= stream_getw(BGP_INPUT(peer
));
2516 length
= stream_getc(BGP_INPUT(peer
));
2518 /* If any attribute appears more than once in the UPDATE
2519 message, then the Error Subcode is set to Malformed Attribute
2522 if (CHECK_BITMAP(seen
, type
)) {
2524 EC_BGP_ATTRIBUTE_REPEATED
,
2525 "%s: error BGP attribute type %d appears twice in a message",
2528 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2529 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2530 return BGP_ATTR_PARSE_ERROR
;
2533 /* Set type to bitmap to check duplicate attribute. `type' is
2534 unsigned char so it never overflow bitmap range. */
2536 SET_BITMAP(seen
, type
);
2538 /* Overflow check. */
2539 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2541 if (attr_endp
> endp
) {
2543 EC_BGP_ATTRIBUTE_TOO_LARGE
,
2544 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
2545 peer
->host
, type
, length
, size
, attr_endp
,
2549 * If any recognized attribute has an Attribute
2550 * Length that conflicts with the expected length
2551 * (based on the attribute type code), then the
2552 * Error Subcode MUST be set to Attribute Length
2553 * Error. The Data field MUST contain the erroneous
2554 * attribute (type, length, and value).
2556 * We do not currently have a good way to determine the
2557 * length of the attribute independent of the length
2558 * received in the message. Instead we send the
2559 * minimum between the amount of data we have and the
2560 * amount specified by the attribute length field.
2562 * Instead of directly passing in the packet buffer and
2563 * offset we use the stream_get* functions to read into
2564 * a stack buffer, since they perform bounds checking
2565 * and we are working with untrusted data.
2567 unsigned char ndata
[BGP_MAX_PACKET_SIZE
];
2568 memset(ndata
, 0x00, sizeof(ndata
));
2570 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
2571 /* Rewind to end of flag field */
2572 stream_forward_getp(BGP_INPUT(peer
), -(1 + lfl
));
2574 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
2576 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
2578 size_t atl
= attr_endp
- startp
;
2579 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
2580 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
2582 bgp_notify_send_with_data(
2583 peer
, BGP_NOTIFY_UPDATE_ERR
,
2584 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
2587 return BGP_ATTR_PARSE_ERROR
;
2590 struct bgp_attr_parser_args attr_args
= {
2597 .total
= attr_endp
- startp
,
2601 /* If any recognized attribute has Attribute Flags that conflict
2602 with the Attribute Type Code, then the Error Subcode is set
2604 Attribute Flags Error. The Data field contains the erroneous
2605 attribute (type, length and value). */
2606 if (bgp_attr_flag_invalid(&attr_args
)) {
2607 ret
= bgp_attr_malformed(
2608 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2610 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2615 /* OK check attribute and store it's value. */
2617 case BGP_ATTR_ORIGIN
:
2618 ret
= bgp_attr_origin(&attr_args
);
2620 case BGP_ATTR_AS_PATH
:
2621 ret
= bgp_attr_aspath(&attr_args
);
2623 case BGP_ATTR_AS4_PATH
:
2624 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
2626 case BGP_ATTR_NEXT_HOP
:
2627 ret
= bgp_attr_nexthop(&attr_args
);
2629 case BGP_ATTR_MULTI_EXIT_DISC
:
2630 ret
= bgp_attr_med(&attr_args
);
2632 case BGP_ATTR_LOCAL_PREF
:
2633 ret
= bgp_attr_local_pref(&attr_args
);
2635 case BGP_ATTR_ATOMIC_AGGREGATE
:
2636 ret
= bgp_attr_atomic(&attr_args
);
2638 case BGP_ATTR_AGGREGATOR
:
2639 ret
= bgp_attr_aggregator(&attr_args
);
2641 case BGP_ATTR_AS4_AGGREGATOR
:
2642 ret
= bgp_attr_as4_aggregator(&attr_args
,
2644 &as4_aggregator_addr
);
2646 case BGP_ATTR_COMMUNITIES
:
2647 ret
= bgp_attr_community(&attr_args
);
2649 case BGP_ATTR_LARGE_COMMUNITIES
:
2650 ret
= bgp_attr_large_community(&attr_args
);
2652 case BGP_ATTR_ORIGINATOR_ID
:
2653 ret
= bgp_attr_originator_id(&attr_args
);
2655 case BGP_ATTR_CLUSTER_LIST
:
2656 ret
= bgp_attr_cluster_list(&attr_args
);
2658 case BGP_ATTR_MP_REACH_NLRI
:
2659 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
2661 case BGP_ATTR_MP_UNREACH_NLRI
:
2662 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
2664 case BGP_ATTR_EXT_COMMUNITIES
:
2665 ret
= bgp_attr_ext_communities(&attr_args
);
2667 #if ENABLE_BGP_VNC_ATTR
2670 case BGP_ATTR_ENCAP
:
2671 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
2674 case BGP_ATTR_PREFIX_SID
:
2675 ret
= bgp_attr_prefix_sid(length
,
2676 &attr_args
, mp_update
);
2678 case BGP_ATTR_PMSI_TUNNEL
:
2679 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
2682 ret
= bgp_attr_unknown(&attr_args
);
2686 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
2687 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2688 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2689 ret
= BGP_ATTR_PARSE_ERROR
;
2692 if (ret
== BGP_ATTR_PARSE_EOR
) {
2694 aspath_unintern(&as4_path
);
2698 /* If hard error occurred immediately return to the caller. */
2699 if (ret
== BGP_ATTR_PARSE_ERROR
) {
2700 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
2701 "%s: Attribute %s, parse error", peer
->host
,
2702 lookup_msg(attr_str
, type
, NULL
));
2704 aspath_unintern(&as4_path
);
2707 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
2710 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
2711 "%s: Attribute %s, parse error - treating as withdrawal",
2712 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2714 aspath_unintern(&as4_path
);
2718 /* Check the fetched length. */
2719 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
2720 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
2721 "%s: BGP attribute %s, fetch error",
2722 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2723 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2724 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2726 aspath_unintern(&as4_path
);
2727 return BGP_ATTR_PARSE_ERROR
;
2731 /* Check final read pointer is same as end pointer. */
2732 if (BGP_INPUT_PNT(peer
) != endp
) {
2733 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
2734 "%s: BGP attribute %s, length mismatch", peer
->host
,
2735 lookup_msg(attr_str
, type
, NULL
));
2736 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2737 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2739 aspath_unintern(&as4_path
);
2740 return BGP_ATTR_PARSE_ERROR
;
2744 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
2745 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
2746 * This is implemented below and will result in a NOTIFICATION. If the
2747 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
2748 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
2749 * message SHOULD NOT be sent. This is implemented elsewhere.
2751 * RFC4760: An UPDATE message that carries no NLRI, other than the one
2752 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
2753 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
2754 * speaker that receives the message SHOULD ignore this attribute.
2756 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2757 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
2758 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
2759 return BGP_ATTR_PARSE_ERROR
;
2763 /* Check all mandatory well-known attributes are present */
2764 if ((ret
= bgp_attr_check(peer
, attr
)) < 0) {
2766 aspath_unintern(&as4_path
);
2771 * At this place we can see whether we got AS4_PATH and/or
2772 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2773 * We can not do this before we've read all attributes because
2774 * the as4 handling does not say whether AS4_PATH has to be sent
2775 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2776 * in relationship to AGGREGATOR.
2777 * So, to be defensive, we are not relying on any order and read
2778 * all attributes first, including these 32bit ones, and now,
2779 * afterwards, we look what and if something is to be done for as4.
2781 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2784 /* actually... this doesn't ever return failure currently, but
2785 * better safe than sorry */
2786 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
2787 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
2788 &as4_aggregator_addr
)) {
2789 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2790 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2792 aspath_unintern(&as4_path
);
2793 return BGP_ATTR_PARSE_ERROR
;
2796 /* At this stage, we have done all fiddling with as4, and the
2797 * resulting info is in attr->aggregator resp. attr->aspath
2798 * so we can chuck as4_aggregator and as4_path alltogether in
2799 * order to save memory
2802 aspath_unintern(&as4_path
); /* unintern - it is in the hash */
2803 /* The flag that we got this is still there, but that does not
2808 * The "rest" of the code does nothing with as4_aggregator.
2809 * there is no memory attached specifically which is not part
2811 * so ignoring just means do nothing.
2814 * Finally do the checks on the aspath we did not do yet
2815 * because we waited for a potentially synthesized aspath.
2817 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
2818 ret
= bgp_attr_aspath_check(peer
, attr
);
2819 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2822 /* Finally intern unknown attribute. */
2824 attr
->transit
= transit_intern(attr
->transit
);
2825 if (attr
->encap_subtlvs
)
2826 attr
->encap_subtlvs
=
2827 encap_intern(attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2829 if (attr
->vnc_subtlvs
)
2831 encap_intern(attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2834 return BGP_ATTR_PARSE_PROCEED
;
2838 * Extract the tunnel type from extended community
2840 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
2841 bgp_encap_types
*tunnel_type
)
2843 struct ecommunity
*ecom
;
2848 ecom
= attr
->ecommunity
;
2849 if (!ecom
|| !ecom
->size
)
2852 for (i
= 0; i
< ecom
->size
; i
++) {
2854 uint8_t type
, sub_type
;
2856 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
2859 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
2860 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
2862 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
2869 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
2870 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
2875 iana_safi_t pkt_safi
;
2878 /* Set extended bit always to encode the attribute length as 2 bytes */
2879 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
2880 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
2881 sizep
= stream_get_endp(s
);
2882 stream_putw(s
, 0); /* Marker: Attribute length. */
2885 /* Convert AFI, SAFI to values for packet. */
2886 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
2888 stream_putw(s
, pkt_afi
); /* AFI */
2889 stream_putc(s
, pkt_safi
); /* SAFI */
2893 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
2894 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
2896 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
2899 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2904 case SAFI_MULTICAST
:
2905 case SAFI_LABELED_UNICAST
:
2907 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
2911 stream_putl(s
, 0); /* RD = 0, per RFC */
2913 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2918 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2921 stream_putc(s
, 0); /* no nexthop for flowspec */
2929 case SAFI_MULTICAST
:
2930 case SAFI_LABELED_UNICAST
:
2932 if (attr
->mp_nexthop_len
2933 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2935 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2936 stream_put(s
, &attr
->mp_nexthop_global
,
2938 stream_put(s
, &attr
->mp_nexthop_local
,
2941 stream_putc(s
, IPV6_MAX_BYTELEN
);
2942 stream_put(s
, &attr
->mp_nexthop_global
,
2946 case SAFI_MPLS_VPN
: {
2947 if (attr
->mp_nexthop_len
2948 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2950 stream_putl(s
, 0); /* RD = 0, per RFC */
2952 stream_put(s
, &attr
->mp_nexthop_global
,
2954 } else if (attr
->mp_nexthop_len
2955 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2957 stream_putl(s
, 0); /* RD = 0, per RFC */
2959 stream_put(s
, &attr
->mp_nexthop_global
,
2961 stream_putl(s
, 0); /* RD = 0, per RFC */
2963 stream_put(s
, &attr
->mp_nexthop_local
,
2968 stream_putc(s
, IPV6_MAX_BYTELEN
);
2969 stream_put(s
, &attr
->mp_nexthop_global
,
2973 stream_putc(s
, 0); /* no nexthop for flowspec */
2979 if (safi
!= SAFI_FLOWSPEC
)
2981 EC_BGP_ATTR_NH_SEND_LEN
,
2982 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
2983 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
2992 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
2993 struct prefix
*p
, struct prefix_rd
*prd
,
2994 mpls_label_t
*label
, uint32_t num_labels
,
2995 int addpath_encode
, uint32_t addpath_tx_id
,
2998 if (safi
== SAFI_MPLS_VPN
) {
3000 stream_putl(s
, addpath_tx_id
);
3001 /* Label, RD, Prefix write. */
3002 stream_putc(s
, p
->prefixlen
+ 88);
3003 stream_put(s
, label
, BGP_LABEL_BYTES
);
3004 stream_put(s
, prd
->val
, 8);
3005 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3006 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3007 /* EVPN prefix - contents depend on type */
3008 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3009 addpath_encode
, addpath_tx_id
);
3010 } else if (safi
== SAFI_LABELED_UNICAST
) {
3011 /* Prefix write with label. */
3012 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3014 } else if (safi
== SAFI_FLOWSPEC
) {
3015 if (PSIZE (p
->prefixlen
)+2 < FLOWSPEC_NLRI_SIZELIMIT
)
3016 stream_putc(s
, PSIZE (p
->prefixlen
)+2);
3018 stream_putw(s
, (PSIZE (p
->prefixlen
)+2)|(0xf<<12));
3019 stream_putc(s
, 2);/* Filter type */
3020 stream_putc(s
, p
->prefixlen
);/* Prefix length */
3021 stream_put(s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
3023 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3026 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
, struct prefix
*p
)
3028 int size
= PSIZE(p
->prefixlen
);
3029 if (safi
== SAFI_MPLS_VPN
)
3031 else if (safi
== SAFI_LABELED_UNICAST
)
3032 size
+= BGP_LABEL_BYTES
;
3033 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3034 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3040 * Encodes the tunnel encapsulation attribute,
3041 * and with ENABLE_BGP_VNC the VNC attribute which uses
3042 * almost the same TLV format
3044 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3045 struct stream
*s
, struct attr
*attr
,
3048 unsigned int attrlenfield
= 0;
3049 unsigned int attrhdrlen
= 0;
3050 struct bgp_attr_encap_subtlv
*subtlvs
;
3051 struct bgp_attr_encap_subtlv
*st
;
3052 const char *attrname
;
3054 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3055 && (!attr
->encap_tunneltype
3056 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3060 case BGP_ATTR_ENCAP
:
3061 attrname
= "Tunnel Encap";
3062 subtlvs
= attr
->encap_subtlvs
;
3063 if (subtlvs
== NULL
) /* nothing to do */
3066 * The tunnel encap attr has an "outer" tlv.
3068 * L = total length of subtlvs,
3069 * V = concatenated subtlvs.
3071 attrlenfield
= 2 + 2; /* T + L */
3072 attrhdrlen
= 1 + 1; /* subTLV T + L */
3075 #if ENABLE_BGP_VNC_ATTR
3078 subtlvs
= attr
->vnc_subtlvs
;
3079 if (subtlvs
== NULL
) /* nothing to do */
3081 attrlenfield
= 0; /* no outer T + L */
3082 attrhdrlen
= 2 + 2; /* subTLV T + L */
3090 /* compute attr length */
3091 for (st
= subtlvs
; st
; st
= st
->next
) {
3092 attrlenfield
+= (attrhdrlen
+ st
->length
);
3095 if (attrlenfield
> 0xffff) {
3096 zlog_info("%s attribute is too long (length=%d), can't send it",
3097 attrname
, attrlenfield
);
3101 if (attrlenfield
> 0xff) {
3102 /* 2-octet length field */
3104 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3105 | BGP_ATTR_FLAG_EXTLEN
);
3106 stream_putc(s
, attrtype
);
3107 stream_putw(s
, attrlenfield
& 0xffff);
3109 /* 1-octet length field */
3110 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3111 stream_putc(s
, attrtype
);
3112 stream_putc(s
, attrlenfield
& 0xff);
3115 if (attrtype
== BGP_ATTR_ENCAP
) {
3116 /* write outer T+L */
3117 stream_putw(s
, attr
->encap_tunneltype
);
3118 stream_putw(s
, attrlenfield
- 4);
3121 /* write each sub-tlv */
3122 for (st
= subtlvs
; st
; st
= st
->next
) {
3123 if (attrtype
== BGP_ATTR_ENCAP
) {
3124 stream_putc(s
, st
->type
);
3125 stream_putc(s
, st
->length
);
3128 stream_putw(s
, st
->type
);
3129 stream_putw(s
, st
->length
);
3132 stream_put(s
, st
->value
, st
->length
);
3136 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3138 /* Set MP attribute length. Don't count the (2) bytes used to encode
3140 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3143 static int bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3145 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3146 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3147 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3148 PEER_FLAG_REMOVE_PRIVATE_AS
)
3149 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3150 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3151 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3152 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3153 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3154 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3159 /* Make attribute packet. */
3160 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3161 struct stream
*s
, struct attr
*attr
,
3162 struct bpacket_attr_vec_arr
*vecarr
,
3163 struct prefix
*p
, afi_t afi
, safi_t safi
,
3164 struct peer
*from
, struct prefix_rd
*prd
,
3165 mpls_label_t
*label
, uint32_t num_labels
,
3166 int addpath_encode
, uint32_t addpath_tx_id
)
3169 size_t aspath_sizep
;
3170 struct aspath
*aspath
;
3171 int send_as4_path
= 0;
3172 int send_as4_aggregator
= 0;
3173 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3178 /* Remember current pointer. */
3179 cp
= stream_get_endp(s
);
3182 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3183 && !peer_cap_enhe(peer
, afi
, safi
))) {
3184 size_t mpattrlen_pos
= 0;
3186 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3188 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3189 num_labels
, addpath_encode
,
3190 addpath_tx_id
, attr
);
3191 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3194 /* Origin attribute. */
3195 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3196 stream_putc(s
, BGP_ATTR_ORIGIN
);
3198 stream_putc(s
, attr
->origin
);
3200 /* AS path attribute. */
3202 /* If remote-peer is EBGP */
3203 if (peer
->sort
== BGP_PEER_EBGP
3204 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3205 PEER_FLAG_AS_PATH_UNCHANGED
)
3206 || attr
->aspath
->segments
== NULL
)
3207 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3208 PEER_FLAG_RSERVER_CLIENT
))) {
3209 aspath
= aspath_dup(attr
->aspath
);
3211 /* Even though we may not be configured for confederations we
3213 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3214 aspath
= aspath_delete_confed_seq(aspath
);
3216 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3217 /* Stuff our path CONFED_ID on the front */
3218 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3220 if (peer
->change_local_as
) {
3221 /* If replace-as is specified, we only use the
3222 change_local_as when
3223 advertising routes. */
3224 if (!CHECK_FLAG(peer
->flags
,
3225 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3226 if (bgp_append_local_as(peer
, afi
,
3228 aspath
= aspath_add_seq(
3229 aspath
, peer
->local_as
);
3230 aspath
= aspath_add_seq(aspath
,
3231 peer
->change_local_as
);
3233 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3236 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3237 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3239 aspath
= aspath_dup(attr
->aspath
);
3240 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3242 aspath
= attr
->aspath
;
3244 /* If peer is not AS4 capable, then:
3245 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3246 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3248 * types are in it (i.e. exclude them if they are there)
3249 * AND do this only if there is at least one asnum > 65535 in the
3251 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3253 * all ASnums > 65535 to BGP_AS_TRANS
3256 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3257 stream_putc(s
, BGP_ATTR_AS_PATH
);
3258 aspath_sizep
= stream_get_endp(s
);
3260 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3262 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3265 if (!use32bit
&& aspath_has_as4(aspath
))
3267 1; /* we'll do this later, at the correct place */
3269 /* Nexthop attribute. */
3270 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3271 && !peer_cap_enhe(peer
, afi
, safi
)) {
3272 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3274 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3275 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3276 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3277 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3280 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3281 } else if (peer_cap_enhe(from
, afi
, safi
)
3282 || (nh_afi
== AFI_IP6
)) {
3284 * Likely this is the case when an IPv4 prefix was
3285 * received with Extended Next-hop capability in this
3286 * or another vrf and is now being advertised to
3287 * non-ENHE peers. Since peer_cap_enhe only checks
3288 * peers in this vrf, also check the nh_afi to catch
3289 * the case where the originator was in another vrf.
3290 * Setting the mandatory (ipv4) next-hop attribute here
3291 * to enable implicit next-hop self with correct A-F
3292 * (ipv4 address family).
3294 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3295 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3296 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3299 stream_put_ipv4(s
, 0);
3303 /* MED attribute. */
3304 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3305 || bgp
->maxmed_active
) {
3306 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3307 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3309 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3313 /* Local preference. */
3314 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3315 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3316 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3318 stream_putl(s
, attr
->local_pref
);
3321 /* Atomic aggregate. */
3322 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3323 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3324 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3329 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3330 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3331 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3332 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3335 /* AS4 capable peer */
3337 stream_putl(s
, attr
->aggregator_as
);
3339 /* 2-byte AS peer */
3342 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3344 if (attr
->aggregator_as
> 65535) {
3345 stream_putw(s
, BGP_AS_TRANS
);
3347 /* we have to send AS4_AGGREGATOR, too.
3348 * we'll do that later in order to send
3349 * attributes in ascending
3352 send_as4_aggregator
= 1;
3354 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3356 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3359 /* Community attribute. */
3360 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3361 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3362 if (attr
->community
->size
* 4 > 255) {
3364 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3365 | BGP_ATTR_FLAG_EXTLEN
);
3366 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3367 stream_putw(s
, attr
->community
->size
* 4);
3370 BGP_ATTR_FLAG_OPTIONAL
3371 | BGP_ATTR_FLAG_TRANS
);
3372 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3373 stream_putc(s
, attr
->community
->size
* 4);
3375 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3379 * Large Community attribute.
3381 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3382 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3383 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3384 if (lcom_length(attr
->lcommunity
) > 255) {
3386 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3387 | BGP_ATTR_FLAG_EXTLEN
);
3388 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3389 stream_putw(s
, lcom_length(attr
->lcommunity
));
3392 BGP_ATTR_FLAG_OPTIONAL
3393 | BGP_ATTR_FLAG_TRANS
);
3394 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3395 stream_putc(s
, lcom_length(attr
->lcommunity
));
3397 stream_put(s
, attr
->lcommunity
->val
,
3398 lcom_length(attr
->lcommunity
));
3401 /* Route Reflector. */
3402 if (peer
->sort
== BGP_PEER_IBGP
&& from
3403 && from
->sort
== BGP_PEER_IBGP
) {
3404 /* Originator ID. */
3405 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3406 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3409 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3410 stream_put_in_addr(s
, &attr
->originator_id
);
3412 stream_put_in_addr(s
, &from
->remote_id
);
3415 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3416 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3418 if (attr
->cluster
) {
3419 stream_putc(s
, attr
->cluster
->length
+ 4);
3420 /* If this peer configuration's parent BGP has
3422 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3423 stream_put_in_addr(s
, &bgp
->cluster_id
);
3425 stream_put_in_addr(s
, &bgp
->router_id
);
3426 stream_put(s
, attr
->cluster
->list
,
3427 attr
->cluster
->length
);
3430 /* If this peer configuration's parent BGP has
3432 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3433 stream_put_in_addr(s
, &bgp
->cluster_id
);
3435 stream_put_in_addr(s
, &bgp
->router_id
);
3439 /* Extended Communities attribute. */
3440 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3441 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3442 if (peer
->sort
== BGP_PEER_IBGP
3443 || peer
->sort
== BGP_PEER_CONFED
) {
3444 if (attr
->ecommunity
->size
* 8 > 255) {
3446 BGP_ATTR_FLAG_OPTIONAL
3447 | BGP_ATTR_FLAG_TRANS
3448 | BGP_ATTR_FLAG_EXTLEN
);
3449 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3450 stream_putw(s
, attr
->ecommunity
->size
* 8);
3453 BGP_ATTR_FLAG_OPTIONAL
3454 | BGP_ATTR_FLAG_TRANS
);
3455 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3456 stream_putc(s
, attr
->ecommunity
->size
* 8);
3458 stream_put(s
, attr
->ecommunity
->val
,
3459 attr
->ecommunity
->size
* 8);
3463 int ecom_tr_size
= 0;
3466 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3467 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3470 if (CHECK_FLAG(tbit
,
3471 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3478 if (ecom_tr_size
* 8 > 255) {
3481 BGP_ATTR_FLAG_OPTIONAL
3482 | BGP_ATTR_FLAG_TRANS
3483 | BGP_ATTR_FLAG_EXTLEN
);
3485 BGP_ATTR_EXT_COMMUNITIES
);
3486 stream_putw(s
, ecom_tr_size
* 8);
3490 BGP_ATTR_FLAG_OPTIONAL
3491 | BGP_ATTR_FLAG_TRANS
);
3493 BGP_ATTR_EXT_COMMUNITIES
);
3494 stream_putc(s
, ecom_tr_size
* 8);
3497 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3498 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3503 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3506 stream_put(s
, pnt
, 8);
3512 /* Label index attribute. */
3513 if (safi
== SAFI_LABELED_UNICAST
) {
3514 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3515 uint32_t label_index
;
3517 label_index
= attr
->label_index
;
3519 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
3521 BGP_ATTR_FLAG_OPTIONAL
3522 | BGP_ATTR_FLAG_TRANS
);
3523 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3525 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3527 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3528 stream_putc(s
, 0); // reserved
3529 stream_putw(s
, 0); // flags
3530 stream_putl(s
, label_index
);
3535 if (send_as4_path
) {
3536 /* If the peer is NOT As4 capable, AND */
3537 /* there are ASnums > 65535 in path THEN
3538 * give out AS4_PATH */
3540 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3542 * Hm, I wonder... confederation things *should* only be at
3543 * the beginning of an aspath, right? Then we should use
3544 * aspath_delete_confed_seq for this, because it is already
3546 * Folks, talk to me: what is reasonable here!?
3548 aspath
= aspath_delete_confed_seq(aspath
);
3551 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3552 | BGP_ATTR_FLAG_EXTLEN
);
3553 stream_putc(s
, BGP_ATTR_AS4_PATH
);
3554 aspath_sizep
= stream_get_endp(s
);
3556 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
3559 if (aspath
!= attr
->aspath
)
3560 aspath_free(aspath
);
3562 if (send_as4_aggregator
) {
3563 /* send AS4_AGGREGATOR, at this place */
3564 /* this section of code moved here in order to ensure the
3566 * *ascending* order of attributes
3568 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3569 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
3571 stream_putl(s
, attr
->aggregator_as
);
3572 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3575 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3576 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3577 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
3578 /* Tunnel Encap attribute */
3579 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3581 #if ENABLE_BGP_VNC_ATTR
3583 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3588 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
3589 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3590 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
3591 stream_putc(s
, 9); // Length
3592 stream_putc(s
, 0); // Flags
3593 stream_putc(s
, attr
->pmsi_tnl_type
);
3594 stream_put(s
, &(attr
->label
),
3595 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
3596 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3597 // Unicast tunnel endpoint IP address
3600 /* Unknown transit attribute. */
3602 stream_put(s
, attr
->transit
->val
, attr
->transit
->length
);
3604 /* Return total size of attribute. */
3605 return stream_get_endp(s
) - cp
;
3608 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
3610 unsigned long attrlen_pnt
;
3612 iana_safi_t pkt_safi
;
3614 /* Set extended bit always to encode the attribute length as 2 bytes */
3615 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3616 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
3618 attrlen_pnt
= stream_get_endp(s
);
3619 stream_putw(s
, 0); /* Length of this attribute. */
3621 /* Convert AFI, SAFI to values for packet. */
3622 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3624 stream_putw(s
, pkt_afi
);
3625 stream_putc(s
, pkt_safi
);
3630 void bgp_packet_mpunreach_prefix(struct stream
*s
, struct prefix
*p
, afi_t afi
,
3631 safi_t safi
, struct prefix_rd
*prd
,
3632 mpls_label_t
*label
, uint32_t num_labels
,
3633 int addpath_encode
, uint32_t addpath_tx_id
,
3636 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
3638 if (safi
== SAFI_LABELED_UNICAST
) {
3639 label
= (mpls_label_t
*)wlabel
;
3643 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
3644 addpath_encode
, addpath_tx_id
, attr
);
3647 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
3649 bgp_packet_mpattr_end(s
, attrlen_pnt
);
3652 /* Initialization of attribute. */
3653 void bgp_attr_init(void)
3665 void bgp_attr_finish(void)
3670 ecommunity_finish();
3671 lcommunity_finish();
3677 /* Make attribute packet. */
3678 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
3679 struct prefix
*prefix
)
3684 struct aspath
*aspath
;
3685 int addpath_encode
= 0;
3686 uint32_t addpath_tx_id
= 0;
3688 /* Remember current pointer. */
3689 cp
= stream_get_endp(s
);
3691 /* Place holder of length. */
3694 /* Origin attribute. */
3695 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3696 stream_putc(s
, BGP_ATTR_ORIGIN
);
3698 stream_putc(s
, attr
->origin
);
3700 aspath
= attr
->aspath
;
3702 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3703 stream_putc(s
, BGP_ATTR_AS_PATH
);
3704 aspath_lenp
= stream_get_endp(s
);
3707 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
3709 /* Nexthop attribute. */
3710 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3711 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
3712 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3713 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3715 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3718 /* MED attribute. */
3719 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
3720 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3721 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3723 stream_putl(s
, attr
->med
);
3726 /* Local preference. */
3727 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
3728 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3729 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3731 stream_putl(s
, attr
->local_pref
);
3734 /* Atomic aggregate. */
3735 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3736 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3737 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3742 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3743 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3744 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3746 stream_putl(s
, attr
->aggregator_as
);
3747 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3750 /* Community attribute. */
3751 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3752 if (attr
->community
->size
* 4 > 255) {
3754 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3755 | BGP_ATTR_FLAG_EXTLEN
);
3756 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3757 stream_putw(s
, attr
->community
->size
* 4);
3760 BGP_ATTR_FLAG_OPTIONAL
3761 | BGP_ATTR_FLAG_TRANS
);
3762 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3763 stream_putc(s
, attr
->community
->size
* 4);
3765 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3768 /* Large Community attribute. */
3769 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
3770 if (lcom_length(attr
->lcommunity
) > 255) {
3772 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3773 | BGP_ATTR_FLAG_EXTLEN
);
3774 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3775 stream_putw(s
, lcom_length(attr
->lcommunity
));
3778 BGP_ATTR_FLAG_OPTIONAL
3779 | BGP_ATTR_FLAG_TRANS
);
3780 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3781 stream_putc(s
, lcom_length(attr
->lcommunity
));
3784 stream_put(s
, attr
->lcommunity
->val
,
3785 lcom_length(attr
->lcommunity
));
3788 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3789 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
3790 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
3791 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
3794 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3795 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3796 sizep
= stream_get_endp(s
);
3799 stream_putc(s
, 0); /* Marker: Attribute length. */
3800 stream_putw(s
, AFI_IP6
); /* AFI */
3801 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3804 stream_putc(s
, attr
->mp_nexthop_len
);
3805 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3806 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3807 stream_put(s
, &attr
->mp_nexthop_local
,
3814 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
3817 /* Set MP attribute length. */
3818 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
3822 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3823 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
3825 BGP_ATTR_FLAG_OPTIONAL
3826 | BGP_ATTR_FLAG_TRANS
);
3827 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3829 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3830 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3831 stream_putc(s
, 0); // reserved
3832 stream_putw(s
, 0); // flags
3833 stream_putl(s
, attr
->label_index
);
3837 /* Return total size of attribute. */
3838 len
= stream_get_endp(s
) - cp
- 2;
3839 stream_putw_at(s
, cp
, len
);