1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_aspath.h"
41 #include "bgpd/bgp_community.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_errors.h"
44 #include "bgpd/bgp_label.h"
45 #include "bgpd/bgp_packet.h"
46 #include "bgpd/bgp_ecommunity.h"
47 #include "bgpd/bgp_lcommunity.h"
48 #include "bgpd/bgp_updgrp.h"
49 #include "bgpd/bgp_encap_types.h"
51 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
52 #include "bgp_encap_types.h"
53 #include "bgp_vnc_types.h"
56 #include "bgp_flowspec_private.h"
59 /* Attribute strings for logging. */
60 static const struct message attr_str
[] = {
61 {BGP_ATTR_ORIGIN
, "ORIGIN"},
62 {BGP_ATTR_AS_PATH
, "AS_PATH"},
63 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
64 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
65 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
66 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
67 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
68 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
69 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
70 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
71 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
72 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
73 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
74 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
75 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
76 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
77 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
78 {BGP_ATTR_ENCAP
, "ENCAP"},
79 {BGP_ATTR_OTC
, "OTC"},
80 #ifdef ENABLE_BGP_VNC_ATTR
81 {BGP_ATTR_VNC
, "VNC"},
83 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
84 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
85 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
86 {BGP_ATTR_AIGP
, "AIGP"},
89 static const struct message attr_flag_str
[] = {
90 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
91 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
92 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
93 /* bgp_attr_flags_diagnose() relies on this bit being last in
95 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
98 static struct hash
*cluster_hash
;
100 static void *cluster_hash_alloc(void *p
)
102 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
103 struct cluster_list
*cluster
;
105 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
106 cluster
->length
= val
->length
;
108 if (cluster
->length
) {
109 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
110 memcpy(cluster
->list
, val
->list
, val
->length
);
112 cluster
->list
= NULL
;
119 /* Cluster list related functions. */
120 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
122 struct cluster_list tmp
= {};
123 struct cluster_list
*cluster
;
126 tmp
.list
= length
== 0 ? NULL
: pnt
;
128 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
133 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
137 for (i
= 0; i
< cluster
->length
/ 4; i
++)
138 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
143 static unsigned int cluster_hash_key_make(const void *p
)
145 const struct cluster_list
*cluster
= p
;
147 return jhash(cluster
->list
, cluster
->length
, 0);
150 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
152 const struct cluster_list
*cluster1
= p1
;
153 const struct cluster_list
*cluster2
= p2
;
155 if (cluster1
->list
== cluster2
->list
)
158 if (!cluster1
->list
|| !cluster2
->list
)
161 if (cluster1
->length
!= cluster2
->length
)
164 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
167 static void cluster_free(struct cluster_list
*cluster
)
169 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
170 XFREE(MTYPE_CLUSTER
, cluster
);
173 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
175 struct cluster_list
*find
;
177 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
183 static void cluster_unintern(struct cluster_list
**cluster
)
185 if ((*cluster
)->refcnt
)
186 (*cluster
)->refcnt
--;
188 if ((*cluster
)->refcnt
== 0) {
189 void *p
= hash_release(cluster_hash
, *cluster
);
190 assert(p
== *cluster
);
191 cluster_free(*cluster
);
196 static void cluster_init(void)
198 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
202 static void cluster_finish(void)
204 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
205 hash_free(cluster_hash
);
209 static struct hash
*encap_hash
= NULL
;
210 #ifdef ENABLE_BGP_VNC
211 static struct hash
*vnc_hash
= NULL
;
213 static struct hash
*srv6_l3vpn_hash
;
214 static struct hash
*srv6_vpn_hash
;
216 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
218 struct bgp_attr_encap_subtlv
*new;
219 struct bgp_attr_encap_subtlv
*tail
;
220 struct bgp_attr_encap_subtlv
*p
;
222 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
223 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
225 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
228 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
231 memcpy(tail
, p
, size
);
238 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
240 struct bgp_attr_encap_subtlv
*next
;
244 XFREE(MTYPE_ENCAP_TLV
, p
);
249 void bgp_attr_flush_encap(struct attr
*attr
)
254 if (attr
->encap_subtlvs
) {
255 encap_free(attr
->encap_subtlvs
);
256 attr
->encap_subtlvs
= NULL
;
258 #ifdef ENABLE_BGP_VNC
259 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
260 bgp_attr_get_vnc_subtlvs(attr
);
263 encap_free(vnc_subtlvs
);
264 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
270 * Compare encap sub-tlv chains
275 * This algorithm could be made faster if needed
277 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
278 const struct bgp_attr_encap_subtlv
*h2
)
280 const struct bgp_attr_encap_subtlv
*p
;
281 const struct bgp_attr_encap_subtlv
*q
;
285 if (h1
== NULL
|| h2
== NULL
)
288 for (p
= h1
; p
; p
= p
->next
) {
289 for (q
= h2
; q
; q
= q
->next
) {
290 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
291 && !memcmp(p
->value
, q
->value
, p
->length
)) {
300 for (p
= h2
; p
; p
= p
->next
) {
301 for (q
= h1
; q
; q
= q
->next
) {
302 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
303 && !memcmp(p
->value
, q
->value
, p
->length
)) {
315 static void *encap_hash_alloc(void *p
)
317 /* Encap structure is already allocated. */
323 #ifdef ENABLE_BGP_VNC
328 static struct bgp_attr_encap_subtlv
*
329 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
331 struct bgp_attr_encap_subtlv
*find
;
332 struct hash
*hash
= encap_hash
;
333 #ifdef ENABLE_BGP_VNC
334 if (type
== VNC_SUBTLV_TYPE
)
338 find
= hash_get(hash
, encap
, encap_hash_alloc
);
346 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
347 encap_subtlv_type type
)
349 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
353 if (encap
->refcnt
== 0) {
354 struct hash
*hash
= encap_hash
;
355 #ifdef ENABLE_BGP_VNC
356 if (type
== VNC_SUBTLV_TYPE
)
359 hash_release(hash
, encap
);
365 static unsigned int encap_hash_key_make(const void *p
)
367 const struct bgp_attr_encap_subtlv
*encap
= p
;
369 return jhash(encap
->value
, encap
->length
, 0);
372 static bool encap_hash_cmp(const void *p1
, const void *p2
)
374 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
375 (const struct bgp_attr_encap_subtlv
*)p2
);
378 static void encap_init(void)
380 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
382 #ifdef ENABLE_BGP_VNC
383 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
388 static void encap_finish(void)
390 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
391 hash_free(encap_hash
);
393 #ifdef ENABLE_BGP_VNC
394 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
400 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
409 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
410 bgp_attr_get_evpn_overlay(a2
));
413 /* Unknown transit attribute. */
414 static struct hash
*transit_hash
;
416 static void transit_free(struct transit
*transit
)
418 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
419 XFREE(MTYPE_TRANSIT
, transit
);
422 static void *transit_hash_alloc(void *p
)
424 /* Transit structure is already allocated. */
428 static struct transit
*transit_intern(struct transit
*transit
)
430 struct transit
*find
;
432 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
434 transit_free(transit
);
440 static void transit_unintern(struct transit
**transit
)
442 if ((*transit
)->refcnt
)
443 (*transit
)->refcnt
--;
445 if ((*transit
)->refcnt
== 0) {
446 hash_release(transit_hash
, *transit
);
447 transit_free(*transit
);
452 static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt
, int length
,
461 ptr_get_be16(data
+ 1, &tlv_length
);
464 /* The value field of the AIGP TLV is always 8 octets
465 * long and its value is interpreted as an unsigned 64-bit
468 if (tlv_type
== BGP_AIGP_TLV_METRIC
) {
469 (void)ptr_get_be64(data
+ 3, aigp
);
471 /* If an AIGP attribute is received and its first AIGP
472 * TLV contains the maximum value 0xffffffffffffffff,
473 * the attribute SHOULD be considered to be malformed
474 * and SHOULD be discarded as specified in this section.
476 if (*aigp
== BGP_AIGP_TLV_METRIC_MAX
) {
477 zlog_err("Bad AIGP TLV (%s) length: %llu",
478 BGP_AIGP_TLV_METRIC_DESC
,
479 BGP_AIGP_TLV_METRIC_MAX
);
487 length
-= tlv_length
;
493 static uint64_t bgp_aigp_metric_total(struct bgp_path_info
*bpi
)
495 uint64_t aigp
= bgp_attr_get_aigp_metric(bpi
->attr
);
498 return aigp
+ bpi
->nexthop
->metric
;
503 static void stream_put_bgp_aigp_tlv_metric(struct stream
*s
,
504 struct bgp_path_info
*bpi
)
506 stream_putc(s
, BGP_AIGP_TLV_METRIC
);
507 stream_putw(s
, BGP_AIGP_TLV_METRIC_LEN
);
508 stream_putq(s
, bgp_aigp_metric_total(bpi
));
511 static bool bgp_attr_aigp_valid(uint8_t *pnt
, int length
)
518 zlog_err("Bad AIGP attribute length (MUST be minimum 3): %u",
525 ptr_get_be16(data
+ 1, &tlv_length
);
528 if (length
< tlv_length
) {
530 "Bad AIGP attribute length: %u, but TLV length: %u",
535 if (tlv_length
< 3) {
536 zlog_err("Bad AIGP TLV length (MUST be minimum 3): %u",
541 /* AIGP TLV, Length: 11 */
542 if (tlv_type
== BGP_AIGP_TLV_METRIC
&&
543 tlv_length
!= BGP_AIGP_TLV_METRIC_LEN
) {
544 zlog_err("Bad AIGP TLV (%s) length: %u",
545 BGP_AIGP_TLV_METRIC_DESC
, tlv_length
);
550 length
-= tlv_length
;
556 static void *srv6_l3vpn_hash_alloc(void *p
)
561 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
563 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
566 static struct bgp_attr_srv6_l3vpn
*
567 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
569 struct bgp_attr_srv6_l3vpn
*find
;
571 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
573 srv6_l3vpn_free(l3vpn
);
578 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
580 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
585 if (l3vpn
->refcnt
== 0) {
586 hash_release(srv6_l3vpn_hash
, l3vpn
);
587 srv6_l3vpn_free(l3vpn
);
592 static void *srv6_vpn_hash_alloc(void *p
)
597 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
599 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
602 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
604 struct bgp_attr_srv6_vpn
*find
;
606 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
613 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
615 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
620 if (vpn
->refcnt
== 0) {
621 hash_release(srv6_vpn_hash
, vpn
);
627 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
629 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
632 key
= jhash(&l3vpn
->sid
, 16, key
);
633 key
= jhash_1word(l3vpn
->sid_flags
, key
);
634 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
635 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
636 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
637 key
= jhash_1word(l3vpn
->func_len
, key
);
638 key
= jhash_1word(l3vpn
->arg_len
, key
);
639 key
= jhash_1word(l3vpn
->transposition_len
, key
);
640 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
644 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
646 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
647 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
649 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
650 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
651 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
652 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
653 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
654 && l3vpn1
->func_len
== l3vpn2
->func_len
655 && l3vpn1
->arg_len
== l3vpn2
->arg_len
656 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
657 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
660 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
661 const struct bgp_attr_srv6_l3vpn
*h2
)
665 else if (h1
== NULL
|| h2
== NULL
)
668 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
671 static unsigned int srv6_vpn_hash_key_make(const void *p
)
673 const struct bgp_attr_srv6_vpn
*vpn
= p
;
676 key
= jhash(&vpn
->sid
, 16, key
);
677 key
= jhash_1word(vpn
->sid_flags
, key
);
681 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
683 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
684 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
686 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
687 && vpn1
->sid_flags
== vpn2
->sid_flags
;
690 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
691 const struct bgp_attr_srv6_vpn
*h2
)
695 else if (h1
== NULL
|| h2
== NULL
)
698 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
701 static void srv6_init(void)
704 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
705 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
706 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
707 "BGP Prefix-SID SRv6-VPN-Service-TLV");
710 static void srv6_finish(void)
712 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
713 hash_free(srv6_l3vpn_hash
);
714 srv6_l3vpn_hash
= NULL
;
715 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
716 hash_free(srv6_vpn_hash
);
717 srv6_vpn_hash
= NULL
;
720 static unsigned int transit_hash_key_make(const void *p
)
722 const struct transit
*transit
= p
;
724 return jhash(transit
->val
, transit
->length
, 0);
727 static bool transit_hash_cmp(const void *p1
, const void *p2
)
729 const struct transit
*transit1
= p1
;
730 const struct transit
*transit2
= p2
;
732 return (transit1
->length
== transit2
->length
733 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
736 static void transit_init(void)
738 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
742 static void transit_finish(void)
744 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
745 hash_free(transit_hash
);
749 /* Attribute hash routines. */
750 static struct hash
*attrhash
;
752 unsigned long int attr_count(void)
754 return attrhash
->count
;
757 unsigned long int attr_unknown_count(void)
759 return transit_hash
->count
;
762 unsigned int attrhash_key_make(const void *p
)
764 const struct attr
*attr
= (struct attr
*)p
;
766 #define MIX(val) key = jhash_1word(val, key)
767 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
769 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
770 MIX3(attr
->local_pref
, attr
->aggregator_as
,
771 attr
->aggregator_addr
.s_addr
);
772 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
773 attr
->originator_id
.s_addr
);
774 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
777 MIX(aspath_key_make(attr
->aspath
));
778 if (bgp_attr_get_community(attr
))
779 MIX(community_hash_make(bgp_attr_get_community(attr
)));
780 if (bgp_attr_get_lcommunity(attr
))
781 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
782 if (bgp_attr_get_ecommunity(attr
))
783 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
784 if (bgp_attr_get_ipv6_ecommunity(attr
))
785 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
786 if (bgp_attr_get_cluster(attr
))
787 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
788 if (bgp_attr_get_transit(attr
))
789 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
790 if (attr
->encap_subtlvs
)
791 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
792 if (attr
->srv6_l3vpn
)
793 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
795 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
796 #ifdef ENABLE_BGP_VNC
797 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
798 bgp_attr_get_vnc_subtlvs(attr
);
800 MIX(encap_hash_key_make(vnc_subtlvs
));
802 MIX(attr
->mp_nexthop_len
);
803 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
804 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
805 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
806 MIX(attr
->rmap_table_id
);
810 MIX(bgp_attr_get_aigp_metric(attr
));
815 bool attrhash_cmp(const void *p1
, const void *p2
)
817 const struct attr
*attr1
= p1
;
818 const struct attr
*attr2
= p2
;
820 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
821 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
822 && attr1
->aspath
== attr2
->aspath
823 && bgp_attr_get_community(attr1
)
824 == bgp_attr_get_community(attr2
)
825 && attr1
->med
== attr2
->med
826 && attr1
->local_pref
== attr2
->local_pref
827 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
828 if (attr1
->aggregator_as
== attr2
->aggregator_as
829 && attr1
->aggregator_addr
.s_addr
830 == attr2
->aggregator_addr
.s_addr
831 && attr1
->weight
== attr2
->weight
832 && attr1
->tag
== attr2
->tag
833 && attr1
->label_index
== attr2
->label_index
834 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
835 && bgp_attr_get_ecommunity(attr1
)
836 == bgp_attr_get_ecommunity(attr2
)
837 && bgp_attr_get_ipv6_ecommunity(attr1
)
838 == bgp_attr_get_ipv6_ecommunity(attr2
)
839 && bgp_attr_get_lcommunity(attr1
)
840 == bgp_attr_get_lcommunity(attr2
)
841 && bgp_attr_get_cluster(attr1
)
842 == bgp_attr_get_cluster(attr2
)
843 && bgp_attr_get_transit(attr1
)
844 == bgp_attr_get_transit(attr2
)
845 && bgp_attr_get_aigp_metric(attr1
)
846 == bgp_attr_get_aigp_metric(attr2
)
847 && attr1
->rmap_table_id
== attr2
->rmap_table_id
848 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
849 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
850 #ifdef ENABLE_BGP_VNC
851 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
852 bgp_attr_get_vnc_subtlvs(attr2
))
854 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
855 &attr2
->mp_nexthop_global
)
856 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
857 &attr2
->mp_nexthop_local
)
858 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
859 &attr2
->mp_nexthop_global_in
)
860 && IPV4_ADDR_SAME(&attr1
->originator_id
,
861 &attr2
->originator_id
)
862 && overlay_index_same(attr1
, attr2
)
863 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
864 && attr1
->es_flags
== attr2
->es_flags
865 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
866 && attr1
->df_pref
== attr2
->df_pref
867 && attr1
->df_alg
== attr2
->df_alg
868 && attr1
->nh_ifindex
== attr2
->nh_ifindex
869 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
870 && attr1
->distance
== attr2
->distance
871 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
872 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
873 && attr1
->srte_color
== attr2
->srte_color
874 && attr1
->nh_type
== attr2
->nh_type
875 && attr1
->bh_type
== attr2
->bh_type
876 && attr1
->otc
== attr2
->otc
)
883 static void attrhash_init(void)
886 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
890 * special for hash_clean below
892 static void attr_vfree(void *attr
)
894 XFREE(MTYPE_ATTR
, attr
);
897 static void attrhash_finish(void)
899 hash_clean(attrhash
, attr_vfree
);
904 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
906 struct attr
*attr
= bucket
->data
;
907 struct in6_addr
*sid
= NULL
;
909 if (attr
->srv6_l3vpn
)
910 sid
= &attr
->srv6_l3vpn
->sid
;
911 else if (attr
->srv6_vpn
)
912 sid
= &attr
->srv6_vpn
->sid
;
914 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
918 " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6\n",
919 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
920 attr
->origin
, attr
->weight
, attr
->label
, sid
);
923 void attr_show_all(struct vty
*vty
)
925 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
926 void *))attr_show_all_iterator
,
930 static void *bgp_attr_hash_alloc(void *p
)
932 struct attr
*val
= (struct attr
*)p
;
935 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
937 if (val
->encap_subtlvs
) {
938 val
->encap_subtlvs
= NULL
;
940 #ifdef ENABLE_BGP_VNC
941 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
942 bgp_attr_get_vnc_subtlvs(val
);
945 bgp_attr_set_vnc_subtlvs(val
, NULL
);
952 /* Internet argument attribute. */
953 struct attr
*bgp_attr_intern(struct attr
*attr
)
956 struct ecommunity
*ecomm
= NULL
;
957 struct ecommunity
*ipv6_ecomm
= NULL
;
958 struct lcommunity
*lcomm
= NULL
;
959 struct community
*comm
= NULL
;
961 /* Intern referenced structure. */
963 if (!attr
->aspath
->refcnt
)
964 attr
->aspath
= aspath_intern(attr
->aspath
);
966 attr
->aspath
->refcnt
++;
969 comm
= bgp_attr_get_community(attr
);
972 bgp_attr_set_community(attr
, community_intern(comm
));
977 ecomm
= bgp_attr_get_ecommunity(attr
);
980 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
985 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
987 if (!ipv6_ecomm
->refcnt
)
988 bgp_attr_set_ipv6_ecommunity(
989 attr
, ecommunity_intern(ipv6_ecomm
));
991 ipv6_ecomm
->refcnt
++;
994 lcomm
= bgp_attr_get_lcommunity(attr
);
997 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
1002 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1005 if (!cluster
->refcnt
)
1006 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
1011 struct transit
*transit
= bgp_attr_get_transit(attr
);
1014 if (!transit
->refcnt
)
1015 bgp_attr_set_transit(attr
, transit_intern(transit
));
1019 if (attr
->encap_subtlvs
) {
1020 if (!attr
->encap_subtlvs
->refcnt
)
1021 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
1024 attr
->encap_subtlvs
->refcnt
++;
1026 if (attr
->srv6_l3vpn
) {
1027 if (!attr
->srv6_l3vpn
->refcnt
)
1028 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
1030 attr
->srv6_l3vpn
->refcnt
++;
1032 if (attr
->srv6_vpn
) {
1033 if (!attr
->srv6_vpn
->refcnt
)
1034 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
1036 attr
->srv6_vpn
->refcnt
++;
1038 #ifdef ENABLE_BGP_VNC
1039 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1040 bgp_attr_get_vnc_subtlvs(attr
);
1043 if (!vnc_subtlvs
->refcnt
)
1044 bgp_attr_set_vnc_subtlvs(
1046 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
1048 vnc_subtlvs
->refcnt
++;
1052 /* At this point, attr only contains intern'd pointers. that means
1053 * if we find it in attrhash, it has all the same pointers and we
1054 * correctly updated the refcounts on these.
1055 * If we don't find it, we need to allocate a one because in all
1056 * cases this returns a new reference to a hashed attr, but the input
1057 * wasn't on hash. */
1058 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
1064 /* Make network statement's attribute. */
1065 struct attr
*bgp_attr_default_set(struct attr
*attr
, struct bgp
*bgp
,
1068 memset(attr
, 0, sizeof(struct attr
));
1070 attr
->origin
= origin
;
1071 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1072 attr
->aspath
= aspath_empty();
1073 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1074 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1076 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
1077 attr
->label
= MPLS_INVALID_LABEL
;
1078 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1079 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1080 attr
->local_pref
= bgp
->default_local_pref
;
1085 /* Create the attributes for an aggregate */
1086 struct attr
*bgp_attr_aggregate_intern(
1087 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
1088 struct community
*community
, struct ecommunity
*ecommunity
,
1089 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
1090 uint8_t atomic_aggregate
, const struct prefix
*p
)
1094 route_map_result_t ret
;
1096 memset(&attr
, 0, sizeof(attr
));
1098 /* Origin attribute. */
1099 attr
.origin
= origin
;
1100 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1104 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1106 /* AS path attribute. */
1108 attr
.aspath
= aspath_intern(aspath
);
1110 attr
.aspath
= aspath_empty();
1111 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1113 /* Next hop attribute. */
1114 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1117 uint32_t gshut
= COMMUNITY_GSHUT
;
1119 /* If we are not shutting down ourselves and we are
1120 * aggregating a route that contains the GSHUT community we
1121 * need to remove that community when creating the aggregate */
1122 if (!bgp_in_graceful_shutdown(bgp
)
1123 && community_include(community
, gshut
)) {
1124 community_del_val(community
, &gshut
);
1127 bgp_attr_set_community(&attr
, community
);
1131 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1134 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1136 if (bgp_in_graceful_shutdown(bgp
))
1137 bgp_attr_add_gshut_community(&attr
);
1139 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1140 attr
.label
= MPLS_INVALID_LABEL
;
1141 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1142 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1143 if (!aggregate
->as_set
|| atomic_aggregate
)
1144 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1145 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1146 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1147 attr
.aggregator_as
= bgp
->confed_id
;
1149 attr
.aggregator_as
= bgp
->as
;
1150 attr
.aggregator_addr
= bgp
->router_id
;
1152 /* Apply route-map */
1153 if (aggregate
->rmap
.name
) {
1154 struct attr attr_tmp
= attr
;
1155 struct bgp_path_info rmap_path
;
1157 memset(&rmap_path
, 0, sizeof(rmap_path
));
1158 rmap_path
.peer
= bgp
->peer_self
;
1159 rmap_path
.attr
= &attr_tmp
;
1161 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1163 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1165 bgp
->peer_self
->rmap_type
= 0;
1167 if (ret
== RMAP_DENYMATCH
) {
1168 /* Free uninterned attribute. */
1169 bgp_attr_flush(&attr_tmp
);
1171 /* Unintern original. */
1172 aspath_unintern(&attr
.aspath
);
1176 if (bgp_in_graceful_shutdown(bgp
))
1177 bgp_attr_add_gshut_community(&attr_tmp
);
1179 new = bgp_attr_intern(&attr_tmp
);
1182 if (bgp_in_graceful_shutdown(bgp
))
1183 bgp_attr_add_gshut_community(&attr
);
1185 new = bgp_attr_intern(&attr
);
1188 /* Always release the 'intern()'ed AS Path. */
1189 aspath_unintern(&attr
.aspath
);
1194 /* Unintern just the sub-components of the attr, but not the attr */
1195 void bgp_attr_unintern_sub(struct attr
*attr
)
1197 struct ecommunity
*ecomm
= NULL
;
1198 struct ecommunity
*ipv6_ecomm
= NULL
;
1199 struct cluster_list
*cluster
;
1200 struct lcommunity
*lcomm
= NULL
;
1201 struct community
*comm
= NULL
;
1203 /* aspath refcount shoud be decrement. */
1204 aspath_unintern(&attr
->aspath
);
1205 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1207 comm
= bgp_attr_get_community(attr
);
1208 community_unintern(&comm
);
1209 bgp_attr_set_community(attr
, NULL
);
1211 ecomm
= bgp_attr_get_ecommunity(attr
);
1212 ecommunity_unintern(&ecomm
);
1213 bgp_attr_set_ecommunity(attr
, NULL
);
1215 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1216 ecommunity_unintern(&ipv6_ecomm
);
1217 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1219 lcomm
= bgp_attr_get_lcommunity(attr
);
1220 lcommunity_unintern(&lcomm
);
1221 bgp_attr_set_lcommunity(attr
, NULL
);
1223 cluster
= bgp_attr_get_cluster(attr
);
1225 cluster_unintern(&cluster
);
1226 bgp_attr_set_cluster(attr
, cluster
);
1228 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1230 struct transit
*transit
= bgp_attr_get_transit(attr
);
1233 transit_unintern(&transit
);
1234 bgp_attr_set_transit(attr
, transit
);
1237 if (attr
->encap_subtlvs
)
1238 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1240 #ifdef ENABLE_BGP_VNC
1241 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1242 bgp_attr_get_vnc_subtlvs(attr
);
1245 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1246 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1250 if (attr
->srv6_l3vpn
)
1251 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1254 srv6_vpn_unintern(&attr
->srv6_vpn
);
1257 /* Free bgp attribute and aspath. */
1258 void bgp_attr_unintern(struct attr
**pattr
)
1260 struct attr
*attr
= *pattr
;
1264 /* Decrement attribute reference. */
1269 /* If reference becomes zero then free attribute object. */
1270 if (attr
->refcnt
== 0) {
1271 ret
= hash_release(attrhash
, attr
);
1272 assert(ret
!= NULL
);
1273 XFREE(MTYPE_ATTR
, attr
);
1277 bgp_attr_unintern_sub(&tmp
);
1280 void bgp_attr_flush(struct attr
*attr
)
1282 struct ecommunity
*ecomm
;
1283 struct ecommunity
*ipv6_ecomm
;
1284 struct cluster_list
*cluster
;
1285 struct lcommunity
*lcomm
;
1286 struct community
*comm
;
1288 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1289 aspath_free(attr
->aspath
);
1290 attr
->aspath
= NULL
;
1292 comm
= bgp_attr_get_community(attr
);
1293 if (comm
&& !comm
->refcnt
)
1294 community_free(&comm
);
1295 bgp_attr_set_community(attr
, NULL
);
1297 ecomm
= bgp_attr_get_ecommunity(attr
);
1298 if (ecomm
&& !ecomm
->refcnt
)
1299 ecommunity_free(&ecomm
);
1300 bgp_attr_set_ecommunity(attr
, NULL
);
1302 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1303 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1304 ecommunity_free(&ipv6_ecomm
);
1305 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1307 lcomm
= bgp_attr_get_lcommunity(attr
);
1308 if (lcomm
&& !lcomm
->refcnt
)
1309 lcommunity_free(&lcomm
);
1310 bgp_attr_set_lcommunity(attr
, NULL
);
1312 cluster
= bgp_attr_get_cluster(attr
);
1313 if (cluster
&& !cluster
->refcnt
) {
1314 cluster_free(cluster
);
1315 bgp_attr_set_cluster(attr
, NULL
);
1318 struct transit
*transit
= bgp_attr_get_transit(attr
);
1320 if (transit
&& !transit
->refcnt
) {
1321 transit_free(transit
);
1322 bgp_attr_set_transit(attr
, NULL
);
1324 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1325 encap_free(attr
->encap_subtlvs
);
1326 attr
->encap_subtlvs
= NULL
;
1328 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1329 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1330 attr
->srv6_l3vpn
= NULL
;
1332 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1333 srv6_vpn_free(attr
->srv6_vpn
);
1334 attr
->srv6_vpn
= NULL
;
1336 #ifdef ENABLE_BGP_VNC
1337 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1338 bgp_attr_get_vnc_subtlvs(attr
);
1340 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1341 encap_free(vnc_subtlvs
);
1342 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1347 /* Implement draft-scudder-idr-optional-transitive behaviour and
1348 * avoid resetting sessions for malformed attributes which are
1349 * are partial/optional and hence where the error likely was not
1350 * introduced by the sending neighbour.
1352 static enum bgp_attr_parse_ret
1353 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1356 struct peer
*const peer
= args
->peer
;
1357 struct attr
*const attr
= args
->attr
;
1358 const uint8_t flags
= args
->flags
;
1359 /* startp and length must be special-cased, as whether or not to
1360 * send the attribute data with the NOTIFY depends on the error,
1361 * the caller therefore signals this with the seperate length argument
1363 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1365 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1366 char attr_str
[BUFSIZ
] = {0};
1368 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1370 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1373 /* Only relax error handling for eBGP peers */
1374 if (peer
->sort
!= BGP_PEER_EBGP
) {
1375 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1376 notify_datap
, length
);
1377 return BGP_ATTR_PARSE_ERROR
;
1380 /* Adjust the stream getp to the end of the attribute, in case we can
1381 * still proceed but the caller hasn't read all the attribute.
1383 stream_set_getp(BGP_INPUT(peer
),
1384 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1387 switch (args
->type
) {
1388 /* where an attribute is relatively inconsequential, e.g. it does not
1389 * affect route selection, and can be safely ignored, then any such
1390 * attributes which are malformed should just be ignored and the route
1391 * processed as normal.
1393 case BGP_ATTR_AS4_AGGREGATOR
:
1394 case BGP_ATTR_AGGREGATOR
:
1395 case BGP_ATTR_ATOMIC_AGGREGATE
:
1396 return BGP_ATTR_PARSE_PROCEED
;
1398 /* Core attributes, particularly ones which may influence route
1399 * selection, should be treat-as-withdraw.
1401 case BGP_ATTR_ORIGIN
:
1402 case BGP_ATTR_AS_PATH
:
1403 case BGP_ATTR_NEXT_HOP
:
1404 case BGP_ATTR_MULTI_EXIT_DISC
:
1405 case BGP_ATTR_LOCAL_PREF
:
1406 case BGP_ATTR_COMMUNITIES
:
1407 case BGP_ATTR_EXT_COMMUNITIES
:
1408 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1409 case BGP_ATTR_LARGE_COMMUNITIES
:
1410 case BGP_ATTR_ORIGINATOR_ID
:
1411 case BGP_ATTR_CLUSTER_LIST
:
1413 return BGP_ATTR_PARSE_WITHDRAW
;
1414 case BGP_ATTR_MP_REACH_NLRI
:
1415 case BGP_ATTR_MP_UNREACH_NLRI
:
1416 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1417 notify_datap
, length
);
1418 return BGP_ATTR_PARSE_ERROR
;
1421 /* Partial optional attributes that are malformed should not cause
1422 * the whole session to be reset. Instead treat it as a withdrawal
1423 * of the routes, if possible.
1425 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1426 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1427 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1428 return BGP_ATTR_PARSE_WITHDRAW
;
1430 /* default to reset */
1431 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1434 /* Find out what is wrong with the path attribute flag bits and log the error.
1435 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1436 Extended Length. Checking O/T/P bits at once implies, that the attribute
1437 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1438 non-transitive" attribute. */
1440 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1441 uint8_t desired_flags
/* how RFC says it must be */
1444 uint8_t seen
= 0, i
;
1445 uint8_t real_flags
= args
->flags
;
1446 const uint8_t attr_code
= args
->type
;
1448 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1449 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1450 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1451 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1452 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1453 flog_err(EC_BGP_ATTR_FLAG
,
1454 "%s attribute must%s be flagged as \"%s\"",
1455 lookup_msg(attr_str
, attr_code
, NULL
),
1456 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1459 attr_flag_str
[i
].str
);
1464 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1465 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1466 real_flags
, desired_flags
);
1470 /* Required flags for attributes. EXTLEN will be masked off when testing,
1471 * as will PARTIAL for optional+transitive attributes.
1473 const uint8_t attr_flags_values
[] = {
1474 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1475 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1476 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1477 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1478 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1479 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1480 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1481 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1482 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1483 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1484 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1485 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1486 [BGP_ATTR_EXT_COMMUNITIES
] =
1487 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1488 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1489 [BGP_ATTR_AS4_AGGREGATOR
] =
1490 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1491 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1492 [BGP_ATTR_LARGE_COMMUNITIES
] =
1493 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1494 [BGP_ATTR_OTC
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1495 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1496 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1497 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1498 [BGP_ATTR_AIGP
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1500 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1502 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1504 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1505 const uint8_t flags
= args
->flags
;
1506 const uint8_t attr_code
= args
->type
;
1508 /* there may be attributes we don't know about */
1509 if (attr_code
> attr_flags_values_max
)
1511 if (attr_flags_values
[attr_code
] == 0)
1514 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1518 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1519 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1522 "%s well-known attributes must have transitive flag set (%x)",
1523 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1527 /* "For well-known attributes and for optional non-transitive
1529 * the Partial bit MUST be set to 0."
1531 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1532 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1533 flog_err(EC_BGP_ATTR_FLAG
,
1534 "%s well-known attribute must NOT have the partial flag set (%x)",
1535 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1538 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1539 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1540 flog_err(EC_BGP_ATTR_FLAG
,
1541 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1542 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1547 /* Optional transitive attributes may go through speakers that don't
1548 * reocgnise them and set the Partial bit.
1550 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1551 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1552 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1554 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1557 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1561 /* Get origin attribute of the update message. */
1562 static enum bgp_attr_parse_ret
1563 bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1565 struct peer
*const peer
= args
->peer
;
1566 struct attr
*const attr
= args
->attr
;
1567 const bgp_size_t length
= args
->length
;
1569 /* If any recognized attribute has Attribute Length that conflicts
1570 with the expected length (based on the attribute type code), then
1571 the Error Subcode is set to Attribute Length Error. The Data
1572 field contains the erroneous attribute (type, length and
1575 flog_err(EC_BGP_ATTR_LEN
,
1576 "Origin attribute length is not one %d", length
);
1577 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1581 /* Fetch origin attribute. */
1582 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1584 /* If the ORIGIN attribute has an undefined value, then the Error
1585 Subcode is set to Invalid Origin Attribute. The Data field
1586 contains the unrecognized attribute (type, length and value). */
1587 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1588 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1589 flog_err(EC_BGP_ATTR_ORIGIN
,
1590 "Origin attribute value is invalid %d", attr
->origin
);
1591 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1595 /* Set oring attribute flag. */
1596 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1601 /* Parse AS path information. This function is wrapper of
1603 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1605 struct attr
*const attr
= args
->attr
;
1606 struct peer
*const peer
= args
->peer
;
1607 const bgp_size_t length
= args
->length
;
1610 * peer with AS4 => will get 4Byte ASnums
1611 * otherwise, will get 16 Bit
1613 attr
->aspath
= aspath_parse(
1615 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1616 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1618 /* In case of IBGP, length will be zero. */
1619 if (!attr
->aspath
) {
1620 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1621 "Malformed AS path from %s, length is %d", peer
->host
,
1623 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1627 /* Conformant BGP speakers SHOULD NOT send BGP
1628 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1629 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1630 * withdraw" error handling behavior as per [RFC7606].
1632 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1633 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1634 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1636 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1640 /* Set aspath attribute flag. */
1641 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1643 return BGP_ATTR_PARSE_PROCEED
;
1646 static enum bgp_attr_parse_ret
bgp_attr_aspath_check(struct peer
*const peer
,
1647 struct attr
*const attr
)
1649 /* These checks were part of bgp_attr_aspath, but with
1650 * as4 we should to check aspath things when
1651 * aspath synthesizing with as4_path has already taken place.
1652 * Otherwise we check ASPATH and use the synthesized thing, and that is
1654 * So do the checks later, i.e. here
1656 struct aspath
*aspath
;
1658 /* Confederation sanity check. */
1659 if ((peer
->sort
== BGP_PEER_CONFED
1660 && !aspath_left_confed_check(attr
->aspath
))
1661 || (peer
->sort
== BGP_PEER_EBGP
1662 && aspath_confed_check(attr
->aspath
))) {
1663 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1665 return BGP_ATTR_PARSE_WITHDRAW
;
1668 /* First AS check for EBGP. */
1669 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1670 if (peer
->sort
== BGP_PEER_EBGP
1671 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1672 flog_err(EC_BGP_ATTR_FIRST_AS
,
1673 "%s incorrect first AS (must be %u)",
1674 peer
->host
, peer
->as
);
1675 return BGP_ATTR_PARSE_WITHDRAW
;
1679 /* Codification of AS 0 Processing */
1680 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1682 EC_BGP_ATTR_MAL_AS_PATH
,
1683 "Malformed AS path, AS number is 0 in the path from %s",
1685 return BGP_ATTR_PARSE_WITHDRAW
;
1688 /* local-as prepend */
1689 if (peer
->change_local_as
1690 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1691 aspath
= aspath_dup(attr
->aspath
);
1692 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1693 aspath_unintern(&attr
->aspath
);
1694 attr
->aspath
= aspath_intern(aspath
);
1697 return BGP_ATTR_PARSE_PROCEED
;
1700 /* Parse AS4 path information. This function is another wrapper of
1702 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1703 struct aspath
**as4_path
)
1705 struct peer
*const peer
= args
->peer
;
1706 struct attr
*const attr
= args
->attr
;
1707 const bgp_size_t length
= args
->length
;
1709 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1711 /* In case of IBGP, length will be zero. */
1713 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1714 "Malformed AS4 path from %s, length is %d", peer
->host
,
1716 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1720 /* Conformant BGP speakers SHOULD NOT send BGP
1721 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1722 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1723 * withdraw" error handling behavior as per [RFC7606].
1725 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1726 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1727 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1729 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1733 /* Set aspath attribute flag. */
1734 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1736 return BGP_ATTR_PARSE_PROCEED
;
1740 * Check that the nexthop attribute is valid.
1742 enum bgp_attr_parse_ret
bgp_attr_nexthop_valid(struct peer
*peer
,
1745 struct bgp
*bgp
= peer
->bgp
;
1747 if (ipv4_martian(&attr
->nexthop
) && !bgp
->allow_martian
) {
1748 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1750 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %pI4",
1752 data
[0] = BGP_ATTR_FLAG_TRANS
;
1753 data
[1] = BGP_ATTR_NEXT_HOP
;
1754 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1755 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1756 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1757 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1759 return BGP_ATTR_PARSE_ERROR
;
1762 return BGP_ATTR_PARSE_PROCEED
;
1765 /* Nexthop attribute. */
1766 static enum bgp_attr_parse_ret
1767 bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1769 struct peer
*const peer
= args
->peer
;
1770 struct attr
*const attr
= args
->attr
;
1771 const bgp_size_t length
= args
->length
;
1773 /* Check nexthop attribute length. */
1775 flog_err(EC_BGP_ATTR_LEN
,
1776 "Nexthop attribute length isn't four [%d]", length
);
1778 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1782 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1783 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1785 return BGP_ATTR_PARSE_PROCEED
;
1788 /* MED atrribute. */
1789 static enum bgp_attr_parse_ret
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1791 struct peer
*const peer
= args
->peer
;
1792 struct attr
*const attr
= args
->attr
;
1793 const bgp_size_t length
= args
->length
;
1797 flog_err(EC_BGP_ATTR_LEN
,
1798 "MED attribute length isn't four [%d]", length
);
1800 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1804 attr
->med
= stream_getl(peer
->curr
);
1806 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1808 return BGP_ATTR_PARSE_PROCEED
;
1811 /* Local preference attribute. */
1812 static enum bgp_attr_parse_ret
1813 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1815 struct peer
*const peer
= args
->peer
;
1816 struct attr
*const attr
= args
->attr
;
1817 const bgp_size_t length
= args
->length
;
1819 /* if received from an internal neighbor, it SHALL be considered
1820 * malformed if its length is not equal to 4. If malformed, the
1821 * UPDATE message SHALL be handled using the approach of "treat-as-
1824 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1825 flog_err(EC_BGP_ATTR_LEN
,
1826 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1827 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1831 /* If it is contained in an UPDATE message that is received from an
1832 external peer, then this attribute MUST be ignored by the
1833 receiving speaker. */
1834 if (peer
->sort
== BGP_PEER_EBGP
) {
1835 STREAM_FORWARD_GETP(peer
->curr
, length
);
1836 return BGP_ATTR_PARSE_PROCEED
;
1839 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1841 /* Set the local-pref flag. */
1842 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1844 return BGP_ATTR_PARSE_PROCEED
;
1847 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1851 /* Atomic aggregate. */
1852 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1854 struct attr
*const attr
= args
->attr
;
1855 const bgp_size_t length
= args
->length
;
1859 flog_err(EC_BGP_ATTR_LEN
,
1860 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1862 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1866 /* Set atomic aggregate flag. */
1867 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1869 return BGP_ATTR_PARSE_PROCEED
;
1872 /* Aggregator attribute */
1873 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1875 struct peer
*const peer
= args
->peer
;
1876 struct attr
*const attr
= args
->attr
;
1877 const bgp_size_t length
= args
->length
;
1882 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1883 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1884 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1887 if (length
!= wantedlen
) {
1888 flog_err(EC_BGP_ATTR_LEN
,
1889 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1891 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1895 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1896 aggregator_as
= stream_getl(peer
->curr
);
1898 aggregator_as
= stream_getw(peer
->curr
);
1900 attr
->aggregator_as
= aggregator_as
;
1901 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1903 /* Codification of AS 0 Processing */
1904 if (aggregator_as
== BGP_AS_ZERO
) {
1905 flog_err(EC_BGP_ATTR_LEN
,
1906 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1907 peer
->host
, aspath_print(attr
->aspath
));
1909 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1910 char attr_str
[BUFSIZ
] = {0};
1912 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1914 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1917 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1920 return BGP_ATTR_PARSE_PROCEED
;
1923 /* New Aggregator attribute */
1924 static enum bgp_attr_parse_ret
1925 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1926 as_t
*as4_aggregator_as
,
1927 struct in_addr
*as4_aggregator_addr
)
1929 struct peer
*const peer
= args
->peer
;
1930 struct attr
*const attr
= args
->attr
;
1931 const bgp_size_t length
= args
->length
;
1935 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1937 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1941 aggregator_as
= stream_getl(peer
->curr
);
1943 *as4_aggregator_as
= aggregator_as
;
1944 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1946 /* Codification of AS 0 Processing */
1947 if (aggregator_as
== BGP_AS_ZERO
) {
1948 flog_err(EC_BGP_ATTR_LEN
,
1949 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1950 peer
->host
, aspath_print(attr
->aspath
));
1952 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1953 char attr_str
[BUFSIZ
] = {0};
1955 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1957 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1960 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1963 return BGP_ATTR_PARSE_PROCEED
;
1966 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1968 static enum bgp_attr_parse_ret
1969 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1970 struct aspath
*as4_path
, as_t as4_aggregator
,
1971 struct in_addr
*as4_aggregator_addr
)
1973 int ignore_as4_path
= 0;
1974 struct aspath
*newpath
;
1976 if (!attr
->aspath
) {
1977 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1979 * checked that all well-known, mandatory attributes were
1982 * Can only be a problem with peer itself - hard error
1984 return BGP_ATTR_PARSE_ERROR
;
1987 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1988 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1990 * It is worth a warning though, because the peer really
1991 * should not send them
1993 if (BGP_DEBUG(as4
, AS4
)) {
1994 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1995 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1996 "AS4 capable peer, yet it sent");
1999 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
2000 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
2002 "AS4 capable peer, yet it sent");
2005 return BGP_ATTR_PARSE_PROCEED
;
2008 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
2009 * because that may override AS4_PATH
2011 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
2012 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
2014 * if the as_number in aggregator is not AS_TRANS,
2015 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
2016 * and the Aggregator shall be taken as
2017 * info on the aggregating node, and the AS_PATH
2018 * shall be taken as the AS_PATH
2020 * the Aggregator shall be ignored and the
2021 * AS4_AGGREGATOR shall be taken as the
2022 * Aggregating node and the AS_PATH is to be
2023 * constructed "as in all other cases"
2025 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
2027 if (BGP_DEBUG(as4
, AS4
))
2029 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
2031 ignore_as4_path
= 1;
2033 /* "New_aggregator shall be taken as aggregator"
2035 attr
->aggregator_as
= as4_aggregator
;
2036 attr
->aggregator_addr
.s_addr
=
2037 as4_aggregator_addr
->s_addr
;
2040 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2041 * That is bogus - but reading the conditions
2042 * we have to handle AS4_AGGREGATOR as if it were
2043 * AGGREGATOR in that case
2045 if (BGP_DEBUG(as4
, AS4
))
2047 "[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",
2049 attr
->aggregator_as
= as4_aggregator
;
2050 /* sweep it under the carpet and simulate a "good"
2052 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
2056 /* need to reconcile NEW_AS_PATH and AS_PATH */
2057 if (!ignore_as4_path
2058 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
2059 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
2061 return BGP_ATTR_PARSE_ERROR
;
2063 aspath_unintern(&attr
->aspath
);
2064 attr
->aspath
= aspath_intern(newpath
);
2066 return BGP_ATTR_PARSE_PROCEED
;
2069 /* Community attribute. */
2070 static enum bgp_attr_parse_ret
2071 bgp_attr_community(struct bgp_attr_parser_args
*args
)
2073 struct peer
*const peer
= args
->peer
;
2074 struct attr
*const attr
= args
->attr
;
2075 const bgp_size_t length
= args
->length
;
2078 bgp_attr_set_community(attr
, NULL
);
2079 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2083 bgp_attr_set_community(
2085 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
2087 /* XXX: fix community_parse to use stream API and remove this */
2088 stream_forward_getp(peer
->curr
, length
);
2090 /* The Community attribute SHALL be considered malformed if its
2091 * length is not a non-zero multiple of 4.
2093 if (!bgp_attr_get_community(attr
))
2094 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2097 return BGP_ATTR_PARSE_PROCEED
;
2100 /* Originator ID attribute. */
2101 static enum bgp_attr_parse_ret
2102 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
2104 struct peer
*const peer
= args
->peer
;
2105 struct attr
*const attr
= args
->attr
;
2106 const bgp_size_t length
= args
->length
;
2108 /* if received from an internal neighbor, it SHALL be considered
2109 * malformed if its length is not equal to 4. If malformed, the
2110 * UPDATE message SHALL be handled using the approach of "treat-as-
2114 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
2117 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2121 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
2123 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2125 return BGP_ATTR_PARSE_PROCEED
;
2128 /* Cluster list attribute. */
2129 static enum bgp_attr_parse_ret
2130 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2132 struct peer
*const peer
= args
->peer
;
2133 struct attr
*const attr
= args
->attr
;
2134 const bgp_size_t length
= args
->length
;
2136 /* if received from an internal neighbor, it SHALL be considered
2137 * malformed if its length is not a non-zero multiple of 4. If
2138 * malformed, the UPDATE message SHALL be handled using the approach
2139 * of "treat-as-withdraw".
2141 if (length
== 0 || length
% 4) {
2142 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2144 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2148 bgp_attr_set_cluster(
2149 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2152 /* XXX: Fix cluster_parse to use stream API and then remove this */
2153 stream_forward_getp(peer
->curr
, length
);
2155 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2157 return BGP_ATTR_PARSE_PROCEED
;
2160 /* Multiprotocol reachability information parse. */
2161 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2162 struct bgp_nlri
*mp_update
)
2166 iana_safi_t pkt_safi
;
2168 bgp_size_t nlri_len
;
2171 struct peer
*const peer
= args
->peer
;
2172 struct attr
*const attr
= args
->attr
;
2173 const bgp_size_t length
= args
->length
;
2175 /* Set end of packet. */
2176 s
= BGP_INPUT(peer
);
2177 start
= stream_get_getp(s
);
2179 /* safe to read statically sized header? */
2180 #define BGP_MP_REACH_MIN_SIZE 5
2181 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2182 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2183 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2184 __func__
, peer
->host
, (unsigned long)length
);
2185 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2188 /* Load AFI, SAFI. */
2189 pkt_afi
= stream_getw(s
);
2190 pkt_safi
= stream_getc(s
);
2192 /* Convert AFI, SAFI to internal values, check. */
2193 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2194 /* Log if AFI or SAFI is unrecognized. This is not an error
2196 * the attribute is otherwise malformed.
2198 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2200 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2201 peer
->host
, iana_afi2str(pkt_afi
),
2202 iana_safi2str(pkt_safi
));
2203 return BGP_ATTR_PARSE_ERROR
;
2206 /* Get nexthop length. */
2207 attr
->mp_nexthop_len
= stream_getc(s
);
2209 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2211 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2212 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2213 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2216 /* Nexthop length check. */
2217 switch (attr
->mp_nexthop_len
) {
2219 if (safi
!= SAFI_FLOWSPEC
) {
2220 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2221 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2222 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2225 case BGP_ATTR_NHLEN_VPNV4
:
2226 stream_getl(s
); /* RD high */
2227 stream_getl(s
); /* RD low */
2229 * NOTE: intentional fall through
2230 * - for consistency in rx processing
2232 * The following comment is to signal GCC this intention
2233 * and suppress the warning
2236 case BGP_ATTR_NHLEN_IPV4
:
2237 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2238 /* Probably needed for RFC 2283 */
2239 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2240 memcpy(&attr
->nexthop
.s_addr
,
2241 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2243 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2244 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2245 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2246 stream_getl(s
); /* RD high */
2247 stream_getl(s
); /* RD low */
2249 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2250 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2251 if (!peer
->nexthop
.ifp
) {
2252 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2254 return BGP_ATTR_PARSE_WITHDRAW
;
2256 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2259 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2260 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2261 if (attr
->mp_nexthop_len
2262 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2263 stream_getl(s
); /* RD high */
2264 stream_getl(s
); /* RD low */
2266 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2267 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2268 if (!peer
->nexthop
.ifp
) {
2269 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",
2271 return BGP_ATTR_PARSE_WITHDRAW
;
2273 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2275 if (attr
->mp_nexthop_len
2276 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2277 stream_getl(s
); /* RD high */
2278 stream_getl(s
); /* RD low */
2280 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2281 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2282 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2284 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2285 peer
->host
, &attr
->mp_nexthop_global
,
2286 &attr
->mp_nexthop_local
);
2288 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2290 if (!peer
->nexthop
.ifp
) {
2291 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2293 return BGP_ATTR_PARSE_WITHDRAW
;
2295 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2298 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2299 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2300 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2304 zlog_info("%s: %s sent SNPA which couldn't be read",
2305 __func__
, peer
->host
);
2306 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2311 if ((val
= stream_getc(s
)))
2313 EC_BGP_DEFUNCT_SNPA_LEN
,
2314 "%s sent non-zero value, %u, for defunct SNPA-length field",
2318 /* must have nrli_len, what is left of the attribute */
2319 nlri_len
= LEN_LEFT
;
2320 if (nlri_len
> STREAM_READABLE(s
)) {
2321 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2322 __func__
, peer
->host
);
2323 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2327 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2328 __func__
, peer
->host
);
2330 mp_update
->afi
= afi
;
2331 mp_update
->safi
= safi
;
2332 return BGP_ATTR_PARSE_EOR
;
2335 mp_update
->afi
= afi
;
2336 mp_update
->safi
= safi
;
2337 mp_update
->nlri
= stream_pnt(s
);
2338 mp_update
->length
= nlri_len
;
2340 stream_forward_getp(s
, nlri_len
);
2342 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2344 return BGP_ATTR_PARSE_PROCEED
;
2348 /* Multiprotocol unreachable parse */
2349 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2350 struct bgp_nlri
*mp_withdraw
)
2355 iana_safi_t pkt_safi
;
2357 uint16_t withdraw_len
;
2358 struct peer
*const peer
= args
->peer
;
2359 struct attr
*const attr
= args
->attr
;
2360 const bgp_size_t length
= args
->length
;
2364 #define BGP_MP_UNREACH_MIN_SIZE 3
2365 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2366 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2368 pkt_afi
= stream_getw(s
);
2369 pkt_safi
= stream_getc(s
);
2371 /* Convert AFI, SAFI to internal values, check. */
2372 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2373 /* Log if AFI or SAFI is unrecognized. This is not an error
2375 * the attribute is otherwise malformed.
2377 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2379 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2380 peer
->host
, iana_afi2str(pkt_afi
),
2381 iana_safi2str(pkt_safi
));
2382 return BGP_ATTR_PARSE_ERROR
;
2385 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2387 mp_withdraw
->afi
= afi
;
2388 mp_withdraw
->safi
= safi
;
2389 mp_withdraw
->nlri
= stream_pnt(s
);
2390 mp_withdraw
->length
= withdraw_len
;
2392 stream_forward_getp(s
, withdraw_len
);
2394 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2396 return BGP_ATTR_PARSE_PROCEED
;
2399 /* Large Community attribute. */
2400 static enum bgp_attr_parse_ret
2401 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2403 struct peer
*const peer
= args
->peer
;
2404 struct attr
*const attr
= args
->attr
;
2405 const bgp_size_t length
= args
->length
;
2408 * Large community follows new attribute format.
2411 bgp_attr_set_lcommunity(attr
, NULL
);
2412 /* Empty extcomm doesn't seem to be invalid per se */
2413 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2417 bgp_attr_set_lcommunity(
2418 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2419 /* XXX: fix ecommunity_parse to use stream API */
2420 stream_forward_getp(peer
->curr
, length
);
2422 if (!bgp_attr_get_lcommunity(attr
))
2423 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2426 return BGP_ATTR_PARSE_PROCEED
;
2429 /* Extended Community attribute. */
2430 static enum bgp_attr_parse_ret
2431 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2433 struct peer
*const peer
= args
->peer
;
2434 struct attr
*const attr
= args
->attr
;
2435 const bgp_size_t length
= args
->length
;
2438 struct ecommunity
*ecomm
;
2441 bgp_attr_set_ecommunity(attr
, NULL
);
2442 /* Empty extcomm doesn't seem to be invalid per se */
2443 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2447 ecomm
= ecommunity_parse(
2448 stream_pnt(peer
->curr
), length
,
2449 CHECK_FLAG(peer
->flags
,
2450 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2451 bgp_attr_set_ecommunity(attr
, ecomm
);
2452 /* XXX: fix ecommunity_parse to use stream API */
2453 stream_forward_getp(peer
->curr
, length
);
2455 /* The Extended Community attribute SHALL be considered malformed if
2456 * its length is not a non-zero multiple of 8.
2458 if (!bgp_attr_get_ecommunity(attr
))
2459 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2462 /* Extract DF election preference and mobility sequence number */
2463 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2465 /* Extract MAC mobility sequence number, if any. */
2466 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2467 attr
->sticky
= sticky
;
2469 /* Check if this is a Gateway MAC-IP advertisement */
2470 attr
->default_gw
= bgp_attr_default_gw(attr
);
2472 /* Handle scenario where router flag ecommunity is not
2473 * set but default gw ext community is present.
2474 * Use default gateway, set and propogate R-bit.
2476 if (attr
->default_gw
)
2477 attr
->router_flag
= 1;
2479 /* Check EVPN Neighbor advertisement flags, R-bit */
2480 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2482 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2484 /* Extract the Rmac, if any */
2485 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2486 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2487 && bgp_mac_exist(&attr
->rmac
))
2488 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2492 /* Get the tunnel type from encap extended community */
2493 bgp_attr_extcom_tunnel_type(attr
,
2494 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2496 /* Extract link bandwidth, if any. */
2497 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2500 return BGP_ATTR_PARSE_PROCEED
;
2503 /* IPv6 Extended Community attribute. */
2504 static enum bgp_attr_parse_ret
2505 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2507 struct peer
*const peer
= args
->peer
;
2508 struct attr
*const attr
= args
->attr
;
2509 const bgp_size_t length
= args
->length
;
2510 struct ecommunity
*ipv6_ecomm
= NULL
;
2513 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2514 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2518 ipv6_ecomm
= ecommunity_parse_ipv6(
2519 stream_pnt(peer
->curr
), length
,
2520 CHECK_FLAG(peer
->flags
,
2521 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2522 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2524 /* XXX: fix ecommunity_parse to use stream API */
2525 stream_forward_getp(peer
->curr
, length
);
2528 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2531 return BGP_ATTR_PARSE_PROCEED
;
2534 /* Parse Tunnel Encap attribute in an UPDATE */
2535 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2536 bgp_size_t length
, /* IN: attr's length field */
2537 struct attr
*attr
, /* IN: caller already allocated */
2538 uint8_t flag
, /* IN: attr's flags field */
2542 uint16_t tunneltype
= 0;
2544 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2546 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2547 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2549 "Tunnel Encap attribute flag isn't optional and transitive %d",
2551 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2552 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2557 if (BGP_ATTR_ENCAP
== type
) {
2558 /* read outer TLV type and length */
2559 uint16_t tlv_length
;
2563 "Tunnel Encap attribute not long enough to contain outer T,L");
2564 bgp_notify_send_with_data(
2565 peer
, BGP_NOTIFY_UPDATE_ERR
,
2566 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2569 tunneltype
= stream_getw(BGP_INPUT(peer
));
2570 tlv_length
= stream_getw(BGP_INPUT(peer
));
2573 if (tlv_length
!= length
) {
2574 zlog_info("%s: tlv_length(%d) != length(%d)",
2575 __func__
, tlv_length
, length
);
2579 while (length
>= 4) {
2580 uint16_t subtype
= 0;
2581 uint16_t sublength
= 0;
2582 struct bgp_attr_encap_subtlv
*tlv
;
2584 if (BGP_ATTR_ENCAP
== type
) {
2585 subtype
= stream_getc(BGP_INPUT(peer
));
2586 sublength
= stream_getc(BGP_INPUT(peer
));
2588 #ifdef ENABLE_BGP_VNC
2590 subtype
= stream_getw(BGP_INPUT(peer
));
2591 sublength
= stream_getw(BGP_INPUT(peer
));
2596 if (sublength
> length
) {
2598 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2600 bgp_notify_send_with_data(
2601 peer
, BGP_NOTIFY_UPDATE_ERR
,
2602 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2606 /* alloc and copy sub-tlv */
2607 /* TBD make sure these are freed when attributes are released */
2608 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2609 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2610 tlv
->type
= subtype
;
2611 tlv
->length
= sublength
;
2612 stream_get(tlv
->value
, peer
->curr
, sublength
);
2613 length
-= sublength
;
2615 /* attach tlv to encap chain */
2616 if (BGP_ATTR_ENCAP
== type
) {
2617 struct bgp_attr_encap_subtlv
*stlv_last
;
2618 for (stlv_last
= attr
->encap_subtlvs
;
2619 stlv_last
&& stlv_last
->next
;
2620 stlv_last
= stlv_last
->next
)
2623 stlv_last
->next
= tlv
;
2625 attr
->encap_subtlvs
= tlv
;
2627 #ifdef ENABLE_BGP_VNC
2629 struct bgp_attr_encap_subtlv
*stlv_last
;
2630 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2631 bgp_attr_get_vnc_subtlvs(attr
);
2633 for (stlv_last
= vnc_subtlvs
;
2634 stlv_last
&& stlv_last
->next
;
2635 stlv_last
= stlv_last
->next
)
2638 stlv_last
->next
= tlv
;
2640 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2645 if (BGP_ATTR_ENCAP
== type
) {
2646 attr
->encap_tunneltype
= tunneltype
;
2650 /* spurious leftover data */
2652 "Tunnel Encap attribute length is bad: %d leftover octets",
2654 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2655 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2664 /* SRv6 Service Data Sub-Sub-TLV attribute
2665 * draft-ietf-bess-srv6-services-07
2667 static enum bgp_attr_parse_ret
2668 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2670 struct peer
*const peer
= args
->peer
;
2671 struct attr
*const attr
= args
->attr
;
2672 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2673 transposition_len
, transposition_offset
;
2675 size_t headersz
= sizeof(type
) + sizeof(length
);
2677 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2680 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2681 headersz
, STREAM_READABLE(peer
->curr
));
2682 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2686 type
= stream_getc(peer
->curr
);
2687 length
= stream_getw(peer
->curr
);
2689 if (STREAM_READABLE(peer
->curr
) < length
) {
2692 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2693 length
, STREAM_READABLE(peer
->curr
));
2694 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2698 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2701 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2702 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2704 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2708 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2709 if (STREAM_READABLE(peer
->curr
) <
2710 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2713 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
2714 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2715 STREAM_READABLE(peer
->curr
));
2716 return bgp_attr_malformed(
2717 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2721 loc_block_len
= stream_getc(peer
->curr
);
2722 loc_node_len
= stream_getc(peer
->curr
);
2723 func_len
= stream_getc(peer
->curr
);
2724 arg_len
= stream_getc(peer
->curr
);
2725 transposition_len
= stream_getc(peer
->curr
);
2726 transposition_offset
= stream_getc(peer
->curr
);
2728 /* Log SRv6 Service Data Sub-Sub-TLV */
2729 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2731 "%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",
2732 __func__
, loc_block_len
, loc_node_len
, func_len
,
2733 arg_len
, transposition_len
,
2734 transposition_offset
);
2737 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2738 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2739 attr
->srv6_l3vpn
->func_len
= func_len
;
2740 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2741 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2742 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2746 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2748 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2751 stream_forward_getp(peer
->curr
, length
);
2754 return BGP_ATTR_PARSE_PROCEED
;
2757 /* SRv6 Service Sub-TLV attribute
2758 * draft-ietf-bess-srv6-services-07
2760 static enum bgp_attr_parse_ret
2761 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2763 struct peer
*const peer
= args
->peer
;
2764 struct attr
*const attr
= args
->attr
;
2765 struct in6_addr ipv6_sid
;
2766 uint8_t type
, sid_flags
;
2767 uint16_t length
, endpoint_behavior
;
2768 size_t headersz
= sizeof(type
) + sizeof(length
);
2769 enum bgp_attr_parse_ret err
;
2771 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2774 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2775 headersz
, STREAM_READABLE(peer
->curr
));
2776 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2780 type
= stream_getc(peer
->curr
);
2781 length
= stream_getw(peer
->curr
);
2783 if (STREAM_READABLE(peer
->curr
) < length
) {
2786 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2787 length
, STREAM_READABLE(peer
->curr
));
2788 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2792 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2793 if (STREAM_READABLE(peer
->curr
) <
2794 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2797 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
2798 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
,
2799 STREAM_READABLE(peer
->curr
));
2800 return bgp_attr_malformed(
2801 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2804 stream_getc(peer
->curr
);
2805 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2806 sid_flags
= stream_getc(peer
->curr
);
2807 endpoint_behavior
= stream_getw(peer
->curr
);
2808 stream_getc(peer
->curr
);
2810 /* Log SRv6 Service Sub-TLV */
2811 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
2813 "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2814 __func__
, &ipv6_sid
, sid_flags
,
2817 /* Configure from Info */
2818 if (attr
->srv6_l3vpn
) {
2819 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2820 "Prefix SID SRv6 L3VPN field repeated");
2821 return bgp_attr_malformed(
2822 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2824 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2825 sizeof(struct bgp_attr_srv6_l3vpn
));
2826 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2827 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2828 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2829 attr
->srv6_l3vpn
->loc_block_len
= 0;
2830 attr
->srv6_l3vpn
->loc_node_len
= 0;
2831 attr
->srv6_l3vpn
->func_len
= 0;
2832 attr
->srv6_l3vpn
->arg_len
= 0;
2833 attr
->srv6_l3vpn
->transposition_len
= 0;
2834 attr
->srv6_l3vpn
->transposition_offset
= 0;
2836 // Sub-Sub-TLV found
2837 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2838 err
= bgp_attr_srv6_service_data(args
);
2840 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2844 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2847 /* Placeholder code for unsupported type */
2849 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2851 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2854 stream_forward_getp(peer
->curr
, length
);
2857 return BGP_ATTR_PARSE_PROCEED
;
2861 * Read an individual SID value returning how much data we have read
2862 * Returns 0 if there was an error that needs to be passed up the stack
2864 static enum bgp_attr_parse_ret
2865 bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2866 struct bgp_attr_parser_args
*args
)
2868 struct peer
*const peer
= args
->peer
;
2869 struct attr
*const attr
= args
->attr
;
2870 uint32_t label_index
;
2871 struct in6_addr ipv6_sid
;
2873 uint32_t srgb_range
;
2875 uint8_t sid_type
, sid_flags
;
2877 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2878 if (STREAM_READABLE(peer
->curr
) < length
2879 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2880 flog_err(EC_BGP_ATTR_LEN
,
2881 "Prefix SID label index length is %hu instead of %u",
2882 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2883 return bgp_attr_malformed(args
,
2884 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2888 /* Ignore flags and reserved */
2889 stream_getc(peer
->curr
);
2890 stream_getw(peer
->curr
);
2892 /* Fetch the label index and see if it is valid. */
2893 label_index
= stream_getl(peer
->curr
);
2894 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2895 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2898 /* Store label index; subsequently, we'll check on
2900 attr
->label_index
= label_index
;
2903 /* Placeholder code for the IPv6 SID type */
2904 else if (type
== BGP_PREFIX_SID_IPV6
) {
2905 if (STREAM_READABLE(peer
->curr
) < length
2906 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2907 flog_err(EC_BGP_ATTR_LEN
,
2908 "Prefix SID IPv6 length is %hu instead of %u",
2909 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2910 return bgp_attr_malformed(args
,
2911 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2915 /* Ignore reserved */
2916 stream_getc(peer
->curr
);
2917 stream_getw(peer
->curr
);
2919 stream_get(&ipv6_sid
, peer
->curr
, 16);
2922 /* Placeholder code for the Originator SRGB type */
2923 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2925 * ietf-idr-bgp-prefix-sid-05:
2926 * Length is the total length of the value portion of the
2927 * TLV: 2 + multiple of 6.
2929 * peer->curr stream readp should be at the beginning of the 16
2930 * bit flag field at this point in the code.
2934 * Check that the TLV length field is sane: at least 2 bytes of
2935 * flag, and at least 1 SRGB (these are 6 bytes each)
2937 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2940 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2942 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2943 return bgp_attr_malformed(
2944 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2949 * Check that we actually have at least as much data as
2950 * specified by the length field
2952 if (STREAM_READABLE(peer
->curr
) < length
) {
2953 flog_err(EC_BGP_ATTR_LEN
,
2954 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2955 length
, STREAM_READABLE(peer
->curr
));
2956 return bgp_attr_malformed(
2957 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2962 * Check that the portion of the TLV containing the sequence of
2963 * SRGBs corresponds to a multiple of the SRGB size; to get
2964 * that length, we skip the 16 bit flags field
2966 stream_getw(peer
->curr
);
2968 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2971 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2972 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2973 return bgp_attr_malformed(
2974 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2978 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2980 for (int i
= 0; i
< srgb_count
; i
++) {
2981 stream_get(&srgb_base
, peer
->curr
, 3);
2982 stream_get(&srgb_range
, peer
->curr
, 3);
2986 /* Placeholder code for the VPN-SID Service type */
2987 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2988 if (STREAM_READABLE(peer
->curr
) < length
2989 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2990 flog_err(EC_BGP_ATTR_LEN
,
2991 "Prefix SID VPN SID length is %hu instead of %u",
2992 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2993 return bgp_attr_malformed(args
,
2994 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2998 /* Parse VPN-SID Sub-TLV */
2999 stream_getc(peer
->curr
); /* reserved */
3000 sid_type
= stream_getc(peer
->curr
); /* sid_type */
3001 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
3002 stream_get(&ipv6_sid
, peer
->curr
,
3003 sizeof(ipv6_sid
)); /* sid_value */
3005 /* Log VPN-SID Sub-TLV */
3006 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
3008 "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
3009 __func__
, &ipv6_sid
, sid_type
, sid_flags
);
3011 /* Configure from Info */
3012 if (attr
->srv6_vpn
) {
3013 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
3014 "Prefix SID SRv6 VPN field repeated");
3015 return bgp_attr_malformed(
3016 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
3018 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
3019 sizeof(struct bgp_attr_srv6_vpn
));
3020 attr
->srv6_vpn
->sid_flags
= sid_flags
;
3021 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
3022 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
3025 /* Placeholder code for the SRv6 L3 Service type */
3026 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
3027 if (STREAM_READABLE(peer
->curr
) < length
) {
3030 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
3031 length
, STREAM_READABLE(peer
->curr
));
3032 return bgp_attr_malformed(args
,
3033 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3037 /* ignore reserved */
3038 stream_getc(peer
->curr
);
3040 return bgp_attr_srv6_service(args
);
3043 /* Placeholder code for Unsupported TLV */
3046 if (STREAM_READABLE(peer
->curr
) < length
) {
3049 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
3050 length
, STREAM_READABLE(peer
->curr
));
3051 return bgp_attr_malformed(
3052 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3056 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3058 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3061 stream_forward_getp(peer
->curr
, length
);
3064 return BGP_ATTR_PARSE_PROCEED
;
3067 /* Prefix SID attribute
3068 * draft-ietf-idr-bgp-prefix-sid-05
3070 enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
3072 struct peer
*const peer
= args
->peer
;
3073 struct attr
*const attr
= args
->attr
;
3074 enum bgp_attr_parse_ret ret
;
3076 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3080 size_t headersz
= sizeof(type
) + sizeof(length
);
3081 size_t psid_parsed_length
= 0;
3083 while (STREAM_READABLE(peer
->curr
) > 0
3084 && psid_parsed_length
< args
->length
) {
3086 if (STREAM_READABLE(peer
->curr
) < headersz
) {
3089 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3090 headersz
, STREAM_READABLE(peer
->curr
));
3091 return bgp_attr_malformed(
3092 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3096 type
= stream_getc(peer
->curr
);
3097 length
= stream_getw(peer
->curr
);
3099 if (STREAM_READABLE(peer
->curr
) < length
) {
3102 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3103 length
, STREAM_READABLE(peer
->curr
));
3104 return bgp_attr_malformed(args
,
3105 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3109 ret
= bgp_attr_psid_sub(type
, length
, args
);
3111 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3114 psid_parsed_length
+= length
+ headersz
;
3116 if (psid_parsed_length
> args
->length
) {
3119 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
3120 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
3121 return bgp_attr_malformed(
3122 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3127 return BGP_ATTR_PARSE_PROCEED
;
3130 /* PMSI tunnel attribute (RFC 6514)
3131 * Basic validation checks done here.
3133 static enum bgp_attr_parse_ret
3134 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
3136 struct peer
*const peer
= args
->peer
;
3137 struct attr
*const attr
= args
->attr
;
3138 const bgp_size_t length
= args
->length
;
3140 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
3142 /* Verify that the receiver is expecting "ingress replication" as we
3143 * can only support that.
3145 if (length
< attr_parse_len
) {
3146 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
3148 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3151 stream_getc(peer
->curr
); /* Flags */
3152 tnl_type
= stream_getc(peer
->curr
);
3153 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3154 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3155 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3156 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3159 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3161 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3162 "Bad PMSI tunnel attribute length %d for IR",
3164 return bgp_attr_malformed(
3165 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3170 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3171 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3172 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3174 /* Forward read pointer of input stream. */
3175 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3177 return BGP_ATTR_PARSE_PROCEED
;
3180 /* AIGP attribute (rfc7311) */
3181 static enum bgp_attr_parse_ret
bgp_attr_aigp(struct bgp_attr_parser_args
*args
)
3183 struct peer
*const peer
= args
->peer
;
3184 struct attr
*const attr
= args
->attr
;
3185 const bgp_size_t length
= args
->length
;
3186 uint8_t *s
= stream_pnt(peer
->curr
);
3189 /* If an AIGP attribute is received on a BGP session for which
3190 * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3191 * as if it were an unrecognized non-transitive attribute.
3192 * That is, it "MUST be quietly ignored and not passed along to
3194 * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3195 * sessions between members of the same BGP Confederation,
3196 * the default value of AIGP_SESSION SHOULD be "enabled".
3198 if (peer
->sort
== BGP_PEER_EBGP
&&
3199 !CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
)) {
3201 "%pBP received AIGP attribute, but eBGP peer do not support it",
3206 if (!bgp_attr_aigp_valid(s
, length
))
3209 /* Extract AIGP Metric TLV */
3210 if (bgp_attr_aigp_get_tlv_metric(s
, length
, &aigp
))
3211 bgp_attr_set_aigp_metric(attr
, aigp
);
3214 stream_forward_getp(peer
->curr
, length
);
3216 return BGP_ATTR_PARSE_PROCEED
;
3219 /* OTC attribute. */
3220 static enum bgp_attr_parse_ret
bgp_attr_otc(struct bgp_attr_parser_args
*args
)
3222 struct peer
*const peer
= args
->peer
;
3223 struct attr
*const attr
= args
->attr
;
3224 const bgp_size_t length
= args
->length
;
3228 flog_err(EC_BGP_ATTR_LEN
, "OTC attribute length isn't 4 [%u]",
3230 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3234 attr
->otc
= stream_getl(peer
->curr
);
3236 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "OTC attribute value is 0");
3237 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
3241 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
3243 return BGP_ATTR_PARSE_PROCEED
;
3246 /* BGP unknown attribute treatment. */
3247 static enum bgp_attr_parse_ret
3248 bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3250 bgp_size_t total
= args
->total
;
3251 struct transit
*transit
;
3252 struct peer
*const peer
= args
->peer
;
3253 struct attr
*const attr
= args
->attr
;
3254 uint8_t *const startp
= args
->startp
;
3255 const uint8_t type
= args
->type
;
3256 const uint8_t flag
= args
->flags
;
3257 const bgp_size_t length
= args
->length
;
3259 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3261 "%s Unknown attribute is received (type %d, length %d)",
3262 peer
->host
, type
, length
);
3264 /* Forward read pointer of input stream. */
3265 stream_forward_getp(peer
->curr
, length
);
3267 /* If any of the mandatory well-known attributes are not recognized,
3268 then the Error Subcode is set to Unrecognized Well-known
3269 Attribute. The Data field contains the unrecognized attribute
3270 (type, length and value). */
3271 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3272 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3276 /* Unrecognized non-transitive optional attributes must be quietly
3277 ignored and not passed along to other BGP peers. */
3278 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3279 return BGP_ATTR_PARSE_PROCEED
;
3281 /* If a path with recognized transitive optional attribute is
3282 accepted and passed along to other BGP peers and the Partial bit
3283 in the Attribute Flags octet is set to 1 by some previous AS, it
3284 is not set back to 0 by the current AS. */
3285 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3287 /* Store transitive attribute to the end of attr->transit. */
3288 transit
= bgp_attr_get_transit(attr
);
3290 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3292 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3293 transit
->length
+ total
);
3295 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3296 transit
->length
+= total
;
3297 bgp_attr_set_transit(attr
, transit
);
3299 return BGP_ATTR_PARSE_PROCEED
;
3302 /* Well-known attribute check. */
3303 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3307 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3309 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3310 return BGP_ATTR_PARSE_PROCEED
;
3312 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3313 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3314 are present, it should. Check for any other attribute being present
3317 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3318 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3319 return BGP_ATTR_PARSE_PROCEED
;
3321 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3322 type
= BGP_ATTR_ORIGIN
;
3324 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3325 type
= BGP_ATTR_AS_PATH
;
3327 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3329 * NLRI is empty. We can't easily check NLRI empty here though.
3331 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3332 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3333 type
= BGP_ATTR_NEXT_HOP
;
3335 if (peer
->sort
== BGP_PEER_IBGP
3336 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3337 type
= BGP_ATTR_LOCAL_PREF
;
3339 /* If any of the well-known mandatory attributes are not present
3340 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3343 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3344 "%s Missing well-known attribute %s.", peer
->host
,
3345 lookup_msg(attr_str
, type
, NULL
));
3346 return BGP_ATTR_PARSE_WITHDRAW
;
3348 return BGP_ATTR_PARSE_PROCEED
;
3351 /* Read attribute of update packet. This function is called from
3352 bgp_update_receive() in bgp_packet.c. */
3353 enum bgp_attr_parse_ret
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3355 struct bgp_nlri
*mp_update
,
3356 struct bgp_nlri
*mp_withdraw
)
3358 enum bgp_attr_parse_ret ret
;
3362 uint8_t *startp
, *endp
;
3364 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3365 /* we need the as4_path only until we have synthesized the as_path with
3367 /* same goes for as4_aggregator */
3368 struct aspath
*as4_path
= NULL
;
3369 as_t as4_aggregator
= 0;
3370 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3371 struct transit
*transit
;
3373 /* Initialize bitmap. */
3374 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3376 /* End pointer of BGP attribute. */
3377 endp
= BGP_INPUT_PNT(peer
) + size
;
3379 /* Get attributes to the end of attribute length. */
3380 while (BGP_INPUT_PNT(peer
) < endp
) {
3381 /* Check remaining length check.*/
3382 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3383 /* XXX warning: long int format, int arg (arg 5) */
3385 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3386 "%s: error BGP attribute length %lu is smaller than min len",
3388 (unsigned long)(endp
3389 - stream_pnt(BGP_INPUT(peer
))));
3391 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3392 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3393 ret
= BGP_ATTR_PARSE_ERROR
;
3397 /* Fetch attribute flag and type. */
3398 startp
= BGP_INPUT_PNT(peer
);
3399 /* "The lower-order four bits of the Attribute Flags octet are
3400 unused. They MUST be zero when sent and MUST be ignored when
3402 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3403 type
= stream_getc(BGP_INPUT(peer
));
3405 /* Check whether Extended-Length applies and is in bounds */
3406 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3407 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3409 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3410 "%s: Extended length set, but just %lu bytes of attr header",
3412 (unsigned long)(endp
3413 - stream_pnt(BGP_INPUT(peer
))));
3415 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3416 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3417 ret
= BGP_ATTR_PARSE_ERROR
;
3421 /* Check extended attribue length bit. */
3422 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3423 length
= stream_getw(BGP_INPUT(peer
));
3425 length
= stream_getc(BGP_INPUT(peer
));
3427 /* If any attribute appears more than once in the UPDATE
3428 message, then the Error Subcode is set to Malformed Attribute
3431 if (CHECK_BITMAP(seen
, type
)) {
3433 EC_BGP_ATTRIBUTE_REPEATED
,
3434 "%s: error BGP attribute type %d appears twice in a message",
3437 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3438 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3439 ret
= BGP_ATTR_PARSE_ERROR
;
3443 /* Set type to bitmap to check duplicate attribute. `type' is
3444 unsigned char so it never overflow bitmap range. */
3446 SET_BITMAP(seen
, type
);
3448 /* Overflow check. */
3449 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3451 if (attr_endp
> endp
) {
3453 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3454 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3455 peer
->host
, type
, length
, size
, attr_endp
,
3459 * If any recognized attribute has an Attribute
3460 * Length that conflicts with the expected length
3461 * (based on the attribute type code), then the
3462 * Error Subcode MUST be set to Attribute Length
3463 * Error. The Data field MUST contain the erroneous
3464 * attribute (type, length, and value).
3466 * We do not currently have a good way to determine the
3467 * length of the attribute independent of the length
3468 * received in the message. Instead we send the
3469 * minimum between the amount of data we have and the
3470 * amount specified by the attribute length field.
3472 * Instead of directly passing in the packet buffer and
3473 * offset we use the stream_get* functions to read into
3474 * a stack buffer, since they perform bounds checking
3475 * and we are working with untrusted data.
3477 unsigned char ndata
[peer
->max_packet_size
];
3478 memset(ndata
, 0x00, sizeof(ndata
));
3480 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3481 /* Rewind to end of flag field */
3482 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3484 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3486 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3488 size_t atl
= attr_endp
- startp
;
3489 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3490 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3492 bgp_notify_send_with_data(
3493 peer
, BGP_NOTIFY_UPDATE_ERR
,
3494 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3497 ret
= BGP_ATTR_PARSE_ERROR
;
3501 struct bgp_attr_parser_args attr_args
= {
3508 .total
= attr_endp
- startp
,
3512 /* If any recognized attribute has Attribute Flags that conflict
3513 with the Attribute Type Code, then the Error Subcode is set
3515 Attribute Flags Error. The Data field contains the erroneous
3516 attribute (type, length and value). */
3517 if (bgp_attr_flag_invalid(&attr_args
)) {
3518 ret
= bgp_attr_malformed(
3519 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3521 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3526 /* OK check attribute and store it's value. */
3528 case BGP_ATTR_ORIGIN
:
3529 ret
= bgp_attr_origin(&attr_args
);
3531 case BGP_ATTR_AS_PATH
:
3532 ret
= bgp_attr_aspath(&attr_args
);
3534 case BGP_ATTR_AS4_PATH
:
3535 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3537 case BGP_ATTR_NEXT_HOP
:
3538 ret
= bgp_attr_nexthop(&attr_args
);
3540 case BGP_ATTR_MULTI_EXIT_DISC
:
3541 ret
= bgp_attr_med(&attr_args
);
3543 case BGP_ATTR_LOCAL_PREF
:
3544 ret
= bgp_attr_local_pref(&attr_args
);
3546 case BGP_ATTR_ATOMIC_AGGREGATE
:
3547 ret
= bgp_attr_atomic(&attr_args
);
3549 case BGP_ATTR_AGGREGATOR
:
3550 ret
= bgp_attr_aggregator(&attr_args
);
3552 case BGP_ATTR_AS4_AGGREGATOR
:
3553 ret
= bgp_attr_as4_aggregator(&attr_args
,
3555 &as4_aggregator_addr
);
3557 case BGP_ATTR_COMMUNITIES
:
3558 ret
= bgp_attr_community(&attr_args
);
3560 case BGP_ATTR_LARGE_COMMUNITIES
:
3561 ret
= bgp_attr_large_community(&attr_args
);
3563 case BGP_ATTR_ORIGINATOR_ID
:
3564 ret
= bgp_attr_originator_id(&attr_args
);
3566 case BGP_ATTR_CLUSTER_LIST
:
3567 ret
= bgp_attr_cluster_list(&attr_args
);
3569 case BGP_ATTR_MP_REACH_NLRI
:
3570 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3572 case BGP_ATTR_MP_UNREACH_NLRI
:
3573 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3575 case BGP_ATTR_EXT_COMMUNITIES
:
3576 ret
= bgp_attr_ext_communities(&attr_args
);
3578 #ifdef ENABLE_BGP_VNC_ATTR
3581 case BGP_ATTR_ENCAP
:
3582 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3585 case BGP_ATTR_PREFIX_SID
:
3586 ret
= bgp_attr_prefix_sid(&attr_args
);
3588 case BGP_ATTR_PMSI_TUNNEL
:
3589 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3591 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3592 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3595 ret
= bgp_attr_otc(&attr_args
);
3598 ret
= bgp_attr_aigp(&attr_args
);
3601 ret
= bgp_attr_unknown(&attr_args
);
3605 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3606 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3607 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3608 ret
= BGP_ATTR_PARSE_ERROR
;
3612 if (ret
== BGP_ATTR_PARSE_EOR
) {
3616 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3617 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3618 "%s: Attribute %s, parse error", peer
->host
,
3619 lookup_msg(attr_str
, type
, NULL
));
3622 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3624 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3625 "%s: Attribute %s, parse error - treating as withdrawal",
3626 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3630 /* Check the fetched length. */
3631 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3632 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3633 "%s: BGP attribute %s, fetch error",
3634 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3635 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3636 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3637 ret
= BGP_ATTR_PARSE_ERROR
;
3643 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3644 * About Prefix-SID path attribute,
3645 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3646 * may only appear in a BGP Prefix-SID attribute attached to
3647 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3648 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3650 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3651 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3653 /* Check final read pointer is same as end pointer. */
3654 if (BGP_INPUT_PNT(peer
) != endp
) {
3655 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3656 "%s: BGP attribute %s, length mismatch", peer
->host
,
3657 lookup_msg(attr_str
, type
, NULL
));
3658 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3659 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3661 ret
= BGP_ATTR_PARSE_ERROR
;
3666 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3667 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3668 * This is implemented below and will result in a NOTIFICATION. If the
3669 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3670 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3671 * message SHOULD NOT be sent. This is implemented elsewhere.
3673 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3674 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3675 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3676 * speaker that receives the message SHOULD ignore this attribute.
3678 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3679 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3680 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3681 ret
= BGP_ATTR_PARSE_ERROR
;
3686 /* Check all mandatory well-known attributes are present */
3687 ret
= bgp_attr_check(peer
, attr
);
3692 * At this place we can see whether we got AS4_PATH and/or
3693 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3694 * We can not do this before we've read all attributes because
3695 * the as4 handling does not say whether AS4_PATH has to be sent
3696 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3697 * in relationship to AGGREGATOR.
3698 * So, to be defensive, we are not relying on any order and read
3699 * all attributes first, including these 32bit ones, and now,
3700 * afterwards, we look what and if something is to be done for as4.
3702 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3705 /* actually... this doesn't ever return failure currently, but
3706 * better safe than sorry */
3707 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3708 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3709 &as4_aggregator_addr
)) {
3710 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3711 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3712 ret
= BGP_ATTR_PARSE_ERROR
;
3717 * Finally do the checks on the aspath we did not do yet
3718 * because we waited for a potentially synthesized aspath.
3720 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3721 ret
= bgp_attr_aspath_check(peer
, attr
);
3722 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3726 ret
= BGP_ATTR_PARSE_PROCEED
;
3730 * At this stage, we have done all fiddling with as4, and the
3731 * resulting info is in attr->aggregator resp. attr->aspath so
3732 * we can chuck as4_aggregator and as4_path alltogether in order
3736 * unintern - it is in the hash
3737 * The flag that we got this is still there, but that
3738 * does not do any trouble
3740 aspath_unintern(&as4_path
);
3742 transit
= bgp_attr_get_transit(attr
);
3743 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3744 /* Finally intern unknown attribute. */
3746 bgp_attr_set_transit(attr
, transit_intern(transit
));
3747 if (attr
->encap_subtlvs
)
3748 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3750 #ifdef ENABLE_BGP_VNC
3751 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3752 bgp_attr_get_vnc_subtlvs(attr
);
3755 bgp_attr_set_vnc_subtlvs(
3757 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3761 transit_free(transit
);
3762 bgp_attr_set_transit(attr
, NULL
);
3765 bgp_attr_flush_encap(attr
);
3769 transit
= bgp_attr_get_transit(attr
);
3771 assert(transit
->refcnt
> 0);
3772 if (attr
->encap_subtlvs
)
3773 assert(attr
->encap_subtlvs
->refcnt
> 0);
3774 #ifdef ENABLE_BGP_VNC
3775 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3776 bgp_attr_get_vnc_subtlvs(attr
);
3779 assert(vnc_subtlvs
->refcnt
> 0);
3786 * Extract the tunnel type from extended community
3788 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3789 bgp_encap_types
*tunnel_type
)
3791 struct ecommunity
*ecom
;
3797 ecom
= bgp_attr_get_ecommunity(attr
);
3798 if (!ecom
|| !ecom
->size
)
3801 for (i
= 0; i
< ecom
->size
; i
++) {
3803 uint8_t type
, sub_type
;
3805 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3808 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3809 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3811 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3818 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3819 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3823 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
3824 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
3827 /* Set extended bit always to encode the attribute length as 2 bytes */
3828 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3829 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3830 sizep
= stream_get_endp(s
);
3831 stream_putw(s
, 0); /* Marker: Attribute length. */
3834 /* Convert AFI, SAFI to values for packet. */
3835 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3837 stream_putw(s
, pkt_afi
); /* AFI */
3838 stream_putc(s
, pkt_safi
); /* SAFI */
3842 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3843 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3844 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3845 else if (safi
== SAFI_FLOWSPEC
)
3848 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3851 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3856 case SAFI_MULTICAST
:
3857 case SAFI_LABELED_UNICAST
:
3859 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3863 stream_putl(s
, 0); /* RD = 0, per RFC */
3865 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3870 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3873 if (attr
->mp_nexthop_len
== 0)
3874 stream_putc(s
, 0); /* no nexthop for flowspec */
3876 stream_putc(s
, attr
->mp_nexthop_len
);
3877 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3882 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
3889 case SAFI_MULTICAST
:
3890 case SAFI_LABELED_UNICAST
:
3892 if (attr
->mp_nexthop_len
3893 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3895 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3896 stream_put(s
, &attr
->mp_nexthop_global
,
3898 stream_put(s
, &attr
->mp_nexthop_local
,
3901 stream_putc(s
, IPV6_MAX_BYTELEN
);
3902 stream_put(s
, &attr
->mp_nexthop_global
,
3906 case SAFI_MPLS_VPN
: {
3907 if (attr
->mp_nexthop_len
3908 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3910 stream_putl(s
, 0); /* RD = 0, per RFC */
3912 stream_put(s
, &attr
->mp_nexthop_global
,
3914 stream_putl(s
, 0); /* RD = 0, per RFC */
3916 stream_put(s
, &attr
->mp_nexthop_local
,
3920 stream_putl(s
, 0); /* RD = 0, per RFC */
3922 stream_put(s
, &attr
->mp_nexthop_global
,
3927 stream_putc(s
, IPV6_MAX_BYTELEN
);
3928 stream_put(s
, &attr
->mp_nexthop_global
,
3932 stream_putc(s
, 0); /* no nexthop for flowspec */
3936 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
3941 if (safi
!= SAFI_FLOWSPEC
)
3943 EC_BGP_ATTR_NH_SEND_LEN
,
3944 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3945 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3949 assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here");
3958 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3959 const struct prefix
*p
,
3960 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3961 uint32_t num_labels
, bool addpath_capable
,
3962 uint32_t addpath_tx_id
, struct attr
*attr
)
3967 assert(!"Dev escape usage of SAFI_UNSPEC or MAX");
3970 if (addpath_capable
)
3971 stream_putl(s
, addpath_tx_id
);
3972 /* Label, RD, Prefix write. */
3973 stream_putc(s
, p
->prefixlen
+ 88);
3974 stream_put(s
, label
, BGP_LABEL_BYTES
);
3975 stream_put(s
, prd
->val
, 8);
3976 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3979 if (afi
== AFI_L2VPN
)
3980 /* EVPN prefix - contents depend on type */
3981 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
,
3982 attr
, addpath_capable
,
3985 assert(!"Add encoding bits here for other AFI's");
3987 case SAFI_LABELED_UNICAST
:
3988 /* Prefix write with label. */
3989 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3993 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3994 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3995 p
->u
.prefix_flowspec
.prefixlen
);
3999 case SAFI_MULTICAST
:
4000 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
4003 assert(!"Please add proper encoding of SAFI_ENCAP");
4008 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
4009 const struct prefix
*p
)
4011 int size
= PSIZE(p
->prefixlen
);
4016 assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE");
4019 case SAFI_MULTICAST
:
4025 /* This has to be wrong, but I don't know what to put here */
4026 assert(!"Do we try to use this?");
4028 case SAFI_LABELED_UNICAST
:
4029 size
+= BGP_LABEL_BYTES
;
4033 * TODO: Maximum possible for type-2, type-3 and type-5
4035 if (afi
== AFI_L2VPN
)
4038 assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values");
4041 size
= ((struct prefix_fs
*)p
)->prefix
.prefixlen
;
4049 * Encodes the tunnel encapsulation attribute,
4050 * and with ENABLE_BGP_VNC the VNC attribute which uses
4051 * almost the same TLV format
4053 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
4054 struct stream
*s
, struct attr
*attr
,
4057 unsigned int attrlenfield
= 0;
4058 unsigned int attrhdrlen
= 0;
4059 struct bgp_attr_encap_subtlv
*subtlvs
;
4060 struct bgp_attr_encap_subtlv
*st
;
4061 const char *attrname
;
4063 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
4064 && (!attr
->encap_tunneltype
4065 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
4069 case BGP_ATTR_ENCAP
:
4070 attrname
= "Tunnel Encap";
4071 subtlvs
= attr
->encap_subtlvs
;
4072 if (subtlvs
== NULL
) /* nothing to do */
4075 * The tunnel encap attr has an "outer" tlv.
4077 * L = total length of subtlvs,
4078 * V = concatenated subtlvs.
4080 attrlenfield
= 2 + 2; /* T + L */
4081 attrhdrlen
= 1 + 1; /* subTLV T + L */
4084 #ifdef ENABLE_BGP_VNC_ATTR
4087 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
4088 if (subtlvs
== NULL
) /* nothing to do */
4090 attrlenfield
= 0; /* no outer T + L */
4091 attrhdrlen
= 2 + 2; /* subTLV T + L */
4099 /* compute attr length */
4100 for (st
= subtlvs
; st
; st
= st
->next
) {
4101 attrlenfield
+= (attrhdrlen
+ st
->length
);
4104 if (attrlenfield
> 0xffff) {
4105 zlog_info("%s attribute is too long (length=%d), can't send it",
4106 attrname
, attrlenfield
);
4110 if (attrlenfield
> 0xff) {
4111 /* 2-octet length field */
4113 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4114 | BGP_ATTR_FLAG_EXTLEN
);
4115 stream_putc(s
, attrtype
);
4116 stream_putw(s
, attrlenfield
& 0xffff);
4118 /* 1-octet length field */
4119 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
4120 stream_putc(s
, attrtype
);
4121 stream_putc(s
, attrlenfield
& 0xff);
4124 if (attrtype
== BGP_ATTR_ENCAP
) {
4125 /* write outer T+L */
4126 stream_putw(s
, attr
->encap_tunneltype
);
4127 stream_putw(s
, attrlenfield
- 4);
4130 /* write each sub-tlv */
4131 for (st
= subtlvs
; st
; st
= st
->next
) {
4132 if (attrtype
== BGP_ATTR_ENCAP
) {
4133 stream_putc(s
, st
->type
);
4134 stream_putc(s
, st
->length
);
4135 #ifdef ENABLE_BGP_VNC
4137 stream_putw(s
, st
->type
);
4138 stream_putw(s
, st
->length
);
4141 stream_put(s
, st
->value
, st
->length
);
4145 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
4147 /* Set MP attribute length. Don't count the (2) bytes used to encode
4149 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
4152 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
4154 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
4155 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
4156 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4157 PEER_FLAG_REMOVE_PRIVATE_AS
)
4158 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4159 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
4160 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4161 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
4162 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4163 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
4168 /* Make attribute packet. */
4169 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
4170 struct stream
*s
, struct attr
*attr
,
4171 struct bpacket_attr_vec_arr
*vecarr
,
4172 struct prefix
*p
, afi_t afi
, safi_t safi
,
4173 struct peer
*from
, struct prefix_rd
*prd
,
4174 mpls_label_t
*label
, uint32_t num_labels
,
4175 bool addpath_capable
, uint32_t addpath_tx_id
,
4176 struct bgp_path_info
*bpi
)
4179 size_t aspath_sizep
;
4180 struct aspath
*aspath
;
4181 int send_as4_path
= 0;
4182 int send_as4_aggregator
= 0;
4183 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
4184 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
4189 /* Remember current pointer. */
4190 cp
= stream_get_endp(s
);
4193 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
4194 && !peer_cap_enhe(peer
, afi
, safi
))) {
4195 size_t mpattrlen_pos
= 0;
4197 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
4199 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
4200 num_labels
, addpath_capable
,
4201 addpath_tx_id
, attr
);
4202 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
4205 /* Origin attribute. */
4206 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4207 stream_putc(s
, BGP_ATTR_ORIGIN
);
4209 stream_putc(s
, attr
->origin
);
4211 /* AS path attribute. */
4213 /* If remote-peer is EBGP */
4214 if (peer
->sort
== BGP_PEER_EBGP
4215 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4216 PEER_FLAG_AS_PATH_UNCHANGED
)
4217 || attr
->aspath
->segments
== NULL
)
4218 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4219 PEER_FLAG_RSERVER_CLIENT
))) {
4220 aspath
= aspath_dup(attr
->aspath
);
4222 /* Even though we may not be configured for confederations we
4224 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4225 aspath
= aspath_delete_confed_seq(aspath
);
4227 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
4228 /* Stuff our path CONFED_ID on the front */
4229 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
4231 if (peer
->change_local_as
) {
4232 /* If replace-as is specified, we only use the
4233 change_local_as when
4234 advertising routes. */
4235 if (!CHECK_FLAG(peer
->flags
,
4236 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
4237 if (bgp_append_local_as(peer
, afi
,
4239 aspath
= aspath_add_seq(
4240 aspath
, peer
->local_as
);
4241 aspath
= aspath_add_seq(aspath
,
4242 peer
->change_local_as
);
4244 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
4247 } else if (peer
->sort
== BGP_PEER_CONFED
) {
4248 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4250 aspath
= aspath_dup(attr
->aspath
);
4251 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
4253 aspath
= attr
->aspath
;
4255 /* If peer is not AS4 capable, then:
4256 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4257 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4259 * types are in it (i.e. exclude them if they are there)
4260 * AND do this only if there is at least one asnum > 65535 in the
4262 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4264 * all ASnums > 65535 to BGP_AS_TRANS
4267 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4268 stream_putc(s
, BGP_ATTR_AS_PATH
);
4269 aspath_sizep
= stream_get_endp(s
);
4271 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4273 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4276 if (!use32bit
&& aspath_has_as4(aspath
))
4278 1; /* we'll do this later, at the correct place */
4280 /* Nexthop attribute. */
4281 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4282 && !peer_cap_enhe(peer
, afi
, safi
)) {
4283 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4285 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4286 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4287 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4288 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4291 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4292 } else if (peer_cap_enhe(from
, afi
, safi
)
4293 || (nh_afi
== AFI_IP6
)) {
4295 * Likely this is the case when an IPv4 prefix was
4296 * received with Extended Next-hop capability in this
4297 * or another vrf and is now being advertised to
4298 * non-ENHE peers. Since peer_cap_enhe only checks
4299 * peers in this vrf, also check the nh_afi to catch
4300 * the case where the originator was in another vrf.
4301 * Setting the mandatory (ipv4) next-hop attribute here
4302 * to enable implicit next-hop self with correct A-F
4303 * (ipv4 address family).
4305 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4306 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4307 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4310 stream_put_ipv4(s
, 0);
4314 /* MED attribute. */
4315 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4316 || bgp
->maxmed_active
) {
4317 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4318 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4320 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4324 /* Local preference. */
4325 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4326 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4327 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4329 stream_putl(s
, attr
->local_pref
);
4332 /* Atomic aggregate. */
4333 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4334 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4335 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4340 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4341 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4342 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4343 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4346 /* AS4 capable peer */
4348 stream_putl(s
, attr
->aggregator_as
);
4350 /* 2-byte AS peer */
4353 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4355 if (attr
->aggregator_as
> UINT16_MAX
) {
4356 stream_putw(s
, BGP_AS_TRANS
);
4358 /* we have to send AS4_AGGREGATOR, too.
4359 * we'll do that later in order to send
4360 * attributes in ascending
4363 send_as4_aggregator
= 1;
4365 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4367 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4370 /* Community attribute. */
4371 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4372 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4373 struct community
*comm
= NULL
;
4375 comm
= bgp_attr_get_community(attr
);
4376 if (comm
->size
* 4 > 255) {
4378 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4379 | BGP_ATTR_FLAG_EXTLEN
);
4380 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4381 stream_putw(s
, comm
->size
* 4);
4384 BGP_ATTR_FLAG_OPTIONAL
4385 | BGP_ATTR_FLAG_TRANS
);
4386 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4387 stream_putc(s
, comm
->size
* 4);
4389 stream_put(s
, comm
->val
, comm
->size
* 4);
4393 * Large Community attribute.
4395 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4396 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4397 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4398 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4400 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4401 | BGP_ATTR_FLAG_EXTLEN
);
4402 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4404 lcom_length(bgp_attr_get_lcommunity(attr
)));
4407 BGP_ATTR_FLAG_OPTIONAL
4408 | BGP_ATTR_FLAG_TRANS
);
4409 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4411 lcom_length(bgp_attr_get_lcommunity(attr
)));
4413 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4414 lcom_length(bgp_attr_get_lcommunity(attr
)));
4417 /* Route Reflector. */
4418 if (peer
->sort
== BGP_PEER_IBGP
&& from
4419 && from
->sort
== BGP_PEER_IBGP
) {
4420 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4422 /* Originator ID. */
4423 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4424 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4427 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4428 stream_put_in_addr(s
, &attr
->originator_id
);
4430 stream_put_in_addr(s
, &from
->remote_id
);
4433 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4434 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4437 stream_putc(s
, cluster
->length
+ 4);
4438 /* If this peer configuration's parent BGP has
4440 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4441 stream_put_in_addr(s
, &bgp
->cluster_id
);
4443 stream_put_in_addr(s
, &bgp
->router_id
);
4444 stream_put(s
, cluster
->list
, cluster
->length
);
4447 /* If this peer configuration's parent BGP has
4449 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4450 stream_put_in_addr(s
, &bgp
->cluster_id
);
4452 stream_put_in_addr(s
, &bgp
->router_id
);
4456 /* Extended Communities attribute. */
4457 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4458 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4459 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4460 bool transparent
= CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4461 PEER_FLAG_RSERVER_CLIENT
) &&
4463 CHECK_FLAG(from
->af_flags
[afi
][safi
],
4464 PEER_FLAG_RSERVER_CLIENT
);
4466 if (peer
->sort
== BGP_PEER_IBGP
||
4467 peer
->sort
== BGP_PEER_CONFED
|| transparent
) {
4468 if (ecomm
->size
* 8 > 255) {
4470 BGP_ATTR_FLAG_OPTIONAL
4471 | BGP_ATTR_FLAG_TRANS
4472 | BGP_ATTR_FLAG_EXTLEN
);
4473 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4474 stream_putw(s
, ecomm
->size
* 8);
4477 BGP_ATTR_FLAG_OPTIONAL
4478 | BGP_ATTR_FLAG_TRANS
);
4479 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4480 stream_putc(s
, ecomm
->size
* 8);
4482 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4486 int ecom_tr_size
= 0;
4489 for (i
= 0; i
< ecomm
->size
; i
++) {
4490 pnt
= ecomm
->val
+ (i
* 8);
4493 if (CHECK_FLAG(tbit
,
4494 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4501 if (ecom_tr_size
* 8 > 255) {
4504 BGP_ATTR_FLAG_OPTIONAL
4505 | BGP_ATTR_FLAG_TRANS
4506 | BGP_ATTR_FLAG_EXTLEN
);
4508 BGP_ATTR_EXT_COMMUNITIES
);
4509 stream_putw(s
, ecom_tr_size
* 8);
4513 BGP_ATTR_FLAG_OPTIONAL
4514 | BGP_ATTR_FLAG_TRANS
);
4516 BGP_ATTR_EXT_COMMUNITIES
);
4517 stream_putc(s
, ecom_tr_size
* 8);
4520 for (i
= 0; i
< ecomm
->size
; i
++) {
4521 pnt
= ecomm
->val
+ (i
* 8);
4526 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4529 stream_put(s
, pnt
, 8);
4535 /* Label index attribute. */
4536 if (safi
== SAFI_LABELED_UNICAST
) {
4537 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4538 uint32_t label_index
;
4540 label_index
= attr
->label_index
;
4542 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4544 BGP_ATTR_FLAG_OPTIONAL
4545 | BGP_ATTR_FLAG_TRANS
);
4546 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4548 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4550 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4551 stream_putc(s
, 0); // reserved
4552 stream_putw(s
, 0); // flags
4553 stream_putl(s
, label_index
);
4558 /* SRv6 Service Information Attribute. */
4559 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4560 if (attr
->srv6_l3vpn
) {
4561 uint8_t subtlv_len
=
4562 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4564 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4565 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4566 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4567 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4568 | BGP_ATTR_FLAG_TRANS
);
4569 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4570 stream_putc(s
, attr_len
);
4571 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4572 stream_putw(s
, tlv_len
);
4573 stream_putc(s
, 0); /* reserved */
4574 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4575 stream_putw(s
, subtlv_len
);
4576 stream_putc(s
, 0); /* reserved */
4577 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4578 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4579 stream_putc(s
, 0); /* sid_flags */
4582 ->endpoint_behavior
); /* endpoint */
4583 stream_putc(s
, 0); /* reserved */
4586 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4589 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4590 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4591 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4592 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4593 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4594 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4595 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4596 } else if (attr
->srv6_vpn
) {
4597 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4598 | BGP_ATTR_FLAG_TRANS
);
4599 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4600 stream_putc(s
, 22); /* tlv len */
4601 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4602 stream_putw(s
, 0x13); /* tlv len */
4603 stream_putc(s
, 0x00); /* reserved */
4604 stream_putc(s
, 0x01); /* sid_type */
4605 stream_putc(s
, 0x00); /* sif_flags */
4606 stream_put(s
, &attr
->srv6_vpn
->sid
,
4607 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4611 if (send_as4_path
) {
4612 /* If the peer is NOT As4 capable, AND */
4613 /* there are ASnums > 65535 in path THEN
4614 * give out AS4_PATH */
4616 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4618 * Hm, I wonder... confederation things *should* only be at
4619 * the beginning of an aspath, right? Then we should use
4620 * aspath_delete_confed_seq for this, because it is already
4622 * Folks, talk to me: what is reasonable here!?
4624 aspath
= aspath_delete_confed_seq(aspath
);
4627 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4628 | BGP_ATTR_FLAG_EXTLEN
);
4629 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4630 aspath_sizep
= stream_get_endp(s
);
4632 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4635 if (aspath
!= attr
->aspath
)
4636 aspath_free(aspath
);
4638 if (send_as4_aggregator
) {
4639 /* send AS4_AGGREGATOR, at this place */
4640 /* this section of code moved here in order to ensure the
4642 * *ascending* order of attributes
4644 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4645 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4647 stream_putl(s
, attr
->aggregator_as
);
4648 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4651 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4652 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4653 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4654 /* Tunnel Encap attribute */
4655 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4657 #ifdef ENABLE_BGP_VNC_ATTR
4659 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4664 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4665 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4666 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4667 stream_putc(s
, 9); // Length
4668 stream_putc(s
, 0); // Flags
4669 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4670 stream_put(s
, &(attr
->label
),
4671 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4672 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4673 // Unicast tunnel endpoint IP address
4677 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4678 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4679 stream_putc(s
, BGP_ATTR_OTC
);
4681 stream_putl(s
, attr
->otc
);
4685 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
) &&
4686 (CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
) ||
4687 peer
->sort
!= BGP_PEER_EBGP
)) {
4688 /* At the moment only AIGP Metric TLV exists for AIGP
4689 * attribute. If more comes in, do not forget to update
4690 * attr_len variable to include new ones.
4692 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4694 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4695 stream_putc(s
, BGP_ATTR_AIGP
);
4696 stream_putc(s
, attr_len
);
4697 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4700 /* Unknown transit attribute. */
4701 struct transit
*transit
= bgp_attr_get_transit(attr
);
4704 stream_put(s
, transit
->val
, transit
->length
);
4706 /* Return total size of attribute. */
4707 return stream_get_endp(s
) - cp
;
4710 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4712 unsigned long attrlen_pnt
;
4713 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
4714 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
4716 /* Set extended bit always to encode the attribute length as 2 bytes */
4717 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4718 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4720 attrlen_pnt
= stream_get_endp(s
);
4721 stream_putw(s
, 0); /* Length of this attribute. */
4723 /* Convert AFI, SAFI to values for packet. */
4724 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4726 stream_putw(s
, pkt_afi
);
4727 stream_putc(s
, pkt_safi
);
4732 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4733 afi_t afi
, safi_t safi
,
4734 const struct prefix_rd
*prd
,
4735 mpls_label_t
*label
, uint32_t num_labels
,
4736 bool addpath_capable
, uint32_t addpath_tx_id
,
4739 uint8_t wlabel
[4] = {0x80, 0x00, 0x00};
4741 if (safi
== SAFI_LABELED_UNICAST
) {
4742 label
= (mpls_label_t
*)wlabel
;
4746 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4747 addpath_capable
, addpath_tx_id
, attr
);
4750 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4752 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4755 /* Initialization of attribute. */
4756 void bgp_attr_init(void)
4769 void bgp_attr_finish(void)
4774 ecommunity_finish();
4775 lcommunity_finish();
4782 /* Make attribute packet. */
4783 void bgp_dump_routes_attr(struct stream
*s
, struct bgp_path_info
*bpi
,
4784 const struct prefix
*prefix
)
4789 struct aspath
*aspath
;
4790 bool addpath_capable
= false;
4791 uint32_t addpath_tx_id
= 0;
4792 struct attr
*attr
= bpi
->attr
;
4794 /* Remember current pointer. */
4795 cp
= stream_get_endp(s
);
4797 /* Place holder of length. */
4800 /* Origin attribute. */
4801 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4802 stream_putc(s
, BGP_ATTR_ORIGIN
);
4804 stream_putc(s
, attr
->origin
);
4806 aspath
= attr
->aspath
;
4808 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4809 stream_putc(s
, BGP_ATTR_AS_PATH
);
4810 aspath_lenp
= stream_get_endp(s
);
4813 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4815 /* Nexthop attribute. */
4816 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4817 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4818 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4819 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4821 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4824 /* MED attribute. */
4825 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4826 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4827 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4829 stream_putl(s
, attr
->med
);
4832 /* Local preference. */
4833 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4834 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4835 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4837 stream_putl(s
, attr
->local_pref
);
4840 /* Atomic aggregate. */
4841 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4842 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4843 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4848 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4849 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4850 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4852 stream_putl(s
, attr
->aggregator_as
);
4853 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4856 /* Community attribute. */
4857 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4858 struct community
*comm
= NULL
;
4860 comm
= bgp_attr_get_community(attr
);
4861 if (comm
->size
* 4 > 255) {
4863 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4864 | BGP_ATTR_FLAG_EXTLEN
);
4865 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4866 stream_putw(s
, comm
->size
* 4);
4869 BGP_ATTR_FLAG_OPTIONAL
4870 | BGP_ATTR_FLAG_TRANS
);
4871 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4872 stream_putc(s
, comm
->size
* 4);
4874 stream_put(s
, comm
->val
, comm
->size
* 4);
4877 /* Large Community attribute. */
4878 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4879 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4881 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4882 | BGP_ATTR_FLAG_EXTLEN
);
4883 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4885 lcom_length(bgp_attr_get_lcommunity(attr
)));
4888 BGP_ATTR_FLAG_OPTIONAL
4889 | BGP_ATTR_FLAG_TRANS
);
4890 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4892 lcom_length(bgp_attr_get_lcommunity(attr
)));
4895 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4896 lcom_length(bgp_attr_get_lcommunity(attr
)));
4899 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4900 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4901 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4902 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4905 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4906 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4907 sizep
= stream_get_endp(s
);
4910 stream_putc(s
, 0); /* Marker: Attribute length. */
4911 stream_putw(s
, AFI_IP6
); /* AFI */
4912 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4915 stream_putc(s
, attr
->mp_nexthop_len
);
4916 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4917 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4918 stream_put(s
, &attr
->mp_nexthop_local
,
4925 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4928 /* Set MP attribute length. */
4929 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4933 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4934 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4936 BGP_ATTR_FLAG_OPTIONAL
4937 | BGP_ATTR_FLAG_TRANS
);
4938 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4940 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4941 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4942 stream_putc(s
, 0); // reserved
4943 stream_putw(s
, 0); // flags
4944 stream_putl(s
, attr
->label_index
);
4949 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4950 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4951 stream_putc(s
, BGP_ATTR_OTC
);
4953 stream_putl(s
, attr
->otc
);
4957 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
4958 /* At the moment only AIGP Metric TLV exists for AIGP
4959 * attribute. If more comes in, do not forget to update
4960 * attr_len variable to include new ones.
4962 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4964 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4965 stream_putc(s
, BGP_ATTR_AIGP
);
4966 stream_putc(s
, attr_len
);
4967 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4970 /* Return total size of attribute. */
4971 len
= stream_get_endp(s
) - cp
- 2;
4972 stream_putw_at(s
, cp
, len
);