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_flag
== attr2
->nh_flag
870 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
871 && attr1
->distance
== attr2
->distance
872 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
873 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
874 && attr1
->srte_color
== attr2
->srte_color
875 && attr1
->nh_type
== attr2
->nh_type
876 && attr1
->bh_type
== attr2
->bh_type
877 && attr1
->otc
== attr2
->otc
)
884 static void attrhash_init(void)
887 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
891 * special for hash_clean below
893 static void attr_vfree(void *attr
)
895 XFREE(MTYPE_ATTR
, attr
);
898 static void attrhash_finish(void)
900 hash_clean(attrhash
, attr_vfree
);
905 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
907 struct attr
*attr
= bucket
->data
;
908 struct in6_addr
*sid
= NULL
;
910 if (attr
->srv6_l3vpn
)
911 sid
= &attr
->srv6_l3vpn
->sid
;
912 else if (attr
->srv6_vpn
)
913 sid
= &attr
->srv6_vpn
->sid
;
915 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
919 " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6\n",
920 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
921 attr
->origin
, attr
->weight
, attr
->label
, sid
);
924 void attr_show_all(struct vty
*vty
)
926 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
927 void *))attr_show_all_iterator
,
931 static void *bgp_attr_hash_alloc(void *p
)
933 struct attr
*val
= (struct attr
*)p
;
936 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
938 if (val
->encap_subtlvs
) {
939 val
->encap_subtlvs
= NULL
;
941 #ifdef ENABLE_BGP_VNC
942 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
943 bgp_attr_get_vnc_subtlvs(val
);
946 bgp_attr_set_vnc_subtlvs(val
, NULL
);
953 /* Internet argument attribute. */
954 struct attr
*bgp_attr_intern(struct attr
*attr
)
957 struct ecommunity
*ecomm
= NULL
;
958 struct ecommunity
*ipv6_ecomm
= NULL
;
959 struct lcommunity
*lcomm
= NULL
;
960 struct community
*comm
= NULL
;
962 /* Intern referenced structure. */
964 if (!attr
->aspath
->refcnt
)
965 attr
->aspath
= aspath_intern(attr
->aspath
);
967 attr
->aspath
->refcnt
++;
970 comm
= bgp_attr_get_community(attr
);
973 bgp_attr_set_community(attr
, community_intern(comm
));
978 ecomm
= bgp_attr_get_ecommunity(attr
);
981 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
986 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
988 if (!ipv6_ecomm
->refcnt
)
989 bgp_attr_set_ipv6_ecommunity(
990 attr
, ecommunity_intern(ipv6_ecomm
));
992 ipv6_ecomm
->refcnt
++;
995 lcomm
= bgp_attr_get_lcommunity(attr
);
998 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
1003 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1006 if (!cluster
->refcnt
)
1007 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
1012 struct transit
*transit
= bgp_attr_get_transit(attr
);
1015 if (!transit
->refcnt
)
1016 bgp_attr_set_transit(attr
, transit_intern(transit
));
1020 if (attr
->encap_subtlvs
) {
1021 if (!attr
->encap_subtlvs
->refcnt
)
1022 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
1025 attr
->encap_subtlvs
->refcnt
++;
1027 if (attr
->srv6_l3vpn
) {
1028 if (!attr
->srv6_l3vpn
->refcnt
)
1029 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
1031 attr
->srv6_l3vpn
->refcnt
++;
1033 if (attr
->srv6_vpn
) {
1034 if (!attr
->srv6_vpn
->refcnt
)
1035 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
1037 attr
->srv6_vpn
->refcnt
++;
1039 #ifdef ENABLE_BGP_VNC
1040 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1041 bgp_attr_get_vnc_subtlvs(attr
);
1044 if (!vnc_subtlvs
->refcnt
)
1045 bgp_attr_set_vnc_subtlvs(
1047 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
1049 vnc_subtlvs
->refcnt
++;
1053 /* At this point, attr only contains intern'd pointers. that means
1054 * if we find it in attrhash, it has all the same pointers and we
1055 * correctly updated the refcounts on these.
1056 * If we don't find it, we need to allocate a one because in all
1057 * cases this returns a new reference to a hashed attr, but the input
1058 * wasn't on hash. */
1059 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
1065 /* Make network statement's attribute. */
1066 struct attr
*bgp_attr_default_set(struct attr
*attr
, struct bgp
*bgp
,
1069 memset(attr
, 0, sizeof(struct attr
));
1071 attr
->origin
= origin
;
1072 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1073 attr
->aspath
= aspath_empty();
1074 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1075 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1077 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
1078 attr
->label
= MPLS_INVALID_LABEL
;
1079 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1080 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1081 attr
->local_pref
= bgp
->default_local_pref
;
1086 /* Create the attributes for an aggregate */
1087 struct attr
*bgp_attr_aggregate_intern(
1088 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
1089 struct community
*community
, struct ecommunity
*ecommunity
,
1090 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
1091 uint8_t atomic_aggregate
, const struct prefix
*p
)
1095 route_map_result_t ret
;
1097 memset(&attr
, 0, sizeof(attr
));
1099 /* Origin attribute. */
1100 attr
.origin
= origin
;
1101 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1105 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1107 /* AS path attribute. */
1109 attr
.aspath
= aspath_intern(aspath
);
1111 attr
.aspath
= aspath_empty();
1112 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1114 /* Next hop attribute. */
1115 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1118 uint32_t gshut
= COMMUNITY_GSHUT
;
1120 /* If we are not shutting down ourselves and we are
1121 * aggregating a route that contains the GSHUT community we
1122 * need to remove that community when creating the aggregate */
1123 if (!bgp_in_graceful_shutdown(bgp
)
1124 && community_include(community
, gshut
)) {
1125 community_del_val(community
, &gshut
);
1128 bgp_attr_set_community(&attr
, community
);
1132 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1135 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1137 if (bgp_in_graceful_shutdown(bgp
))
1138 bgp_attr_add_gshut_community(&attr
);
1140 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1141 attr
.label
= MPLS_INVALID_LABEL
;
1142 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1143 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1144 if (!aggregate
->as_set
|| atomic_aggregate
)
1145 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1146 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1147 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1148 attr
.aggregator_as
= bgp
->confed_id
;
1150 attr
.aggregator_as
= bgp
->as
;
1151 attr
.aggregator_addr
= bgp
->router_id
;
1153 /* Apply route-map */
1154 if (aggregate
->rmap
.name
) {
1155 struct attr attr_tmp
= attr
;
1156 struct bgp_path_info rmap_path
;
1158 memset(&rmap_path
, 0, sizeof(rmap_path
));
1159 rmap_path
.peer
= bgp
->peer_self
;
1160 rmap_path
.attr
= &attr_tmp
;
1162 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1164 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1166 bgp
->peer_self
->rmap_type
= 0;
1168 if (ret
== RMAP_DENYMATCH
) {
1169 /* Free uninterned attribute. */
1170 bgp_attr_flush(&attr_tmp
);
1172 /* Unintern original. */
1173 aspath_unintern(&attr
.aspath
);
1177 if (bgp_in_graceful_shutdown(bgp
))
1178 bgp_attr_add_gshut_community(&attr_tmp
);
1180 new = bgp_attr_intern(&attr_tmp
);
1183 if (bgp_in_graceful_shutdown(bgp
))
1184 bgp_attr_add_gshut_community(&attr
);
1186 new = bgp_attr_intern(&attr
);
1189 /* Always release the 'intern()'ed AS Path. */
1190 aspath_unintern(&attr
.aspath
);
1195 /* Unintern just the sub-components of the attr, but not the attr */
1196 void bgp_attr_unintern_sub(struct attr
*attr
)
1198 struct ecommunity
*ecomm
= NULL
;
1199 struct ecommunity
*ipv6_ecomm
= NULL
;
1200 struct cluster_list
*cluster
;
1201 struct lcommunity
*lcomm
= NULL
;
1202 struct community
*comm
= NULL
;
1204 /* aspath refcount shoud be decrement. */
1205 aspath_unintern(&attr
->aspath
);
1206 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1208 comm
= bgp_attr_get_community(attr
);
1209 community_unintern(&comm
);
1210 bgp_attr_set_community(attr
, NULL
);
1212 ecomm
= bgp_attr_get_ecommunity(attr
);
1213 ecommunity_unintern(&ecomm
);
1214 bgp_attr_set_ecommunity(attr
, NULL
);
1216 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1217 ecommunity_unintern(&ipv6_ecomm
);
1218 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1220 lcomm
= bgp_attr_get_lcommunity(attr
);
1221 lcommunity_unintern(&lcomm
);
1222 bgp_attr_set_lcommunity(attr
, NULL
);
1224 cluster
= bgp_attr_get_cluster(attr
);
1226 cluster_unintern(&cluster
);
1227 bgp_attr_set_cluster(attr
, cluster
);
1229 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1231 struct transit
*transit
= bgp_attr_get_transit(attr
);
1234 transit_unintern(&transit
);
1235 bgp_attr_set_transit(attr
, transit
);
1238 if (attr
->encap_subtlvs
)
1239 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1241 #ifdef ENABLE_BGP_VNC
1242 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1243 bgp_attr_get_vnc_subtlvs(attr
);
1246 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1247 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1251 if (attr
->srv6_l3vpn
)
1252 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1255 srv6_vpn_unintern(&attr
->srv6_vpn
);
1258 /* Free bgp attribute and aspath. */
1259 void bgp_attr_unintern(struct attr
**pattr
)
1261 struct attr
*attr
= *pattr
;
1265 /* Decrement attribute reference. */
1270 /* If reference becomes zero then free attribute object. */
1271 if (attr
->refcnt
== 0) {
1272 ret
= hash_release(attrhash
, attr
);
1273 assert(ret
!= NULL
);
1274 XFREE(MTYPE_ATTR
, attr
);
1278 bgp_attr_unintern_sub(&tmp
);
1281 void bgp_attr_flush(struct attr
*attr
)
1283 struct ecommunity
*ecomm
;
1284 struct ecommunity
*ipv6_ecomm
;
1285 struct cluster_list
*cluster
;
1286 struct lcommunity
*lcomm
;
1287 struct community
*comm
;
1289 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1290 aspath_free(attr
->aspath
);
1291 attr
->aspath
= NULL
;
1293 comm
= bgp_attr_get_community(attr
);
1294 if (comm
&& !comm
->refcnt
)
1295 community_free(&comm
);
1296 bgp_attr_set_community(attr
, NULL
);
1298 ecomm
= bgp_attr_get_ecommunity(attr
);
1299 if (ecomm
&& !ecomm
->refcnt
)
1300 ecommunity_free(&ecomm
);
1301 bgp_attr_set_ecommunity(attr
, NULL
);
1303 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1304 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1305 ecommunity_free(&ipv6_ecomm
);
1306 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1308 lcomm
= bgp_attr_get_lcommunity(attr
);
1309 if (lcomm
&& !lcomm
->refcnt
)
1310 lcommunity_free(&lcomm
);
1311 bgp_attr_set_lcommunity(attr
, NULL
);
1313 cluster
= bgp_attr_get_cluster(attr
);
1314 if (cluster
&& !cluster
->refcnt
) {
1315 cluster_free(cluster
);
1316 bgp_attr_set_cluster(attr
, NULL
);
1319 struct transit
*transit
= bgp_attr_get_transit(attr
);
1321 if (transit
&& !transit
->refcnt
) {
1322 transit_free(transit
);
1323 bgp_attr_set_transit(attr
, NULL
);
1325 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1326 encap_free(attr
->encap_subtlvs
);
1327 attr
->encap_subtlvs
= NULL
;
1329 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1330 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1331 attr
->srv6_l3vpn
= NULL
;
1333 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1334 srv6_vpn_free(attr
->srv6_vpn
);
1335 attr
->srv6_vpn
= NULL
;
1337 #ifdef ENABLE_BGP_VNC
1338 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1339 bgp_attr_get_vnc_subtlvs(attr
);
1341 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1342 encap_free(vnc_subtlvs
);
1343 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1348 /* Implement draft-scudder-idr-optional-transitive behaviour and
1349 * avoid resetting sessions for malformed attributes which are
1350 * are partial/optional and hence where the error likely was not
1351 * introduced by the sending neighbour.
1353 static enum bgp_attr_parse_ret
1354 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1357 struct peer
*const peer
= args
->peer
;
1358 struct attr
*const attr
= args
->attr
;
1359 const uint8_t flags
= args
->flags
;
1360 /* startp and length must be special-cased, as whether or not to
1361 * send the attribute data with the NOTIFY depends on the error,
1362 * the caller therefore signals this with the seperate length argument
1364 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1366 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1367 char attr_str
[BUFSIZ
] = {0};
1369 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1371 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1374 /* Only relax error handling for eBGP peers */
1375 if (peer
->sort
!= BGP_PEER_EBGP
) {
1376 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1377 notify_datap
, length
);
1378 return BGP_ATTR_PARSE_ERROR
;
1381 /* Adjust the stream getp to the end of the attribute, in case we can
1382 * still proceed but the caller hasn't read all the attribute.
1384 stream_set_getp(BGP_INPUT(peer
),
1385 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1388 switch (args
->type
) {
1389 /* where an attribute is relatively inconsequential, e.g. it does not
1390 * affect route selection, and can be safely ignored, then any such
1391 * attributes which are malformed should just be ignored and the route
1392 * processed as normal.
1394 case BGP_ATTR_AS4_AGGREGATOR
:
1395 case BGP_ATTR_AGGREGATOR
:
1396 case BGP_ATTR_ATOMIC_AGGREGATE
:
1397 return BGP_ATTR_PARSE_PROCEED
;
1399 /* Core attributes, particularly ones which may influence route
1400 * selection, should be treat-as-withdraw.
1402 case BGP_ATTR_ORIGIN
:
1403 case BGP_ATTR_AS_PATH
:
1404 case BGP_ATTR_NEXT_HOP
:
1405 case BGP_ATTR_MULTI_EXIT_DISC
:
1406 case BGP_ATTR_LOCAL_PREF
:
1407 case BGP_ATTR_COMMUNITIES
:
1408 case BGP_ATTR_EXT_COMMUNITIES
:
1409 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1410 case BGP_ATTR_LARGE_COMMUNITIES
:
1411 case BGP_ATTR_ORIGINATOR_ID
:
1412 case BGP_ATTR_CLUSTER_LIST
:
1414 return BGP_ATTR_PARSE_WITHDRAW
;
1415 case BGP_ATTR_MP_REACH_NLRI
:
1416 case BGP_ATTR_MP_UNREACH_NLRI
:
1417 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1418 notify_datap
, length
);
1419 return BGP_ATTR_PARSE_ERROR
;
1422 /* Partial optional attributes that are malformed should not cause
1423 * the whole session to be reset. Instead treat it as a withdrawal
1424 * of the routes, if possible.
1426 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1427 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1428 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1429 return BGP_ATTR_PARSE_WITHDRAW
;
1431 /* default to reset */
1432 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1435 /* Find out what is wrong with the path attribute flag bits and log the error.
1436 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1437 Extended Length. Checking O/T/P bits at once implies, that the attribute
1438 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1439 non-transitive" attribute. */
1441 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1442 uint8_t desired_flags
/* how RFC says it must be */
1445 uint8_t seen
= 0, i
;
1446 uint8_t real_flags
= args
->flags
;
1447 const uint8_t attr_code
= args
->type
;
1449 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1450 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1451 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1452 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1453 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1454 flog_err(EC_BGP_ATTR_FLAG
,
1455 "%s attribute must%s be flagged as \"%s\"",
1456 lookup_msg(attr_str
, attr_code
, NULL
),
1457 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1460 attr_flag_str
[i
].str
);
1465 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1466 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1467 real_flags
, desired_flags
);
1471 /* Required flags for attributes. EXTLEN will be masked off when testing,
1472 * as will PARTIAL for optional+transitive attributes.
1474 const uint8_t attr_flags_values
[] = {
1475 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1476 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1477 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1478 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1479 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1480 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1481 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1482 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1483 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1484 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1485 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1486 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1487 [BGP_ATTR_EXT_COMMUNITIES
] =
1488 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1489 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1490 [BGP_ATTR_AS4_AGGREGATOR
] =
1491 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1492 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1493 [BGP_ATTR_LARGE_COMMUNITIES
] =
1494 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1495 [BGP_ATTR_OTC
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1496 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1497 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1498 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1499 [BGP_ATTR_AIGP
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1501 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1503 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1505 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1506 const uint8_t flags
= args
->flags
;
1507 const uint8_t attr_code
= args
->type
;
1509 /* there may be attributes we don't know about */
1510 if (attr_code
> attr_flags_values_max
)
1512 if (attr_flags_values
[attr_code
] == 0)
1515 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1519 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1520 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1523 "%s well-known attributes must have transitive flag set (%x)",
1524 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1528 /* "For well-known attributes and for optional non-transitive
1530 * the Partial bit MUST be set to 0."
1532 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1533 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1534 flog_err(EC_BGP_ATTR_FLAG
,
1535 "%s well-known attribute must NOT have the partial flag set (%x)",
1536 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1539 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1540 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1541 flog_err(EC_BGP_ATTR_FLAG
,
1542 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1543 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1548 /* Optional transitive attributes may go through speakers that don't
1549 * reocgnise them and set the Partial bit.
1551 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1552 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1553 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1555 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1558 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1562 /* Get origin attribute of the update message. */
1563 static enum bgp_attr_parse_ret
1564 bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1566 struct peer
*const peer
= args
->peer
;
1567 struct attr
*const attr
= args
->attr
;
1568 const bgp_size_t length
= args
->length
;
1570 /* If any recognized attribute has Attribute Length that conflicts
1571 with the expected length (based on the attribute type code), then
1572 the Error Subcode is set to Attribute Length Error. The Data
1573 field contains the erroneous attribute (type, length and
1576 flog_err(EC_BGP_ATTR_LEN
,
1577 "Origin attribute length is not one %d", length
);
1578 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1582 /* Fetch origin attribute. */
1583 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1585 /* If the ORIGIN attribute has an undefined value, then the Error
1586 Subcode is set to Invalid Origin Attribute. The Data field
1587 contains the unrecognized attribute (type, length and value). */
1588 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1589 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1590 flog_err(EC_BGP_ATTR_ORIGIN
,
1591 "Origin attribute value is invalid %d", attr
->origin
);
1592 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1596 /* Set oring attribute flag. */
1597 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1602 /* Parse AS path information. This function is wrapper of
1604 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1606 struct attr
*const attr
= args
->attr
;
1607 struct peer
*const peer
= args
->peer
;
1608 const bgp_size_t length
= args
->length
;
1611 * peer with AS4 => will get 4Byte ASnums
1612 * otherwise, will get 16 Bit
1614 attr
->aspath
= aspath_parse(
1616 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1617 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1619 /* In case of IBGP, length will be zero. */
1620 if (!attr
->aspath
) {
1621 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1622 "Malformed AS path from %s, length is %d", peer
->host
,
1624 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1628 /* Conformant BGP speakers SHOULD NOT send BGP
1629 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1630 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1631 * withdraw" error handling behavior as per [RFC7606].
1633 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1634 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1635 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1637 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1641 /* Set aspath attribute flag. */
1642 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1644 return BGP_ATTR_PARSE_PROCEED
;
1647 static enum bgp_attr_parse_ret
bgp_attr_aspath_check(struct peer
*const peer
,
1648 struct attr
*const attr
)
1650 /* These checks were part of bgp_attr_aspath, but with
1651 * as4 we should to check aspath things when
1652 * aspath synthesizing with as4_path has already taken place.
1653 * Otherwise we check ASPATH and use the synthesized thing, and that is
1655 * So do the checks later, i.e. here
1657 struct aspath
*aspath
;
1659 /* Confederation sanity check. */
1660 if ((peer
->sort
== BGP_PEER_CONFED
1661 && !aspath_left_confed_check(attr
->aspath
))
1662 || (peer
->sort
== BGP_PEER_EBGP
1663 && aspath_confed_check(attr
->aspath
))) {
1664 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1666 return BGP_ATTR_PARSE_WITHDRAW
;
1669 /* First AS check for EBGP. */
1670 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1671 if (peer
->sort
== BGP_PEER_EBGP
1672 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1673 flog_err(EC_BGP_ATTR_FIRST_AS
,
1674 "%s incorrect first AS (must be %u)",
1675 peer
->host
, peer
->as
);
1676 return BGP_ATTR_PARSE_WITHDRAW
;
1680 /* Codification of AS 0 Processing */
1681 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1683 EC_BGP_ATTR_MAL_AS_PATH
,
1684 "Malformed AS path, AS number is 0 in the path from %s",
1686 return BGP_ATTR_PARSE_WITHDRAW
;
1689 /* local-as prepend */
1690 if (peer
->change_local_as
1691 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1692 aspath
= aspath_dup(attr
->aspath
);
1693 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1694 aspath_unintern(&attr
->aspath
);
1695 attr
->aspath
= aspath_intern(aspath
);
1698 return BGP_ATTR_PARSE_PROCEED
;
1701 /* Parse AS4 path information. This function is another wrapper of
1703 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1704 struct aspath
**as4_path
)
1706 struct peer
*const peer
= args
->peer
;
1707 struct attr
*const attr
= args
->attr
;
1708 const bgp_size_t length
= args
->length
;
1710 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1712 /* In case of IBGP, length will be zero. */
1714 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1715 "Malformed AS4 path from %s, length is %d", peer
->host
,
1717 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1721 /* Conformant BGP speakers SHOULD NOT send BGP
1722 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1723 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1724 * withdraw" error handling behavior as per [RFC7606].
1726 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1727 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1728 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1730 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1734 /* Set aspath attribute flag. */
1735 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1737 return BGP_ATTR_PARSE_PROCEED
;
1741 * Check that the nexthop attribute is valid.
1743 enum bgp_attr_parse_ret
bgp_attr_nexthop_valid(struct peer
*peer
,
1746 struct bgp
*bgp
= peer
->bgp
;
1748 if (ipv4_martian(&attr
->nexthop
) && !bgp
->allow_martian
) {
1749 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1751 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %pI4",
1753 data
[0] = BGP_ATTR_FLAG_TRANS
;
1754 data
[1] = BGP_ATTR_NEXT_HOP
;
1755 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1756 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1757 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1758 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1760 return BGP_ATTR_PARSE_ERROR
;
1763 return BGP_ATTR_PARSE_PROCEED
;
1766 /* Nexthop attribute. */
1767 static enum bgp_attr_parse_ret
1768 bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1770 struct peer
*const peer
= args
->peer
;
1771 struct attr
*const attr
= args
->attr
;
1772 const bgp_size_t length
= args
->length
;
1774 /* Check nexthop attribute length. */
1776 flog_err(EC_BGP_ATTR_LEN
,
1777 "Nexthop attribute length isn't four [%d]", length
);
1779 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1783 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1784 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1786 return BGP_ATTR_PARSE_PROCEED
;
1789 /* MED atrribute. */
1790 static enum bgp_attr_parse_ret
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1792 struct peer
*const peer
= args
->peer
;
1793 struct attr
*const attr
= args
->attr
;
1794 const bgp_size_t length
= args
->length
;
1798 flog_err(EC_BGP_ATTR_LEN
,
1799 "MED attribute length isn't four [%d]", length
);
1801 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1805 attr
->med
= stream_getl(peer
->curr
);
1807 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1809 return BGP_ATTR_PARSE_PROCEED
;
1812 /* Local preference attribute. */
1813 static enum bgp_attr_parse_ret
1814 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1816 struct peer
*const peer
= args
->peer
;
1817 struct attr
*const attr
= args
->attr
;
1818 const bgp_size_t length
= args
->length
;
1820 /* if received from an internal neighbor, it SHALL be considered
1821 * malformed if its length is not equal to 4. If malformed, the
1822 * UPDATE message SHALL be handled using the approach of "treat-as-
1825 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1826 flog_err(EC_BGP_ATTR_LEN
,
1827 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1828 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1832 /* If it is contained in an UPDATE message that is received from an
1833 external peer, then this attribute MUST be ignored by the
1834 receiving speaker. */
1835 if (peer
->sort
== BGP_PEER_EBGP
) {
1836 STREAM_FORWARD_GETP(peer
->curr
, length
);
1837 return BGP_ATTR_PARSE_PROCEED
;
1840 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1842 /* Set the local-pref flag. */
1843 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1845 return BGP_ATTR_PARSE_PROCEED
;
1848 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1852 /* Atomic aggregate. */
1853 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1855 struct attr
*const attr
= args
->attr
;
1856 const bgp_size_t length
= args
->length
;
1860 flog_err(EC_BGP_ATTR_LEN
,
1861 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1863 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1867 /* Set atomic aggregate flag. */
1868 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1870 return BGP_ATTR_PARSE_PROCEED
;
1873 /* Aggregator attribute */
1874 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1876 struct peer
*const peer
= args
->peer
;
1877 struct attr
*const attr
= args
->attr
;
1878 const bgp_size_t length
= args
->length
;
1883 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1884 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1885 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1888 if (length
!= wantedlen
) {
1889 flog_err(EC_BGP_ATTR_LEN
,
1890 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1892 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1896 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1897 aggregator_as
= stream_getl(peer
->curr
);
1899 aggregator_as
= stream_getw(peer
->curr
);
1901 attr
->aggregator_as
= aggregator_as
;
1902 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1904 /* Codification of AS 0 Processing */
1905 if (aggregator_as
== BGP_AS_ZERO
) {
1906 flog_err(EC_BGP_ATTR_LEN
,
1907 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1908 peer
->host
, aspath_print(attr
->aspath
));
1910 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1911 char attr_str
[BUFSIZ
] = {0};
1913 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1915 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1918 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1921 return BGP_ATTR_PARSE_PROCEED
;
1924 /* New Aggregator attribute */
1925 static enum bgp_attr_parse_ret
1926 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1927 as_t
*as4_aggregator_as
,
1928 struct in_addr
*as4_aggregator_addr
)
1930 struct peer
*const peer
= args
->peer
;
1931 struct attr
*const attr
= args
->attr
;
1932 const bgp_size_t length
= args
->length
;
1936 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1938 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1942 aggregator_as
= stream_getl(peer
->curr
);
1944 *as4_aggregator_as
= aggregator_as
;
1945 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1947 /* Codification of AS 0 Processing */
1948 if (aggregator_as
== BGP_AS_ZERO
) {
1949 flog_err(EC_BGP_ATTR_LEN
,
1950 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1951 peer
->host
, aspath_print(attr
->aspath
));
1953 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1954 char attr_str
[BUFSIZ
] = {0};
1956 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1958 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1961 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1964 return BGP_ATTR_PARSE_PROCEED
;
1967 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1969 static enum bgp_attr_parse_ret
1970 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1971 struct aspath
*as4_path
, as_t as4_aggregator
,
1972 struct in_addr
*as4_aggregator_addr
)
1974 int ignore_as4_path
= 0;
1975 struct aspath
*newpath
;
1977 if (!attr
->aspath
) {
1978 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1980 * checked that all well-known, mandatory attributes were
1983 * Can only be a problem with peer itself - hard error
1985 return BGP_ATTR_PARSE_ERROR
;
1988 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1989 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1991 * It is worth a warning though, because the peer really
1992 * should not send them
1994 if (BGP_DEBUG(as4
, AS4
)) {
1995 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1996 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1997 "AS4 capable peer, yet it sent");
2000 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
2001 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
2003 "AS4 capable peer, yet it sent");
2006 return BGP_ATTR_PARSE_PROCEED
;
2009 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
2010 * because that may override AS4_PATH
2012 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
2013 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
2015 * if the as_number in aggregator is not AS_TRANS,
2016 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
2017 * and the Aggregator shall be taken as
2018 * info on the aggregating node, and the AS_PATH
2019 * shall be taken as the AS_PATH
2021 * the Aggregator shall be ignored and the
2022 * AS4_AGGREGATOR shall be taken as the
2023 * Aggregating node and the AS_PATH is to be
2024 * constructed "as in all other cases"
2026 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
2028 if (BGP_DEBUG(as4
, AS4
))
2030 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
2032 ignore_as4_path
= 1;
2034 /* "New_aggregator shall be taken as aggregator"
2036 attr
->aggregator_as
= as4_aggregator
;
2037 attr
->aggregator_addr
.s_addr
=
2038 as4_aggregator_addr
->s_addr
;
2041 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2042 * That is bogus - but reading the conditions
2043 * we have to handle AS4_AGGREGATOR as if it were
2044 * AGGREGATOR in that case
2046 if (BGP_DEBUG(as4
, AS4
))
2048 "[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",
2050 attr
->aggregator_as
= as4_aggregator
;
2051 /* sweep it under the carpet and simulate a "good"
2053 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
2057 /* need to reconcile NEW_AS_PATH and AS_PATH */
2058 if (!ignore_as4_path
2059 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
2060 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
2062 return BGP_ATTR_PARSE_ERROR
;
2064 aspath_unintern(&attr
->aspath
);
2065 attr
->aspath
= aspath_intern(newpath
);
2067 return BGP_ATTR_PARSE_PROCEED
;
2070 /* Community attribute. */
2071 static enum bgp_attr_parse_ret
2072 bgp_attr_community(struct bgp_attr_parser_args
*args
)
2074 struct peer
*const peer
= args
->peer
;
2075 struct attr
*const attr
= args
->attr
;
2076 const bgp_size_t length
= args
->length
;
2079 bgp_attr_set_community(attr
, NULL
);
2080 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2084 bgp_attr_set_community(
2086 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
2088 /* XXX: fix community_parse to use stream API and remove this */
2089 stream_forward_getp(peer
->curr
, length
);
2091 /* The Community attribute SHALL be considered malformed if its
2092 * length is not a non-zero multiple of 4.
2094 if (!bgp_attr_get_community(attr
))
2095 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2098 return BGP_ATTR_PARSE_PROCEED
;
2101 /* Originator ID attribute. */
2102 static enum bgp_attr_parse_ret
2103 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
2105 struct peer
*const peer
= args
->peer
;
2106 struct attr
*const attr
= args
->attr
;
2107 const bgp_size_t length
= args
->length
;
2109 /* if received from an internal neighbor, it SHALL be considered
2110 * malformed if its length is not equal to 4. If malformed, the
2111 * UPDATE message SHALL be handled using the approach of "treat-as-
2115 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
2118 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2122 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
2124 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2126 return BGP_ATTR_PARSE_PROCEED
;
2129 /* Cluster list attribute. */
2130 static enum bgp_attr_parse_ret
2131 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2133 struct peer
*const peer
= args
->peer
;
2134 struct attr
*const attr
= args
->attr
;
2135 const bgp_size_t length
= args
->length
;
2137 /* if received from an internal neighbor, it SHALL be considered
2138 * malformed if its length is not a non-zero multiple of 4. If
2139 * malformed, the UPDATE message SHALL be handled using the approach
2140 * of "treat-as-withdraw".
2142 if (length
== 0 || length
% 4) {
2143 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2145 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2149 bgp_attr_set_cluster(
2150 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2153 /* XXX: Fix cluster_parse to use stream API and then remove this */
2154 stream_forward_getp(peer
->curr
, length
);
2156 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2158 return BGP_ATTR_PARSE_PROCEED
;
2161 /* Multiprotocol reachability information parse. */
2162 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2163 struct bgp_nlri
*mp_update
)
2167 iana_safi_t pkt_safi
;
2169 bgp_size_t nlri_len
;
2172 struct peer
*const peer
= args
->peer
;
2173 struct attr
*const attr
= args
->attr
;
2174 const bgp_size_t length
= args
->length
;
2176 /* Set end of packet. */
2177 s
= BGP_INPUT(peer
);
2178 start
= stream_get_getp(s
);
2180 /* safe to read statically sized header? */
2181 #define BGP_MP_REACH_MIN_SIZE 5
2182 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2183 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2184 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2185 __func__
, peer
->host
, (unsigned long)length
);
2186 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2189 /* Load AFI, SAFI. */
2190 pkt_afi
= stream_getw(s
);
2191 pkt_safi
= stream_getc(s
);
2193 /* Convert AFI, SAFI to internal values, check. */
2194 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2195 /* Log if AFI or SAFI is unrecognized. This is not an error
2197 * the attribute is otherwise malformed.
2199 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2201 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2202 peer
->host
, iana_afi2str(pkt_afi
),
2203 iana_safi2str(pkt_safi
));
2204 return BGP_ATTR_PARSE_ERROR
;
2207 /* Get nexthop length. */
2208 attr
->mp_nexthop_len
= stream_getc(s
);
2210 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2212 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2213 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2214 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2217 /* Nexthop length check. */
2218 switch (attr
->mp_nexthop_len
) {
2220 if (safi
!= SAFI_FLOWSPEC
) {
2221 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2222 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2223 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2226 case BGP_ATTR_NHLEN_VPNV4
:
2227 stream_getl(s
); /* RD high */
2228 stream_getl(s
); /* RD low */
2230 * NOTE: intentional fall through
2231 * - for consistency in rx processing
2233 * The following comment is to signal GCC this intention
2234 * and suppress the warning
2237 case BGP_ATTR_NHLEN_IPV4
:
2238 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2239 /* Probably needed for RFC 2283 */
2240 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2241 memcpy(&attr
->nexthop
.s_addr
,
2242 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2244 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2245 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2246 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2247 stream_getl(s
); /* RD high */
2248 stream_getl(s
); /* RD low */
2250 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2251 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2252 if (!peer
->nexthop
.ifp
) {
2253 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2255 return BGP_ATTR_PARSE_WITHDRAW
;
2257 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2260 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2261 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2262 if (attr
->mp_nexthop_len
2263 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2264 stream_getl(s
); /* RD high */
2265 stream_getl(s
); /* RD low */
2267 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2268 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2269 if (!peer
->nexthop
.ifp
) {
2270 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",
2272 return BGP_ATTR_PARSE_WITHDRAW
;
2274 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2276 if (attr
->mp_nexthop_len
2277 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2278 stream_getl(s
); /* RD high */
2279 stream_getl(s
); /* RD low */
2281 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2282 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2283 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2285 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2286 peer
->host
, &attr
->mp_nexthop_global
,
2287 &attr
->mp_nexthop_local
);
2289 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2291 if (!peer
->nexthop
.ifp
) {
2292 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2294 return BGP_ATTR_PARSE_WITHDRAW
;
2296 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2299 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2300 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2301 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2305 zlog_info("%s: %s sent SNPA which couldn't be read",
2306 __func__
, peer
->host
);
2307 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2312 if ((val
= stream_getc(s
)))
2314 EC_BGP_DEFUNCT_SNPA_LEN
,
2315 "%s sent non-zero value, %u, for defunct SNPA-length field",
2319 /* must have nrli_len, what is left of the attribute */
2320 nlri_len
= LEN_LEFT
;
2321 if (nlri_len
> STREAM_READABLE(s
)) {
2322 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2323 __func__
, peer
->host
);
2324 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2328 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2329 __func__
, peer
->host
);
2331 mp_update
->afi
= afi
;
2332 mp_update
->safi
= safi
;
2333 return BGP_ATTR_PARSE_EOR
;
2336 mp_update
->afi
= afi
;
2337 mp_update
->safi
= safi
;
2338 mp_update
->nlri
= stream_pnt(s
);
2339 mp_update
->length
= nlri_len
;
2341 stream_forward_getp(s
, nlri_len
);
2343 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2345 return BGP_ATTR_PARSE_PROCEED
;
2349 /* Multiprotocol unreachable parse */
2350 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2351 struct bgp_nlri
*mp_withdraw
)
2356 iana_safi_t pkt_safi
;
2358 uint16_t withdraw_len
;
2359 struct peer
*const peer
= args
->peer
;
2360 struct attr
*const attr
= args
->attr
;
2361 const bgp_size_t length
= args
->length
;
2365 #define BGP_MP_UNREACH_MIN_SIZE 3
2366 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2367 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2369 pkt_afi
= stream_getw(s
);
2370 pkt_safi
= stream_getc(s
);
2372 /* Convert AFI, SAFI to internal values, check. */
2373 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2374 /* Log if AFI or SAFI is unrecognized. This is not an error
2376 * the attribute is otherwise malformed.
2378 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2380 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2381 peer
->host
, iana_afi2str(pkt_afi
),
2382 iana_safi2str(pkt_safi
));
2383 return BGP_ATTR_PARSE_ERROR
;
2386 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2388 mp_withdraw
->afi
= afi
;
2389 mp_withdraw
->safi
= safi
;
2390 mp_withdraw
->nlri
= stream_pnt(s
);
2391 mp_withdraw
->length
= withdraw_len
;
2393 stream_forward_getp(s
, withdraw_len
);
2395 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2397 return BGP_ATTR_PARSE_PROCEED
;
2400 /* Large Community attribute. */
2401 static enum bgp_attr_parse_ret
2402 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2404 struct peer
*const peer
= args
->peer
;
2405 struct attr
*const attr
= args
->attr
;
2406 const bgp_size_t length
= args
->length
;
2409 * Large community follows new attribute format.
2412 bgp_attr_set_lcommunity(attr
, NULL
);
2413 /* Empty extcomm doesn't seem to be invalid per se */
2414 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2418 bgp_attr_set_lcommunity(
2419 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2420 /* XXX: fix ecommunity_parse to use stream API */
2421 stream_forward_getp(peer
->curr
, length
);
2423 if (!bgp_attr_get_lcommunity(attr
))
2424 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2427 return BGP_ATTR_PARSE_PROCEED
;
2430 /* Extended Community attribute. */
2431 static enum bgp_attr_parse_ret
2432 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2434 struct peer
*const peer
= args
->peer
;
2435 struct attr
*const attr
= args
->attr
;
2436 const bgp_size_t length
= args
->length
;
2439 struct ecommunity
*ecomm
;
2442 bgp_attr_set_ecommunity(attr
, NULL
);
2443 /* Empty extcomm doesn't seem to be invalid per se */
2444 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2448 ecomm
= ecommunity_parse(
2449 stream_pnt(peer
->curr
), length
,
2450 CHECK_FLAG(peer
->flags
,
2451 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2452 bgp_attr_set_ecommunity(attr
, ecomm
);
2453 /* XXX: fix ecommunity_parse to use stream API */
2454 stream_forward_getp(peer
->curr
, length
);
2456 /* The Extended Community attribute SHALL be considered malformed if
2457 * its length is not a non-zero multiple of 8.
2459 if (!bgp_attr_get_ecommunity(attr
))
2460 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2463 /* Extract DF election preference and mobility sequence number */
2464 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2466 /* Extract MAC mobility sequence number, if any. */
2467 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2468 attr
->sticky
= sticky
;
2470 /* Check if this is a Gateway MAC-IP advertisement */
2471 attr
->default_gw
= bgp_attr_default_gw(attr
);
2473 /* Handle scenario where router flag ecommunity is not
2474 * set but default gw ext community is present.
2475 * Use default gateway, set and propogate R-bit.
2477 if (attr
->default_gw
)
2478 attr
->router_flag
= 1;
2480 /* Check EVPN Neighbor advertisement flags, R-bit */
2481 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2483 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2485 /* Extract the Rmac, if any */
2486 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2487 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2488 && bgp_mac_exist(&attr
->rmac
))
2489 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2493 /* Get the tunnel type from encap extended community */
2494 bgp_attr_extcom_tunnel_type(attr
,
2495 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2497 /* Extract link bandwidth, if any. */
2498 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2501 return BGP_ATTR_PARSE_PROCEED
;
2504 /* IPv6 Extended Community attribute. */
2505 static enum bgp_attr_parse_ret
2506 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2508 struct peer
*const peer
= args
->peer
;
2509 struct attr
*const attr
= args
->attr
;
2510 const bgp_size_t length
= args
->length
;
2511 struct ecommunity
*ipv6_ecomm
= NULL
;
2514 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2515 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2519 ipv6_ecomm
= ecommunity_parse_ipv6(
2520 stream_pnt(peer
->curr
), length
,
2521 CHECK_FLAG(peer
->flags
,
2522 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2523 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2525 /* XXX: fix ecommunity_parse to use stream API */
2526 stream_forward_getp(peer
->curr
, length
);
2529 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2532 return BGP_ATTR_PARSE_PROCEED
;
2535 /* Parse Tunnel Encap attribute in an UPDATE */
2536 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2537 bgp_size_t length
, /* IN: attr's length field */
2538 struct attr
*attr
, /* IN: caller already allocated */
2539 uint8_t flag
, /* IN: attr's flags field */
2543 uint16_t tunneltype
= 0;
2545 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2547 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2548 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2550 "Tunnel Encap attribute flag isn't optional and transitive %d",
2552 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2553 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2558 if (BGP_ATTR_ENCAP
== type
) {
2559 /* read outer TLV type and length */
2560 uint16_t tlv_length
;
2564 "Tunnel Encap attribute not long enough to contain outer T,L");
2565 bgp_notify_send_with_data(
2566 peer
, BGP_NOTIFY_UPDATE_ERR
,
2567 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2570 tunneltype
= stream_getw(BGP_INPUT(peer
));
2571 tlv_length
= stream_getw(BGP_INPUT(peer
));
2574 if (tlv_length
!= length
) {
2575 zlog_info("%s: tlv_length(%d) != length(%d)",
2576 __func__
, tlv_length
, length
);
2580 while (length
>= 4) {
2581 uint16_t subtype
= 0;
2582 uint16_t sublength
= 0;
2583 struct bgp_attr_encap_subtlv
*tlv
;
2585 if (BGP_ATTR_ENCAP
== type
) {
2586 subtype
= stream_getc(BGP_INPUT(peer
));
2587 sublength
= stream_getc(BGP_INPUT(peer
));
2589 #ifdef ENABLE_BGP_VNC
2591 subtype
= stream_getw(BGP_INPUT(peer
));
2592 sublength
= stream_getw(BGP_INPUT(peer
));
2597 if (sublength
> length
) {
2599 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2601 bgp_notify_send_with_data(
2602 peer
, BGP_NOTIFY_UPDATE_ERR
,
2603 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2607 /* alloc and copy sub-tlv */
2608 /* TBD make sure these are freed when attributes are released */
2609 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2610 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2611 tlv
->type
= subtype
;
2612 tlv
->length
= sublength
;
2613 stream_get(tlv
->value
, peer
->curr
, sublength
);
2614 length
-= sublength
;
2616 /* attach tlv to encap chain */
2617 if (BGP_ATTR_ENCAP
== type
) {
2618 struct bgp_attr_encap_subtlv
*stlv_last
;
2619 for (stlv_last
= attr
->encap_subtlvs
;
2620 stlv_last
&& stlv_last
->next
;
2621 stlv_last
= stlv_last
->next
)
2624 stlv_last
->next
= tlv
;
2626 attr
->encap_subtlvs
= tlv
;
2628 #ifdef ENABLE_BGP_VNC
2630 struct bgp_attr_encap_subtlv
*stlv_last
;
2631 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2632 bgp_attr_get_vnc_subtlvs(attr
);
2634 for (stlv_last
= vnc_subtlvs
;
2635 stlv_last
&& stlv_last
->next
;
2636 stlv_last
= stlv_last
->next
)
2639 stlv_last
->next
= tlv
;
2641 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2646 if (BGP_ATTR_ENCAP
== type
) {
2647 attr
->encap_tunneltype
= tunneltype
;
2651 /* spurious leftover data */
2653 "Tunnel Encap attribute length is bad: %d leftover octets",
2655 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2656 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2665 /* SRv6 Service Data Sub-Sub-TLV attribute
2666 * draft-ietf-bess-srv6-services-07
2668 static enum bgp_attr_parse_ret
2669 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2671 struct peer
*const peer
= args
->peer
;
2672 struct attr
*const attr
= args
->attr
;
2673 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2674 transposition_len
, transposition_offset
;
2676 size_t headersz
= sizeof(type
) + sizeof(length
);
2678 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2681 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2682 headersz
, STREAM_READABLE(peer
->curr
));
2683 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2687 type
= stream_getc(peer
->curr
);
2688 length
= stream_getw(peer
->curr
);
2690 if (STREAM_READABLE(peer
->curr
) < length
) {
2693 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2694 length
, STREAM_READABLE(peer
->curr
));
2695 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2699 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2702 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2703 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2705 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2709 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2710 if (STREAM_READABLE(peer
->curr
) <
2711 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2714 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
2715 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2716 STREAM_READABLE(peer
->curr
));
2717 return bgp_attr_malformed(
2718 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2722 loc_block_len
= stream_getc(peer
->curr
);
2723 loc_node_len
= stream_getc(peer
->curr
);
2724 func_len
= stream_getc(peer
->curr
);
2725 arg_len
= stream_getc(peer
->curr
);
2726 transposition_len
= stream_getc(peer
->curr
);
2727 transposition_offset
= stream_getc(peer
->curr
);
2729 /* Log SRv6 Service Data Sub-Sub-TLV */
2730 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2732 "%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",
2733 __func__
, loc_block_len
, loc_node_len
, func_len
,
2734 arg_len
, transposition_len
,
2735 transposition_offset
);
2738 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2739 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2740 attr
->srv6_l3vpn
->func_len
= func_len
;
2741 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2742 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2743 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2747 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2749 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2752 stream_forward_getp(peer
->curr
, length
);
2755 return BGP_ATTR_PARSE_PROCEED
;
2758 /* SRv6 Service Sub-TLV attribute
2759 * draft-ietf-bess-srv6-services-07
2761 static enum bgp_attr_parse_ret
2762 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2764 struct peer
*const peer
= args
->peer
;
2765 struct attr
*const attr
= args
->attr
;
2766 struct in6_addr ipv6_sid
;
2767 uint8_t type
, sid_flags
;
2768 uint16_t length
, endpoint_behavior
;
2769 size_t headersz
= sizeof(type
) + sizeof(length
);
2770 enum bgp_attr_parse_ret err
;
2772 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2775 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2776 headersz
, STREAM_READABLE(peer
->curr
));
2777 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2781 type
= stream_getc(peer
->curr
);
2782 length
= stream_getw(peer
->curr
);
2784 if (STREAM_READABLE(peer
->curr
) < length
) {
2787 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2788 length
, STREAM_READABLE(peer
->curr
));
2789 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2793 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2794 if (STREAM_READABLE(peer
->curr
) <
2795 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2798 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
2799 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
,
2800 STREAM_READABLE(peer
->curr
));
2801 return bgp_attr_malformed(
2802 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2805 stream_getc(peer
->curr
);
2806 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2807 sid_flags
= stream_getc(peer
->curr
);
2808 endpoint_behavior
= stream_getw(peer
->curr
);
2809 stream_getc(peer
->curr
);
2811 /* Log SRv6 Service Sub-TLV */
2812 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
2814 "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2815 __func__
, &ipv6_sid
, sid_flags
,
2818 /* Configure from Info */
2819 if (attr
->srv6_l3vpn
) {
2820 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2821 "Prefix SID SRv6 L3VPN field repeated");
2822 return bgp_attr_malformed(
2823 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2825 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2826 sizeof(struct bgp_attr_srv6_l3vpn
));
2827 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2828 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2829 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2830 attr
->srv6_l3vpn
->loc_block_len
= 0;
2831 attr
->srv6_l3vpn
->loc_node_len
= 0;
2832 attr
->srv6_l3vpn
->func_len
= 0;
2833 attr
->srv6_l3vpn
->arg_len
= 0;
2834 attr
->srv6_l3vpn
->transposition_len
= 0;
2835 attr
->srv6_l3vpn
->transposition_offset
= 0;
2837 // Sub-Sub-TLV found
2838 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2839 err
= bgp_attr_srv6_service_data(args
);
2841 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2845 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2848 /* Placeholder code for unsupported type */
2850 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2852 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2855 stream_forward_getp(peer
->curr
, length
);
2858 return BGP_ATTR_PARSE_PROCEED
;
2862 * Read an individual SID value returning how much data we have read
2863 * Returns 0 if there was an error that needs to be passed up the stack
2865 static enum bgp_attr_parse_ret
2866 bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2867 struct bgp_attr_parser_args
*args
)
2869 struct peer
*const peer
= args
->peer
;
2870 struct attr
*const attr
= args
->attr
;
2871 uint32_t label_index
;
2872 struct in6_addr ipv6_sid
;
2874 uint32_t srgb_range
;
2876 uint8_t sid_type
, sid_flags
;
2878 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2879 if (STREAM_READABLE(peer
->curr
) < length
2880 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2881 flog_err(EC_BGP_ATTR_LEN
,
2882 "Prefix SID label index length is %hu instead of %u",
2883 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2884 return bgp_attr_malformed(args
,
2885 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2889 /* Ignore flags and reserved */
2890 stream_getc(peer
->curr
);
2891 stream_getw(peer
->curr
);
2893 /* Fetch the label index and see if it is valid. */
2894 label_index
= stream_getl(peer
->curr
);
2895 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2896 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2899 /* Store label index; subsequently, we'll check on
2901 attr
->label_index
= label_index
;
2904 /* Placeholder code for the IPv6 SID type */
2905 else if (type
== BGP_PREFIX_SID_IPV6
) {
2906 if (STREAM_READABLE(peer
->curr
) < length
2907 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2908 flog_err(EC_BGP_ATTR_LEN
,
2909 "Prefix SID IPv6 length is %hu instead of %u",
2910 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2911 return bgp_attr_malformed(args
,
2912 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2916 /* Ignore reserved */
2917 stream_getc(peer
->curr
);
2918 stream_getw(peer
->curr
);
2920 stream_get(&ipv6_sid
, peer
->curr
, 16);
2923 /* Placeholder code for the Originator SRGB type */
2924 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2926 * ietf-idr-bgp-prefix-sid-05:
2927 * Length is the total length of the value portion of the
2928 * TLV: 2 + multiple of 6.
2930 * peer->curr stream readp should be at the beginning of the 16
2931 * bit flag field at this point in the code.
2935 * Check that the TLV length field is sane: at least 2 bytes of
2936 * flag, and at least 1 SRGB (these are 6 bytes each)
2938 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2941 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2943 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2944 return bgp_attr_malformed(
2945 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2950 * Check that we actually have at least as much data as
2951 * specified by the length field
2953 if (STREAM_READABLE(peer
->curr
) < length
) {
2954 flog_err(EC_BGP_ATTR_LEN
,
2955 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2956 length
, STREAM_READABLE(peer
->curr
));
2957 return bgp_attr_malformed(
2958 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2963 * Check that the portion of the TLV containing the sequence of
2964 * SRGBs corresponds to a multiple of the SRGB size; to get
2965 * that length, we skip the 16 bit flags field
2967 stream_getw(peer
->curr
);
2969 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2972 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2973 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2974 return bgp_attr_malformed(
2975 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2979 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2981 for (int i
= 0; i
< srgb_count
; i
++) {
2982 stream_get(&srgb_base
, peer
->curr
, 3);
2983 stream_get(&srgb_range
, peer
->curr
, 3);
2987 /* Placeholder code for the VPN-SID Service type */
2988 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2989 if (STREAM_READABLE(peer
->curr
) < length
2990 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2991 flog_err(EC_BGP_ATTR_LEN
,
2992 "Prefix SID VPN SID length is %hu instead of %u",
2993 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2994 return bgp_attr_malformed(args
,
2995 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2999 /* Parse VPN-SID Sub-TLV */
3000 stream_getc(peer
->curr
); /* reserved */
3001 sid_type
= stream_getc(peer
->curr
); /* sid_type */
3002 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
3003 stream_get(&ipv6_sid
, peer
->curr
,
3004 sizeof(ipv6_sid
)); /* sid_value */
3006 /* Log VPN-SID Sub-TLV */
3007 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
3009 "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
3010 __func__
, &ipv6_sid
, sid_type
, sid_flags
);
3012 /* Configure from Info */
3013 if (attr
->srv6_vpn
) {
3014 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
3015 "Prefix SID SRv6 VPN field repeated");
3016 return bgp_attr_malformed(
3017 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
3019 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
3020 sizeof(struct bgp_attr_srv6_vpn
));
3021 attr
->srv6_vpn
->sid_flags
= sid_flags
;
3022 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
3023 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
3026 /* Placeholder code for the SRv6 L3 Service type */
3027 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
3028 if (STREAM_READABLE(peer
->curr
) < length
) {
3031 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
3032 length
, STREAM_READABLE(peer
->curr
));
3033 return bgp_attr_malformed(args
,
3034 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3038 /* ignore reserved */
3039 stream_getc(peer
->curr
);
3041 return bgp_attr_srv6_service(args
);
3044 /* Placeholder code for Unsupported TLV */
3047 if (STREAM_READABLE(peer
->curr
) < length
) {
3050 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
3051 length
, STREAM_READABLE(peer
->curr
));
3052 return bgp_attr_malformed(
3053 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3057 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3059 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3062 stream_forward_getp(peer
->curr
, length
);
3065 return BGP_ATTR_PARSE_PROCEED
;
3068 /* Prefix SID attribute
3069 * draft-ietf-idr-bgp-prefix-sid-05
3071 enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
3073 struct peer
*const peer
= args
->peer
;
3074 struct attr
*const attr
= args
->attr
;
3075 enum bgp_attr_parse_ret ret
;
3077 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3081 size_t headersz
= sizeof(type
) + sizeof(length
);
3082 size_t psid_parsed_length
= 0;
3084 while (STREAM_READABLE(peer
->curr
) > 0
3085 && psid_parsed_length
< args
->length
) {
3087 if (STREAM_READABLE(peer
->curr
) < headersz
) {
3090 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3091 headersz
, STREAM_READABLE(peer
->curr
));
3092 return bgp_attr_malformed(
3093 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3097 type
= stream_getc(peer
->curr
);
3098 length
= stream_getw(peer
->curr
);
3100 if (STREAM_READABLE(peer
->curr
) < length
) {
3103 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3104 length
, STREAM_READABLE(peer
->curr
));
3105 return bgp_attr_malformed(args
,
3106 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3110 ret
= bgp_attr_psid_sub(type
, length
, args
);
3112 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3115 psid_parsed_length
+= length
+ headersz
;
3117 if (psid_parsed_length
> args
->length
) {
3120 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
3121 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
3122 return bgp_attr_malformed(
3123 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3128 return BGP_ATTR_PARSE_PROCEED
;
3131 /* PMSI tunnel attribute (RFC 6514)
3132 * Basic validation checks done here.
3134 static enum bgp_attr_parse_ret
3135 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
3137 struct peer
*const peer
= args
->peer
;
3138 struct attr
*const attr
= args
->attr
;
3139 const bgp_size_t length
= args
->length
;
3141 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
3143 /* Verify that the receiver is expecting "ingress replication" as we
3144 * can only support that.
3146 if (length
< attr_parse_len
) {
3147 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
3149 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3152 stream_getc(peer
->curr
); /* Flags */
3153 tnl_type
= stream_getc(peer
->curr
);
3154 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3155 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3156 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3157 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3160 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3162 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3163 "Bad PMSI tunnel attribute length %d for IR",
3165 return bgp_attr_malformed(
3166 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3171 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3172 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3173 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3175 /* Forward read pointer of input stream. */
3176 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3178 return BGP_ATTR_PARSE_PROCEED
;
3181 /* AIGP attribute (rfc7311) */
3182 static enum bgp_attr_parse_ret
bgp_attr_aigp(struct bgp_attr_parser_args
*args
)
3184 struct peer
*const peer
= args
->peer
;
3185 struct attr
*const attr
= args
->attr
;
3186 const bgp_size_t length
= args
->length
;
3187 uint8_t *s
= stream_pnt(peer
->curr
);
3190 /* If an AIGP attribute is received on a BGP session for which
3191 * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3192 * as if it were an unrecognized non-transitive attribute.
3193 * That is, it "MUST be quietly ignored and not passed along to
3195 * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3196 * sessions between members of the same BGP Confederation,
3197 * the default value of AIGP_SESSION SHOULD be "enabled".
3199 if (peer
->sort
== BGP_PEER_EBGP
&&
3200 !CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
)) {
3202 "%pBP received AIGP attribute, but eBGP peer do not support it",
3207 if (!bgp_attr_aigp_valid(s
, length
))
3210 /* Extract AIGP Metric TLV */
3211 if (bgp_attr_aigp_get_tlv_metric(s
, length
, &aigp
))
3212 bgp_attr_set_aigp_metric(attr
, aigp
);
3215 stream_forward_getp(peer
->curr
, length
);
3217 return BGP_ATTR_PARSE_PROCEED
;
3220 /* OTC attribute. */
3221 static enum bgp_attr_parse_ret
bgp_attr_otc(struct bgp_attr_parser_args
*args
)
3223 struct peer
*const peer
= args
->peer
;
3224 struct attr
*const attr
= args
->attr
;
3225 const bgp_size_t length
= args
->length
;
3229 flog_err(EC_BGP_ATTR_LEN
, "OTC attribute length isn't 4 [%u]",
3231 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3235 attr
->otc
= stream_getl(peer
->curr
);
3237 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "OTC attribute value is 0");
3238 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
3242 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
3244 return BGP_ATTR_PARSE_PROCEED
;
3247 /* BGP unknown attribute treatment. */
3248 static enum bgp_attr_parse_ret
3249 bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3251 bgp_size_t total
= args
->total
;
3252 struct transit
*transit
;
3253 struct peer
*const peer
= args
->peer
;
3254 struct attr
*const attr
= args
->attr
;
3255 uint8_t *const startp
= args
->startp
;
3256 const uint8_t type
= args
->type
;
3257 const uint8_t flag
= args
->flags
;
3258 const bgp_size_t length
= args
->length
;
3260 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3262 "%s Unknown attribute is received (type %d, length %d)",
3263 peer
->host
, type
, length
);
3265 /* Forward read pointer of input stream. */
3266 stream_forward_getp(peer
->curr
, length
);
3268 /* If any of the mandatory well-known attributes are not recognized,
3269 then the Error Subcode is set to Unrecognized Well-known
3270 Attribute. The Data field contains the unrecognized attribute
3271 (type, length and value). */
3272 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3273 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3277 /* Unrecognized non-transitive optional attributes must be quietly
3278 ignored and not passed along to other BGP peers. */
3279 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3280 return BGP_ATTR_PARSE_PROCEED
;
3282 /* If a path with recognized transitive optional attribute is
3283 accepted and passed along to other BGP peers and the Partial bit
3284 in the Attribute Flags octet is set to 1 by some previous AS, it
3285 is not set back to 0 by the current AS. */
3286 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3288 /* Store transitive attribute to the end of attr->transit. */
3289 transit
= bgp_attr_get_transit(attr
);
3291 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3293 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3294 transit
->length
+ total
);
3296 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3297 transit
->length
+= total
;
3298 bgp_attr_set_transit(attr
, transit
);
3300 return BGP_ATTR_PARSE_PROCEED
;
3303 /* Well-known attribute check. */
3304 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3308 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3310 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3311 return BGP_ATTR_PARSE_PROCEED
;
3313 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3314 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3315 are present, it should. Check for any other attribute being present
3318 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3319 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3320 return BGP_ATTR_PARSE_PROCEED
;
3322 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3323 type
= BGP_ATTR_ORIGIN
;
3325 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3326 type
= BGP_ATTR_AS_PATH
;
3328 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3330 * NLRI is empty. We can't easily check NLRI empty here though.
3332 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3333 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3334 type
= BGP_ATTR_NEXT_HOP
;
3336 if (peer
->sort
== BGP_PEER_IBGP
3337 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3338 type
= BGP_ATTR_LOCAL_PREF
;
3340 /* If any of the well-known mandatory attributes are not present
3341 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3344 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3345 "%s Missing well-known attribute %s.", peer
->host
,
3346 lookup_msg(attr_str
, type
, NULL
));
3347 return BGP_ATTR_PARSE_WITHDRAW
;
3349 return BGP_ATTR_PARSE_PROCEED
;
3352 /* Read attribute of update packet. This function is called from
3353 bgp_update_receive() in bgp_packet.c. */
3354 enum bgp_attr_parse_ret
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3356 struct bgp_nlri
*mp_update
,
3357 struct bgp_nlri
*mp_withdraw
)
3359 enum bgp_attr_parse_ret ret
;
3363 uint8_t *startp
, *endp
;
3365 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3366 /* we need the as4_path only until we have synthesized the as_path with
3368 /* same goes for as4_aggregator */
3369 struct aspath
*as4_path
= NULL
;
3370 as_t as4_aggregator
= 0;
3371 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3372 struct transit
*transit
;
3374 /* Initialize bitmap. */
3375 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3377 /* End pointer of BGP attribute. */
3378 endp
= BGP_INPUT_PNT(peer
) + size
;
3380 /* Get attributes to the end of attribute length. */
3381 while (BGP_INPUT_PNT(peer
) < endp
) {
3382 /* Check remaining length check.*/
3383 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3384 /* XXX warning: long int format, int arg (arg 5) */
3386 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3387 "%s: error BGP attribute length %lu is smaller than min len",
3389 (unsigned long)(endp
3390 - stream_pnt(BGP_INPUT(peer
))));
3392 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3393 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3394 ret
= BGP_ATTR_PARSE_ERROR
;
3398 /* Fetch attribute flag and type. */
3399 startp
= BGP_INPUT_PNT(peer
);
3400 /* "The lower-order four bits of the Attribute Flags octet are
3401 unused. They MUST be zero when sent and MUST be ignored when
3403 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3404 type
= stream_getc(BGP_INPUT(peer
));
3406 /* Check whether Extended-Length applies and is in bounds */
3407 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3408 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3410 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3411 "%s: Extended length set, but just %lu bytes of attr header",
3413 (unsigned long)(endp
3414 - stream_pnt(BGP_INPUT(peer
))));
3416 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3417 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3418 ret
= BGP_ATTR_PARSE_ERROR
;
3422 /* Check extended attribue length bit. */
3423 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3424 length
= stream_getw(BGP_INPUT(peer
));
3426 length
= stream_getc(BGP_INPUT(peer
));
3428 /* If any attribute appears more than once in the UPDATE
3429 message, then the Error Subcode is set to Malformed Attribute
3432 if (CHECK_BITMAP(seen
, type
)) {
3434 EC_BGP_ATTRIBUTE_REPEATED
,
3435 "%s: error BGP attribute type %d appears twice in a message",
3438 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3439 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3440 ret
= BGP_ATTR_PARSE_ERROR
;
3444 /* Set type to bitmap to check duplicate attribute. `type' is
3445 unsigned char so it never overflow bitmap range. */
3447 SET_BITMAP(seen
, type
);
3449 /* Overflow check. */
3450 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3452 if (attr_endp
> endp
) {
3454 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3455 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3456 peer
->host
, type
, length
, size
, attr_endp
,
3460 * If any recognized attribute has an Attribute
3461 * Length that conflicts with the expected length
3462 * (based on the attribute type code), then the
3463 * Error Subcode MUST be set to Attribute Length
3464 * Error. The Data field MUST contain the erroneous
3465 * attribute (type, length, and value).
3467 * We do not currently have a good way to determine the
3468 * length of the attribute independent of the length
3469 * received in the message. Instead we send the
3470 * minimum between the amount of data we have and the
3471 * amount specified by the attribute length field.
3473 * Instead of directly passing in the packet buffer and
3474 * offset we use the stream_get* functions to read into
3475 * a stack buffer, since they perform bounds checking
3476 * and we are working with untrusted data.
3478 unsigned char ndata
[peer
->max_packet_size
];
3479 memset(ndata
, 0x00, sizeof(ndata
));
3481 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3482 /* Rewind to end of flag field */
3483 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3485 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3487 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3489 size_t atl
= attr_endp
- startp
;
3490 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3491 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3493 bgp_notify_send_with_data(
3494 peer
, BGP_NOTIFY_UPDATE_ERR
,
3495 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3498 ret
= BGP_ATTR_PARSE_ERROR
;
3502 struct bgp_attr_parser_args attr_args
= {
3509 .total
= attr_endp
- startp
,
3513 /* If any recognized attribute has Attribute Flags that conflict
3514 with the Attribute Type Code, then the Error Subcode is set
3516 Attribute Flags Error. The Data field contains the erroneous
3517 attribute (type, length and value). */
3518 if (bgp_attr_flag_invalid(&attr_args
)) {
3519 ret
= bgp_attr_malformed(
3520 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3522 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3527 /* OK check attribute and store it's value. */
3529 case BGP_ATTR_ORIGIN
:
3530 ret
= bgp_attr_origin(&attr_args
);
3532 case BGP_ATTR_AS_PATH
:
3533 ret
= bgp_attr_aspath(&attr_args
);
3535 case BGP_ATTR_AS4_PATH
:
3536 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3538 case BGP_ATTR_NEXT_HOP
:
3539 ret
= bgp_attr_nexthop(&attr_args
);
3541 case BGP_ATTR_MULTI_EXIT_DISC
:
3542 ret
= bgp_attr_med(&attr_args
);
3544 case BGP_ATTR_LOCAL_PREF
:
3545 ret
= bgp_attr_local_pref(&attr_args
);
3547 case BGP_ATTR_ATOMIC_AGGREGATE
:
3548 ret
= bgp_attr_atomic(&attr_args
);
3550 case BGP_ATTR_AGGREGATOR
:
3551 ret
= bgp_attr_aggregator(&attr_args
);
3553 case BGP_ATTR_AS4_AGGREGATOR
:
3554 ret
= bgp_attr_as4_aggregator(&attr_args
,
3556 &as4_aggregator_addr
);
3558 case BGP_ATTR_COMMUNITIES
:
3559 ret
= bgp_attr_community(&attr_args
);
3561 case BGP_ATTR_LARGE_COMMUNITIES
:
3562 ret
= bgp_attr_large_community(&attr_args
);
3564 case BGP_ATTR_ORIGINATOR_ID
:
3565 ret
= bgp_attr_originator_id(&attr_args
);
3567 case BGP_ATTR_CLUSTER_LIST
:
3568 ret
= bgp_attr_cluster_list(&attr_args
);
3570 case BGP_ATTR_MP_REACH_NLRI
:
3571 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3573 case BGP_ATTR_MP_UNREACH_NLRI
:
3574 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3576 case BGP_ATTR_EXT_COMMUNITIES
:
3577 ret
= bgp_attr_ext_communities(&attr_args
);
3579 #ifdef ENABLE_BGP_VNC_ATTR
3582 case BGP_ATTR_ENCAP
:
3583 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3586 case BGP_ATTR_PREFIX_SID
:
3587 ret
= bgp_attr_prefix_sid(&attr_args
);
3589 case BGP_ATTR_PMSI_TUNNEL
:
3590 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3592 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3593 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3596 ret
= bgp_attr_otc(&attr_args
);
3599 ret
= bgp_attr_aigp(&attr_args
);
3602 ret
= bgp_attr_unknown(&attr_args
);
3606 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3607 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3608 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3609 ret
= BGP_ATTR_PARSE_ERROR
;
3613 if (ret
== BGP_ATTR_PARSE_EOR
) {
3617 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3618 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3619 "%s: Attribute %s, parse error", peer
->host
,
3620 lookup_msg(attr_str
, type
, NULL
));
3623 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3625 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3626 "%s: Attribute %s, parse error - treating as withdrawal",
3627 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3631 /* Check the fetched length. */
3632 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3633 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3634 "%s: BGP attribute %s, fetch error",
3635 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3636 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3637 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3638 ret
= BGP_ATTR_PARSE_ERROR
;
3644 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3645 * About Prefix-SID path attribute,
3646 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3647 * may only appear in a BGP Prefix-SID attribute attached to
3648 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3649 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3651 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3652 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3654 /* Check final read pointer is same as end pointer. */
3655 if (BGP_INPUT_PNT(peer
) != endp
) {
3656 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3657 "%s: BGP attribute %s, length mismatch", peer
->host
,
3658 lookup_msg(attr_str
, type
, NULL
));
3659 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3660 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3662 ret
= BGP_ATTR_PARSE_ERROR
;
3667 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3668 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3669 * This is implemented below and will result in a NOTIFICATION. If the
3670 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3671 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3672 * message SHOULD NOT be sent. This is implemented elsewhere.
3674 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3675 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3676 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3677 * speaker that receives the message SHOULD ignore this attribute.
3679 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3680 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3681 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3682 ret
= BGP_ATTR_PARSE_ERROR
;
3687 /* Check all mandatory well-known attributes are present */
3688 ret
= bgp_attr_check(peer
, attr
);
3693 * At this place we can see whether we got AS4_PATH and/or
3694 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3695 * We can not do this before we've read all attributes because
3696 * the as4 handling does not say whether AS4_PATH has to be sent
3697 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3698 * in relationship to AGGREGATOR.
3699 * So, to be defensive, we are not relying on any order and read
3700 * all attributes first, including these 32bit ones, and now,
3701 * afterwards, we look what and if something is to be done for as4.
3703 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3706 /* actually... this doesn't ever return failure currently, but
3707 * better safe than sorry */
3708 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3709 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3710 &as4_aggregator_addr
)) {
3711 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3712 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3713 ret
= BGP_ATTR_PARSE_ERROR
;
3718 * Finally do the checks on the aspath we did not do yet
3719 * because we waited for a potentially synthesized aspath.
3721 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3722 ret
= bgp_attr_aspath_check(peer
, attr
);
3723 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3727 ret
= BGP_ATTR_PARSE_PROCEED
;
3731 * At this stage, we have done all fiddling with as4, and the
3732 * resulting info is in attr->aggregator resp. attr->aspath so
3733 * we can chuck as4_aggregator and as4_path alltogether in order
3737 * unintern - it is in the hash
3738 * The flag that we got this is still there, but that
3739 * does not do any trouble
3741 aspath_unintern(&as4_path
);
3743 transit
= bgp_attr_get_transit(attr
);
3744 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3745 /* Finally intern unknown attribute. */
3747 bgp_attr_set_transit(attr
, transit_intern(transit
));
3748 if (attr
->encap_subtlvs
)
3749 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3751 #ifdef ENABLE_BGP_VNC
3752 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3753 bgp_attr_get_vnc_subtlvs(attr
);
3756 bgp_attr_set_vnc_subtlvs(
3758 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3762 transit_free(transit
);
3763 bgp_attr_set_transit(attr
, NULL
);
3766 bgp_attr_flush_encap(attr
);
3770 transit
= bgp_attr_get_transit(attr
);
3772 assert(transit
->refcnt
> 0);
3773 if (attr
->encap_subtlvs
)
3774 assert(attr
->encap_subtlvs
->refcnt
> 0);
3775 #ifdef ENABLE_BGP_VNC
3776 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3777 bgp_attr_get_vnc_subtlvs(attr
);
3780 assert(vnc_subtlvs
->refcnt
> 0);
3787 * Extract the tunnel type from extended community
3789 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3790 bgp_encap_types
*tunnel_type
)
3792 struct ecommunity
*ecom
;
3798 ecom
= bgp_attr_get_ecommunity(attr
);
3799 if (!ecom
|| !ecom
->size
)
3802 for (i
= 0; i
< ecom
->size
; i
++) {
3804 uint8_t type
, sub_type
;
3806 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3809 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3810 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3812 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3819 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3820 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3824 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
3825 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
3828 /* Set extended bit always to encode the attribute length as 2 bytes */
3829 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3830 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3831 sizep
= stream_get_endp(s
);
3832 stream_putw(s
, 0); /* Marker: Attribute length. */
3835 /* Convert AFI, SAFI to values for packet. */
3836 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3838 stream_putw(s
, pkt_afi
); /* AFI */
3839 stream_putc(s
, pkt_safi
); /* SAFI */
3843 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3844 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3845 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3846 else if (safi
== SAFI_FLOWSPEC
)
3849 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3852 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3857 case SAFI_MULTICAST
:
3858 case SAFI_LABELED_UNICAST
:
3860 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3864 stream_putl(s
, 0); /* RD = 0, per RFC */
3866 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3871 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3874 if (attr
->mp_nexthop_len
== 0)
3875 stream_putc(s
, 0); /* no nexthop for flowspec */
3877 stream_putc(s
, attr
->mp_nexthop_len
);
3878 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3887 case SAFI_MULTICAST
:
3888 case SAFI_LABELED_UNICAST
:
3890 if (attr
->mp_nexthop_len
3891 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3893 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3894 stream_put(s
, &attr
->mp_nexthop_global
,
3896 stream_put(s
, &attr
->mp_nexthop_local
,
3899 stream_putc(s
, IPV6_MAX_BYTELEN
);
3900 stream_put(s
, &attr
->mp_nexthop_global
,
3904 case SAFI_MPLS_VPN
: {
3905 if (attr
->mp_nexthop_len
3906 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3908 stream_putl(s
, 0); /* RD = 0, per RFC */
3910 stream_put(s
, &attr
->mp_nexthop_global
,
3912 stream_putl(s
, 0); /* RD = 0, per RFC */
3914 stream_put(s
, &attr
->mp_nexthop_local
,
3918 stream_putl(s
, 0); /* RD = 0, per RFC */
3920 stream_put(s
, &attr
->mp_nexthop_global
,
3925 stream_putc(s
, IPV6_MAX_BYTELEN
);
3926 stream_put(s
, &attr
->mp_nexthop_global
,
3930 stream_putc(s
, 0); /* no nexthop for flowspec */
3936 if (safi
!= SAFI_FLOWSPEC
)
3938 EC_BGP_ATTR_NH_SEND_LEN
,
3939 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3940 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3949 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3950 const struct prefix
*p
,
3951 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3952 uint32_t num_labels
, bool addpath_capable
,
3953 uint32_t addpath_tx_id
, struct attr
*attr
)
3955 if (safi
== SAFI_MPLS_VPN
) {
3956 if (addpath_capable
)
3957 stream_putl(s
, addpath_tx_id
);
3958 /* Label, RD, Prefix write. */
3959 stream_putc(s
, p
->prefixlen
+ 88);
3960 stream_put(s
, label
, BGP_LABEL_BYTES
);
3961 stream_put(s
, prd
->val
, 8);
3962 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3963 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3964 /* EVPN prefix - contents depend on type */
3965 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3966 addpath_capable
, addpath_tx_id
);
3967 } else if (safi
== SAFI_LABELED_UNICAST
) {
3968 /* Prefix write with label. */
3969 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3971 } else if (safi
== SAFI_FLOWSPEC
) {
3972 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3973 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3974 p
->u
.prefix_flowspec
.prefixlen
);
3976 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
3979 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3980 const struct prefix
*p
)
3982 int size
= PSIZE(p
->prefixlen
);
3983 if (safi
== SAFI_MPLS_VPN
)
3985 else if (safi
== SAFI_LABELED_UNICAST
)
3986 size
+= BGP_LABEL_BYTES
;
3987 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3988 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3990 else if (safi
== SAFI_FLOWSPEC
)
3991 size
= ((struct prefix_fs
*)p
)->prefix
.prefixlen
;
3996 * Encodes the tunnel encapsulation attribute,
3997 * and with ENABLE_BGP_VNC the VNC attribute which uses
3998 * almost the same TLV format
4000 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
4001 struct stream
*s
, struct attr
*attr
,
4004 unsigned int attrlenfield
= 0;
4005 unsigned int attrhdrlen
= 0;
4006 struct bgp_attr_encap_subtlv
*subtlvs
;
4007 struct bgp_attr_encap_subtlv
*st
;
4008 const char *attrname
;
4010 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
4011 && (!attr
->encap_tunneltype
4012 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
4016 case BGP_ATTR_ENCAP
:
4017 attrname
= "Tunnel Encap";
4018 subtlvs
= attr
->encap_subtlvs
;
4019 if (subtlvs
== NULL
) /* nothing to do */
4022 * The tunnel encap attr has an "outer" tlv.
4024 * L = total length of subtlvs,
4025 * V = concatenated subtlvs.
4027 attrlenfield
= 2 + 2; /* T + L */
4028 attrhdrlen
= 1 + 1; /* subTLV T + L */
4031 #ifdef ENABLE_BGP_VNC_ATTR
4034 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
4035 if (subtlvs
== NULL
) /* nothing to do */
4037 attrlenfield
= 0; /* no outer T + L */
4038 attrhdrlen
= 2 + 2; /* subTLV T + L */
4046 /* compute attr length */
4047 for (st
= subtlvs
; st
; st
= st
->next
) {
4048 attrlenfield
+= (attrhdrlen
+ st
->length
);
4051 if (attrlenfield
> 0xffff) {
4052 zlog_info("%s attribute is too long (length=%d), can't send it",
4053 attrname
, attrlenfield
);
4057 if (attrlenfield
> 0xff) {
4058 /* 2-octet length field */
4060 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4061 | BGP_ATTR_FLAG_EXTLEN
);
4062 stream_putc(s
, attrtype
);
4063 stream_putw(s
, attrlenfield
& 0xffff);
4065 /* 1-octet length field */
4066 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
4067 stream_putc(s
, attrtype
);
4068 stream_putc(s
, attrlenfield
& 0xff);
4071 if (attrtype
== BGP_ATTR_ENCAP
) {
4072 /* write outer T+L */
4073 stream_putw(s
, attr
->encap_tunneltype
);
4074 stream_putw(s
, attrlenfield
- 4);
4077 /* write each sub-tlv */
4078 for (st
= subtlvs
; st
; st
= st
->next
) {
4079 if (attrtype
== BGP_ATTR_ENCAP
) {
4080 stream_putc(s
, st
->type
);
4081 stream_putc(s
, st
->length
);
4082 #ifdef ENABLE_BGP_VNC
4084 stream_putw(s
, st
->type
);
4085 stream_putw(s
, st
->length
);
4088 stream_put(s
, st
->value
, st
->length
);
4092 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
4094 /* Set MP attribute length. Don't count the (2) bytes used to encode
4096 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
4099 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
4101 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
4102 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
4103 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4104 PEER_FLAG_REMOVE_PRIVATE_AS
)
4105 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4106 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
4107 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4108 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
4109 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4110 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
4115 /* Make attribute packet. */
4116 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
4117 struct stream
*s
, struct attr
*attr
,
4118 struct bpacket_attr_vec_arr
*vecarr
,
4119 struct prefix
*p
, afi_t afi
, safi_t safi
,
4120 struct peer
*from
, struct prefix_rd
*prd
,
4121 mpls_label_t
*label
, uint32_t num_labels
,
4122 bool addpath_capable
, uint32_t addpath_tx_id
,
4123 struct bgp_path_info
*bpi
)
4126 size_t aspath_sizep
;
4127 struct aspath
*aspath
;
4128 int send_as4_path
= 0;
4129 int send_as4_aggregator
= 0;
4130 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
4131 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
4136 /* Remember current pointer. */
4137 cp
= stream_get_endp(s
);
4140 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
4141 && !peer_cap_enhe(peer
, afi
, safi
))) {
4142 size_t mpattrlen_pos
= 0;
4144 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
4146 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
4147 num_labels
, addpath_capable
,
4148 addpath_tx_id
, attr
);
4149 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
4152 /* Origin attribute. */
4153 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4154 stream_putc(s
, BGP_ATTR_ORIGIN
);
4156 stream_putc(s
, attr
->origin
);
4158 /* AS path attribute. */
4160 /* If remote-peer is EBGP */
4161 if (peer
->sort
== BGP_PEER_EBGP
4162 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4163 PEER_FLAG_AS_PATH_UNCHANGED
)
4164 || attr
->aspath
->segments
== NULL
)
4165 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4166 PEER_FLAG_RSERVER_CLIENT
))) {
4167 aspath
= aspath_dup(attr
->aspath
);
4169 /* Even though we may not be configured for confederations we
4171 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4172 aspath
= aspath_delete_confed_seq(aspath
);
4174 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
4175 /* Stuff our path CONFED_ID on the front */
4176 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
4178 if (peer
->change_local_as
) {
4179 /* If replace-as is specified, we only use the
4180 change_local_as when
4181 advertising routes. */
4182 if (!CHECK_FLAG(peer
->flags
,
4183 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
4184 if (bgp_append_local_as(peer
, afi
,
4186 aspath
= aspath_add_seq(
4187 aspath
, peer
->local_as
);
4188 aspath
= aspath_add_seq(aspath
,
4189 peer
->change_local_as
);
4191 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
4194 } else if (peer
->sort
== BGP_PEER_CONFED
) {
4195 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4197 aspath
= aspath_dup(attr
->aspath
);
4198 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
4200 aspath
= attr
->aspath
;
4202 /* If peer is not AS4 capable, then:
4203 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4204 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4206 * types are in it (i.e. exclude them if they are there)
4207 * AND do this only if there is at least one asnum > 65535 in the
4209 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4211 * all ASnums > 65535 to BGP_AS_TRANS
4214 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4215 stream_putc(s
, BGP_ATTR_AS_PATH
);
4216 aspath_sizep
= stream_get_endp(s
);
4218 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4220 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4223 if (!use32bit
&& aspath_has_as4(aspath
))
4225 1; /* we'll do this later, at the correct place */
4227 /* Nexthop attribute. */
4228 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4229 && !peer_cap_enhe(peer
, afi
, safi
)) {
4230 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4232 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4233 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4234 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4235 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4238 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4239 } else if (peer_cap_enhe(from
, afi
, safi
)
4240 || (nh_afi
== AFI_IP6
)) {
4242 * Likely this is the case when an IPv4 prefix was
4243 * received with Extended Next-hop capability in this
4244 * or another vrf and is now being advertised to
4245 * non-ENHE peers. Since peer_cap_enhe only checks
4246 * peers in this vrf, also check the nh_afi to catch
4247 * the case where the originator was in another vrf.
4248 * Setting the mandatory (ipv4) next-hop attribute here
4249 * to enable implicit next-hop self with correct A-F
4250 * (ipv4 address family).
4252 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4253 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4254 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4257 stream_put_ipv4(s
, 0);
4261 /* MED attribute. */
4262 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4263 || bgp
->maxmed_active
) {
4264 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4265 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4267 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4271 /* Local preference. */
4272 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4273 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4274 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4276 stream_putl(s
, attr
->local_pref
);
4279 /* Atomic aggregate. */
4280 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4281 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4282 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4287 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4288 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4289 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4290 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4293 /* AS4 capable peer */
4295 stream_putl(s
, attr
->aggregator_as
);
4297 /* 2-byte AS peer */
4300 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4302 if (attr
->aggregator_as
> UINT16_MAX
) {
4303 stream_putw(s
, BGP_AS_TRANS
);
4305 /* we have to send AS4_AGGREGATOR, too.
4306 * we'll do that later in order to send
4307 * attributes in ascending
4310 send_as4_aggregator
= 1;
4312 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4314 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4317 /* Community attribute. */
4318 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4319 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4320 struct community
*comm
= NULL
;
4322 comm
= bgp_attr_get_community(attr
);
4323 if (comm
->size
* 4 > 255) {
4325 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4326 | BGP_ATTR_FLAG_EXTLEN
);
4327 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4328 stream_putw(s
, comm
->size
* 4);
4331 BGP_ATTR_FLAG_OPTIONAL
4332 | BGP_ATTR_FLAG_TRANS
);
4333 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4334 stream_putc(s
, comm
->size
* 4);
4336 stream_put(s
, comm
->val
, comm
->size
* 4);
4340 * Large Community attribute.
4342 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4343 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4344 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4345 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4347 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4348 | BGP_ATTR_FLAG_EXTLEN
);
4349 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4351 lcom_length(bgp_attr_get_lcommunity(attr
)));
4354 BGP_ATTR_FLAG_OPTIONAL
4355 | BGP_ATTR_FLAG_TRANS
);
4356 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4358 lcom_length(bgp_attr_get_lcommunity(attr
)));
4360 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4361 lcom_length(bgp_attr_get_lcommunity(attr
)));
4364 /* Route Reflector. */
4365 if (peer
->sort
== BGP_PEER_IBGP
&& from
4366 && from
->sort
== BGP_PEER_IBGP
) {
4367 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4369 /* Originator ID. */
4370 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4371 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4374 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4375 stream_put_in_addr(s
, &attr
->originator_id
);
4377 stream_put_in_addr(s
, &from
->remote_id
);
4380 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4381 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4384 stream_putc(s
, cluster
->length
+ 4);
4385 /* If this peer configuration's parent BGP has
4387 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4388 stream_put_in_addr(s
, &bgp
->cluster_id
);
4390 stream_put_in_addr(s
, &bgp
->router_id
);
4391 stream_put(s
, cluster
->list
, cluster
->length
);
4394 /* If this peer configuration's parent BGP has
4396 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4397 stream_put_in_addr(s
, &bgp
->cluster_id
);
4399 stream_put_in_addr(s
, &bgp
->router_id
);
4403 /* Extended Communities attribute. */
4404 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4405 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4406 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4407 bool transparent
= CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4408 PEER_FLAG_RSERVER_CLIENT
) &&
4410 CHECK_FLAG(from
->af_flags
[afi
][safi
],
4411 PEER_FLAG_RSERVER_CLIENT
);
4413 if (peer
->sort
== BGP_PEER_IBGP
||
4414 peer
->sort
== BGP_PEER_CONFED
|| transparent
) {
4415 if (ecomm
->size
* 8 > 255) {
4417 BGP_ATTR_FLAG_OPTIONAL
4418 | BGP_ATTR_FLAG_TRANS
4419 | BGP_ATTR_FLAG_EXTLEN
);
4420 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4421 stream_putw(s
, ecomm
->size
* 8);
4424 BGP_ATTR_FLAG_OPTIONAL
4425 | BGP_ATTR_FLAG_TRANS
);
4426 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4427 stream_putc(s
, ecomm
->size
* 8);
4429 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4433 int ecom_tr_size
= 0;
4436 for (i
= 0; i
< ecomm
->size
; i
++) {
4437 pnt
= ecomm
->val
+ (i
* 8);
4440 if (CHECK_FLAG(tbit
,
4441 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4448 if (ecom_tr_size
* 8 > 255) {
4451 BGP_ATTR_FLAG_OPTIONAL
4452 | BGP_ATTR_FLAG_TRANS
4453 | BGP_ATTR_FLAG_EXTLEN
);
4455 BGP_ATTR_EXT_COMMUNITIES
);
4456 stream_putw(s
, ecom_tr_size
* 8);
4460 BGP_ATTR_FLAG_OPTIONAL
4461 | BGP_ATTR_FLAG_TRANS
);
4463 BGP_ATTR_EXT_COMMUNITIES
);
4464 stream_putc(s
, ecom_tr_size
* 8);
4467 for (i
= 0; i
< ecomm
->size
; i
++) {
4468 pnt
= ecomm
->val
+ (i
* 8);
4473 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4476 stream_put(s
, pnt
, 8);
4482 /* Label index attribute. */
4483 if (safi
== SAFI_LABELED_UNICAST
) {
4484 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4485 uint32_t label_index
;
4487 label_index
= attr
->label_index
;
4489 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4491 BGP_ATTR_FLAG_OPTIONAL
4492 | BGP_ATTR_FLAG_TRANS
);
4493 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4495 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4497 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4498 stream_putc(s
, 0); // reserved
4499 stream_putw(s
, 0); // flags
4500 stream_putl(s
, label_index
);
4505 /* SRv6 Service Information Attribute. */
4506 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4507 if (attr
->srv6_l3vpn
) {
4508 uint8_t subtlv_len
=
4509 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4511 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4512 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4513 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4514 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4515 | BGP_ATTR_FLAG_TRANS
);
4516 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4517 stream_putc(s
, attr_len
);
4518 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4519 stream_putw(s
, tlv_len
);
4520 stream_putc(s
, 0); /* reserved */
4521 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4522 stream_putw(s
, subtlv_len
);
4523 stream_putc(s
, 0); /* reserved */
4524 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4525 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4526 stream_putc(s
, 0); /* sid_flags */
4529 ->endpoint_behavior
); /* endpoint */
4530 stream_putc(s
, 0); /* reserved */
4533 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4536 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4537 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4538 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4539 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4540 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4541 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4542 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4543 } else if (attr
->srv6_vpn
) {
4544 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4545 | BGP_ATTR_FLAG_TRANS
);
4546 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4547 stream_putc(s
, 22); /* tlv len */
4548 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4549 stream_putw(s
, 0x13); /* tlv len */
4550 stream_putc(s
, 0x00); /* reserved */
4551 stream_putc(s
, 0x01); /* sid_type */
4552 stream_putc(s
, 0x00); /* sif_flags */
4553 stream_put(s
, &attr
->srv6_vpn
->sid
,
4554 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4558 if (send_as4_path
) {
4559 /* If the peer is NOT As4 capable, AND */
4560 /* there are ASnums > 65535 in path THEN
4561 * give out AS4_PATH */
4563 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4565 * Hm, I wonder... confederation things *should* only be at
4566 * the beginning of an aspath, right? Then we should use
4567 * aspath_delete_confed_seq for this, because it is already
4569 * Folks, talk to me: what is reasonable here!?
4571 aspath
= aspath_delete_confed_seq(aspath
);
4574 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4575 | BGP_ATTR_FLAG_EXTLEN
);
4576 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4577 aspath_sizep
= stream_get_endp(s
);
4579 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4582 if (aspath
!= attr
->aspath
)
4583 aspath_free(aspath
);
4585 if (send_as4_aggregator
) {
4586 /* send AS4_AGGREGATOR, at this place */
4587 /* this section of code moved here in order to ensure the
4589 * *ascending* order of attributes
4591 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4592 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4594 stream_putl(s
, attr
->aggregator_as
);
4595 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4598 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4599 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4600 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4601 /* Tunnel Encap attribute */
4602 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4604 #ifdef ENABLE_BGP_VNC_ATTR
4606 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4611 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4612 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4613 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4614 stream_putc(s
, 9); // Length
4615 stream_putc(s
, 0); // Flags
4616 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4617 stream_put(s
, &(attr
->label
),
4618 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4619 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4620 // Unicast tunnel endpoint IP address
4624 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4625 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4626 stream_putc(s
, BGP_ATTR_OTC
);
4628 stream_putl(s
, attr
->otc
);
4632 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
) &&
4633 (CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
) ||
4634 peer
->sort
!= BGP_PEER_EBGP
)) {
4635 /* At the moment only AIGP Metric TLV exists for AIGP
4636 * attribute. If more comes in, do not forget to update
4637 * attr_len variable to include new ones.
4639 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4641 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4642 stream_putc(s
, BGP_ATTR_AIGP
);
4643 stream_putc(s
, attr_len
);
4644 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4647 /* Unknown transit attribute. */
4648 struct transit
*transit
= bgp_attr_get_transit(attr
);
4651 stream_put(s
, transit
->val
, transit
->length
);
4653 /* Return total size of attribute. */
4654 return stream_get_endp(s
) - cp
;
4657 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4659 unsigned long attrlen_pnt
;
4660 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
4661 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
4663 /* Set extended bit always to encode the attribute length as 2 bytes */
4664 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4665 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4667 attrlen_pnt
= stream_get_endp(s
);
4668 stream_putw(s
, 0); /* Length of this attribute. */
4670 /* Convert AFI, SAFI to values for packet. */
4671 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4673 stream_putw(s
, pkt_afi
);
4674 stream_putc(s
, pkt_safi
);
4679 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4680 afi_t afi
, safi_t safi
,
4681 const struct prefix_rd
*prd
,
4682 mpls_label_t
*label
, uint32_t num_labels
,
4683 bool addpath_capable
, uint32_t addpath_tx_id
,
4686 uint8_t wlabel
[4] = {0x80, 0x00, 0x00};
4688 if (safi
== SAFI_LABELED_UNICAST
) {
4689 label
= (mpls_label_t
*)wlabel
;
4693 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4694 addpath_capable
, addpath_tx_id
, attr
);
4697 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4699 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4702 /* Initialization of attribute. */
4703 void bgp_attr_init(void)
4716 void bgp_attr_finish(void)
4721 ecommunity_finish();
4722 lcommunity_finish();
4729 /* Make attribute packet. */
4730 void bgp_dump_routes_attr(struct stream
*s
, struct bgp_path_info
*bpi
,
4731 const struct prefix
*prefix
)
4736 struct aspath
*aspath
;
4737 bool addpath_capable
= false;
4738 uint32_t addpath_tx_id
= 0;
4739 struct attr
*attr
= bpi
->attr
;
4741 /* Remember current pointer. */
4742 cp
= stream_get_endp(s
);
4744 /* Place holder of length. */
4747 /* Origin attribute. */
4748 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4749 stream_putc(s
, BGP_ATTR_ORIGIN
);
4751 stream_putc(s
, attr
->origin
);
4753 aspath
= attr
->aspath
;
4755 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4756 stream_putc(s
, BGP_ATTR_AS_PATH
);
4757 aspath_lenp
= stream_get_endp(s
);
4760 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4762 /* Nexthop attribute. */
4763 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4764 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4765 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4766 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4768 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4771 /* MED attribute. */
4772 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4773 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4774 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4776 stream_putl(s
, attr
->med
);
4779 /* Local preference. */
4780 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4781 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4782 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4784 stream_putl(s
, attr
->local_pref
);
4787 /* Atomic aggregate. */
4788 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4789 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4790 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4795 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4796 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4797 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4799 stream_putl(s
, attr
->aggregator_as
);
4800 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4803 /* Community attribute. */
4804 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4805 struct community
*comm
= NULL
;
4807 comm
= bgp_attr_get_community(attr
);
4808 if (comm
->size
* 4 > 255) {
4810 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4811 | BGP_ATTR_FLAG_EXTLEN
);
4812 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4813 stream_putw(s
, comm
->size
* 4);
4816 BGP_ATTR_FLAG_OPTIONAL
4817 | BGP_ATTR_FLAG_TRANS
);
4818 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4819 stream_putc(s
, comm
->size
* 4);
4821 stream_put(s
, comm
->val
, comm
->size
* 4);
4824 /* Large Community attribute. */
4825 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4826 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4828 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4829 | BGP_ATTR_FLAG_EXTLEN
);
4830 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4832 lcom_length(bgp_attr_get_lcommunity(attr
)));
4835 BGP_ATTR_FLAG_OPTIONAL
4836 | BGP_ATTR_FLAG_TRANS
);
4837 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4839 lcom_length(bgp_attr_get_lcommunity(attr
)));
4842 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4843 lcom_length(bgp_attr_get_lcommunity(attr
)));
4846 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4847 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4848 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4849 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4852 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4853 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4854 sizep
= stream_get_endp(s
);
4857 stream_putc(s
, 0); /* Marker: Attribute length. */
4858 stream_putw(s
, AFI_IP6
); /* AFI */
4859 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4862 stream_putc(s
, attr
->mp_nexthop_len
);
4863 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4864 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4865 stream_put(s
, &attr
->mp_nexthop_local
,
4872 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4875 /* Set MP attribute length. */
4876 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4880 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4881 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4883 BGP_ATTR_FLAG_OPTIONAL
4884 | BGP_ATTR_FLAG_TRANS
);
4885 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4887 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4888 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4889 stream_putc(s
, 0); // reserved
4890 stream_putw(s
, 0); // flags
4891 stream_putl(s
, attr
->label_index
);
4896 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4897 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4898 stream_putc(s
, BGP_ATTR_OTC
);
4900 stream_putl(s
, attr
->otc
);
4904 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
4905 /* At the moment only AIGP Metric TLV exists for AIGP
4906 * attribute. If more comes in, do not forget to update
4907 * attr_len variable to include new ones.
4909 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4911 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4912 stream_putc(s
, BGP_ATTR_AIGP
);
4913 stream_putc(s
, attr_len
);
4914 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4917 /* Return total size of attribute. */
4918 len
= stream_get_endp(s
) - cp
- 2;
4919 stream_putw_at(s
, cp
, len
);