1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP attributes management routines.
3 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
23 #include "bgpd/bgpd.h"
24 #include "bgpd/bgp_attr.h"
25 #include "bgpd/bgp_route.h"
26 #include "bgpd/bgp_aspath.h"
27 #include "bgpd/bgp_community.h"
28 #include "bgpd/bgp_debug.h"
29 #include "bgpd/bgp_errors.h"
30 #include "bgpd/bgp_label.h"
31 #include "bgpd/bgp_packet.h"
32 #include "bgpd/bgp_ecommunity.h"
33 #include "bgpd/bgp_lcommunity.h"
34 #include "bgpd/bgp_updgrp.h"
35 #include "bgpd/bgp_encap_types.h"
37 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
38 #include "bgp_encap_types.h"
39 #include "bgp_vnc_types.h"
42 #include "bgp_flowspec_private.h"
45 /* Attribute strings for logging. */
46 static const struct message attr_str
[] = {
47 {BGP_ATTR_ORIGIN
, "ORIGIN"},
48 {BGP_ATTR_AS_PATH
, "AS_PATH"},
49 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
50 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
51 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
52 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
53 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
54 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
55 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
56 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
57 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
58 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
59 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
60 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
61 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
62 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
63 {BGP_ATTR_ENCAP
, "ENCAP"},
64 {BGP_ATTR_OTC
, "OTC"},
65 #ifdef ENABLE_BGP_VNC_ATTR
66 {BGP_ATTR_VNC
, "VNC"},
68 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
69 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
70 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
71 {BGP_ATTR_AIGP
, "AIGP"},
74 static const struct message attr_flag_str
[] = {
75 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
76 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
77 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
78 /* bgp_attr_flags_diagnose() relies on this bit being last in
80 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
83 static struct hash
*cluster_hash
;
85 static void *cluster_hash_alloc(void *p
)
87 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
88 struct cluster_list
*cluster
;
90 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
91 cluster
->length
= val
->length
;
93 if (cluster
->length
) {
94 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
95 memcpy(cluster
->list
, val
->list
, val
->length
);
104 /* Cluster list related functions. */
105 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
107 struct cluster_list tmp
= {};
108 struct cluster_list
*cluster
;
111 tmp
.list
= length
== 0 ? NULL
: pnt
;
113 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
118 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
122 for (i
= 0; i
< cluster
->length
/ 4; i
++)
123 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
128 static unsigned int cluster_hash_key_make(const void *p
)
130 const struct cluster_list
*cluster
= p
;
132 return jhash(cluster
->list
, cluster
->length
, 0);
135 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
137 const struct cluster_list
*cluster1
= p1
;
138 const struct cluster_list
*cluster2
= p2
;
140 if (cluster1
->list
== cluster2
->list
)
143 if (!cluster1
->list
|| !cluster2
->list
)
146 if (cluster1
->length
!= cluster2
->length
)
149 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
152 static void cluster_free(struct cluster_list
*cluster
)
154 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
155 XFREE(MTYPE_CLUSTER
, cluster
);
158 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
160 struct cluster_list
*find
;
162 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
168 static void cluster_unintern(struct cluster_list
**cluster
)
170 if ((*cluster
)->refcnt
)
171 (*cluster
)->refcnt
--;
173 if ((*cluster
)->refcnt
== 0) {
174 void *p
= hash_release(cluster_hash
, *cluster
);
175 assert(p
== *cluster
);
176 cluster_free(*cluster
);
181 static void cluster_init(void)
183 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
187 static void cluster_finish(void)
189 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
190 hash_free(cluster_hash
);
194 static struct hash
*encap_hash
= NULL
;
195 #ifdef ENABLE_BGP_VNC
196 static struct hash
*vnc_hash
= NULL
;
198 static struct hash
*srv6_l3vpn_hash
;
199 static struct hash
*srv6_vpn_hash
;
201 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
203 struct bgp_attr_encap_subtlv
*new;
204 struct bgp_attr_encap_subtlv
*tail
;
205 struct bgp_attr_encap_subtlv
*p
;
207 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
208 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
210 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
213 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
216 memcpy(tail
, p
, size
);
223 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
225 struct bgp_attr_encap_subtlv
*next
;
229 XFREE(MTYPE_ENCAP_TLV
, p
);
234 void bgp_attr_flush_encap(struct attr
*attr
)
239 if (attr
->encap_subtlvs
) {
240 encap_free(attr
->encap_subtlvs
);
241 attr
->encap_subtlvs
= NULL
;
243 #ifdef ENABLE_BGP_VNC
244 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
245 bgp_attr_get_vnc_subtlvs(attr
);
248 encap_free(vnc_subtlvs
);
249 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
255 * Compare encap sub-tlv chains
260 * This algorithm could be made faster if needed
262 static bool 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. */
308 #ifdef ENABLE_BGP_VNC
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
;
318 #ifdef ENABLE_BGP_VNC
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
;
340 #ifdef ENABLE_BGP_VNC
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
,
367 #ifdef ENABLE_BGP_VNC
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
);
378 #ifdef ENABLE_BGP_VNC
379 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
385 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
394 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
395 bgp_attr_get_evpn_overlay(a2
));
398 /* Unknown transit attribute. */
399 static struct hash
*transit_hash
;
401 static void transit_free(struct transit
*transit
)
403 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
404 XFREE(MTYPE_TRANSIT
, transit
);
407 static void *transit_hash_alloc(void *p
)
409 /* Transit structure is already allocated. */
413 static struct transit
*transit_intern(struct transit
*transit
)
415 struct transit
*find
;
417 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
419 transit_free(transit
);
425 static void transit_unintern(struct transit
**transit
)
427 if ((*transit
)->refcnt
)
428 (*transit
)->refcnt
--;
430 if ((*transit
)->refcnt
== 0) {
431 hash_release(transit_hash
, *transit
);
432 transit_free(*transit
);
437 static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt
, int length
,
446 ptr_get_be16(data
+ 1, &tlv_length
);
449 /* The value field of the AIGP TLV is always 8 octets
450 * long and its value is interpreted as an unsigned 64-bit
453 if (tlv_type
== BGP_AIGP_TLV_METRIC
) {
454 (void)ptr_get_be64(data
+ 3, aigp
);
456 /* If an AIGP attribute is received and its first AIGP
457 * TLV contains the maximum value 0xffffffffffffffff,
458 * the attribute SHOULD be considered to be malformed
459 * and SHOULD be discarded as specified in this section.
461 if (*aigp
== BGP_AIGP_TLV_METRIC_MAX
) {
462 zlog_err("Bad AIGP TLV (%s) length: %llu",
463 BGP_AIGP_TLV_METRIC_DESC
,
464 BGP_AIGP_TLV_METRIC_MAX
);
472 length
-= tlv_length
;
478 static uint64_t bgp_aigp_metric_total(struct bgp_path_info
*bpi
)
480 uint64_t aigp
= bgp_attr_get_aigp_metric(bpi
->attr
);
483 return aigp
+ bpi
->nexthop
->metric
;
488 static void stream_put_bgp_aigp_tlv_metric(struct stream
*s
,
489 struct bgp_path_info
*bpi
)
491 stream_putc(s
, BGP_AIGP_TLV_METRIC
);
492 stream_putw(s
, BGP_AIGP_TLV_METRIC_LEN
);
493 stream_putq(s
, bgp_aigp_metric_total(bpi
));
496 static bool bgp_attr_aigp_valid(uint8_t *pnt
, int length
)
503 zlog_err("Bad AIGP attribute length (MUST be minimum 3): %u",
510 ptr_get_be16(data
+ 1, &tlv_length
);
513 if (length
< tlv_length
) {
515 "Bad AIGP attribute length: %u, but TLV length: %u",
520 if (tlv_length
< 3) {
521 zlog_err("Bad AIGP TLV length (MUST be minimum 3): %u",
526 /* AIGP TLV, Length: 11 */
527 if (tlv_type
== BGP_AIGP_TLV_METRIC
&&
528 tlv_length
!= BGP_AIGP_TLV_METRIC_LEN
) {
529 zlog_err("Bad AIGP TLV (%s) length: %u",
530 BGP_AIGP_TLV_METRIC_DESC
, tlv_length
);
535 length
-= tlv_length
;
541 static void *srv6_l3vpn_hash_alloc(void *p
)
546 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
548 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
551 static struct bgp_attr_srv6_l3vpn
*
552 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
554 struct bgp_attr_srv6_l3vpn
*find
;
556 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
558 srv6_l3vpn_free(l3vpn
);
563 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
565 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
570 if (l3vpn
->refcnt
== 0) {
571 hash_release(srv6_l3vpn_hash
, l3vpn
);
572 srv6_l3vpn_free(l3vpn
);
577 static void *srv6_vpn_hash_alloc(void *p
)
582 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
584 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
587 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
589 struct bgp_attr_srv6_vpn
*find
;
591 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
598 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
600 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
605 if (vpn
->refcnt
== 0) {
606 hash_release(srv6_vpn_hash
, vpn
);
612 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
614 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
617 key
= jhash(&l3vpn
->sid
, 16, key
);
618 key
= jhash_1word(l3vpn
->sid_flags
, key
);
619 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
620 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
621 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
622 key
= jhash_1word(l3vpn
->func_len
, key
);
623 key
= jhash_1word(l3vpn
->arg_len
, key
);
624 key
= jhash_1word(l3vpn
->transposition_len
, key
);
625 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
629 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
631 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
632 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
634 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
635 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
636 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
637 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
638 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
639 && l3vpn1
->func_len
== l3vpn2
->func_len
640 && l3vpn1
->arg_len
== l3vpn2
->arg_len
641 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
642 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
645 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
646 const struct bgp_attr_srv6_l3vpn
*h2
)
650 else if (h1
== NULL
|| h2
== NULL
)
653 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
656 static unsigned int srv6_vpn_hash_key_make(const void *p
)
658 const struct bgp_attr_srv6_vpn
*vpn
= p
;
661 key
= jhash(&vpn
->sid
, 16, key
);
662 key
= jhash_1word(vpn
->sid_flags
, key
);
666 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
668 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
669 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
671 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
672 && vpn1
->sid_flags
== vpn2
->sid_flags
;
675 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
676 const struct bgp_attr_srv6_vpn
*h2
)
680 else if (h1
== NULL
|| h2
== NULL
)
683 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
686 static void srv6_init(void)
689 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
690 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
691 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
692 "BGP Prefix-SID SRv6-VPN-Service-TLV");
695 static void srv6_finish(void)
697 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
698 hash_free(srv6_l3vpn_hash
);
699 srv6_l3vpn_hash
= NULL
;
700 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
701 hash_free(srv6_vpn_hash
);
702 srv6_vpn_hash
= NULL
;
705 static unsigned int transit_hash_key_make(const void *p
)
707 const struct transit
*transit
= p
;
709 return jhash(transit
->val
, transit
->length
, 0);
712 static bool transit_hash_cmp(const void *p1
, const void *p2
)
714 const struct transit
*transit1
= p1
;
715 const struct transit
*transit2
= p2
;
717 return (transit1
->length
== transit2
->length
718 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
721 static void transit_init(void)
723 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
727 static void transit_finish(void)
729 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
730 hash_free(transit_hash
);
734 /* Attribute hash routines. */
735 static struct hash
*attrhash
;
737 unsigned long int attr_count(void)
739 return attrhash
->count
;
742 unsigned long int attr_unknown_count(void)
744 return transit_hash
->count
;
747 unsigned int attrhash_key_make(const void *p
)
749 const struct attr
*attr
= (struct attr
*)p
;
751 #define MIX(val) key = jhash_1word(val, key)
752 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
754 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
755 MIX3(attr
->local_pref
, attr
->aggregator_as
,
756 attr
->aggregator_addr
.s_addr
);
757 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
758 attr
->originator_id
.s_addr
);
759 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
762 MIX(aspath_key_make(attr
->aspath
));
763 if (bgp_attr_get_community(attr
))
764 MIX(community_hash_make(bgp_attr_get_community(attr
)));
765 if (bgp_attr_get_lcommunity(attr
))
766 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
767 if (bgp_attr_get_ecommunity(attr
))
768 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
769 if (bgp_attr_get_ipv6_ecommunity(attr
))
770 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
771 if (bgp_attr_get_cluster(attr
))
772 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
773 if (bgp_attr_get_transit(attr
))
774 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
775 if (attr
->encap_subtlvs
)
776 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
777 if (attr
->srv6_l3vpn
)
778 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
780 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
781 #ifdef ENABLE_BGP_VNC
782 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
783 bgp_attr_get_vnc_subtlvs(attr
);
785 MIX(encap_hash_key_make(vnc_subtlvs
));
787 MIX(attr
->mp_nexthop_len
);
788 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
789 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
790 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
791 MIX(attr
->rmap_table_id
);
795 MIX(bgp_attr_get_aigp_metric(attr
));
800 bool attrhash_cmp(const void *p1
, const void *p2
)
802 const struct attr
*attr1
= p1
;
803 const struct attr
*attr2
= p2
;
805 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
806 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
807 && attr1
->aspath
== attr2
->aspath
808 && bgp_attr_get_community(attr1
)
809 == bgp_attr_get_community(attr2
)
810 && attr1
->med
== attr2
->med
811 && attr1
->local_pref
== attr2
->local_pref
812 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
813 if (attr1
->aggregator_as
== attr2
->aggregator_as
814 && attr1
->aggregator_addr
.s_addr
815 == attr2
->aggregator_addr
.s_addr
816 && attr1
->weight
== attr2
->weight
817 && attr1
->tag
== attr2
->tag
818 && attr1
->label_index
== attr2
->label_index
819 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
820 && bgp_attr_get_ecommunity(attr1
)
821 == bgp_attr_get_ecommunity(attr2
)
822 && bgp_attr_get_ipv6_ecommunity(attr1
)
823 == bgp_attr_get_ipv6_ecommunity(attr2
)
824 && bgp_attr_get_lcommunity(attr1
)
825 == bgp_attr_get_lcommunity(attr2
)
826 && bgp_attr_get_cluster(attr1
)
827 == bgp_attr_get_cluster(attr2
)
828 && bgp_attr_get_transit(attr1
)
829 == bgp_attr_get_transit(attr2
)
830 && bgp_attr_get_aigp_metric(attr1
)
831 == bgp_attr_get_aigp_metric(attr2
)
832 && attr1
->rmap_table_id
== attr2
->rmap_table_id
833 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
834 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
835 #ifdef ENABLE_BGP_VNC
836 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
837 bgp_attr_get_vnc_subtlvs(attr2
))
839 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
840 &attr2
->mp_nexthop_global
)
841 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
842 &attr2
->mp_nexthop_local
)
843 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
844 &attr2
->mp_nexthop_global_in
)
845 && IPV4_ADDR_SAME(&attr1
->originator_id
,
846 &attr2
->originator_id
)
847 && overlay_index_same(attr1
, attr2
)
848 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
849 && attr1
->es_flags
== attr2
->es_flags
850 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
851 && attr1
->df_pref
== attr2
->df_pref
852 && attr1
->df_alg
== attr2
->df_alg
853 && attr1
->nh_ifindex
== attr2
->nh_ifindex
854 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
855 && attr1
->distance
== attr2
->distance
856 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
857 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
858 && attr1
->srte_color
== attr2
->srte_color
859 && attr1
->nh_type
== attr2
->nh_type
860 && attr1
->bh_type
== attr2
->bh_type
861 && attr1
->otc
== attr2
->otc
)
868 static void attrhash_init(void)
871 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
875 * special for hash_clean below
877 static void attr_vfree(void *attr
)
879 XFREE(MTYPE_ATTR
, attr
);
882 static void attrhash_finish(void)
884 hash_clean(attrhash
, attr_vfree
);
889 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
891 struct attr
*attr
= bucket
->data
;
892 struct in6_addr
*sid
= NULL
;
894 if (attr
->srv6_l3vpn
)
895 sid
= &attr
->srv6_l3vpn
->sid
;
896 else if (attr
->srv6_vpn
)
897 sid
= &attr
->srv6_vpn
->sid
;
899 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
903 " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6\n",
904 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
905 attr
->origin
, attr
->weight
, attr
->label
, sid
);
908 void attr_show_all(struct vty
*vty
)
910 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
911 void *))attr_show_all_iterator
,
915 static void *bgp_attr_hash_alloc(void *p
)
917 struct attr
*val
= (struct attr
*)p
;
920 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
922 if (val
->encap_subtlvs
) {
923 val
->encap_subtlvs
= NULL
;
925 #ifdef ENABLE_BGP_VNC
926 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
927 bgp_attr_get_vnc_subtlvs(val
);
930 bgp_attr_set_vnc_subtlvs(val
, NULL
);
937 /* Internet argument attribute. */
938 struct attr
*bgp_attr_intern(struct attr
*attr
)
941 struct ecommunity
*ecomm
= NULL
;
942 struct ecommunity
*ipv6_ecomm
= NULL
;
943 struct lcommunity
*lcomm
= NULL
;
944 struct community
*comm
= NULL
;
946 /* Intern referenced structure. */
948 if (!attr
->aspath
->refcnt
)
949 attr
->aspath
= aspath_intern(attr
->aspath
);
951 attr
->aspath
->refcnt
++;
954 comm
= bgp_attr_get_community(attr
);
957 bgp_attr_set_community(attr
, community_intern(comm
));
962 ecomm
= bgp_attr_get_ecommunity(attr
);
965 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
970 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
972 if (!ipv6_ecomm
->refcnt
)
973 bgp_attr_set_ipv6_ecommunity(
974 attr
, ecommunity_intern(ipv6_ecomm
));
976 ipv6_ecomm
->refcnt
++;
979 lcomm
= bgp_attr_get_lcommunity(attr
);
982 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
987 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
990 if (!cluster
->refcnt
)
991 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
996 struct transit
*transit
= bgp_attr_get_transit(attr
);
999 if (!transit
->refcnt
)
1000 bgp_attr_set_transit(attr
, transit_intern(transit
));
1004 if (attr
->encap_subtlvs
) {
1005 if (!attr
->encap_subtlvs
->refcnt
)
1006 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
1009 attr
->encap_subtlvs
->refcnt
++;
1011 if (attr
->srv6_l3vpn
) {
1012 if (!attr
->srv6_l3vpn
->refcnt
)
1013 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
1015 attr
->srv6_l3vpn
->refcnt
++;
1017 if (attr
->srv6_vpn
) {
1018 if (!attr
->srv6_vpn
->refcnt
)
1019 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
1021 attr
->srv6_vpn
->refcnt
++;
1023 #ifdef ENABLE_BGP_VNC
1024 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1025 bgp_attr_get_vnc_subtlvs(attr
);
1028 if (!vnc_subtlvs
->refcnt
)
1029 bgp_attr_set_vnc_subtlvs(
1031 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
1033 vnc_subtlvs
->refcnt
++;
1037 /* At this point, attr only contains intern'd pointers. that means
1038 * if we find it in attrhash, it has all the same pointers and we
1039 * correctly updated the refcounts on these.
1040 * If we don't find it, we need to allocate a one because in all
1041 * cases this returns a new reference to a hashed attr, but the input
1042 * wasn't on hash. */
1043 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
1049 /* Make network statement's attribute. */
1050 struct attr
*bgp_attr_default_set(struct attr
*attr
, struct bgp
*bgp
,
1053 memset(attr
, 0, sizeof(struct attr
));
1055 attr
->origin
= origin
;
1056 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1057 attr
->aspath
= aspath_empty(bgp
->asnotation
);
1058 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1059 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1061 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
1062 attr
->label
= MPLS_INVALID_LABEL
;
1063 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1064 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1065 attr
->local_pref
= bgp
->default_local_pref
;
1070 /* Create the attributes for an aggregate */
1071 struct attr
*bgp_attr_aggregate_intern(
1072 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
1073 struct community
*community
, struct ecommunity
*ecommunity
,
1074 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
1075 uint8_t atomic_aggregate
, const struct prefix
*p
)
1079 route_map_result_t ret
;
1081 memset(&attr
, 0, sizeof(attr
));
1083 /* Origin attribute. */
1084 attr
.origin
= origin
;
1085 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1089 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1091 /* AS path attribute. */
1093 attr
.aspath
= aspath_intern(aspath
);
1095 attr
.aspath
= aspath_empty(bgp
->asnotation
);
1096 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1098 /* Next hop attribute. */
1099 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1102 uint32_t gshut
= COMMUNITY_GSHUT
;
1104 /* If we are not shutting down ourselves and we are
1105 * aggregating a route that contains the GSHUT community we
1106 * need to remove that community when creating the aggregate */
1107 if (!bgp_in_graceful_shutdown(bgp
)
1108 && community_include(community
, gshut
)) {
1109 community_del_val(community
, &gshut
);
1112 bgp_attr_set_community(&attr
, community
);
1116 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1119 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1121 if (bgp_in_graceful_shutdown(bgp
))
1122 bgp_attr_add_gshut_community(&attr
);
1124 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1125 attr
.label
= MPLS_INVALID_LABEL
;
1126 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1127 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1128 if (!aggregate
->as_set
|| atomic_aggregate
)
1129 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1130 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1131 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1132 attr
.aggregator_as
= bgp
->confed_id
;
1134 attr
.aggregator_as
= bgp
->as
;
1135 attr
.aggregator_addr
= bgp
->router_id
;
1137 /* Apply route-map */
1138 if (aggregate
->rmap
.name
) {
1139 struct attr attr_tmp
= attr
;
1140 struct bgp_path_info rmap_path
;
1142 memset(&rmap_path
, 0, sizeof(rmap_path
));
1143 rmap_path
.peer
= bgp
->peer_self
;
1144 rmap_path
.attr
= &attr_tmp
;
1146 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1148 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1150 bgp
->peer_self
->rmap_type
= 0;
1152 if (ret
== RMAP_DENYMATCH
) {
1153 /* Free uninterned attribute. */
1154 bgp_attr_flush(&attr_tmp
);
1156 /* Unintern original. */
1157 aspath_unintern(&attr
.aspath
);
1161 if (bgp_in_graceful_shutdown(bgp
))
1162 bgp_attr_add_gshut_community(&attr_tmp
);
1164 new = bgp_attr_intern(&attr_tmp
);
1167 if (bgp_in_graceful_shutdown(bgp
))
1168 bgp_attr_add_gshut_community(&attr
);
1170 new = bgp_attr_intern(&attr
);
1173 /* Always release the 'intern()'ed AS Path. */
1174 aspath_unintern(&attr
.aspath
);
1179 /* Unintern just the sub-components of the attr, but not the attr */
1180 void bgp_attr_unintern_sub(struct attr
*attr
)
1182 struct ecommunity
*ecomm
= NULL
;
1183 struct ecommunity
*ipv6_ecomm
= NULL
;
1184 struct cluster_list
*cluster
;
1185 struct lcommunity
*lcomm
= NULL
;
1186 struct community
*comm
= NULL
;
1188 /* aspath refcount shoud be decrement. */
1189 aspath_unintern(&attr
->aspath
);
1190 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1192 comm
= bgp_attr_get_community(attr
);
1193 community_unintern(&comm
);
1194 bgp_attr_set_community(attr
, NULL
);
1196 ecomm
= bgp_attr_get_ecommunity(attr
);
1197 ecommunity_unintern(&ecomm
);
1198 bgp_attr_set_ecommunity(attr
, NULL
);
1200 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1201 ecommunity_unintern(&ipv6_ecomm
);
1202 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1204 lcomm
= bgp_attr_get_lcommunity(attr
);
1205 lcommunity_unintern(&lcomm
);
1206 bgp_attr_set_lcommunity(attr
, NULL
);
1208 cluster
= bgp_attr_get_cluster(attr
);
1210 cluster_unintern(&cluster
);
1211 bgp_attr_set_cluster(attr
, cluster
);
1213 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1215 struct transit
*transit
= bgp_attr_get_transit(attr
);
1218 transit_unintern(&transit
);
1219 bgp_attr_set_transit(attr
, transit
);
1222 if (attr
->encap_subtlvs
)
1223 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1225 #ifdef ENABLE_BGP_VNC
1226 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1227 bgp_attr_get_vnc_subtlvs(attr
);
1230 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1231 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1235 if (attr
->srv6_l3vpn
)
1236 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1239 srv6_vpn_unintern(&attr
->srv6_vpn
);
1242 /* Free bgp attribute and aspath. */
1243 void bgp_attr_unintern(struct attr
**pattr
)
1245 struct attr
*attr
= *pattr
;
1249 /* Decrement attribute reference. */
1254 /* If reference becomes zero then free attribute object. */
1255 if (attr
->refcnt
== 0) {
1256 ret
= hash_release(attrhash
, attr
);
1257 assert(ret
!= NULL
);
1258 XFREE(MTYPE_ATTR
, attr
);
1262 bgp_attr_unintern_sub(&tmp
);
1265 void bgp_attr_flush(struct attr
*attr
)
1267 struct ecommunity
*ecomm
;
1268 struct ecommunity
*ipv6_ecomm
;
1269 struct cluster_list
*cluster
;
1270 struct lcommunity
*lcomm
;
1271 struct community
*comm
;
1273 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1274 aspath_free(attr
->aspath
);
1275 attr
->aspath
= NULL
;
1277 comm
= bgp_attr_get_community(attr
);
1278 if (comm
&& !comm
->refcnt
)
1279 community_free(&comm
);
1280 bgp_attr_set_community(attr
, NULL
);
1282 ecomm
= bgp_attr_get_ecommunity(attr
);
1283 if (ecomm
&& !ecomm
->refcnt
)
1284 ecommunity_free(&ecomm
);
1285 bgp_attr_set_ecommunity(attr
, NULL
);
1287 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1288 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1289 ecommunity_free(&ipv6_ecomm
);
1290 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1292 lcomm
= bgp_attr_get_lcommunity(attr
);
1293 if (lcomm
&& !lcomm
->refcnt
)
1294 lcommunity_free(&lcomm
);
1295 bgp_attr_set_lcommunity(attr
, NULL
);
1297 cluster
= bgp_attr_get_cluster(attr
);
1298 if (cluster
&& !cluster
->refcnt
) {
1299 cluster_free(cluster
);
1300 bgp_attr_set_cluster(attr
, NULL
);
1303 struct transit
*transit
= bgp_attr_get_transit(attr
);
1305 if (transit
&& !transit
->refcnt
) {
1306 transit_free(transit
);
1307 bgp_attr_set_transit(attr
, NULL
);
1309 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1310 encap_free(attr
->encap_subtlvs
);
1311 attr
->encap_subtlvs
= NULL
;
1313 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1314 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1315 attr
->srv6_l3vpn
= NULL
;
1317 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1318 srv6_vpn_free(attr
->srv6_vpn
);
1319 attr
->srv6_vpn
= NULL
;
1321 #ifdef ENABLE_BGP_VNC
1322 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1323 bgp_attr_get_vnc_subtlvs(attr
);
1325 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1326 encap_free(vnc_subtlvs
);
1327 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1332 /* Implement draft-scudder-idr-optional-transitive behaviour and
1333 * avoid resetting sessions for malformed attributes which are
1334 * are partial/optional and hence where the error likely was not
1335 * introduced by the sending neighbour.
1337 static enum bgp_attr_parse_ret
1338 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1341 struct peer
*const peer
= args
->peer
;
1342 struct attr
*const attr
= args
->attr
;
1343 const uint8_t flags
= args
->flags
;
1344 /* startp and length must be special-cased, as whether or not to
1345 * send the attribute data with the NOTIFY depends on the error,
1346 * the caller therefore signals this with the seperate length argument
1348 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1350 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1351 char attr_str
[BUFSIZ
] = {0};
1353 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1355 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1358 /* Only relax error handling for eBGP peers */
1359 if (peer
->sort
!= BGP_PEER_EBGP
) {
1360 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1361 notify_datap
, length
);
1362 return BGP_ATTR_PARSE_ERROR
;
1365 /* Adjust the stream getp to the end of the attribute, in case we can
1366 * still proceed but the caller hasn't read all the attribute.
1368 stream_set_getp(BGP_INPUT(peer
),
1369 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1372 switch (args
->type
) {
1373 /* where an attribute is relatively inconsequential, e.g. it does not
1374 * affect route selection, and can be safely ignored, then any such
1375 * attributes which are malformed should just be ignored and the route
1376 * processed as normal.
1378 case BGP_ATTR_AS4_AGGREGATOR
:
1379 case BGP_ATTR_AGGREGATOR
:
1380 case BGP_ATTR_ATOMIC_AGGREGATE
:
1381 return BGP_ATTR_PARSE_PROCEED
;
1383 /* Core attributes, particularly ones which may influence route
1384 * selection, should be treat-as-withdraw.
1386 case BGP_ATTR_ORIGIN
:
1387 case BGP_ATTR_AS_PATH
:
1388 case BGP_ATTR_NEXT_HOP
:
1389 case BGP_ATTR_MULTI_EXIT_DISC
:
1390 case BGP_ATTR_LOCAL_PREF
:
1391 case BGP_ATTR_COMMUNITIES
:
1392 case BGP_ATTR_EXT_COMMUNITIES
:
1393 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1394 case BGP_ATTR_LARGE_COMMUNITIES
:
1395 case BGP_ATTR_ORIGINATOR_ID
:
1396 case BGP_ATTR_CLUSTER_LIST
:
1398 return BGP_ATTR_PARSE_WITHDRAW
;
1399 case BGP_ATTR_MP_REACH_NLRI
:
1400 case BGP_ATTR_MP_UNREACH_NLRI
:
1401 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1402 notify_datap
, length
);
1403 return BGP_ATTR_PARSE_ERROR
;
1406 /* Partial optional attributes that are malformed should not cause
1407 * the whole session to be reset. Instead treat it as a withdrawal
1408 * of the routes, if possible.
1410 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1411 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1412 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1413 return BGP_ATTR_PARSE_WITHDRAW
;
1415 /* default to reset */
1416 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1419 /* Find out what is wrong with the path attribute flag bits and log the error.
1420 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1421 Extended Length. Checking O/T/P bits at once implies, that the attribute
1422 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1423 non-transitive" attribute. */
1425 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1426 uint8_t desired_flags
/* how RFC says it must be */
1429 uint8_t seen
= 0, i
;
1430 uint8_t real_flags
= args
->flags
;
1431 const uint8_t attr_code
= args
->type
;
1433 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1434 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1435 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1436 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1437 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1438 flog_err(EC_BGP_ATTR_FLAG
,
1439 "%s attribute must%s be flagged as \"%s\"",
1440 lookup_msg(attr_str
, attr_code
, NULL
),
1441 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1444 attr_flag_str
[i
].str
);
1449 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1450 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1451 real_flags
, desired_flags
);
1455 /* Required flags for attributes. EXTLEN will be masked off when testing,
1456 * as will PARTIAL for optional+transitive attributes.
1458 const uint8_t attr_flags_values
[] = {
1459 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1460 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1461 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1462 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1463 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1464 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1465 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1466 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1467 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1468 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1469 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1470 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1471 [BGP_ATTR_EXT_COMMUNITIES
] =
1472 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1473 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1474 [BGP_ATTR_AS4_AGGREGATOR
] =
1475 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1476 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1477 [BGP_ATTR_LARGE_COMMUNITIES
] =
1478 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1479 [BGP_ATTR_OTC
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1480 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1481 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1482 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1483 [BGP_ATTR_AIGP
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1485 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1487 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1489 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1490 const uint8_t flags
= args
->flags
;
1491 const uint8_t attr_code
= args
->type
;
1493 /* there may be attributes we don't know about */
1494 if (attr_code
> attr_flags_values_max
)
1496 if (attr_flags_values
[attr_code
] == 0)
1499 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1503 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1504 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1507 "%s well-known attributes must have transitive flag set (%x)",
1508 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1512 /* "For well-known attributes and for optional non-transitive
1514 * the Partial bit MUST be set to 0."
1516 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1517 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1518 flog_err(EC_BGP_ATTR_FLAG
,
1519 "%s well-known attribute must NOT have the partial flag set (%x)",
1520 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1523 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1524 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1525 flog_err(EC_BGP_ATTR_FLAG
,
1526 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1527 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1532 /* Optional transitive attributes may go through speakers that don't
1533 * reocgnise them and set the Partial bit.
1535 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1536 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1537 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1539 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1542 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1546 /* Get origin attribute of the update message. */
1547 static enum bgp_attr_parse_ret
1548 bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1550 struct peer
*const peer
= args
->peer
;
1551 struct attr
*const attr
= args
->attr
;
1552 const bgp_size_t length
= args
->length
;
1554 /* If any recognized attribute has Attribute Length that conflicts
1555 with the expected length (based on the attribute type code), then
1556 the Error Subcode is set to Attribute Length Error. The Data
1557 field contains the erroneous attribute (type, length and
1560 flog_err(EC_BGP_ATTR_LEN
,
1561 "Origin attribute length is not one %d", length
);
1562 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1566 /* Fetch origin attribute. */
1567 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1569 /* If the ORIGIN attribute has an undefined value, then the Error
1570 Subcode is set to Invalid Origin Attribute. The Data field
1571 contains the unrecognized attribute (type, length and value). */
1572 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1573 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1574 flog_err(EC_BGP_ATTR_ORIGIN
,
1575 "Origin attribute value is invalid %d", attr
->origin
);
1576 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1580 /* Set oring attribute flag. */
1581 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1586 /* Parse AS path information. This function is wrapper of
1588 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1590 struct attr
*const attr
= args
->attr
;
1591 struct peer
*const peer
= args
->peer
;
1592 const bgp_size_t length
= args
->length
;
1593 enum asnotation_mode asnotation
;
1595 asnotation
= bgp_get_asnotation(
1596 args
->peer
&& args
->peer
->bgp
? args
->peer
->bgp
: NULL
);
1598 * peer with AS4 => will get 4Byte ASnums
1599 * otherwise, will get 16 Bit
1602 aspath_parse(peer
->curr
, length
,
1603 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
) &&
1604 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
),
1607 /* In case of IBGP, length will be zero. */
1608 if (!attr
->aspath
) {
1609 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1610 "Malformed AS path from %s, length is %d", peer
->host
,
1612 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1616 /* Conformant BGP speakers SHOULD NOT send BGP
1617 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1618 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1619 * withdraw" error handling behavior as per [RFC7606].
1621 if (peer
->bgp
&& peer
->bgp
->reject_as_sets
&&
1622 aspath_check_as_sets(attr
->aspath
)) {
1623 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1624 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1626 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1630 /* Set aspath attribute flag. */
1631 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1633 return BGP_ATTR_PARSE_PROCEED
;
1636 static enum bgp_attr_parse_ret
bgp_attr_aspath_check(struct peer
*const peer
,
1637 struct attr
*const attr
)
1639 /* These checks were part of bgp_attr_aspath, but with
1640 * as4 we should to check aspath things when
1641 * aspath synthesizing with as4_path has already taken place.
1642 * Otherwise we check ASPATH and use the synthesized thing, and that is
1644 * So do the checks later, i.e. here
1646 struct aspath
*aspath
;
1648 /* Confederation sanity check. */
1649 if ((peer
->sort
== BGP_PEER_CONFED
1650 && !aspath_left_confed_check(attr
->aspath
))
1651 || (peer
->sort
== BGP_PEER_EBGP
1652 && aspath_confed_check(attr
->aspath
))) {
1653 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1655 return BGP_ATTR_PARSE_WITHDRAW
;
1658 /* First AS check for EBGP. */
1659 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1660 if (peer
->sort
== BGP_PEER_EBGP
1661 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1662 flog_err(EC_BGP_ATTR_FIRST_AS
,
1663 "%s incorrect first AS (must be %u)",
1664 peer
->host
, peer
->as
);
1665 return BGP_ATTR_PARSE_WITHDRAW
;
1669 /* Codification of AS 0 Processing */
1670 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1672 EC_BGP_ATTR_MAL_AS_PATH
,
1673 "Malformed AS path, AS number is 0 in the path from %s",
1675 return BGP_ATTR_PARSE_WITHDRAW
;
1678 /* local-as prepend */
1679 if (peer
->change_local_as
1680 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1681 aspath
= aspath_dup(attr
->aspath
);
1682 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1683 aspath_unintern(&attr
->aspath
);
1684 attr
->aspath
= aspath_intern(aspath
);
1687 return BGP_ATTR_PARSE_PROCEED
;
1690 /* Parse AS4 path information. This function is another wrapper of
1692 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1693 struct aspath
**as4_path
)
1695 struct peer
*const peer
= args
->peer
;
1696 struct attr
*const attr
= args
->attr
;
1697 const bgp_size_t length
= args
->length
;
1698 enum asnotation_mode asnotation
;
1700 asnotation
= bgp_get_asnotation(peer
->bgp
);
1702 *as4_path
= aspath_parse(peer
->curr
, length
, 1, asnotation
);
1704 /* In case of IBGP, length will be zero. */
1706 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1707 "Malformed AS4 path from %s, length is %d", peer
->host
,
1709 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1713 /* Conformant BGP speakers SHOULD NOT send BGP
1714 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1715 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1716 * withdraw" error handling behavior as per [RFC7606].
1718 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1719 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1720 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1722 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1726 /* Set aspath attribute flag. */
1727 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1729 return BGP_ATTR_PARSE_PROCEED
;
1733 * Check that the nexthop attribute is valid.
1735 enum bgp_attr_parse_ret
bgp_attr_nexthop_valid(struct peer
*peer
,
1738 struct bgp
*bgp
= peer
->bgp
;
1740 if (ipv4_martian(&attr
->nexthop
) && !bgp
->allow_martian
) {
1741 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1743 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %pI4",
1745 data
[0] = BGP_ATTR_FLAG_TRANS
;
1746 data
[1] = BGP_ATTR_NEXT_HOP
;
1747 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1748 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1749 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1750 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1752 return BGP_ATTR_PARSE_ERROR
;
1755 return BGP_ATTR_PARSE_PROCEED
;
1758 /* Nexthop attribute. */
1759 static enum bgp_attr_parse_ret
1760 bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1762 struct peer
*const peer
= args
->peer
;
1763 struct attr
*const attr
= args
->attr
;
1764 const bgp_size_t length
= args
->length
;
1766 /* Check nexthop attribute length. */
1768 flog_err(EC_BGP_ATTR_LEN
,
1769 "Nexthop attribute length isn't four [%d]", length
);
1771 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1775 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1776 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1778 return BGP_ATTR_PARSE_PROCEED
;
1781 /* MED atrribute. */
1782 static enum bgp_attr_parse_ret
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1784 struct peer
*const peer
= args
->peer
;
1785 struct attr
*const attr
= args
->attr
;
1786 const bgp_size_t length
= args
->length
;
1790 flog_err(EC_BGP_ATTR_LEN
,
1791 "MED attribute length isn't four [%d]", length
);
1793 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1797 attr
->med
= stream_getl(peer
->curr
);
1799 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1801 return BGP_ATTR_PARSE_PROCEED
;
1804 /* Local preference attribute. */
1805 static enum bgp_attr_parse_ret
1806 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1808 struct peer
*const peer
= args
->peer
;
1809 struct attr
*const attr
= args
->attr
;
1810 const bgp_size_t length
= args
->length
;
1812 /* if received from an internal neighbor, it SHALL be considered
1813 * malformed if its length is not equal to 4. If malformed, the
1814 * UPDATE message SHALL be handled using the approach of "treat-as-
1817 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1818 flog_err(EC_BGP_ATTR_LEN
,
1819 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1820 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1824 /* If it is contained in an UPDATE message that is received from an
1825 external peer, then this attribute MUST be ignored by the
1826 receiving speaker. */
1827 if (peer
->sort
== BGP_PEER_EBGP
) {
1828 STREAM_FORWARD_GETP(peer
->curr
, length
);
1829 return BGP_ATTR_PARSE_PROCEED
;
1832 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1834 /* Set the local-pref flag. */
1835 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1837 return BGP_ATTR_PARSE_PROCEED
;
1840 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1844 /* Atomic aggregate. */
1845 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1847 struct peer
*const peer
= args
->peer
;
1848 struct attr
*const attr
= args
->attr
;
1849 const bgp_size_t length
= args
->length
;
1853 flog_err(EC_BGP_ATTR_LEN
,
1854 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1856 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1860 if (peer
->discard_attrs
[args
->type
] || peer
->withdraw_attrs
[args
->type
])
1863 /* Set atomic aggregate flag. */
1864 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1866 return BGP_ATTR_PARSE_PROCEED
;
1869 stream_forward_getp(peer
->curr
, length
);
1871 return bgp_attr_ignore(peer
, args
->type
);
1874 /* Aggregator attribute */
1875 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1877 struct peer
*const peer
= args
->peer
;
1878 struct attr
*const attr
= args
->attr
;
1879 const bgp_size_t length
= args
->length
;
1884 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1885 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1886 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1889 if (length
!= wantedlen
) {
1890 flog_err(EC_BGP_ATTR_LEN
,
1891 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1893 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1897 if (peer
->discard_attrs
[args
->type
] || peer
->withdraw_attrs
[args
->type
])
1898 goto aggregator_ignore
;
1900 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1901 aggregator_as
= stream_getl(peer
->curr
);
1903 aggregator_as
= stream_getw(peer
->curr
);
1905 attr
->aggregator_as
= aggregator_as
;
1906 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1908 /* Codification of AS 0 Processing */
1909 if (aggregator_as
== BGP_AS_ZERO
) {
1910 flog_err(EC_BGP_ATTR_LEN
,
1911 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1912 peer
->host
, aspath_print(attr
->aspath
));
1914 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1915 char attr_str
[BUFSIZ
] = {0};
1917 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1919 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1922 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1925 return BGP_ATTR_PARSE_PROCEED
;
1928 stream_forward_getp(peer
->curr
, length
);
1930 return bgp_attr_ignore(peer
, args
->type
);
1933 /* New Aggregator attribute */
1934 static enum bgp_attr_parse_ret
1935 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1936 as_t
*as4_aggregator_as
,
1937 struct in_addr
*as4_aggregator_addr
)
1939 struct peer
*const peer
= args
->peer
;
1940 struct attr
*const attr
= args
->attr
;
1941 const bgp_size_t length
= args
->length
;
1945 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1947 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1951 if (peer
->discard_attrs
[args
->type
] || peer
->withdraw_attrs
[args
->type
])
1952 goto as4_aggregator_ignore
;
1954 aggregator_as
= stream_getl(peer
->curr
);
1956 *as4_aggregator_as
= aggregator_as
;
1957 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1959 /* Codification of AS 0 Processing */
1960 if (aggregator_as
== BGP_AS_ZERO
) {
1961 flog_err(EC_BGP_ATTR_LEN
,
1962 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1963 peer
->host
, aspath_print(attr
->aspath
));
1965 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1966 char attr_str
[BUFSIZ
] = {0};
1968 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1970 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1973 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1976 return BGP_ATTR_PARSE_PROCEED
;
1978 as4_aggregator_ignore
:
1979 stream_forward_getp(peer
->curr
, length
);
1981 return bgp_attr_ignore(peer
, args
->type
);
1984 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1986 static enum bgp_attr_parse_ret
1987 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1988 struct aspath
*as4_path
, as_t as4_aggregator
,
1989 struct in_addr
*as4_aggregator_addr
)
1991 int ignore_as4_path
= 0;
1992 struct aspath
*newpath
;
1994 if (!attr
->aspath
) {
1995 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1997 * checked that all well-known, mandatory attributes were
2000 * Can only be a problem with peer itself - hard error
2002 return BGP_ATTR_PARSE_ERROR
;
2005 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
2006 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
2008 * It is worth a warning though, because the peer really
2009 * should not send them
2011 if (BGP_DEBUG(as4
, AS4
)) {
2012 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
2013 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
2014 "AS4 capable peer, yet it sent");
2017 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
2018 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
2020 "AS4 capable peer, yet it sent");
2023 return BGP_ATTR_PARSE_PROCEED
;
2026 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
2027 * because that may override AS4_PATH
2029 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
2030 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
2032 * if the as_number in aggregator is not AS_TRANS,
2033 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
2034 * and the Aggregator shall be taken as
2035 * info on the aggregating node, and the AS_PATH
2036 * shall be taken as the AS_PATH
2038 * the Aggregator shall be ignored and the
2039 * AS4_AGGREGATOR shall be taken as the
2040 * Aggregating node and the AS_PATH is to be
2041 * constructed "as in all other cases"
2043 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
2045 if (BGP_DEBUG(as4
, AS4
))
2047 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
2049 ignore_as4_path
= 1;
2051 /* "New_aggregator shall be taken as aggregator"
2053 attr
->aggregator_as
= as4_aggregator
;
2054 attr
->aggregator_addr
.s_addr
=
2055 as4_aggregator_addr
->s_addr
;
2058 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2059 * That is bogus - but reading the conditions
2060 * we have to handle AS4_AGGREGATOR as if it were
2061 * AGGREGATOR in that case
2063 if (BGP_DEBUG(as4
, AS4
))
2065 "[AS4] %s BGP not AS4 capable peer send AS4_AGGREGATOR but no AGGREGATOR, will take it as if AGGREGATOR with AS_TRANS had been there",
2067 attr
->aggregator_as
= as4_aggregator
;
2068 /* sweep it under the carpet and simulate a "good"
2070 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
2074 /* need to reconcile NEW_AS_PATH and AS_PATH */
2075 if (!ignore_as4_path
2076 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
2077 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
2079 return BGP_ATTR_PARSE_ERROR
;
2081 aspath_unintern(&attr
->aspath
);
2082 attr
->aspath
= aspath_intern(newpath
);
2084 return BGP_ATTR_PARSE_PROCEED
;
2087 /* Community attribute. */
2088 static enum bgp_attr_parse_ret
2089 bgp_attr_community(struct bgp_attr_parser_args
*args
)
2091 struct peer
*const peer
= args
->peer
;
2092 struct attr
*const attr
= args
->attr
;
2093 const bgp_size_t length
= args
->length
;
2096 bgp_attr_set_community(attr
, NULL
);
2097 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2101 if (peer
->discard_attrs
[args
->type
] || peer
->withdraw_attrs
[args
->type
])
2102 goto community_ignore
;
2104 bgp_attr_set_community(
2106 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
2108 /* XXX: fix community_parse to use stream API and remove this */
2109 stream_forward_getp(peer
->curr
, length
);
2111 /* The Community attribute SHALL be considered malformed if its
2112 * length is not a non-zero multiple of 4.
2114 if (!bgp_attr_get_community(attr
))
2115 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2118 return BGP_ATTR_PARSE_PROCEED
;
2121 stream_forward_getp(peer
->curr
, length
);
2123 return bgp_attr_ignore(peer
, args
->type
);
2126 /* Originator ID attribute. */
2127 static enum bgp_attr_parse_ret
2128 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
2130 struct peer
*const peer
= args
->peer
;
2131 struct attr
*const attr
= args
->attr
;
2132 const bgp_size_t length
= args
->length
;
2134 /* if received from an internal neighbor, it SHALL be considered
2135 * malformed if its length is not equal to 4. If malformed, the
2136 * UPDATE message SHALL be handled using the approach of "treat-as-
2140 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
2143 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2147 if (peer
->discard_attrs
[args
->type
] || peer
->withdraw_attrs
[args
->type
])
2148 goto originator_id_ignore
;
2150 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
2152 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2154 return BGP_ATTR_PARSE_PROCEED
;
2156 originator_id_ignore
:
2157 stream_forward_getp(peer
->curr
, length
);
2159 return bgp_attr_ignore(peer
, args
->type
);
2162 /* Cluster list attribute. */
2163 static enum bgp_attr_parse_ret
2164 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2166 struct peer
*const peer
= args
->peer
;
2167 struct attr
*const attr
= args
->attr
;
2168 const bgp_size_t length
= args
->length
;
2170 /* if received from an internal neighbor, it SHALL be considered
2171 * malformed if its length is not a non-zero multiple of 4. If
2172 * malformed, the UPDATE message SHALL be handled using the approach
2173 * of "treat-as-withdraw".
2175 if (length
== 0 || length
% 4) {
2176 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2178 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2182 if (peer
->discard_attrs
[args
->type
] || peer
->withdraw_attrs
[args
->type
])
2183 goto cluster_list_ignore
;
2185 bgp_attr_set_cluster(
2186 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2189 /* XXX: Fix cluster_parse to use stream API and then remove this */
2190 stream_forward_getp(peer
->curr
, length
);
2192 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2194 return BGP_ATTR_PARSE_PROCEED
;
2196 cluster_list_ignore
:
2197 stream_forward_getp(peer
->curr
, length
);
2199 return bgp_attr_ignore(peer
, args
->type
);
2202 /* Multiprotocol reachability information parse. */
2203 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2204 struct bgp_nlri
*mp_update
)
2208 iana_safi_t pkt_safi
;
2210 bgp_size_t nlri_len
;
2213 struct peer
*const peer
= args
->peer
;
2214 struct attr
*const attr
= args
->attr
;
2215 const bgp_size_t length
= args
->length
;
2217 /* Set end of packet. */
2218 s
= BGP_INPUT(peer
);
2219 start
= stream_get_getp(s
);
2221 /* safe to read statically sized header? */
2222 #define BGP_MP_REACH_MIN_SIZE 5
2223 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2224 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2225 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2226 __func__
, peer
->host
, (unsigned long)length
);
2227 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2230 /* Load AFI, SAFI. */
2231 pkt_afi
= stream_getw(s
);
2232 pkt_safi
= stream_getc(s
);
2234 /* Convert AFI, SAFI to internal values, check. */
2235 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2236 /* Log if AFI or SAFI is unrecognized. This is not an error
2238 * the attribute is otherwise malformed.
2240 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2242 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2243 peer
->host
, iana_afi2str(pkt_afi
),
2244 iana_safi2str(pkt_safi
));
2245 return BGP_ATTR_PARSE_ERROR
;
2248 /* Get nexthop length. */
2249 attr
->mp_nexthop_len
= stream_getc(s
);
2251 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2253 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2254 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2255 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2258 /* Nexthop length check. */
2259 switch (attr
->mp_nexthop_len
) {
2261 if (safi
!= SAFI_FLOWSPEC
) {
2262 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2263 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2264 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2267 case BGP_ATTR_NHLEN_VPNV4
:
2268 stream_getl(s
); /* RD high */
2269 stream_getl(s
); /* RD low */
2271 * NOTE: intentional fall through
2272 * - for consistency in rx processing
2274 * The following comment is to signal GCC this intention
2275 * and suppress the warning
2278 case BGP_ATTR_NHLEN_IPV4
:
2279 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2280 /* Probably needed for RFC 2283 */
2281 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2282 memcpy(&attr
->nexthop
.s_addr
,
2283 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2285 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2286 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2287 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2288 stream_getl(s
); /* RD high */
2289 stream_getl(s
); /* RD low */
2291 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2292 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2293 if (!peer
->nexthop
.ifp
) {
2294 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2296 return BGP_ATTR_PARSE_WITHDRAW
;
2298 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2301 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2302 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2303 if (attr
->mp_nexthop_len
2304 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2305 stream_getl(s
); /* RD high */
2306 stream_getl(s
); /* RD low */
2308 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2309 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2310 if (!peer
->nexthop
.ifp
) {
2311 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",
2313 return BGP_ATTR_PARSE_WITHDRAW
;
2315 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2317 if (attr
->mp_nexthop_len
2318 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2319 stream_getl(s
); /* RD high */
2320 stream_getl(s
); /* RD low */
2322 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2323 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2324 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2326 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2327 peer
->host
, &attr
->mp_nexthop_global
,
2328 &attr
->mp_nexthop_local
);
2330 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2332 if (!peer
->nexthop
.ifp
) {
2333 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2335 return BGP_ATTR_PARSE_WITHDRAW
;
2337 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2340 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2341 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2342 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2346 zlog_info("%s: %s sent SNPA which couldn't be read",
2347 __func__
, peer
->host
);
2348 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2353 if ((val
= stream_getc(s
)))
2355 EC_BGP_DEFUNCT_SNPA_LEN
,
2356 "%s sent non-zero value, %u, for defunct SNPA-length field",
2360 /* must have nrli_len, what is left of the attribute */
2361 nlri_len
= LEN_LEFT
;
2362 if (nlri_len
> STREAM_READABLE(s
)) {
2363 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2364 __func__
, peer
->host
);
2365 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2369 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2370 __func__
, peer
->host
);
2372 mp_update
->afi
= afi
;
2373 mp_update
->safi
= safi
;
2374 return BGP_ATTR_PARSE_EOR
;
2377 mp_update
->afi
= afi
;
2378 mp_update
->safi
= safi
;
2379 mp_update
->nlri
= stream_pnt(s
);
2380 mp_update
->length
= nlri_len
;
2382 stream_forward_getp(s
, nlri_len
);
2384 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2386 return BGP_ATTR_PARSE_PROCEED
;
2390 /* Multiprotocol unreachable parse */
2391 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2392 struct bgp_nlri
*mp_withdraw
)
2397 iana_safi_t pkt_safi
;
2399 uint16_t withdraw_len
;
2400 struct peer
*const peer
= args
->peer
;
2401 struct attr
*const attr
= args
->attr
;
2402 const bgp_size_t length
= args
->length
;
2406 #define BGP_MP_UNREACH_MIN_SIZE 3
2407 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2408 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2410 pkt_afi
= stream_getw(s
);
2411 pkt_safi
= stream_getc(s
);
2413 /* Convert AFI, SAFI to internal values, check. */
2414 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2415 /* Log if AFI or SAFI is unrecognized. This is not an error
2417 * the attribute is otherwise malformed.
2419 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2421 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2422 peer
->host
, iana_afi2str(pkt_afi
),
2423 iana_safi2str(pkt_safi
));
2424 return BGP_ATTR_PARSE_ERROR
;
2427 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2429 mp_withdraw
->afi
= afi
;
2430 mp_withdraw
->safi
= safi
;
2431 mp_withdraw
->nlri
= stream_pnt(s
);
2432 mp_withdraw
->length
= withdraw_len
;
2434 stream_forward_getp(s
, withdraw_len
);
2436 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2438 return BGP_ATTR_PARSE_PROCEED
;
2441 /* Large Community attribute. */
2442 static enum bgp_attr_parse_ret
2443 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2445 struct peer
*const peer
= args
->peer
;
2446 struct attr
*const attr
= args
->attr
;
2447 const bgp_size_t length
= args
->length
;
2450 * Large community follows new attribute format.
2453 bgp_attr_set_lcommunity(attr
, NULL
);
2454 /* Empty extcomm doesn't seem to be invalid per se */
2455 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2459 if (peer
->discard_attrs
[args
->type
] || peer
->withdraw_attrs
[args
->type
])
2460 goto large_community_ignore
;
2462 bgp_attr_set_lcommunity(
2463 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2464 /* XXX: fix ecommunity_parse to use stream API */
2465 stream_forward_getp(peer
->curr
, length
);
2467 if (!bgp_attr_get_lcommunity(attr
))
2468 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2471 return BGP_ATTR_PARSE_PROCEED
;
2473 large_community_ignore
:
2474 stream_forward_getp(peer
->curr
, length
);
2476 return bgp_attr_ignore(peer
, args
->type
);
2479 /* Extended Community attribute. */
2480 static enum bgp_attr_parse_ret
2481 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2483 struct peer
*const peer
= args
->peer
;
2484 struct attr
*const attr
= args
->attr
;
2485 const bgp_size_t length
= args
->length
;
2488 struct ecommunity
*ecomm
;
2491 bgp_attr_set_ecommunity(attr
, NULL
);
2492 /* Empty extcomm doesn't seem to be invalid per se */
2493 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2497 ecomm
= ecommunity_parse(
2498 stream_pnt(peer
->curr
), length
,
2499 CHECK_FLAG(peer
->flags
,
2500 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2501 bgp_attr_set_ecommunity(attr
, ecomm
);
2502 /* XXX: fix ecommunity_parse to use stream API */
2503 stream_forward_getp(peer
->curr
, length
);
2505 /* The Extended Community attribute SHALL be considered malformed if
2506 * its length is not a non-zero multiple of 8.
2508 if (!bgp_attr_get_ecommunity(attr
))
2509 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2512 /* Extract DF election preference and mobility sequence number */
2513 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2515 /* Extract MAC mobility sequence number, if any. */
2516 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2517 attr
->sticky
= sticky
;
2519 /* Check if this is a Gateway MAC-IP advertisement */
2520 attr
->default_gw
= bgp_attr_default_gw(attr
);
2522 /* Handle scenario where router flag ecommunity is not
2523 * set but default gw ext community is present.
2524 * Use default gateway, set and propogate R-bit.
2526 if (attr
->default_gw
)
2527 attr
->router_flag
= 1;
2529 /* Check EVPN Neighbor advertisement flags, R-bit */
2530 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2532 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2534 /* Extract the Rmac, if any */
2535 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2536 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2537 && bgp_mac_exist(&attr
->rmac
))
2538 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2542 /* Get the tunnel type from encap extended community */
2543 bgp_attr_extcom_tunnel_type(attr
,
2544 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2546 /* Extract link bandwidth, if any. */
2547 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2550 return BGP_ATTR_PARSE_PROCEED
;
2553 /* IPv6 Extended Community attribute. */
2554 static enum bgp_attr_parse_ret
2555 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2557 struct peer
*const peer
= args
->peer
;
2558 struct attr
*const attr
= args
->attr
;
2559 const bgp_size_t length
= args
->length
;
2560 struct ecommunity
*ipv6_ecomm
= NULL
;
2563 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2564 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2568 if (peer
->discard_attrs
[args
->type
] || peer
->withdraw_attrs
[args
->type
])
2569 goto ipv6_ext_community_ignore
;
2571 ipv6_ecomm
= ecommunity_parse_ipv6(
2572 stream_pnt(peer
->curr
), length
,
2573 CHECK_FLAG(peer
->flags
,
2574 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2575 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2577 /* XXX: fix ecommunity_parse to use stream API */
2578 stream_forward_getp(peer
->curr
, length
);
2581 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2584 return BGP_ATTR_PARSE_PROCEED
;
2586 ipv6_ext_community_ignore
:
2587 stream_forward_getp(peer
->curr
, length
);
2589 return bgp_attr_ignore(peer
, args
->type
);
2592 /* Parse Tunnel Encap attribute in an UPDATE */
2593 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2594 bgp_size_t length
, /* IN: attr's length field */
2595 struct attr
*attr
, /* IN: caller already allocated */
2596 uint8_t flag
, /* IN: attr's flags field */
2600 uint16_t tunneltype
= 0;
2602 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2604 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2605 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2607 "Tunnel Encap attribute flag isn't optional and transitive %d",
2609 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2610 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2615 if (BGP_ATTR_ENCAP
== type
) {
2616 /* read outer TLV type and length */
2617 uint16_t tlv_length
;
2621 "Tunnel Encap attribute not long enough to contain outer T,L");
2622 bgp_notify_send_with_data(
2623 peer
, BGP_NOTIFY_UPDATE_ERR
,
2624 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2627 tunneltype
= stream_getw(BGP_INPUT(peer
));
2628 tlv_length
= stream_getw(BGP_INPUT(peer
));
2631 if (tlv_length
!= length
) {
2632 zlog_info("%s: tlv_length(%d) != length(%d)",
2633 __func__
, tlv_length
, length
);
2637 while (length
>= 4) {
2638 uint16_t subtype
= 0;
2639 uint16_t sublength
= 0;
2640 struct bgp_attr_encap_subtlv
*tlv
;
2642 if (BGP_ATTR_ENCAP
== type
) {
2643 subtype
= stream_getc(BGP_INPUT(peer
));
2644 sublength
= stream_getc(BGP_INPUT(peer
));
2646 #ifdef ENABLE_BGP_VNC
2648 subtype
= stream_getw(BGP_INPUT(peer
));
2649 sublength
= stream_getw(BGP_INPUT(peer
));
2654 if (sublength
> length
) {
2656 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2658 bgp_notify_send_with_data(
2659 peer
, BGP_NOTIFY_UPDATE_ERR
,
2660 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2664 /* alloc and copy sub-tlv */
2665 /* TBD make sure these are freed when attributes are released */
2666 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2667 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2668 tlv
->type
= subtype
;
2669 tlv
->length
= sublength
;
2670 stream_get(tlv
->value
, peer
->curr
, sublength
);
2671 length
-= sublength
;
2673 /* attach tlv to encap chain */
2674 if (BGP_ATTR_ENCAP
== type
) {
2675 struct bgp_attr_encap_subtlv
*stlv_last
;
2676 for (stlv_last
= attr
->encap_subtlvs
;
2677 stlv_last
&& stlv_last
->next
;
2678 stlv_last
= stlv_last
->next
)
2681 stlv_last
->next
= tlv
;
2683 attr
->encap_subtlvs
= tlv
;
2685 #ifdef ENABLE_BGP_VNC
2687 struct bgp_attr_encap_subtlv
*stlv_last
;
2688 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2689 bgp_attr_get_vnc_subtlvs(attr
);
2691 for (stlv_last
= vnc_subtlvs
;
2692 stlv_last
&& stlv_last
->next
;
2693 stlv_last
= stlv_last
->next
)
2696 stlv_last
->next
= tlv
;
2698 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2703 if (BGP_ATTR_ENCAP
== type
) {
2704 attr
->encap_tunneltype
= tunneltype
;
2708 /* spurious leftover data */
2710 "Tunnel Encap attribute length is bad: %d leftover octets",
2712 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2713 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2722 /* SRv6 Service Data Sub-Sub-TLV attribute
2723 * draft-ietf-bess-srv6-services-07
2725 static enum bgp_attr_parse_ret
2726 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2728 struct peer
*const peer
= args
->peer
;
2729 struct attr
*const attr
= args
->attr
;
2730 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2731 transposition_len
, transposition_offset
;
2733 size_t headersz
= sizeof(type
) + sizeof(length
);
2735 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2738 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2739 headersz
, STREAM_READABLE(peer
->curr
));
2740 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2744 type
= stream_getc(peer
->curr
);
2745 length
= stream_getw(peer
->curr
);
2747 if (STREAM_READABLE(peer
->curr
) < length
) {
2750 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2751 length
, STREAM_READABLE(peer
->curr
));
2752 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2756 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2759 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2760 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2762 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2766 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2767 if (STREAM_READABLE(peer
->curr
) <
2768 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2771 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
2772 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2773 STREAM_READABLE(peer
->curr
));
2774 return bgp_attr_malformed(
2775 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2779 loc_block_len
= stream_getc(peer
->curr
);
2780 loc_node_len
= stream_getc(peer
->curr
);
2781 func_len
= stream_getc(peer
->curr
);
2782 arg_len
= stream_getc(peer
->curr
);
2783 transposition_len
= stream_getc(peer
->curr
);
2784 transposition_offset
= stream_getc(peer
->curr
);
2786 /* Log SRv6 Service Data Sub-Sub-TLV */
2787 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2789 "%s: srv6-l3-srv-data loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u, transposition-len=%u, transposition-offset=%u",
2790 __func__
, loc_block_len
, loc_node_len
, func_len
,
2791 arg_len
, transposition_len
,
2792 transposition_offset
);
2795 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2796 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2797 attr
->srv6_l3vpn
->func_len
= func_len
;
2798 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2799 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2800 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2804 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2806 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2809 stream_forward_getp(peer
->curr
, length
);
2812 return BGP_ATTR_PARSE_PROCEED
;
2815 /* SRv6 Service Sub-TLV attribute
2816 * draft-ietf-bess-srv6-services-07
2818 static enum bgp_attr_parse_ret
2819 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2821 struct peer
*const peer
= args
->peer
;
2822 struct attr
*const attr
= args
->attr
;
2823 struct in6_addr ipv6_sid
;
2824 uint8_t type
, sid_flags
;
2825 uint16_t length
, endpoint_behavior
;
2826 size_t headersz
= sizeof(type
) + sizeof(length
);
2827 enum bgp_attr_parse_ret err
;
2829 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2832 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2833 headersz
, STREAM_READABLE(peer
->curr
));
2834 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2838 type
= stream_getc(peer
->curr
);
2839 length
= stream_getw(peer
->curr
);
2841 if (STREAM_READABLE(peer
->curr
) < length
) {
2844 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2845 length
, STREAM_READABLE(peer
->curr
));
2846 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2850 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2851 if (STREAM_READABLE(peer
->curr
) <
2852 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2855 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
2856 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
,
2857 STREAM_READABLE(peer
->curr
));
2858 return bgp_attr_malformed(
2859 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2862 stream_getc(peer
->curr
);
2863 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2864 sid_flags
= stream_getc(peer
->curr
);
2865 endpoint_behavior
= stream_getw(peer
->curr
);
2866 stream_getc(peer
->curr
);
2868 /* Log SRv6 Service Sub-TLV */
2869 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
2871 "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2872 __func__
, &ipv6_sid
, sid_flags
,
2875 /* Configure from Info */
2876 if (attr
->srv6_l3vpn
) {
2877 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2878 "Prefix SID SRv6 L3VPN field repeated");
2879 return bgp_attr_malformed(
2880 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2882 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2883 sizeof(struct bgp_attr_srv6_l3vpn
));
2884 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2885 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2886 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2887 attr
->srv6_l3vpn
->loc_block_len
= 0;
2888 attr
->srv6_l3vpn
->loc_node_len
= 0;
2889 attr
->srv6_l3vpn
->func_len
= 0;
2890 attr
->srv6_l3vpn
->arg_len
= 0;
2891 attr
->srv6_l3vpn
->transposition_len
= 0;
2892 attr
->srv6_l3vpn
->transposition_offset
= 0;
2894 // Sub-Sub-TLV found
2895 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2896 err
= bgp_attr_srv6_service_data(args
);
2898 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2902 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2905 /* Placeholder code for unsupported type */
2907 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2909 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2912 stream_forward_getp(peer
->curr
, length
);
2915 return BGP_ATTR_PARSE_PROCEED
;
2919 * Read an individual SID value returning how much data we have read
2920 * Returns 0 if there was an error that needs to be passed up the stack
2922 static enum bgp_attr_parse_ret
2923 bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2924 struct bgp_attr_parser_args
*args
)
2926 struct peer
*const peer
= args
->peer
;
2927 struct attr
*const attr
= args
->attr
;
2928 uint32_t label_index
;
2929 struct in6_addr ipv6_sid
;
2931 uint32_t srgb_range
;
2933 uint8_t sid_type
, sid_flags
;
2935 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2936 if (STREAM_READABLE(peer
->curr
) < length
2937 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2938 flog_err(EC_BGP_ATTR_LEN
,
2939 "Prefix SID label index length is %hu instead of %u",
2940 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2941 return bgp_attr_malformed(args
,
2942 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2946 /* Ignore flags and reserved */
2947 stream_getc(peer
->curr
);
2948 stream_getw(peer
->curr
);
2950 /* Fetch the label index and see if it is valid. */
2951 label_index
= stream_getl(peer
->curr
);
2952 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2953 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2956 /* Store label index; subsequently, we'll check on
2958 attr
->label_index
= label_index
;
2961 /* Placeholder code for the IPv6 SID type */
2962 else if (type
== BGP_PREFIX_SID_IPV6
) {
2963 if (STREAM_READABLE(peer
->curr
) < length
2964 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2965 flog_err(EC_BGP_ATTR_LEN
,
2966 "Prefix SID IPv6 length is %hu instead of %u",
2967 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2968 return bgp_attr_malformed(args
,
2969 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2973 /* Ignore reserved */
2974 stream_getc(peer
->curr
);
2975 stream_getw(peer
->curr
);
2977 stream_get(&ipv6_sid
, peer
->curr
, 16);
2980 /* Placeholder code for the Originator SRGB type */
2981 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2983 * ietf-idr-bgp-prefix-sid-05:
2984 * Length is the total length of the value portion of the
2985 * TLV: 2 + multiple of 6.
2987 * peer->curr stream readp should be at the beginning of the 16
2988 * bit flag field at this point in the code.
2992 * Check that the TLV length field is sane: at least 2 bytes of
2993 * flag, and at least 1 SRGB (these are 6 bytes each)
2995 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2998 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
3000 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
3001 return bgp_attr_malformed(
3002 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3007 * Check that we actually have at least as much data as
3008 * specified by the length field
3010 if (STREAM_READABLE(peer
->curr
) < length
) {
3011 flog_err(EC_BGP_ATTR_LEN
,
3012 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
3013 length
, STREAM_READABLE(peer
->curr
));
3014 return bgp_attr_malformed(
3015 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3020 * Check that the portion of the TLV containing the sequence of
3021 * SRGBs corresponds to a multiple of the SRGB size; to get
3022 * that length, we skip the 16 bit flags field
3024 stream_getw(peer
->curr
);
3026 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
3029 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
3030 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
3031 return bgp_attr_malformed(
3032 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3036 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
3038 for (int i
= 0; i
< srgb_count
; i
++) {
3039 stream_get(&srgb_base
, peer
->curr
, 3);
3040 stream_get(&srgb_range
, peer
->curr
, 3);
3044 /* Placeholder code for the VPN-SID Service type */
3045 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
3046 if (STREAM_READABLE(peer
->curr
) < length
3047 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
3048 flog_err(EC_BGP_ATTR_LEN
,
3049 "Prefix SID VPN SID length is %hu instead of %u",
3050 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
3051 return bgp_attr_malformed(args
,
3052 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3056 /* Parse VPN-SID Sub-TLV */
3057 stream_getc(peer
->curr
); /* reserved */
3058 sid_type
= stream_getc(peer
->curr
); /* sid_type */
3059 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
3060 stream_get(&ipv6_sid
, peer
->curr
,
3061 sizeof(ipv6_sid
)); /* sid_value */
3063 /* Log VPN-SID Sub-TLV */
3064 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
3066 "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
3067 __func__
, &ipv6_sid
, sid_type
, sid_flags
);
3069 /* Configure from Info */
3070 if (attr
->srv6_vpn
) {
3071 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
3072 "Prefix SID SRv6 VPN field repeated");
3073 return bgp_attr_malformed(
3074 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
3076 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
3077 sizeof(struct bgp_attr_srv6_vpn
));
3078 attr
->srv6_vpn
->sid_flags
= sid_flags
;
3079 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
3080 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
3083 /* Placeholder code for the SRv6 L3 Service type */
3084 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
3085 if (STREAM_READABLE(peer
->curr
) < length
) {
3088 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
3089 length
, STREAM_READABLE(peer
->curr
));
3090 return bgp_attr_malformed(args
,
3091 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3095 /* ignore reserved */
3096 stream_getc(peer
->curr
);
3098 return bgp_attr_srv6_service(args
);
3101 /* Placeholder code for Unsupported TLV */
3104 if (STREAM_READABLE(peer
->curr
) < length
) {
3107 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
3108 length
, STREAM_READABLE(peer
->curr
));
3109 return bgp_attr_malformed(
3110 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3114 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3116 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3119 stream_forward_getp(peer
->curr
, length
);
3122 return BGP_ATTR_PARSE_PROCEED
;
3125 /* Prefix SID attribute
3126 * draft-ietf-idr-bgp-prefix-sid-05
3128 enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
3130 struct peer
*const peer
= args
->peer
;
3131 struct attr
*const attr
= args
->attr
;
3132 enum bgp_attr_parse_ret ret
;
3134 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3138 size_t headersz
= sizeof(type
) + sizeof(length
);
3139 size_t psid_parsed_length
= 0;
3141 while (STREAM_READABLE(peer
->curr
) > 0
3142 && psid_parsed_length
< args
->length
) {
3144 if (STREAM_READABLE(peer
->curr
) < headersz
) {
3147 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3148 headersz
, STREAM_READABLE(peer
->curr
));
3149 return bgp_attr_malformed(
3150 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3154 type
= stream_getc(peer
->curr
);
3155 length
= stream_getw(peer
->curr
);
3157 if (STREAM_READABLE(peer
->curr
) < length
) {
3160 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3161 length
, STREAM_READABLE(peer
->curr
));
3162 return bgp_attr_malformed(args
,
3163 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3167 ret
= bgp_attr_psid_sub(type
, length
, args
);
3169 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3172 psid_parsed_length
+= length
+ headersz
;
3174 if (psid_parsed_length
> args
->length
) {
3177 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
3178 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
3179 return bgp_attr_malformed(
3180 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3185 return BGP_ATTR_PARSE_PROCEED
;
3188 /* PMSI tunnel attribute (RFC 6514)
3189 * Basic validation checks done here.
3191 static enum bgp_attr_parse_ret
3192 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
3194 struct peer
*const peer
= args
->peer
;
3195 struct attr
*const attr
= args
->attr
;
3196 const bgp_size_t length
= args
->length
;
3198 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
3200 /* Verify that the receiver is expecting "ingress replication" as we
3201 * can only support that.
3203 if (length
< attr_parse_len
) {
3204 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
3206 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3209 stream_getc(peer
->curr
); /* Flags */
3210 tnl_type
= stream_getc(peer
->curr
);
3211 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3212 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3213 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3214 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3217 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3219 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3220 "Bad PMSI tunnel attribute length %d for IR",
3222 return bgp_attr_malformed(
3223 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3228 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3229 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3230 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3232 /* Forward read pointer of input stream. */
3233 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3235 return BGP_ATTR_PARSE_PROCEED
;
3238 /* AIGP attribute (rfc7311) */
3239 static enum bgp_attr_parse_ret
bgp_attr_aigp(struct bgp_attr_parser_args
*args
)
3241 struct peer
*const peer
= args
->peer
;
3242 struct attr
*const attr
= args
->attr
;
3243 const bgp_size_t length
= args
->length
;
3244 uint8_t *s
= stream_pnt(peer
->curr
);
3247 /* If an AIGP attribute is received on a BGP session for which
3248 * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3249 * as if it were an unrecognized non-transitive attribute.
3250 * That is, it "MUST be quietly ignored and not passed along to
3252 * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3253 * sessions between members of the same BGP Confederation,
3254 * the default value of AIGP_SESSION SHOULD be "enabled".
3256 if (peer
->sort
== BGP_PEER_EBGP
&&
3257 !CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
)) {
3259 "%pBP received AIGP attribute, but eBGP peer do not support it",
3264 if (peer
->discard_attrs
[args
->type
] || peer
->withdraw_attrs
[args
->type
])
3267 if (!bgp_attr_aigp_valid(s
, length
))
3270 /* Extract AIGP Metric TLV */
3271 if (bgp_attr_aigp_get_tlv_metric(s
, length
, &aigp
))
3272 bgp_attr_set_aigp_metric(attr
, aigp
);
3275 stream_forward_getp(peer
->curr
, length
);
3277 return bgp_attr_ignore(peer
, args
->type
);
3280 /* OTC attribute. */
3281 static enum bgp_attr_parse_ret
bgp_attr_otc(struct bgp_attr_parser_args
*args
)
3283 struct peer
*const peer
= args
->peer
;
3284 struct attr
*const attr
= args
->attr
;
3285 const bgp_size_t length
= args
->length
;
3289 flog_err(EC_BGP_ATTR_LEN
, "OTC attribute length isn't 4 [%u]",
3291 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3295 if (peer
->discard_attrs
[args
->type
] || peer
->withdraw_attrs
[args
->type
])
3298 attr
->otc
= stream_getl(peer
->curr
);
3300 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "OTC attribute value is 0");
3301 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
3305 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
3307 return BGP_ATTR_PARSE_PROCEED
;
3310 stream_forward_getp(peer
->curr
, length
);
3312 return bgp_attr_ignore(peer
, args
->type
);
3315 /* BGP unknown attribute treatment. */
3316 static enum bgp_attr_parse_ret
3317 bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3319 bgp_size_t total
= args
->total
;
3320 struct transit
*transit
;
3321 struct peer
*const peer
= args
->peer
;
3322 struct attr
*const attr
= args
->attr
;
3323 uint8_t *const startp
= args
->startp
;
3324 const uint8_t type
= args
->type
;
3325 const uint8_t flag
= args
->flags
;
3326 const bgp_size_t length
= args
->length
;
3328 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3330 "%s Unknown attribute is received (type %d, length %d)",
3331 peer
->host
, type
, length
);
3333 /* Forward read pointer of input stream. */
3334 stream_forward_getp(peer
->curr
, length
);
3336 if (peer
->discard_attrs
[type
] || peer
->withdraw_attrs
[type
])
3337 return bgp_attr_ignore(peer
, type
);
3339 /* If any of the mandatory well-known attributes are not recognized,
3340 then the Error Subcode is set to Unrecognized Well-known
3341 Attribute. The Data field contains the unrecognized attribute
3342 (type, length and value). */
3343 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3344 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3348 /* Unrecognized non-transitive optional attributes must be quietly
3349 ignored and not passed along to other BGP peers. */
3350 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3351 return BGP_ATTR_PARSE_PROCEED
;
3353 /* If a path with recognized transitive optional attribute is
3354 accepted and passed along to other BGP peers and the Partial bit
3355 in the Attribute Flags octet is set to 1 by some previous AS, it
3356 is not set back to 0 by the current AS. */
3357 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3359 /* Store transitive attribute to the end of attr->transit. */
3360 transit
= bgp_attr_get_transit(attr
);
3362 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3364 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3365 transit
->length
+ total
);
3367 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3368 transit
->length
+= total
;
3369 bgp_attr_set_transit(attr
, transit
);
3371 return BGP_ATTR_PARSE_PROCEED
;
3374 /* Well-known attribute check. */
3375 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3379 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3381 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3382 return BGP_ATTR_PARSE_PROCEED
;
3384 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3385 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3386 are present, it should. Check for any other attribute being present
3389 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3390 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3391 return BGP_ATTR_PARSE_PROCEED
;
3393 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3394 type
= BGP_ATTR_ORIGIN
;
3396 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3397 type
= BGP_ATTR_AS_PATH
;
3399 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3401 * NLRI is empty. We can't easily check NLRI empty here though.
3403 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3404 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3405 type
= BGP_ATTR_NEXT_HOP
;
3407 if (peer
->sort
== BGP_PEER_IBGP
3408 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3409 type
= BGP_ATTR_LOCAL_PREF
;
3411 /* If any of the well-known mandatory attributes are not present
3412 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3415 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3416 "%s Missing well-known attribute %s.", peer
->host
,
3417 lookup_msg(attr_str
, type
, NULL
));
3418 return BGP_ATTR_PARSE_WITHDRAW
;
3420 return BGP_ATTR_PARSE_PROCEED
;
3423 /* Read attribute of update packet. This function is called from
3424 bgp_update_receive() in bgp_packet.c. */
3425 enum bgp_attr_parse_ret
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3427 struct bgp_nlri
*mp_update
,
3428 struct bgp_nlri
*mp_withdraw
)
3430 enum bgp_attr_parse_ret ret
;
3434 uint8_t *startp
, *endp
;
3436 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3437 /* we need the as4_path only until we have synthesized the as_path with
3439 /* same goes for as4_aggregator */
3440 struct aspath
*as4_path
= NULL
;
3441 as_t as4_aggregator
= 0;
3442 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3443 struct transit
*transit
;
3445 /* Initialize bitmap. */
3446 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3448 /* End pointer of BGP attribute. */
3449 endp
= BGP_INPUT_PNT(peer
) + size
;
3451 /* Get attributes to the end of attribute length. */
3452 while (BGP_INPUT_PNT(peer
) < endp
) {
3453 /* Check remaining length check.*/
3454 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3455 /* XXX warning: long int format, int arg (arg 5) */
3457 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3458 "%s: error BGP attribute length %lu is smaller than min len",
3460 (unsigned long)(endp
3461 - stream_pnt(BGP_INPUT(peer
))));
3463 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3464 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3465 ret
= BGP_ATTR_PARSE_ERROR
;
3469 /* Fetch attribute flag and type. */
3470 startp
= BGP_INPUT_PNT(peer
);
3471 /* "The lower-order four bits of the Attribute Flags octet are
3472 unused. They MUST be zero when sent and MUST be ignored when
3474 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3475 type
= stream_getc(BGP_INPUT(peer
));
3477 /* Check whether Extended-Length applies and is in bounds */
3478 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3479 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3481 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3482 "%s: Extended length set, but just %lu bytes of attr header",
3484 (unsigned long)(endp
3485 - stream_pnt(BGP_INPUT(peer
))));
3487 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3488 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3489 ret
= BGP_ATTR_PARSE_ERROR
;
3493 /* Check extended attribue length bit. */
3494 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3495 length
= stream_getw(BGP_INPUT(peer
));
3497 length
= stream_getc(BGP_INPUT(peer
));
3499 /* If any attribute appears more than once in the UPDATE
3500 message, then the Error Subcode is set to Malformed Attribute
3503 if (CHECK_BITMAP(seen
, type
)) {
3505 EC_BGP_ATTRIBUTE_REPEATED
,
3506 "%s: error BGP attribute type %d appears twice in a message",
3509 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3510 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3511 ret
= BGP_ATTR_PARSE_ERROR
;
3515 /* Set type to bitmap to check duplicate attribute. `type' is
3516 unsigned char so it never overflow bitmap range. */
3518 SET_BITMAP(seen
, type
);
3520 /* Overflow check. */
3521 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3523 if (attr_endp
> endp
) {
3525 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3526 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3527 peer
->host
, type
, length
, size
, attr_endp
,
3531 * If any recognized attribute has an Attribute
3532 * Length that conflicts with the expected length
3533 * (based on the attribute type code), then the
3534 * Error Subcode MUST be set to Attribute Length
3535 * Error. The Data field MUST contain the erroneous
3536 * attribute (type, length, and value).
3538 * We do not currently have a good way to determine the
3539 * length of the attribute independent of the length
3540 * received in the message. Instead we send the
3541 * minimum between the amount of data we have and the
3542 * amount specified by the attribute length field.
3544 * Instead of directly passing in the packet buffer and
3545 * offset we use the stream_get* functions to read into
3546 * a stack buffer, since they perform bounds checking
3547 * and we are working with untrusted data.
3549 unsigned char ndata
[peer
->max_packet_size
];
3550 memset(ndata
, 0x00, sizeof(ndata
));
3552 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3553 /* Rewind to end of flag field */
3554 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3556 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3558 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3560 size_t atl
= attr_endp
- startp
;
3561 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3562 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3564 bgp_notify_send_with_data(
3565 peer
, BGP_NOTIFY_UPDATE_ERR
,
3566 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3569 ret
= BGP_ATTR_PARSE_ERROR
;
3573 struct bgp_attr_parser_args attr_args
= {
3580 .total
= attr_endp
- startp
,
3584 /* If any recognized attribute has Attribute Flags that conflict
3585 with the Attribute Type Code, then the Error Subcode is set
3587 Attribute Flags Error. The Data field contains the erroneous
3588 attribute (type, length and value). */
3589 if (bgp_attr_flag_invalid(&attr_args
)) {
3590 ret
= bgp_attr_malformed(
3591 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3593 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3598 /* OK check attribute and store it's value. */
3600 case BGP_ATTR_ORIGIN
:
3601 ret
= bgp_attr_origin(&attr_args
);
3603 case BGP_ATTR_AS_PATH
:
3604 ret
= bgp_attr_aspath(&attr_args
);
3606 case BGP_ATTR_AS4_PATH
:
3607 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3609 case BGP_ATTR_NEXT_HOP
:
3610 ret
= bgp_attr_nexthop(&attr_args
);
3612 case BGP_ATTR_MULTI_EXIT_DISC
:
3613 ret
= bgp_attr_med(&attr_args
);
3615 case BGP_ATTR_LOCAL_PREF
:
3616 ret
= bgp_attr_local_pref(&attr_args
);
3618 case BGP_ATTR_ATOMIC_AGGREGATE
:
3619 ret
= bgp_attr_atomic(&attr_args
);
3621 case BGP_ATTR_AGGREGATOR
:
3622 ret
= bgp_attr_aggregator(&attr_args
);
3624 case BGP_ATTR_AS4_AGGREGATOR
:
3625 ret
= bgp_attr_as4_aggregator(&attr_args
,
3627 &as4_aggregator_addr
);
3629 case BGP_ATTR_COMMUNITIES
:
3630 ret
= bgp_attr_community(&attr_args
);
3632 case BGP_ATTR_LARGE_COMMUNITIES
:
3633 ret
= bgp_attr_large_community(&attr_args
);
3635 case BGP_ATTR_ORIGINATOR_ID
:
3636 ret
= bgp_attr_originator_id(&attr_args
);
3638 case BGP_ATTR_CLUSTER_LIST
:
3639 ret
= bgp_attr_cluster_list(&attr_args
);
3641 case BGP_ATTR_MP_REACH_NLRI
:
3642 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3644 case BGP_ATTR_MP_UNREACH_NLRI
:
3645 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3647 case BGP_ATTR_EXT_COMMUNITIES
:
3648 ret
= bgp_attr_ext_communities(&attr_args
);
3650 #ifdef ENABLE_BGP_VNC_ATTR
3653 case BGP_ATTR_ENCAP
:
3654 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3657 case BGP_ATTR_PREFIX_SID
:
3658 ret
= bgp_attr_prefix_sid(&attr_args
);
3660 case BGP_ATTR_PMSI_TUNNEL
:
3661 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3663 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3664 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3667 ret
= bgp_attr_otc(&attr_args
);
3670 ret
= bgp_attr_aigp(&attr_args
);
3673 ret
= bgp_attr_unknown(&attr_args
);
3677 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3678 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3679 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3680 ret
= BGP_ATTR_PARSE_ERROR
;
3684 if (ret
== BGP_ATTR_PARSE_EOR
) {
3688 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3689 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3690 "%s: Attribute %s, parse error", peer
->host
,
3691 lookup_msg(attr_str
, type
, NULL
));
3694 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3696 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3697 "%s: Attribute %s, parse error - treating as withdrawal",
3698 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3702 /* Check the fetched length. */
3703 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3704 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3705 "%s: BGP attribute %s, fetch error",
3706 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3707 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3708 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3709 ret
= BGP_ATTR_PARSE_ERROR
;
3715 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3716 * About Prefix-SID path attribute,
3717 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3718 * may only appear in a BGP Prefix-SID attribute attached to
3719 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3720 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3722 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3723 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3725 /* Check final read pointer is same as end pointer. */
3726 if (BGP_INPUT_PNT(peer
) != endp
) {
3727 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3728 "%s: BGP attribute %s, length mismatch", peer
->host
,
3729 lookup_msg(attr_str
, type
, NULL
));
3730 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3731 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3733 ret
= BGP_ATTR_PARSE_ERROR
;
3738 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3739 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3740 * This is implemented below and will result in a NOTIFICATION. If the
3741 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3742 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3743 * message SHOULD NOT be sent. This is implemented elsewhere.
3745 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3746 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3747 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3748 * speaker that receives the message SHOULD ignore this attribute.
3750 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3751 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3752 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3753 ret
= BGP_ATTR_PARSE_ERROR
;
3758 /* Check all mandatory well-known attributes are present */
3759 ret
= bgp_attr_check(peer
, attr
);
3764 * At this place we can see whether we got AS4_PATH and/or
3765 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3766 * We can not do this before we've read all attributes because
3767 * the as4 handling does not say whether AS4_PATH has to be sent
3768 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3769 * in relationship to AGGREGATOR.
3770 * So, to be defensive, we are not relying on any order and read
3771 * all attributes first, including these 32bit ones, and now,
3772 * afterwards, we look what and if something is to be done for as4.
3774 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3777 /* actually... this doesn't ever return failure currently, but
3778 * better safe than sorry */
3779 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3780 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3781 &as4_aggregator_addr
)) {
3782 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3783 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3784 ret
= BGP_ATTR_PARSE_ERROR
;
3789 * Finally do the checks on the aspath we did not do yet
3790 * because we waited for a potentially synthesized aspath.
3792 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3793 ret
= bgp_attr_aspath_check(peer
, attr
);
3794 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3798 ret
= BGP_ATTR_PARSE_PROCEED
;
3802 * At this stage, we have done all fiddling with as4, and the
3803 * resulting info is in attr->aggregator resp. attr->aspath so
3804 * we can chuck as4_aggregator and as4_path alltogether in order
3808 * unintern - it is in the hash
3809 * The flag that we got this is still there, but that
3810 * does not do any trouble
3812 aspath_unintern(&as4_path
);
3814 transit
= bgp_attr_get_transit(attr
);
3815 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3816 /* Finally intern unknown attribute. */
3818 bgp_attr_set_transit(attr
, transit_intern(transit
));
3819 if (attr
->encap_subtlvs
)
3820 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3822 #ifdef ENABLE_BGP_VNC
3823 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3824 bgp_attr_get_vnc_subtlvs(attr
);
3827 bgp_attr_set_vnc_subtlvs(
3829 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3833 transit_free(transit
);
3834 bgp_attr_set_transit(attr
, NULL
);
3837 bgp_attr_flush_encap(attr
);
3841 transit
= bgp_attr_get_transit(attr
);
3843 assert(transit
->refcnt
> 0);
3844 if (attr
->encap_subtlvs
)
3845 assert(attr
->encap_subtlvs
->refcnt
> 0);
3846 #ifdef ENABLE_BGP_VNC
3847 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3848 bgp_attr_get_vnc_subtlvs(attr
);
3851 assert(vnc_subtlvs
->refcnt
> 0);
3858 * Extract the tunnel type from extended community
3860 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3861 bgp_encap_types
*tunnel_type
)
3863 struct ecommunity
*ecom
;
3869 ecom
= bgp_attr_get_ecommunity(attr
);
3870 if (!ecom
|| !ecom
->size
)
3873 for (i
= 0; i
< ecom
->size
; i
++) {
3875 uint8_t type
, sub_type
;
3877 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3880 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3881 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3883 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3890 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3891 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3895 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
3896 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
3899 /* Set extended bit always to encode the attribute length as 2 bytes */
3900 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3901 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3902 sizep
= stream_get_endp(s
);
3903 stream_putw(s
, 0); /* Marker: Attribute length. */
3906 /* Convert AFI, SAFI to values for packet. */
3907 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3909 stream_putw(s
, pkt_afi
); /* AFI */
3910 stream_putc(s
, pkt_safi
); /* SAFI */
3914 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3915 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3916 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3917 else if (safi
== SAFI_FLOWSPEC
)
3920 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3923 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3928 case SAFI_MULTICAST
:
3929 case SAFI_LABELED_UNICAST
:
3931 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3935 stream_putl(s
, 0); /* RD = 0, per RFC */
3937 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3942 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3945 if (attr
->mp_nexthop_len
== 0)
3946 stream_putc(s
, 0); /* no nexthop for flowspec */
3948 stream_putc(s
, attr
->mp_nexthop_len
);
3949 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3954 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
3961 case SAFI_MULTICAST
:
3962 case SAFI_LABELED_UNICAST
:
3964 if (attr
->mp_nexthop_len
3965 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3967 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3968 stream_put(s
, &attr
->mp_nexthop_global
,
3970 stream_put(s
, &attr
->mp_nexthop_local
,
3973 stream_putc(s
, IPV6_MAX_BYTELEN
);
3974 stream_put(s
, &attr
->mp_nexthop_global
,
3978 case SAFI_MPLS_VPN
: {
3979 if (attr
->mp_nexthop_len
==
3980 BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
3982 stream_putl(s
, 0); /* RD = 0, per RFC */
3984 stream_put(s
, &attr
->mp_nexthop_global
,
3986 stream_putl(s
, 0); /* RD = 0, per RFC */
3988 stream_put(s
, &attr
->mp_nexthop_local
,
3992 stream_putl(s
, 0); /* RD = 0, per RFC */
3994 stream_put(s
, &attr
->mp_nexthop_global
,
3999 stream_putc(s
, IPV6_MAX_BYTELEN
);
4000 stream_put(s
, &attr
->mp_nexthop_global
,
4004 stream_putc(s
, 0); /* no nexthop for flowspec */
4008 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
4013 if (safi
!= SAFI_FLOWSPEC
)
4015 EC_BGP_ATTR_NH_SEND_LEN
,
4016 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
4017 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
4021 assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here");
4030 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
4031 const struct prefix
*p
,
4032 const struct prefix_rd
*prd
, mpls_label_t
*label
,
4033 uint32_t num_labels
, bool addpath_capable
,
4034 uint32_t addpath_tx_id
, struct attr
*attr
)
4039 assert(!"Dev escape usage of SAFI_UNSPEC or MAX");
4042 if (addpath_capable
)
4043 stream_putl(s
, addpath_tx_id
);
4044 /* Label, RD, Prefix write. */
4045 stream_putc(s
, p
->prefixlen
+ 88);
4046 stream_put(s
, label
, BGP_LABEL_BYTES
);
4047 stream_put(s
, prd
->val
, 8);
4048 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
4051 if (afi
== AFI_L2VPN
)
4052 /* EVPN prefix - contents depend on type */
4053 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
,
4054 attr
, addpath_capable
,
4057 assert(!"Add encoding bits here for other AFI's");
4059 case SAFI_LABELED_UNICAST
:
4060 /* Prefix write with label. */
4061 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
4065 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
4066 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
4067 p
->u
.prefix_flowspec
.prefixlen
);
4071 case SAFI_MULTICAST
:
4072 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
4075 assert(!"Please add proper encoding of SAFI_ENCAP");
4080 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
4081 const struct prefix
*p
)
4083 int size
= PSIZE(p
->prefixlen
);
4088 assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE");
4091 case SAFI_MULTICAST
:
4097 /* This has to be wrong, but I don't know what to put here */
4098 assert(!"Do we try to use this?");
4100 case SAFI_LABELED_UNICAST
:
4101 size
+= BGP_LABEL_BYTES
;
4105 * TODO: Maximum possible for type-2, type-3 and type-5
4107 if (afi
== AFI_L2VPN
)
4110 assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values");
4113 size
= ((struct prefix_fs
*)p
)->prefix
.prefixlen
;
4121 * Encodes the tunnel encapsulation attribute,
4122 * and with ENABLE_BGP_VNC the VNC attribute which uses
4123 * almost the same TLV format
4125 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
4126 struct stream
*s
, struct attr
*attr
,
4129 unsigned int attrlenfield
= 0;
4130 unsigned int attrhdrlen
= 0;
4131 struct bgp_attr_encap_subtlv
*subtlvs
;
4132 struct bgp_attr_encap_subtlv
*st
;
4133 const char *attrname
;
4135 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
4136 && (!attr
->encap_tunneltype
4137 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
4141 case BGP_ATTR_ENCAP
:
4142 attrname
= "Tunnel Encap";
4143 subtlvs
= attr
->encap_subtlvs
;
4144 if (subtlvs
== NULL
) /* nothing to do */
4147 * The tunnel encap attr has an "outer" tlv.
4149 * L = total length of subtlvs,
4150 * V = concatenated subtlvs.
4152 attrlenfield
= 2 + 2; /* T + L */
4153 attrhdrlen
= 1 + 1; /* subTLV T + L */
4156 #ifdef ENABLE_BGP_VNC_ATTR
4159 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
4160 if (subtlvs
== NULL
) /* nothing to do */
4162 attrlenfield
= 0; /* no outer T + L */
4163 attrhdrlen
= 2 + 2; /* subTLV T + L */
4171 /* compute attr length */
4172 for (st
= subtlvs
; st
; st
= st
->next
) {
4173 attrlenfield
+= (attrhdrlen
+ st
->length
);
4176 if (attrlenfield
> 0xffff) {
4177 zlog_info("%s attribute is too long (length=%d), can't send it",
4178 attrname
, attrlenfield
);
4182 if (attrlenfield
> 0xff) {
4183 /* 2-octet length field */
4185 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4186 | BGP_ATTR_FLAG_EXTLEN
);
4187 stream_putc(s
, attrtype
);
4188 stream_putw(s
, attrlenfield
& 0xffff);
4190 /* 1-octet length field */
4191 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
4192 stream_putc(s
, attrtype
);
4193 stream_putc(s
, attrlenfield
& 0xff);
4196 if (attrtype
== BGP_ATTR_ENCAP
) {
4197 /* write outer T+L */
4198 stream_putw(s
, attr
->encap_tunneltype
);
4199 stream_putw(s
, attrlenfield
- 4);
4202 /* write each sub-tlv */
4203 for (st
= subtlvs
; st
; st
= st
->next
) {
4204 if (attrtype
== BGP_ATTR_ENCAP
) {
4205 stream_putc(s
, st
->type
);
4206 stream_putc(s
, st
->length
);
4207 #ifdef ENABLE_BGP_VNC
4209 stream_putw(s
, st
->type
);
4210 stream_putw(s
, st
->length
);
4213 stream_put(s
, st
->value
, st
->length
);
4217 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
4219 /* Set MP attribute length. Don't count the (2) bytes used to encode
4221 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
4224 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
4226 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
4227 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
4228 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4229 PEER_FLAG_REMOVE_PRIVATE_AS
)
4230 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4231 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
4232 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4233 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
4234 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4235 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
4240 /* Make attribute packet. */
4241 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
4242 struct stream
*s
, struct attr
*attr
,
4243 struct bpacket_attr_vec_arr
*vecarr
,
4244 struct prefix
*p
, afi_t afi
, safi_t safi
,
4245 struct peer
*from
, struct prefix_rd
*prd
,
4246 mpls_label_t
*label
, uint32_t num_labels
,
4247 bool addpath_capable
, uint32_t addpath_tx_id
,
4248 struct bgp_path_info
*bpi
)
4251 size_t aspath_sizep
;
4252 struct aspath
*aspath
;
4253 int send_as4_path
= 0;
4254 int send_as4_aggregator
= 0;
4255 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
4256 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
4261 /* Remember current pointer. */
4262 cp
= stream_get_endp(s
);
4265 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
4266 && !peer_cap_enhe(peer
, afi
, safi
))) {
4267 size_t mpattrlen_pos
= 0;
4269 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
4271 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
4272 num_labels
, addpath_capable
,
4273 addpath_tx_id
, attr
);
4274 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
4277 /* Origin attribute. */
4278 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4279 stream_putc(s
, BGP_ATTR_ORIGIN
);
4281 stream_putc(s
, attr
->origin
);
4283 /* AS path attribute. */
4285 /* If remote-peer is EBGP */
4286 if (peer
->sort
== BGP_PEER_EBGP
4287 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4288 PEER_FLAG_AS_PATH_UNCHANGED
)
4289 || attr
->aspath
->segments
== NULL
)
4290 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4291 PEER_FLAG_RSERVER_CLIENT
))) {
4292 aspath
= aspath_dup(attr
->aspath
);
4294 /* Even though we may not be configured for confederations we
4296 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4297 aspath
= aspath_delete_confed_seq(aspath
);
4299 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
4300 /* Stuff our path CONFED_ID on the front */
4301 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
4303 if (peer
->change_local_as
) {
4304 /* If replace-as is specified, we only use the
4305 change_local_as when
4306 advertising routes. */
4307 if (!CHECK_FLAG(peer
->flags
,
4308 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
4309 if (bgp_append_local_as(peer
, afi
,
4311 aspath
= aspath_add_seq(
4312 aspath
, peer
->local_as
);
4313 aspath
= aspath_add_seq(aspath
,
4314 peer
->change_local_as
);
4316 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
4319 } else if (peer
->sort
== BGP_PEER_CONFED
) {
4320 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4322 aspath
= aspath_dup(attr
->aspath
);
4323 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
4325 aspath
= attr
->aspath
;
4327 /* If peer is not AS4 capable, then:
4328 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4329 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4331 * types are in it (i.e. exclude them if they are there)
4332 * AND do this only if there is at least one asnum > 65535 in the
4334 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4336 * all ASnums > 65535 to BGP_AS_TRANS
4339 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4340 stream_putc(s
, BGP_ATTR_AS_PATH
);
4341 aspath_sizep
= stream_get_endp(s
);
4343 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4345 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4348 if (!use32bit
&& aspath_has_as4(aspath
))
4350 1; /* we'll do this later, at the correct place */
4352 /* Nexthop attribute. */
4353 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4354 && !peer_cap_enhe(peer
, afi
, safi
)) {
4355 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4357 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4358 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4359 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4360 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4363 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4364 } else if (peer_cap_enhe(from
, afi
, safi
)
4365 || (nh_afi
== AFI_IP6
)) {
4367 * Likely this is the case when an IPv4 prefix was
4368 * received with Extended Next-hop capability in this
4369 * or another vrf and is now being advertised to
4370 * non-ENHE peers. Since peer_cap_enhe only checks
4371 * peers in this vrf, also check the nh_afi to catch
4372 * the case where the originator was in another vrf.
4373 * Setting the mandatory (ipv4) next-hop attribute here
4374 * to enable implicit next-hop self with correct A-F
4375 * (ipv4 address family).
4377 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4378 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4379 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4382 stream_put_ipv4(s
, 0);
4386 /* MED attribute. */
4387 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4388 || bgp
->maxmed_active
) {
4389 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4390 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4392 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4396 /* Local preference. */
4397 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4398 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4399 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4401 stream_putl(s
, attr
->local_pref
);
4404 /* Atomic aggregate. */
4405 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4406 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4407 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4412 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4413 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4414 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4415 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4418 /* AS4 capable peer */
4420 stream_putl(s
, attr
->aggregator_as
);
4422 /* 2-byte AS peer */
4425 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4427 if (attr
->aggregator_as
> UINT16_MAX
) {
4428 stream_putw(s
, BGP_AS_TRANS
);
4430 /* we have to send AS4_AGGREGATOR, too.
4431 * we'll do that later in order to send
4432 * attributes in ascending
4435 send_as4_aggregator
= 1;
4437 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4439 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4442 /* Community attribute. */
4443 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4444 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4445 struct community
*comm
= NULL
;
4447 comm
= bgp_attr_get_community(attr
);
4448 if (comm
->size
* 4 > 255) {
4450 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4451 | BGP_ATTR_FLAG_EXTLEN
);
4452 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4453 stream_putw(s
, comm
->size
* 4);
4456 BGP_ATTR_FLAG_OPTIONAL
4457 | BGP_ATTR_FLAG_TRANS
);
4458 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4459 stream_putc(s
, comm
->size
* 4);
4461 stream_put(s
, comm
->val
, comm
->size
* 4);
4465 * Large Community attribute.
4467 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4468 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4469 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4470 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4472 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4473 | BGP_ATTR_FLAG_EXTLEN
);
4474 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4476 lcom_length(bgp_attr_get_lcommunity(attr
)));
4479 BGP_ATTR_FLAG_OPTIONAL
4480 | BGP_ATTR_FLAG_TRANS
);
4481 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4483 lcom_length(bgp_attr_get_lcommunity(attr
)));
4485 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4486 lcom_length(bgp_attr_get_lcommunity(attr
)));
4489 /* Route Reflector. */
4490 if (peer
->sort
== BGP_PEER_IBGP
&& from
4491 && from
->sort
== BGP_PEER_IBGP
) {
4492 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4494 /* Originator ID. */
4495 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4496 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4499 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4500 stream_put_in_addr(s
, &attr
->originator_id
);
4502 stream_put_in_addr(s
, &from
->remote_id
);
4505 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4506 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4509 stream_putc(s
, cluster
->length
+ 4);
4510 /* If this peer configuration's parent BGP has
4512 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4513 stream_put_in_addr(s
, &bgp
->cluster_id
);
4515 stream_put_in_addr(s
, &bgp
->router_id
);
4516 stream_put(s
, cluster
->list
, cluster
->length
);
4519 /* If this peer configuration's parent BGP has
4521 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4522 stream_put_in_addr(s
, &bgp
->cluster_id
);
4524 stream_put_in_addr(s
, &bgp
->router_id
);
4528 /* Extended Communities attribute. */
4529 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4530 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4531 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4532 bool transparent
= CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4533 PEER_FLAG_RSERVER_CLIENT
) &&
4535 CHECK_FLAG(from
->af_flags
[afi
][safi
],
4536 PEER_FLAG_RSERVER_CLIENT
);
4538 if (peer
->sort
== BGP_PEER_IBGP
||
4539 peer
->sort
== BGP_PEER_CONFED
|| transparent
) {
4540 if (ecomm
->size
* 8 > 255) {
4542 BGP_ATTR_FLAG_OPTIONAL
4543 | BGP_ATTR_FLAG_TRANS
4544 | BGP_ATTR_FLAG_EXTLEN
);
4545 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4546 stream_putw(s
, ecomm
->size
* 8);
4549 BGP_ATTR_FLAG_OPTIONAL
4550 | BGP_ATTR_FLAG_TRANS
);
4551 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4552 stream_putc(s
, ecomm
->size
* 8);
4554 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4558 int ecom_tr_size
= 0;
4561 for (i
= 0; i
< ecomm
->size
; i
++) {
4562 pnt
= ecomm
->val
+ (i
* 8);
4565 if (CHECK_FLAG(tbit
,
4566 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4573 if (ecom_tr_size
* 8 > 255) {
4576 BGP_ATTR_FLAG_OPTIONAL
4577 | BGP_ATTR_FLAG_TRANS
4578 | BGP_ATTR_FLAG_EXTLEN
);
4580 BGP_ATTR_EXT_COMMUNITIES
);
4581 stream_putw(s
, ecom_tr_size
* 8);
4585 BGP_ATTR_FLAG_OPTIONAL
4586 | BGP_ATTR_FLAG_TRANS
);
4588 BGP_ATTR_EXT_COMMUNITIES
);
4589 stream_putc(s
, ecom_tr_size
* 8);
4592 for (i
= 0; i
< ecomm
->size
; i
++) {
4593 pnt
= ecomm
->val
+ (i
* 8);
4598 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4601 stream_put(s
, pnt
, 8);
4607 /* Label index attribute. */
4608 if (safi
== SAFI_LABELED_UNICAST
) {
4609 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4610 uint32_t label_index
;
4612 label_index
= attr
->label_index
;
4614 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4616 BGP_ATTR_FLAG_OPTIONAL
4617 | BGP_ATTR_FLAG_TRANS
);
4618 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4620 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4622 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4623 stream_putc(s
, 0); // reserved
4624 stream_putw(s
, 0); // flags
4625 stream_putl(s
, label_index
);
4630 /* SRv6 Service Information Attribute. */
4631 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4632 if (attr
->srv6_l3vpn
) {
4633 uint8_t subtlv_len
=
4634 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4636 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4637 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4638 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4639 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4640 | BGP_ATTR_FLAG_TRANS
);
4641 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4642 stream_putc(s
, attr_len
);
4643 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4644 stream_putw(s
, tlv_len
);
4645 stream_putc(s
, 0); /* reserved */
4646 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4647 stream_putw(s
, subtlv_len
);
4648 stream_putc(s
, 0); /* reserved */
4649 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4650 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4651 stream_putc(s
, 0); /* sid_flags */
4654 ->endpoint_behavior
); /* endpoint */
4655 stream_putc(s
, 0); /* reserved */
4658 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4661 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4662 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4663 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4664 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4665 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4666 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4667 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4668 } else if (attr
->srv6_vpn
) {
4669 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4670 | BGP_ATTR_FLAG_TRANS
);
4671 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4672 stream_putc(s
, 22); /* tlv len */
4673 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4674 stream_putw(s
, 0x13); /* tlv len */
4675 stream_putc(s
, 0x00); /* reserved */
4676 stream_putc(s
, 0x01); /* sid_type */
4677 stream_putc(s
, 0x00); /* sif_flags */
4678 stream_put(s
, &attr
->srv6_vpn
->sid
,
4679 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4683 if (send_as4_path
) {
4684 /* If the peer is NOT As4 capable, AND */
4685 /* there are ASnums > 65535 in path THEN
4686 * give out AS4_PATH */
4688 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4690 * Hm, I wonder... confederation things *should* only be at
4691 * the beginning of an aspath, right? Then we should use
4692 * aspath_delete_confed_seq for this, because it is already
4694 * Folks, talk to me: what is reasonable here!?
4696 aspath
= aspath_delete_confed_seq(aspath
);
4699 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4700 | BGP_ATTR_FLAG_EXTLEN
);
4701 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4702 aspath_sizep
= stream_get_endp(s
);
4704 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4707 if (aspath
!= attr
->aspath
)
4708 aspath_free(aspath
);
4710 if (send_as4_aggregator
) {
4711 /* send AS4_AGGREGATOR, at this place */
4712 /* this section of code moved here in order to ensure the
4714 * *ascending* order of attributes
4716 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4717 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4719 stream_putl(s
, attr
->aggregator_as
);
4720 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4723 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4724 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4725 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4726 /* Tunnel Encap attribute */
4727 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4729 #ifdef ENABLE_BGP_VNC_ATTR
4731 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4736 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4737 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4738 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4739 stream_putc(s
, 9); // Length
4740 stream_putc(s
, 0); // Flags
4741 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4742 stream_put(s
, &(attr
->label
),
4743 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4744 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4745 // Unicast tunnel endpoint IP address
4749 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4750 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4751 stream_putc(s
, BGP_ATTR_OTC
);
4753 stream_putl(s
, attr
->otc
);
4757 if (bpi
&& attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
) &&
4758 (CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
) ||
4759 peer
->sort
!= BGP_PEER_EBGP
)) {
4760 /* At the moment only AIGP Metric TLV exists for AIGP
4761 * attribute. If more comes in, do not forget to update
4762 * attr_len variable to include new ones.
4764 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4766 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4767 stream_putc(s
, BGP_ATTR_AIGP
);
4768 stream_putc(s
, attr_len
);
4769 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4772 /* Unknown transit attribute. */
4773 struct transit
*transit
= bgp_attr_get_transit(attr
);
4776 stream_put(s
, transit
->val
, transit
->length
);
4778 /* Return total size of attribute. */
4779 return stream_get_endp(s
) - cp
;
4782 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4784 unsigned long attrlen_pnt
;
4785 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
4786 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
4788 /* Set extended bit always to encode the attribute length as 2 bytes */
4789 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4790 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4792 attrlen_pnt
= stream_get_endp(s
);
4793 stream_putw(s
, 0); /* Length of this attribute. */
4795 /* Convert AFI, SAFI to values for packet. */
4796 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4798 stream_putw(s
, pkt_afi
);
4799 stream_putc(s
, pkt_safi
);
4804 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4805 afi_t afi
, safi_t safi
,
4806 const struct prefix_rd
*prd
,
4807 mpls_label_t
*label
, uint32_t num_labels
,
4808 bool addpath_capable
, uint32_t addpath_tx_id
,
4811 uint8_t wlabel
[4] = {0x80, 0x00, 0x00};
4813 if (safi
== SAFI_LABELED_UNICAST
) {
4814 label
= (mpls_label_t
*)wlabel
;
4818 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4819 addpath_capable
, addpath_tx_id
, attr
);
4822 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4824 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4827 /* Initialization of attribute. */
4828 void bgp_attr_init(void)
4841 void bgp_attr_finish(void)
4846 ecommunity_finish();
4847 lcommunity_finish();
4854 /* Make attribute packet. */
4855 void bgp_dump_routes_attr(struct stream
*s
, struct bgp_path_info
*bpi
,
4856 const struct prefix
*prefix
)
4861 struct aspath
*aspath
;
4862 bool addpath_capable
= false;
4863 uint32_t addpath_tx_id
= 0;
4864 struct attr
*attr
= bpi
->attr
;
4866 /* Remember current pointer. */
4867 cp
= stream_get_endp(s
);
4869 /* Place holder of length. */
4872 /* Origin attribute. */
4873 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4874 stream_putc(s
, BGP_ATTR_ORIGIN
);
4876 stream_putc(s
, attr
->origin
);
4878 aspath
= attr
->aspath
;
4880 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4881 stream_putc(s
, BGP_ATTR_AS_PATH
);
4882 aspath_lenp
= stream_get_endp(s
);
4885 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4887 /* Nexthop attribute. */
4888 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4889 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4890 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4891 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4893 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4896 /* MED attribute. */
4897 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4898 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4899 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4901 stream_putl(s
, attr
->med
);
4904 /* Local preference. */
4905 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4906 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4907 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4909 stream_putl(s
, attr
->local_pref
);
4912 /* Atomic aggregate. */
4913 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4914 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4915 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4920 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4921 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4922 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4924 stream_putl(s
, attr
->aggregator_as
);
4925 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4928 /* Community attribute. */
4929 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4930 struct community
*comm
= NULL
;
4932 comm
= bgp_attr_get_community(attr
);
4933 if (comm
->size
* 4 > 255) {
4935 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4936 | BGP_ATTR_FLAG_EXTLEN
);
4937 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4938 stream_putw(s
, comm
->size
* 4);
4941 BGP_ATTR_FLAG_OPTIONAL
4942 | BGP_ATTR_FLAG_TRANS
);
4943 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4944 stream_putc(s
, comm
->size
* 4);
4946 stream_put(s
, comm
->val
, comm
->size
* 4);
4949 /* Large Community attribute. */
4950 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4951 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4953 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4954 | BGP_ATTR_FLAG_EXTLEN
);
4955 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4957 lcom_length(bgp_attr_get_lcommunity(attr
)));
4960 BGP_ATTR_FLAG_OPTIONAL
4961 | BGP_ATTR_FLAG_TRANS
);
4962 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4964 lcom_length(bgp_attr_get_lcommunity(attr
)));
4967 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4968 lcom_length(bgp_attr_get_lcommunity(attr
)));
4971 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4972 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4973 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4974 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4977 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4978 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4979 sizep
= stream_get_endp(s
);
4982 stream_putc(s
, 0); /* Marker: Attribute length. */
4983 stream_putw(s
, AFI_IP6
); /* AFI */
4984 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4987 stream_putc(s
, attr
->mp_nexthop_len
);
4988 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4989 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4990 stream_put(s
, &attr
->mp_nexthop_local
,
4997 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
5000 /* Set MP attribute length. */
5001 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
5005 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
5006 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5008 BGP_ATTR_FLAG_OPTIONAL
5009 | BGP_ATTR_FLAG_TRANS
);
5010 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
5012 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
5013 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
5014 stream_putc(s
, 0); // reserved
5015 stream_putw(s
, 0); // flags
5016 stream_putl(s
, attr
->label_index
);
5021 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
5022 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
5023 stream_putc(s
, BGP_ATTR_OTC
);
5025 stream_putl(s
, attr
->otc
);
5029 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
5030 /* At the moment only AIGP Metric TLV exists for AIGP
5031 * attribute. If more comes in, do not forget to update
5032 * attr_len variable to include new ones.
5034 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
5036 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
5037 stream_putc(s
, BGP_ATTR_AIGP
);
5038 stream_putc(s
, attr_len
);
5039 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
5042 /* Return total size of attribute. */
5043 len
= stream_get_endp(s
) - cp
- 2;
5044 stream_putw_at(s
, cp
, len
);
5047 void bgp_path_attribute_discard_vty(struct vty
*vty
, struct peer
*peer
,
5048 const char *discard_attrs
, bool set
)
5050 int i
, num_attributes
;
5056 /* If `no` command specified without arbitrary attributes,
5059 if (!discard_attrs
) {
5060 for (i
= 0; i
< BGP_ATTR_MAX
; i
++)
5061 peer
->discard_attrs
[i
] = false;
5062 goto discard_soft_clear
;
5065 if (discard_attrs
) {
5066 frrstr_split(discard_attrs
, " ", &attributes
, &num_attributes
);
5069 for (i
= 0; i
< BGP_ATTR_MAX
; i
++)
5070 peer
->discard_attrs
[i
] = false;
5072 for (i
= 0; i
< num_attributes
; i
++) {
5073 uint8_t attr_num
= strtoul(attributes
[i
], NULL
, 10);
5075 XFREE(MTYPE_TMP
, attributes
[i
]);
5077 /* Some of the attributes, just can't be ignored. */
5078 if (attr_num
== BGP_ATTR_ORIGIN
||
5079 attr_num
== BGP_ATTR_AS_PATH
||
5080 attr_num
== BGP_ATTR_NEXT_HOP
||
5081 attr_num
== BGP_ATTR_MULTI_EXIT_DISC
||
5082 attr_num
== BGP_ATTR_MP_REACH_NLRI
||
5083 attr_num
== BGP_ATTR_MP_UNREACH_NLRI
||
5084 attr_num
== BGP_ATTR_EXT_COMMUNITIES
) {
5086 "%% Can't discard path-attribute %s, ignoring.\n",
5087 lookup_msg(attr_str
, attr_num
, NULL
));
5091 /* Ignore local-pref, originator-id, cluster-list only
5094 if (peer
->sort
!= BGP_PEER_EBGP
&&
5095 (attr_num
== BGP_ATTR_LOCAL_PREF
||
5096 attr_num
== BGP_ATTR_ORIGINATOR_ID
||
5097 attr_num
== BGP_ATTR_CLUSTER_LIST
)) {
5099 "%% Can discard path-attribute %s only for eBGP, ignoring.\n",
5100 lookup_msg(attr_str
, attr_num
, NULL
));
5104 peer
->discard_attrs
[attr_num
] = set
;
5106 XFREE(MTYPE_TMP
, attributes
);
5108 /* Configuring path attributes to be discarded will trigger
5109 * an inbound Route Refresh to ensure that the routing table
5112 FOREACH_AFI_SAFI (afi
, safi
)
5113 peer_clear_soft(peer
, afi
, safi
, BGP_CLEAR_SOFT_IN
);
5117 void bgp_path_attribute_withdraw_vty(struct vty
*vty
, struct peer
*peer
,
5118 const char *withdraw_attrs
, bool set
)
5120 int i
, num_attributes
;
5125 /* If `no` command specified without arbitrary attributes,
5128 if (!withdraw_attrs
) {
5129 for (i
= 0; i
< BGP_ATTR_MAX
; i
++)
5130 peer
->withdraw_attrs
[i
] = false;
5131 goto withdraw_soft_clear
;
5134 if (withdraw_attrs
) {
5135 frrstr_split(withdraw_attrs
, " ", &attributes
, &num_attributes
);
5138 for (i
= 0; i
< BGP_ATTR_MAX
; i
++)
5139 peer
->withdraw_attrs
[i
] = false;
5141 for (i
= 0; i
< num_attributes
; i
++) {
5142 uint8_t attr_num
= strtoul(attributes
[i
], NULL
, 10);
5144 XFREE(MTYPE_TMP
, attributes
[i
]);
5146 /* Some of the attributes, just can't be ignored. */
5147 if (attr_num
== BGP_ATTR_ORIGIN
||
5148 attr_num
== BGP_ATTR_AS_PATH
||
5149 attr_num
== BGP_ATTR_NEXT_HOP
||
5150 attr_num
== BGP_ATTR_MULTI_EXIT_DISC
||
5151 attr_num
== BGP_ATTR_MP_REACH_NLRI
||
5152 attr_num
== BGP_ATTR_MP_UNREACH_NLRI
||
5153 attr_num
== BGP_ATTR_EXT_COMMUNITIES
) {
5155 "%% Can't treat-as-withdraw path-attribute %s, ignoring.\n",
5156 lookup_msg(attr_str
, attr_num
, NULL
));
5160 /* Ignore local-pref, originator-id, cluster-list only
5163 if (peer
->sort
!= BGP_PEER_EBGP
&&
5164 (attr_num
== BGP_ATTR_LOCAL_PREF
||
5165 attr_num
== BGP_ATTR_ORIGINATOR_ID
||
5166 attr_num
== BGP_ATTR_CLUSTER_LIST
)) {
5168 "%% Can treat-as-withdraw path-attribute %s only for eBGP, ignoring.\n",
5169 lookup_msg(attr_str
, attr_num
, NULL
));
5173 peer
->withdraw_attrs
[attr_num
] = set
;
5175 XFREE(MTYPE_TMP
, attributes
);
5176 withdraw_soft_clear
:
5177 /* Configuring path attributes to be treated as withdraw will
5179 * an inbound Route Refresh to ensure that the routing table
5182 FOREACH_AFI_SAFI (afi
, safi
)
5183 peer_clear_soft(peer
, afi
, safi
, BGP_CLEAR_SOFT_IN
);
5187 enum bgp_attr_parse_ret
bgp_attr_ignore(struct peer
*peer
, uint8_t type
)
5189 bool discard
= peer
->discard_attrs
[type
];
5190 bool withdraw
= peer
->withdraw_attrs
[type
];
5192 if (bgp_debug_update(peer
, NULL
, NULL
, 1) && (discard
|| withdraw
))
5193 zlog_debug("%pBP: Ignoring attribute %s (%s)", peer
,
5194 lookup_msg(attr_str
, type
, NULL
),
5195 withdraw
? "treat-as-withdraw" : "discard");
5197 return withdraw
? BGP_ATTR_PARSE_WITHDRAW
: BGP_ATTR_PARSE_PROCEED
;