1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_aspath.h"
41 #include "bgpd/bgp_community.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_errors.h"
44 #include "bgpd/bgp_label.h"
45 #include "bgpd/bgp_packet.h"
46 #include "bgpd/bgp_ecommunity.h"
47 #include "bgpd/bgp_lcommunity.h"
48 #include "bgpd/bgp_updgrp.h"
49 #include "bgpd/bgp_encap_types.h"
51 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
52 #include "bgp_encap_types.h"
53 #include "bgp_vnc_types.h"
56 #include "bgp_flowspec_private.h"
59 /* Attribute strings for logging. */
60 static const struct message attr_str
[] = {
61 {BGP_ATTR_ORIGIN
, "ORIGIN"},
62 {BGP_ATTR_AS_PATH
, "AS_PATH"},
63 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
64 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
65 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
66 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
67 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
68 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
69 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
70 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
71 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
72 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
73 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
74 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
75 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
76 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
77 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
78 {BGP_ATTR_ENCAP
, "ENCAP"},
79 {BGP_ATTR_OTC
, "OTC"},
80 #ifdef ENABLE_BGP_VNC_ATTR
81 {BGP_ATTR_VNC
, "VNC"},
83 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
84 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
85 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
86 {BGP_ATTR_AIGP
, "AIGP"},
89 static const struct message attr_flag_str
[] = {
90 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
91 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
92 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
93 /* bgp_attr_flags_diagnose() relies on this bit being last in
95 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
98 static struct hash
*cluster_hash
;
100 static void *cluster_hash_alloc(void *p
)
102 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
103 struct cluster_list
*cluster
;
105 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
106 cluster
->length
= val
->length
;
108 if (cluster
->length
) {
109 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
110 memcpy(cluster
->list
, val
->list
, val
->length
);
112 cluster
->list
= NULL
;
119 /* Cluster list related functions. */
120 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
122 struct cluster_list tmp
= {};
123 struct cluster_list
*cluster
;
126 tmp
.list
= length
== 0 ? NULL
: pnt
;
128 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
133 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
137 for (i
= 0; i
< cluster
->length
/ 4; i
++)
138 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
143 static unsigned int cluster_hash_key_make(const void *p
)
145 const struct cluster_list
*cluster
= p
;
147 return jhash(cluster
->list
, cluster
->length
, 0);
150 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
152 const struct cluster_list
*cluster1
= p1
;
153 const struct cluster_list
*cluster2
= p2
;
155 if (cluster1
->list
== cluster2
->list
)
158 if (!cluster1
->list
|| !cluster2
->list
)
161 if (cluster1
->length
!= cluster2
->length
)
164 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
167 static void cluster_free(struct cluster_list
*cluster
)
169 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
170 XFREE(MTYPE_CLUSTER
, cluster
);
173 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
175 struct cluster_list
*find
;
177 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
183 static void cluster_unintern(struct cluster_list
**cluster
)
185 if ((*cluster
)->refcnt
)
186 (*cluster
)->refcnt
--;
188 if ((*cluster
)->refcnt
== 0) {
189 void *p
= hash_release(cluster_hash
, *cluster
);
190 assert(p
== *cluster
);
191 cluster_free(*cluster
);
196 static void cluster_init(void)
198 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
202 static void cluster_finish(void)
204 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
205 hash_free(cluster_hash
);
209 static struct hash
*encap_hash
= NULL
;
210 #ifdef ENABLE_BGP_VNC
211 static struct hash
*vnc_hash
= NULL
;
213 static struct hash
*srv6_l3vpn_hash
;
214 static struct hash
*srv6_vpn_hash
;
216 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
218 struct bgp_attr_encap_subtlv
*new;
219 struct bgp_attr_encap_subtlv
*tail
;
220 struct bgp_attr_encap_subtlv
*p
;
222 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
223 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
225 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
228 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
231 memcpy(tail
, p
, size
);
238 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
240 struct bgp_attr_encap_subtlv
*next
;
244 XFREE(MTYPE_ENCAP_TLV
, p
);
249 void bgp_attr_flush_encap(struct attr
*attr
)
254 if (attr
->encap_subtlvs
) {
255 encap_free(attr
->encap_subtlvs
);
256 attr
->encap_subtlvs
= NULL
;
258 #ifdef ENABLE_BGP_VNC
259 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
260 bgp_attr_get_vnc_subtlvs(attr
);
263 encap_free(vnc_subtlvs
);
264 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
270 * Compare encap sub-tlv chains
275 * This algorithm could be made faster if needed
277 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
278 const struct bgp_attr_encap_subtlv
*h2
)
280 const struct bgp_attr_encap_subtlv
*p
;
281 const struct bgp_attr_encap_subtlv
*q
;
285 if (h1
== NULL
|| h2
== NULL
)
288 for (p
= h1
; p
; p
= p
->next
) {
289 for (q
= h2
; q
; q
= q
->next
) {
290 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
291 && !memcmp(p
->value
, q
->value
, p
->length
)) {
300 for (p
= h2
; p
; p
= p
->next
) {
301 for (q
= h1
; q
; q
= q
->next
) {
302 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
303 && !memcmp(p
->value
, q
->value
, p
->length
)) {
315 static void *encap_hash_alloc(void *p
)
317 /* Encap structure is already allocated. */
323 #ifdef ENABLE_BGP_VNC
328 static struct bgp_attr_encap_subtlv
*
329 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
331 struct bgp_attr_encap_subtlv
*find
;
332 struct hash
*hash
= encap_hash
;
333 #ifdef ENABLE_BGP_VNC
334 if (type
== VNC_SUBTLV_TYPE
)
338 find
= hash_get(hash
, encap
, encap_hash_alloc
);
346 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
347 encap_subtlv_type type
)
349 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
353 if (encap
->refcnt
== 0) {
354 struct hash
*hash
= encap_hash
;
355 #ifdef ENABLE_BGP_VNC
356 if (type
== VNC_SUBTLV_TYPE
)
359 hash_release(hash
, encap
);
365 static unsigned int encap_hash_key_make(const void *p
)
367 const struct bgp_attr_encap_subtlv
*encap
= p
;
369 return jhash(encap
->value
, encap
->length
, 0);
372 static bool encap_hash_cmp(const void *p1
, const void *p2
)
374 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
375 (const struct bgp_attr_encap_subtlv
*)p2
);
378 static void encap_init(void)
380 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
382 #ifdef ENABLE_BGP_VNC
383 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
388 static void encap_finish(void)
390 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
391 hash_free(encap_hash
);
393 #ifdef ENABLE_BGP_VNC
394 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
400 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
409 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
410 bgp_attr_get_evpn_overlay(a2
));
413 /* Unknown transit attribute. */
414 static struct hash
*transit_hash
;
416 static void transit_free(struct transit
*transit
)
418 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
419 XFREE(MTYPE_TRANSIT
, transit
);
422 static void *transit_hash_alloc(void *p
)
424 /* Transit structure is already allocated. */
428 static struct transit
*transit_intern(struct transit
*transit
)
430 struct transit
*find
;
432 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
434 transit_free(transit
);
440 static void transit_unintern(struct transit
**transit
)
442 if ((*transit
)->refcnt
)
443 (*transit
)->refcnt
--;
445 if ((*transit
)->refcnt
== 0) {
446 hash_release(transit_hash
, *transit
);
447 transit_free(*transit
);
452 static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt
, int length
,
461 ptr_get_be16(data
+ 1, &tlv_length
);
464 /* The value field of the AIGP TLV is always 8 octets
465 * long and its value is interpreted as an unsigned 64-bit
468 if (tlv_type
== BGP_AIGP_TLV_METRIC
) {
469 (void)ptr_get_be64(data
+ 3, aigp
);
471 /* If an AIGP attribute is received and its first AIGP
472 * TLV contains the maximum value 0xffffffffffffffff,
473 * the attribute SHOULD be considered to be malformed
474 * and SHOULD be discarded as specified in this section.
476 if (*aigp
== BGP_AIGP_TLV_METRIC_MAX
) {
477 zlog_err("Bad AIGP TLV (%s) length: %llu",
478 BGP_AIGP_TLV_METRIC_DESC
,
479 BGP_AIGP_TLV_METRIC_MAX
);
487 length
-= tlv_length
;
493 static uint64_t bgp_aigp_metric_total(struct bgp_path_info
*bpi
)
495 uint64_t aigp
= bgp_attr_get_aigp_metric(bpi
->attr
);
498 return aigp
+ bpi
->nexthop
->metric
;
503 static void stream_put_bgp_aigp_tlv_metric(struct stream
*s
,
504 struct bgp_path_info
*bpi
)
506 stream_putc(s
, BGP_AIGP_TLV_METRIC
);
507 stream_putw(s
, BGP_AIGP_TLV_METRIC_LEN
);
508 stream_putq(s
, bgp_aigp_metric_total(bpi
));
511 static bool bgp_attr_aigp_valid(uint8_t *pnt
, int length
)
518 zlog_err("Bad AIGP attribute length (MUST be minimum 3): %u",
525 ptr_get_be16(data
+ 1, &tlv_length
);
528 if (length
< tlv_length
) {
530 "Bad AIGP attribute length: %u, but TLV length: %u",
535 if (tlv_length
< 3) {
536 zlog_err("Bad AIGP TLV length (MUST be minimum 3): %u",
541 /* AIGP TLV, Length: 11 */
542 if (tlv_type
== BGP_AIGP_TLV_METRIC
&&
543 tlv_length
!= BGP_AIGP_TLV_METRIC_LEN
) {
544 zlog_err("Bad AIGP TLV (%s) length: %u",
545 BGP_AIGP_TLV_METRIC_DESC
, tlv_length
);
550 length
-= tlv_length
;
556 static void *srv6_l3vpn_hash_alloc(void *p
)
561 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
563 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
566 static struct bgp_attr_srv6_l3vpn
*
567 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
569 struct bgp_attr_srv6_l3vpn
*find
;
571 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
573 srv6_l3vpn_free(l3vpn
);
578 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
580 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
585 if (l3vpn
->refcnt
== 0) {
586 hash_release(srv6_l3vpn_hash
, l3vpn
);
587 srv6_l3vpn_free(l3vpn
);
592 static void *srv6_vpn_hash_alloc(void *p
)
597 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
599 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
602 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
604 struct bgp_attr_srv6_vpn
*find
;
606 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
613 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
615 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
620 if (vpn
->refcnt
== 0) {
621 hash_release(srv6_vpn_hash
, vpn
);
627 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
629 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
632 key
= jhash(&l3vpn
->sid
, 16, key
);
633 key
= jhash_1word(l3vpn
->sid_flags
, key
);
634 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
635 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
636 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
637 key
= jhash_1word(l3vpn
->func_len
, key
);
638 key
= jhash_1word(l3vpn
->arg_len
, key
);
639 key
= jhash_1word(l3vpn
->transposition_len
, key
);
640 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
644 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
646 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
647 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
649 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
650 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
651 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
652 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
653 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
654 && l3vpn1
->func_len
== l3vpn2
->func_len
655 && l3vpn1
->arg_len
== l3vpn2
->arg_len
656 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
657 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
660 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
661 const struct bgp_attr_srv6_l3vpn
*h2
)
665 else if (h1
== NULL
|| h2
== NULL
)
668 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
671 static unsigned int srv6_vpn_hash_key_make(const void *p
)
673 const struct bgp_attr_srv6_vpn
*vpn
= p
;
676 key
= jhash(&vpn
->sid
, 16, key
);
677 key
= jhash_1word(vpn
->sid_flags
, key
);
681 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
683 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
684 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
686 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
687 && vpn1
->sid_flags
== vpn2
->sid_flags
;
690 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
691 const struct bgp_attr_srv6_vpn
*h2
)
695 else if (h1
== NULL
|| h2
== NULL
)
698 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
701 static void srv6_init(void)
704 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
705 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
706 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
707 "BGP Prefix-SID SRv6-VPN-Service-TLV");
710 static void srv6_finish(void)
712 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
713 hash_free(srv6_l3vpn_hash
);
714 srv6_l3vpn_hash
= NULL
;
715 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
716 hash_free(srv6_vpn_hash
);
717 srv6_vpn_hash
= NULL
;
720 static unsigned int transit_hash_key_make(const void *p
)
722 const struct transit
*transit
= p
;
724 return jhash(transit
->val
, transit
->length
, 0);
727 static bool transit_hash_cmp(const void *p1
, const void *p2
)
729 const struct transit
*transit1
= p1
;
730 const struct transit
*transit2
= p2
;
732 return (transit1
->length
== transit2
->length
733 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
736 static void transit_init(void)
738 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
742 static void transit_finish(void)
744 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
745 hash_free(transit_hash
);
749 /* Attribute hash routines. */
750 static struct hash
*attrhash
;
752 unsigned long int attr_count(void)
754 return attrhash
->count
;
757 unsigned long int attr_unknown_count(void)
759 return transit_hash
->count
;
762 unsigned int attrhash_key_make(const void *p
)
764 const struct attr
*attr
= (struct attr
*)p
;
766 #define MIX(val) key = jhash_1word(val, key)
767 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
769 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
770 MIX3(attr
->local_pref
, attr
->aggregator_as
,
771 attr
->aggregator_addr
.s_addr
);
772 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
773 attr
->originator_id
.s_addr
);
774 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
777 MIX(aspath_key_make(attr
->aspath
));
778 if (bgp_attr_get_community(attr
))
779 MIX(community_hash_make(bgp_attr_get_community(attr
)));
780 if (bgp_attr_get_lcommunity(attr
))
781 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
782 if (bgp_attr_get_ecommunity(attr
))
783 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
784 if (bgp_attr_get_ipv6_ecommunity(attr
))
785 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
786 if (bgp_attr_get_cluster(attr
))
787 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
788 if (bgp_attr_get_transit(attr
))
789 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
790 if (attr
->encap_subtlvs
)
791 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
792 if (attr
->srv6_l3vpn
)
793 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
795 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
796 #ifdef ENABLE_BGP_VNC
797 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
798 bgp_attr_get_vnc_subtlvs(attr
);
800 MIX(encap_hash_key_make(vnc_subtlvs
));
802 MIX(attr
->mp_nexthop_len
);
803 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
804 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
805 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
806 MIX(attr
->rmap_table_id
);
810 MIX(bgp_attr_get_aigp_metric(attr
));
815 bool attrhash_cmp(const void *p1
, const void *p2
)
817 const struct attr
*attr1
= p1
;
818 const struct attr
*attr2
= p2
;
820 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
821 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
822 && attr1
->aspath
== attr2
->aspath
823 && bgp_attr_get_community(attr1
)
824 == bgp_attr_get_community(attr2
)
825 && attr1
->med
== attr2
->med
826 && attr1
->local_pref
== attr2
->local_pref
827 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
828 if (attr1
->aggregator_as
== attr2
->aggregator_as
829 && attr1
->aggregator_addr
.s_addr
830 == attr2
->aggregator_addr
.s_addr
831 && attr1
->weight
== attr2
->weight
832 && attr1
->tag
== attr2
->tag
833 && attr1
->label_index
== attr2
->label_index
834 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
835 && bgp_attr_get_ecommunity(attr1
)
836 == bgp_attr_get_ecommunity(attr2
)
837 && bgp_attr_get_ipv6_ecommunity(attr1
)
838 == bgp_attr_get_ipv6_ecommunity(attr2
)
839 && bgp_attr_get_lcommunity(attr1
)
840 == bgp_attr_get_lcommunity(attr2
)
841 && bgp_attr_get_cluster(attr1
)
842 == bgp_attr_get_cluster(attr2
)
843 && bgp_attr_get_transit(attr1
)
844 == bgp_attr_get_transit(attr2
)
845 && bgp_attr_get_aigp_metric(attr1
)
846 == bgp_attr_get_aigp_metric(attr2
)
847 && attr1
->rmap_table_id
== attr2
->rmap_table_id
848 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
849 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
850 #ifdef ENABLE_BGP_VNC
851 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
852 bgp_attr_get_vnc_subtlvs(attr2
))
854 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
855 &attr2
->mp_nexthop_global
)
856 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
857 &attr2
->mp_nexthop_local
)
858 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
859 &attr2
->mp_nexthop_global_in
)
860 && IPV4_ADDR_SAME(&attr1
->originator_id
,
861 &attr2
->originator_id
)
862 && overlay_index_same(attr1
, attr2
)
863 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
864 && attr1
->es_flags
== attr2
->es_flags
865 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
866 && attr1
->df_pref
== attr2
->df_pref
867 && attr1
->df_alg
== attr2
->df_alg
868 && attr1
->nh_ifindex
== attr2
->nh_ifindex
869 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
870 && attr1
->distance
== attr2
->distance
871 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
872 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
873 && attr1
->srte_color
== attr2
->srte_color
874 && attr1
->nh_type
== attr2
->nh_type
875 && attr1
->bh_type
== attr2
->bh_type
876 && attr1
->otc
== attr2
->otc
)
883 static void attrhash_init(void)
886 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
890 * special for hash_clean below
892 static void attr_vfree(void *attr
)
894 XFREE(MTYPE_ATTR
, attr
);
897 static void attrhash_finish(void)
899 hash_clean(attrhash
, attr_vfree
);
904 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
906 struct attr
*attr
= bucket
->data
;
908 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
912 " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6\n",
913 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
914 attr
->origin
, attr
->weight
, attr
->label
,
915 attr
->srv6_l3vpn
? &attr
->srv6_l3vpn
->sid
916 : &attr
->srv6_vpn
->sid
);
919 void attr_show_all(struct vty
*vty
)
921 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
922 void *))attr_show_all_iterator
,
926 static void *bgp_attr_hash_alloc(void *p
)
928 struct attr
*val
= (struct attr
*)p
;
931 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
933 if (val
->encap_subtlvs
) {
934 val
->encap_subtlvs
= NULL
;
936 #ifdef ENABLE_BGP_VNC
937 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
938 bgp_attr_get_vnc_subtlvs(val
);
941 bgp_attr_set_vnc_subtlvs(val
, NULL
);
948 /* Internet argument attribute. */
949 struct attr
*bgp_attr_intern(struct attr
*attr
)
952 struct ecommunity
*ecomm
= NULL
;
953 struct ecommunity
*ipv6_ecomm
= NULL
;
954 struct lcommunity
*lcomm
= NULL
;
955 struct community
*comm
= NULL
;
957 /* Intern referenced structure. */
959 if (!attr
->aspath
->refcnt
)
960 attr
->aspath
= aspath_intern(attr
->aspath
);
962 attr
->aspath
->refcnt
++;
965 comm
= bgp_attr_get_community(attr
);
968 bgp_attr_set_community(attr
, community_intern(comm
));
973 ecomm
= bgp_attr_get_ecommunity(attr
);
976 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
981 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
983 if (!ipv6_ecomm
->refcnt
)
984 bgp_attr_set_ipv6_ecommunity(
985 attr
, ecommunity_intern(ipv6_ecomm
));
987 ipv6_ecomm
->refcnt
++;
990 lcomm
= bgp_attr_get_lcommunity(attr
);
993 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
998 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1001 if (!cluster
->refcnt
)
1002 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
1007 struct transit
*transit
= bgp_attr_get_transit(attr
);
1010 if (!transit
->refcnt
)
1011 bgp_attr_set_transit(attr
, transit_intern(transit
));
1015 if (attr
->encap_subtlvs
) {
1016 if (!attr
->encap_subtlvs
->refcnt
)
1017 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
1020 attr
->encap_subtlvs
->refcnt
++;
1022 if (attr
->srv6_l3vpn
) {
1023 if (!attr
->srv6_l3vpn
->refcnt
)
1024 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
1026 attr
->srv6_l3vpn
->refcnt
++;
1028 if (attr
->srv6_vpn
) {
1029 if (!attr
->srv6_vpn
->refcnt
)
1030 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
1032 attr
->srv6_vpn
->refcnt
++;
1034 #ifdef ENABLE_BGP_VNC
1035 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1036 bgp_attr_get_vnc_subtlvs(attr
);
1039 if (!vnc_subtlvs
->refcnt
)
1040 bgp_attr_set_vnc_subtlvs(
1042 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
1044 vnc_subtlvs
->refcnt
++;
1048 /* At this point, attr only contains intern'd pointers. that means
1049 * if we find it in attrhash, it has all the same pointers and we
1050 * correctly updated the refcounts on these.
1051 * If we don't find it, we need to allocate a one because in all
1052 * cases this returns a new reference to a hashed attr, but the input
1053 * wasn't on hash. */
1054 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
1060 /* Make network statement's attribute. */
1061 struct attr
*bgp_attr_default_set(struct attr
*attr
, struct bgp
*bgp
,
1064 memset(attr
, 0, sizeof(struct attr
));
1066 attr
->origin
= origin
;
1067 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1068 attr
->aspath
= aspath_empty();
1069 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1070 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1072 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
1073 attr
->label
= MPLS_INVALID_LABEL
;
1074 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1075 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1076 attr
->local_pref
= bgp
->default_local_pref
;
1081 /* Create the attributes for an aggregate */
1082 struct attr
*bgp_attr_aggregate_intern(
1083 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
1084 struct community
*community
, struct ecommunity
*ecommunity
,
1085 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
1086 uint8_t atomic_aggregate
, const struct prefix
*p
)
1090 route_map_result_t ret
;
1092 memset(&attr
, 0, sizeof(attr
));
1094 /* Origin attribute. */
1095 attr
.origin
= origin
;
1096 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1100 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1102 /* AS path attribute. */
1104 attr
.aspath
= aspath_intern(aspath
);
1106 attr
.aspath
= aspath_empty();
1107 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1109 /* Next hop attribute. */
1110 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1113 uint32_t gshut
= COMMUNITY_GSHUT
;
1115 /* If we are not shutting down ourselves and we are
1116 * aggregating a route that contains the GSHUT community we
1117 * need to remove that community when creating the aggregate */
1118 if (!bgp_in_graceful_shutdown(bgp
)
1119 && community_include(community
, gshut
)) {
1120 community_del_val(community
, &gshut
);
1123 bgp_attr_set_community(&attr
, community
);
1127 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1130 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1132 if (bgp_in_graceful_shutdown(bgp
))
1133 bgp_attr_add_gshut_community(&attr
);
1135 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1136 attr
.label
= MPLS_INVALID_LABEL
;
1137 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1138 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1139 if (!aggregate
->as_set
|| atomic_aggregate
)
1140 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1141 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1142 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1143 attr
.aggregator_as
= bgp
->confed_id
;
1145 attr
.aggregator_as
= bgp
->as
;
1146 attr
.aggregator_addr
= bgp
->router_id
;
1148 /* Apply route-map */
1149 if (aggregate
->rmap
.name
) {
1150 struct attr attr_tmp
= attr
;
1151 struct bgp_path_info rmap_path
;
1153 memset(&rmap_path
, 0, sizeof(rmap_path
));
1154 rmap_path
.peer
= bgp
->peer_self
;
1155 rmap_path
.attr
= &attr_tmp
;
1157 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1159 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1161 bgp
->peer_self
->rmap_type
= 0;
1163 if (ret
== RMAP_DENYMATCH
) {
1164 /* Free uninterned attribute. */
1165 bgp_attr_flush(&attr_tmp
);
1167 /* Unintern original. */
1168 aspath_unintern(&attr
.aspath
);
1172 if (bgp_in_graceful_shutdown(bgp
))
1173 bgp_attr_add_gshut_community(&attr_tmp
);
1175 new = bgp_attr_intern(&attr_tmp
);
1178 if (bgp_in_graceful_shutdown(bgp
))
1179 bgp_attr_add_gshut_community(&attr
);
1181 new = bgp_attr_intern(&attr
);
1184 /* Always release the 'intern()'ed AS Path. */
1185 aspath_unintern(&attr
.aspath
);
1190 /* Unintern just the sub-components of the attr, but not the attr */
1191 void bgp_attr_unintern_sub(struct attr
*attr
)
1193 struct ecommunity
*ecomm
= NULL
;
1194 struct ecommunity
*ipv6_ecomm
= NULL
;
1195 struct cluster_list
*cluster
;
1196 struct lcommunity
*lcomm
= NULL
;
1197 struct community
*comm
= NULL
;
1199 /* aspath refcount shoud be decrement. */
1200 aspath_unintern(&attr
->aspath
);
1201 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1203 comm
= bgp_attr_get_community(attr
);
1204 community_unintern(&comm
);
1205 bgp_attr_set_community(attr
, NULL
);
1207 ecomm
= bgp_attr_get_ecommunity(attr
);
1208 ecommunity_unintern(&ecomm
);
1209 bgp_attr_set_ecommunity(attr
, NULL
);
1211 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1212 ecommunity_unintern(&ipv6_ecomm
);
1213 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1215 lcomm
= bgp_attr_get_lcommunity(attr
);
1216 lcommunity_unintern(&lcomm
);
1217 bgp_attr_set_lcommunity(attr
, NULL
);
1219 cluster
= bgp_attr_get_cluster(attr
);
1221 cluster_unintern(&cluster
);
1222 bgp_attr_set_cluster(attr
, cluster
);
1224 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1226 struct transit
*transit
= bgp_attr_get_transit(attr
);
1229 transit_unintern(&transit
);
1230 bgp_attr_set_transit(attr
, transit
);
1233 if (attr
->encap_subtlvs
)
1234 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1236 #ifdef ENABLE_BGP_VNC
1237 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1238 bgp_attr_get_vnc_subtlvs(attr
);
1241 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1242 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1246 if (attr
->srv6_l3vpn
)
1247 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1250 srv6_vpn_unintern(&attr
->srv6_vpn
);
1253 /* Free bgp attribute and aspath. */
1254 void bgp_attr_unintern(struct attr
**pattr
)
1256 struct attr
*attr
= *pattr
;
1260 /* Decrement attribute reference. */
1265 /* If reference becomes zero then free attribute object. */
1266 if (attr
->refcnt
== 0) {
1267 ret
= hash_release(attrhash
, attr
);
1268 assert(ret
!= NULL
);
1269 XFREE(MTYPE_ATTR
, attr
);
1273 bgp_attr_unintern_sub(&tmp
);
1276 void bgp_attr_flush(struct attr
*attr
)
1278 struct ecommunity
*ecomm
;
1279 struct ecommunity
*ipv6_ecomm
;
1280 struct cluster_list
*cluster
;
1281 struct lcommunity
*lcomm
;
1282 struct community
*comm
;
1284 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1285 aspath_free(attr
->aspath
);
1286 attr
->aspath
= NULL
;
1288 comm
= bgp_attr_get_community(attr
);
1289 if (comm
&& !comm
->refcnt
)
1290 community_free(&comm
);
1291 bgp_attr_set_community(attr
, NULL
);
1293 ecomm
= bgp_attr_get_ecommunity(attr
);
1294 if (ecomm
&& !ecomm
->refcnt
)
1295 ecommunity_free(&ecomm
);
1296 bgp_attr_set_ecommunity(attr
, NULL
);
1298 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1299 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1300 ecommunity_free(&ipv6_ecomm
);
1301 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1303 lcomm
= bgp_attr_get_lcommunity(attr
);
1304 if (lcomm
&& !lcomm
->refcnt
)
1305 lcommunity_free(&lcomm
);
1306 bgp_attr_set_lcommunity(attr
, NULL
);
1308 cluster
= bgp_attr_get_cluster(attr
);
1309 if (cluster
&& !cluster
->refcnt
) {
1310 cluster_free(cluster
);
1311 bgp_attr_set_cluster(attr
, NULL
);
1314 struct transit
*transit
= bgp_attr_get_transit(attr
);
1316 if (transit
&& !transit
->refcnt
) {
1317 transit_free(transit
);
1318 bgp_attr_set_transit(attr
, NULL
);
1320 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1321 encap_free(attr
->encap_subtlvs
);
1322 attr
->encap_subtlvs
= NULL
;
1324 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1325 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1326 attr
->srv6_l3vpn
= NULL
;
1328 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1329 srv6_vpn_free(attr
->srv6_vpn
);
1330 attr
->srv6_vpn
= NULL
;
1332 #ifdef ENABLE_BGP_VNC
1333 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1334 bgp_attr_get_vnc_subtlvs(attr
);
1336 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1337 encap_free(vnc_subtlvs
);
1338 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1343 /* Implement draft-scudder-idr-optional-transitive behaviour and
1344 * avoid resetting sessions for malformed attributes which are
1345 * are partial/optional and hence where the error likely was not
1346 * introduced by the sending neighbour.
1348 static enum bgp_attr_parse_ret
1349 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1352 struct peer
*const peer
= args
->peer
;
1353 struct attr
*const attr
= args
->attr
;
1354 const uint8_t flags
= args
->flags
;
1355 /* startp and length must be special-cased, as whether or not to
1356 * send the attribute data with the NOTIFY depends on the error,
1357 * the caller therefore signals this with the seperate length argument
1359 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1361 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1362 char attr_str
[BUFSIZ
] = {0};
1364 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1366 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1369 /* Only relax error handling for eBGP peers */
1370 if (peer
->sort
!= BGP_PEER_EBGP
) {
1371 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1372 notify_datap
, length
);
1373 return BGP_ATTR_PARSE_ERROR
;
1376 /* Adjust the stream getp to the end of the attribute, in case we can
1377 * still proceed but the caller hasn't read all the attribute.
1379 stream_set_getp(BGP_INPUT(peer
),
1380 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1383 switch (args
->type
) {
1384 /* where an attribute is relatively inconsequential, e.g. it does not
1385 * affect route selection, and can be safely ignored, then any such
1386 * attributes which are malformed should just be ignored and the route
1387 * processed as normal.
1389 case BGP_ATTR_AS4_AGGREGATOR
:
1390 case BGP_ATTR_AGGREGATOR
:
1391 case BGP_ATTR_ATOMIC_AGGREGATE
:
1392 return BGP_ATTR_PARSE_PROCEED
;
1394 /* Core attributes, particularly ones which may influence route
1395 * selection, should be treat-as-withdraw.
1397 case BGP_ATTR_ORIGIN
:
1398 case BGP_ATTR_AS_PATH
:
1399 case BGP_ATTR_NEXT_HOP
:
1400 case BGP_ATTR_MULTI_EXIT_DISC
:
1401 case BGP_ATTR_LOCAL_PREF
:
1402 case BGP_ATTR_COMMUNITIES
:
1403 case BGP_ATTR_EXT_COMMUNITIES
:
1404 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1405 case BGP_ATTR_LARGE_COMMUNITIES
:
1406 case BGP_ATTR_ORIGINATOR_ID
:
1407 case BGP_ATTR_CLUSTER_LIST
:
1409 return BGP_ATTR_PARSE_WITHDRAW
;
1410 case BGP_ATTR_MP_REACH_NLRI
:
1411 case BGP_ATTR_MP_UNREACH_NLRI
:
1412 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1413 notify_datap
, length
);
1414 return BGP_ATTR_PARSE_ERROR
;
1417 /* Partial optional attributes that are malformed should not cause
1418 * the whole session to be reset. Instead treat it as a withdrawal
1419 * of the routes, if possible.
1421 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1422 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1423 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1424 return BGP_ATTR_PARSE_WITHDRAW
;
1426 /* default to reset */
1427 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1430 /* Find out what is wrong with the path attribute flag bits and log the error.
1431 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1432 Extended Length. Checking O/T/P bits at once implies, that the attribute
1433 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1434 non-transitive" attribute. */
1436 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1437 uint8_t desired_flags
/* how RFC says it must be */
1440 uint8_t seen
= 0, i
;
1441 uint8_t real_flags
= args
->flags
;
1442 const uint8_t attr_code
= args
->type
;
1444 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1445 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1446 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1447 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1448 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1449 flog_err(EC_BGP_ATTR_FLAG
,
1450 "%s attribute must%s be flagged as \"%s\"",
1451 lookup_msg(attr_str
, attr_code
, NULL
),
1452 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1455 attr_flag_str
[i
].str
);
1460 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1461 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1462 real_flags
, desired_flags
);
1466 /* Required flags for attributes. EXTLEN will be masked off when testing,
1467 * as will PARTIAL for optional+transitive attributes.
1469 const uint8_t attr_flags_values
[] = {
1470 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1471 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1472 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1473 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1474 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1475 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1476 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1477 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1478 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1479 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1480 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1481 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1482 [BGP_ATTR_EXT_COMMUNITIES
] =
1483 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1484 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1485 [BGP_ATTR_AS4_AGGREGATOR
] =
1486 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1487 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1488 [BGP_ATTR_LARGE_COMMUNITIES
] =
1489 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1490 [BGP_ATTR_OTC
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1491 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1492 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1493 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1494 [BGP_ATTR_AIGP
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1496 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1498 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1500 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1501 const uint8_t flags
= args
->flags
;
1502 const uint8_t attr_code
= args
->type
;
1504 /* there may be attributes we don't know about */
1505 if (attr_code
> attr_flags_values_max
)
1507 if (attr_flags_values
[attr_code
] == 0)
1510 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1514 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1515 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1518 "%s well-known attributes must have transitive flag set (%x)",
1519 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1523 /* "For well-known attributes and for optional non-transitive
1525 * the Partial bit MUST be set to 0."
1527 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1528 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1529 flog_err(EC_BGP_ATTR_FLAG
,
1530 "%s well-known attribute must NOT have the partial flag set (%x)",
1531 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1534 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1535 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1536 flog_err(EC_BGP_ATTR_FLAG
,
1537 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1538 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1543 /* Optional transitive attributes may go through speakers that don't
1544 * reocgnise them and set the Partial bit.
1546 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1547 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1548 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1550 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1553 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1557 /* Get origin attribute of the update message. */
1558 static enum bgp_attr_parse_ret
1559 bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1561 struct peer
*const peer
= args
->peer
;
1562 struct attr
*const attr
= args
->attr
;
1563 const bgp_size_t length
= args
->length
;
1565 /* If any recognized attribute has Attribute Length that conflicts
1566 with the expected length (based on the attribute type code), then
1567 the Error Subcode is set to Attribute Length Error. The Data
1568 field contains the erroneous attribute (type, length and
1571 flog_err(EC_BGP_ATTR_LEN
,
1572 "Origin attribute length is not one %d", length
);
1573 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1577 /* Fetch origin attribute. */
1578 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1580 /* If the ORIGIN attribute has an undefined value, then the Error
1581 Subcode is set to Invalid Origin Attribute. The Data field
1582 contains the unrecognized attribute (type, length and value). */
1583 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1584 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1585 flog_err(EC_BGP_ATTR_ORIGIN
,
1586 "Origin attribute value is invalid %d", attr
->origin
);
1587 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1591 /* Set oring attribute flag. */
1592 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1597 /* Parse AS path information. This function is wrapper of
1599 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1601 struct attr
*const attr
= args
->attr
;
1602 struct peer
*const peer
= args
->peer
;
1603 const bgp_size_t length
= args
->length
;
1606 * peer with AS4 => will get 4Byte ASnums
1607 * otherwise, will get 16 Bit
1609 attr
->aspath
= aspath_parse(
1611 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1612 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1614 /* In case of IBGP, length will be zero. */
1615 if (!attr
->aspath
) {
1616 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1617 "Malformed AS path from %s, length is %d", peer
->host
,
1619 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1623 /* Conformant BGP speakers SHOULD NOT send BGP
1624 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1625 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1626 * withdraw" error handling behavior as per [RFC7606].
1628 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1629 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1630 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1632 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1636 /* Set aspath attribute flag. */
1637 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1639 return BGP_ATTR_PARSE_PROCEED
;
1642 static enum bgp_attr_parse_ret
bgp_attr_aspath_check(struct peer
*const peer
,
1643 struct attr
*const attr
)
1645 /* These checks were part of bgp_attr_aspath, but with
1646 * as4 we should to check aspath things when
1647 * aspath synthesizing with as4_path has already taken place.
1648 * Otherwise we check ASPATH and use the synthesized thing, and that is
1650 * So do the checks later, i.e. here
1652 struct aspath
*aspath
;
1654 /* Confederation sanity check. */
1655 if ((peer
->sort
== BGP_PEER_CONFED
1656 && !aspath_left_confed_check(attr
->aspath
))
1657 || (peer
->sort
== BGP_PEER_EBGP
1658 && aspath_confed_check(attr
->aspath
))) {
1659 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1661 return BGP_ATTR_PARSE_WITHDRAW
;
1664 /* First AS check for EBGP. */
1665 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1666 if (peer
->sort
== BGP_PEER_EBGP
1667 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1668 flog_err(EC_BGP_ATTR_FIRST_AS
,
1669 "%s incorrect first AS (must be %u)",
1670 peer
->host
, peer
->as
);
1671 return BGP_ATTR_PARSE_WITHDRAW
;
1675 /* Codification of AS 0 Processing */
1676 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1678 EC_BGP_ATTR_MAL_AS_PATH
,
1679 "Malformed AS path, AS number is 0 in the path from %s",
1681 return BGP_ATTR_PARSE_WITHDRAW
;
1684 /* local-as prepend */
1685 if (peer
->change_local_as
1686 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1687 aspath
= aspath_dup(attr
->aspath
);
1688 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1689 aspath_unintern(&attr
->aspath
);
1690 attr
->aspath
= aspath_intern(aspath
);
1693 return BGP_ATTR_PARSE_PROCEED
;
1696 /* Parse AS4 path information. This function is another wrapper of
1698 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1699 struct aspath
**as4_path
)
1701 struct peer
*const peer
= args
->peer
;
1702 struct attr
*const attr
= args
->attr
;
1703 const bgp_size_t length
= args
->length
;
1705 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1707 /* In case of IBGP, length will be zero. */
1709 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1710 "Malformed AS4 path from %s, length is %d", peer
->host
,
1712 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1716 /* Conformant BGP speakers SHOULD NOT send BGP
1717 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1718 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1719 * withdraw" error handling behavior as per [RFC7606].
1721 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1722 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1723 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1725 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1729 /* Set aspath attribute flag. */
1730 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1732 return BGP_ATTR_PARSE_PROCEED
;
1736 * Check that the nexthop attribute is valid.
1738 enum bgp_attr_parse_ret
bgp_attr_nexthop_valid(struct peer
*peer
,
1741 struct bgp
*bgp
= peer
->bgp
;
1743 if (ipv4_martian(&attr
->nexthop
) && !bgp
->allow_martian
) {
1744 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1746 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %pI4",
1748 data
[0] = BGP_ATTR_FLAG_TRANS
;
1749 data
[1] = BGP_ATTR_NEXT_HOP
;
1750 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1751 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1752 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1753 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1755 return BGP_ATTR_PARSE_ERROR
;
1758 return BGP_ATTR_PARSE_PROCEED
;
1761 /* Nexthop attribute. */
1762 static enum bgp_attr_parse_ret
1763 bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1765 struct peer
*const peer
= args
->peer
;
1766 struct attr
*const attr
= args
->attr
;
1767 const bgp_size_t length
= args
->length
;
1769 /* Check nexthop attribute length. */
1771 flog_err(EC_BGP_ATTR_LEN
,
1772 "Nexthop attribute length isn't four [%d]", length
);
1774 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1778 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1779 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1781 return BGP_ATTR_PARSE_PROCEED
;
1784 /* MED atrribute. */
1785 static enum bgp_attr_parse_ret
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1787 struct peer
*const peer
= args
->peer
;
1788 struct attr
*const attr
= args
->attr
;
1789 const bgp_size_t length
= args
->length
;
1793 flog_err(EC_BGP_ATTR_LEN
,
1794 "MED attribute length isn't four [%d]", length
);
1796 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1800 attr
->med
= stream_getl(peer
->curr
);
1802 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1804 return BGP_ATTR_PARSE_PROCEED
;
1807 /* Local preference attribute. */
1808 static enum bgp_attr_parse_ret
1809 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1811 struct peer
*const peer
= args
->peer
;
1812 struct attr
*const attr
= args
->attr
;
1813 const bgp_size_t length
= args
->length
;
1815 /* if received from an internal neighbor, it SHALL be considered
1816 * malformed if its length is not equal to 4. If malformed, the
1817 * UPDATE message SHALL be handled using the approach of "treat-as-
1820 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1821 flog_err(EC_BGP_ATTR_LEN
,
1822 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1823 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1827 /* If it is contained in an UPDATE message that is received from an
1828 external peer, then this attribute MUST be ignored by the
1829 receiving speaker. */
1830 if (peer
->sort
== BGP_PEER_EBGP
) {
1831 STREAM_FORWARD_GETP(peer
->curr
, length
);
1832 return BGP_ATTR_PARSE_PROCEED
;
1835 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1837 /* Set the local-pref flag. */
1838 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1840 return BGP_ATTR_PARSE_PROCEED
;
1843 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1847 /* Atomic aggregate. */
1848 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1850 struct attr
*const attr
= args
->attr
;
1851 const bgp_size_t length
= args
->length
;
1855 flog_err(EC_BGP_ATTR_LEN
,
1856 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1858 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1862 /* Set atomic aggregate flag. */
1863 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1865 return BGP_ATTR_PARSE_PROCEED
;
1868 /* Aggregator attribute */
1869 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1871 struct peer
*const peer
= args
->peer
;
1872 struct attr
*const attr
= args
->attr
;
1873 const bgp_size_t length
= args
->length
;
1878 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1879 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1880 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1883 if (length
!= wantedlen
) {
1884 flog_err(EC_BGP_ATTR_LEN
,
1885 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1887 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1891 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1892 aggregator_as
= stream_getl(peer
->curr
);
1894 aggregator_as
= stream_getw(peer
->curr
);
1896 attr
->aggregator_as
= aggregator_as
;
1897 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1899 /* Codification of AS 0 Processing */
1900 if (aggregator_as
== BGP_AS_ZERO
) {
1901 flog_err(EC_BGP_ATTR_LEN
,
1902 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1903 peer
->host
, aspath_print(attr
->aspath
));
1905 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1906 char attr_str
[BUFSIZ
] = {0};
1908 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1910 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1913 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1916 return BGP_ATTR_PARSE_PROCEED
;
1919 /* New Aggregator attribute */
1920 static enum bgp_attr_parse_ret
1921 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1922 as_t
*as4_aggregator_as
,
1923 struct in_addr
*as4_aggregator_addr
)
1925 struct peer
*const peer
= args
->peer
;
1926 struct attr
*const attr
= args
->attr
;
1927 const bgp_size_t length
= args
->length
;
1931 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1933 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1937 aggregator_as
= stream_getl(peer
->curr
);
1939 *as4_aggregator_as
= aggregator_as
;
1940 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1942 /* Codification of AS 0 Processing */
1943 if (aggregator_as
== BGP_AS_ZERO
) {
1944 flog_err(EC_BGP_ATTR_LEN
,
1945 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1946 peer
->host
, aspath_print(attr
->aspath
));
1948 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1949 char attr_str
[BUFSIZ
] = {0};
1951 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1953 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1956 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1959 return BGP_ATTR_PARSE_PROCEED
;
1962 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1964 static enum bgp_attr_parse_ret
1965 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1966 struct aspath
*as4_path
, as_t as4_aggregator
,
1967 struct in_addr
*as4_aggregator_addr
)
1969 int ignore_as4_path
= 0;
1970 struct aspath
*newpath
;
1972 if (!attr
->aspath
) {
1973 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1975 * checked that all well-known, mandatory attributes were
1978 * Can only be a problem with peer itself - hard error
1980 return BGP_ATTR_PARSE_ERROR
;
1983 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1984 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1986 * It is worth a warning though, because the peer really
1987 * should not send them
1989 if (BGP_DEBUG(as4
, AS4
)) {
1990 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1991 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1992 "AS4 capable peer, yet it sent");
1995 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1996 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1998 "AS4 capable peer, yet it sent");
2001 return BGP_ATTR_PARSE_PROCEED
;
2004 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
2005 * because that may override AS4_PATH
2007 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
2008 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
2010 * if the as_number in aggregator is not AS_TRANS,
2011 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
2012 * and the Aggregator shall be taken as
2013 * info on the aggregating node, and the AS_PATH
2014 * shall be taken as the AS_PATH
2016 * the Aggregator shall be ignored and the
2017 * AS4_AGGREGATOR shall be taken as the
2018 * Aggregating node and the AS_PATH is to be
2019 * constructed "as in all other cases"
2021 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
2023 if (BGP_DEBUG(as4
, AS4
))
2025 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
2027 ignore_as4_path
= 1;
2029 /* "New_aggregator shall be taken as aggregator"
2031 attr
->aggregator_as
= as4_aggregator
;
2032 attr
->aggregator_addr
.s_addr
=
2033 as4_aggregator_addr
->s_addr
;
2036 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2037 * That is bogus - but reading the conditions
2038 * we have to handle AS4_AGGREGATOR as if it were
2039 * AGGREGATOR in that case
2041 if (BGP_DEBUG(as4
, AS4
))
2043 "[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",
2045 attr
->aggregator_as
= as4_aggregator
;
2046 /* sweep it under the carpet and simulate a "good"
2048 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
2052 /* need to reconcile NEW_AS_PATH and AS_PATH */
2053 if (!ignore_as4_path
2054 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
2055 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
2057 return BGP_ATTR_PARSE_ERROR
;
2059 aspath_unintern(&attr
->aspath
);
2060 attr
->aspath
= aspath_intern(newpath
);
2062 return BGP_ATTR_PARSE_PROCEED
;
2065 /* Community attribute. */
2066 static enum bgp_attr_parse_ret
2067 bgp_attr_community(struct bgp_attr_parser_args
*args
)
2069 struct peer
*const peer
= args
->peer
;
2070 struct attr
*const attr
= args
->attr
;
2071 const bgp_size_t length
= args
->length
;
2074 bgp_attr_set_community(attr
, NULL
);
2075 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2079 bgp_attr_set_community(
2081 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
2083 /* XXX: fix community_parse to use stream API and remove this */
2084 stream_forward_getp(peer
->curr
, length
);
2086 /* The Community attribute SHALL be considered malformed if its
2087 * length is not a non-zero multiple of 4.
2089 if (!bgp_attr_get_community(attr
))
2090 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2093 return BGP_ATTR_PARSE_PROCEED
;
2096 /* Originator ID attribute. */
2097 static enum bgp_attr_parse_ret
2098 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
2100 struct peer
*const peer
= args
->peer
;
2101 struct attr
*const attr
= args
->attr
;
2102 const bgp_size_t length
= args
->length
;
2104 /* if received from an internal neighbor, it SHALL be considered
2105 * malformed if its length is not equal to 4. If malformed, the
2106 * UPDATE message SHALL be handled using the approach of "treat-as-
2110 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
2113 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2117 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
2119 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2121 return BGP_ATTR_PARSE_PROCEED
;
2124 /* Cluster list attribute. */
2125 static enum bgp_attr_parse_ret
2126 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2128 struct peer
*const peer
= args
->peer
;
2129 struct attr
*const attr
= args
->attr
;
2130 const bgp_size_t length
= args
->length
;
2132 /* if received from an internal neighbor, it SHALL be considered
2133 * malformed if its length is not a non-zero multiple of 4. If
2134 * malformed, the UPDATE message SHALL be handled using the approach
2135 * of "treat-as-withdraw".
2137 if (length
== 0 || length
% 4) {
2138 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2140 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2144 bgp_attr_set_cluster(
2145 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2148 /* XXX: Fix cluster_parse to use stream API and then remove this */
2149 stream_forward_getp(peer
->curr
, length
);
2151 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2153 return BGP_ATTR_PARSE_PROCEED
;
2156 /* Multiprotocol reachability information parse. */
2157 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2158 struct bgp_nlri
*mp_update
)
2162 iana_safi_t pkt_safi
;
2164 bgp_size_t nlri_len
;
2167 struct peer
*const peer
= args
->peer
;
2168 struct attr
*const attr
= args
->attr
;
2169 const bgp_size_t length
= args
->length
;
2171 /* Set end of packet. */
2172 s
= BGP_INPUT(peer
);
2173 start
= stream_get_getp(s
);
2175 /* safe to read statically sized header? */
2176 #define BGP_MP_REACH_MIN_SIZE 5
2177 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2178 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2179 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2180 __func__
, peer
->host
, (unsigned long)length
);
2181 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2184 /* Load AFI, SAFI. */
2185 pkt_afi
= stream_getw(s
);
2186 pkt_safi
= stream_getc(s
);
2188 /* Convert AFI, SAFI to internal values, check. */
2189 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2190 /* Log if AFI or SAFI is unrecognized. This is not an error
2192 * the attribute is otherwise malformed.
2194 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2196 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2197 peer
->host
, iana_afi2str(pkt_afi
),
2198 iana_safi2str(pkt_safi
));
2199 return BGP_ATTR_PARSE_ERROR
;
2202 /* Get nexthop length. */
2203 attr
->mp_nexthop_len
= stream_getc(s
);
2205 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2207 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2208 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2209 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2212 /* Nexthop length check. */
2213 switch (attr
->mp_nexthop_len
) {
2215 if (safi
!= SAFI_FLOWSPEC
) {
2216 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2217 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2218 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2221 case BGP_ATTR_NHLEN_VPNV4
:
2222 stream_getl(s
); /* RD high */
2223 stream_getl(s
); /* RD low */
2225 * NOTE: intentional fall through
2226 * - for consistency in rx processing
2228 * The following comment is to signal GCC this intention
2229 * and suppress the warning
2232 case BGP_ATTR_NHLEN_IPV4
:
2233 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2234 /* Probably needed for RFC 2283 */
2235 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2236 memcpy(&attr
->nexthop
.s_addr
,
2237 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2239 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2240 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2241 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2242 stream_getl(s
); /* RD high */
2243 stream_getl(s
); /* RD low */
2245 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2246 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2247 if (!peer
->nexthop
.ifp
) {
2248 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2250 return BGP_ATTR_PARSE_WITHDRAW
;
2252 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2255 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2256 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2257 if (attr
->mp_nexthop_len
2258 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2259 stream_getl(s
); /* RD high */
2260 stream_getl(s
); /* RD low */
2262 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2263 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2264 if (!peer
->nexthop
.ifp
) {
2265 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",
2267 return BGP_ATTR_PARSE_WITHDRAW
;
2269 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2271 if (attr
->mp_nexthop_len
2272 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2273 stream_getl(s
); /* RD high */
2274 stream_getl(s
); /* RD low */
2276 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2277 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2278 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2280 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2281 peer
->host
, &attr
->mp_nexthop_global
,
2282 &attr
->mp_nexthop_local
);
2284 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2286 if (!peer
->nexthop
.ifp
) {
2287 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2289 return BGP_ATTR_PARSE_WITHDRAW
;
2291 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2294 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2295 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2296 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2300 zlog_info("%s: %s sent SNPA which couldn't be read",
2301 __func__
, peer
->host
);
2302 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2307 if ((val
= stream_getc(s
)))
2309 EC_BGP_DEFUNCT_SNPA_LEN
,
2310 "%s sent non-zero value, %u, for defunct SNPA-length field",
2314 /* must have nrli_len, what is left of the attribute */
2315 nlri_len
= LEN_LEFT
;
2316 if (nlri_len
> STREAM_READABLE(s
)) {
2317 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2318 __func__
, peer
->host
);
2319 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2323 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2324 __func__
, peer
->host
);
2326 mp_update
->afi
= afi
;
2327 mp_update
->safi
= safi
;
2328 return BGP_ATTR_PARSE_EOR
;
2331 mp_update
->afi
= afi
;
2332 mp_update
->safi
= safi
;
2333 mp_update
->nlri
= stream_pnt(s
);
2334 mp_update
->length
= nlri_len
;
2336 stream_forward_getp(s
, nlri_len
);
2338 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2340 return BGP_ATTR_PARSE_PROCEED
;
2344 /* Multiprotocol unreachable parse */
2345 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2346 struct bgp_nlri
*mp_withdraw
)
2351 iana_safi_t pkt_safi
;
2353 uint16_t withdraw_len
;
2354 struct peer
*const peer
= args
->peer
;
2355 struct attr
*const attr
= args
->attr
;
2356 const bgp_size_t length
= args
->length
;
2360 #define BGP_MP_UNREACH_MIN_SIZE 3
2361 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2362 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2364 pkt_afi
= stream_getw(s
);
2365 pkt_safi
= stream_getc(s
);
2367 /* Convert AFI, SAFI to internal values, check. */
2368 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2369 /* Log if AFI or SAFI is unrecognized. This is not an error
2371 * the attribute is otherwise malformed.
2373 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2375 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2376 peer
->host
, iana_afi2str(pkt_afi
),
2377 iana_safi2str(pkt_safi
));
2378 return BGP_ATTR_PARSE_ERROR
;
2381 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2383 mp_withdraw
->afi
= afi
;
2384 mp_withdraw
->safi
= safi
;
2385 mp_withdraw
->nlri
= stream_pnt(s
);
2386 mp_withdraw
->length
= withdraw_len
;
2388 stream_forward_getp(s
, withdraw_len
);
2390 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2392 return BGP_ATTR_PARSE_PROCEED
;
2395 /* Large Community attribute. */
2396 static enum bgp_attr_parse_ret
2397 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2399 struct peer
*const peer
= args
->peer
;
2400 struct attr
*const attr
= args
->attr
;
2401 const bgp_size_t length
= args
->length
;
2404 * Large community follows new attribute format.
2407 bgp_attr_set_lcommunity(attr
, NULL
);
2408 /* Empty extcomm doesn't seem to be invalid per se */
2409 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2413 bgp_attr_set_lcommunity(
2414 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2415 /* XXX: fix ecommunity_parse to use stream API */
2416 stream_forward_getp(peer
->curr
, length
);
2418 if (!bgp_attr_get_lcommunity(attr
))
2419 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2422 return BGP_ATTR_PARSE_PROCEED
;
2425 /* Extended Community attribute. */
2426 static enum bgp_attr_parse_ret
2427 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2429 struct peer
*const peer
= args
->peer
;
2430 struct attr
*const attr
= args
->attr
;
2431 const bgp_size_t length
= args
->length
;
2434 struct ecommunity
*ecomm
;
2437 bgp_attr_set_ecommunity(attr
, NULL
);
2438 /* Empty extcomm doesn't seem to be invalid per se */
2439 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2443 ecomm
= ecommunity_parse(
2444 stream_pnt(peer
->curr
), length
,
2445 CHECK_FLAG(peer
->flags
,
2446 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2447 bgp_attr_set_ecommunity(attr
, ecomm
);
2448 /* XXX: fix ecommunity_parse to use stream API */
2449 stream_forward_getp(peer
->curr
, length
);
2451 /* The Extended Community attribute SHALL be considered malformed if
2452 * its length is not a non-zero multiple of 8.
2454 if (!bgp_attr_get_ecommunity(attr
))
2455 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2458 /* Extract DF election preference and mobility sequence number */
2459 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2461 /* Extract MAC mobility sequence number, if any. */
2462 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2463 attr
->sticky
= sticky
;
2465 /* Check if this is a Gateway MAC-IP advertisement */
2466 attr
->default_gw
= bgp_attr_default_gw(attr
);
2468 /* Handle scenario where router flag ecommunity is not
2469 * set but default gw ext community is present.
2470 * Use default gateway, set and propogate R-bit.
2472 if (attr
->default_gw
)
2473 attr
->router_flag
= 1;
2475 /* Check EVPN Neighbor advertisement flags, R-bit */
2476 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2478 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2480 /* Extract the Rmac, if any */
2481 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2482 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2483 && bgp_mac_exist(&attr
->rmac
))
2484 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2488 /* Get the tunnel type from encap extended community */
2489 bgp_attr_extcom_tunnel_type(attr
,
2490 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2492 /* Extract link bandwidth, if any. */
2493 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2496 return BGP_ATTR_PARSE_PROCEED
;
2499 /* IPv6 Extended Community attribute. */
2500 static enum bgp_attr_parse_ret
2501 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2503 struct peer
*const peer
= args
->peer
;
2504 struct attr
*const attr
= args
->attr
;
2505 const bgp_size_t length
= args
->length
;
2506 struct ecommunity
*ipv6_ecomm
= NULL
;
2509 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2510 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2514 ipv6_ecomm
= ecommunity_parse_ipv6(
2515 stream_pnt(peer
->curr
), length
,
2516 CHECK_FLAG(peer
->flags
,
2517 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2518 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2520 /* XXX: fix ecommunity_parse to use stream API */
2521 stream_forward_getp(peer
->curr
, length
);
2524 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2527 return BGP_ATTR_PARSE_PROCEED
;
2530 /* Parse Tunnel Encap attribute in an UPDATE */
2531 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2532 bgp_size_t length
, /* IN: attr's length field */
2533 struct attr
*attr
, /* IN: caller already allocated */
2534 uint8_t flag
, /* IN: attr's flags field */
2538 uint16_t tunneltype
= 0;
2540 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2542 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2543 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2545 "Tunnel Encap attribute flag isn't optional and transitive %d",
2547 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2548 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2553 if (BGP_ATTR_ENCAP
== type
) {
2554 /* read outer TLV type and length */
2555 uint16_t tlv_length
;
2559 "Tunnel Encap attribute not long enough to contain outer T,L");
2560 bgp_notify_send_with_data(
2561 peer
, BGP_NOTIFY_UPDATE_ERR
,
2562 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2565 tunneltype
= stream_getw(BGP_INPUT(peer
));
2566 tlv_length
= stream_getw(BGP_INPUT(peer
));
2569 if (tlv_length
!= length
) {
2570 zlog_info("%s: tlv_length(%d) != length(%d)",
2571 __func__
, tlv_length
, length
);
2575 while (length
>= 4) {
2576 uint16_t subtype
= 0;
2577 uint16_t sublength
= 0;
2578 struct bgp_attr_encap_subtlv
*tlv
;
2580 if (BGP_ATTR_ENCAP
== type
) {
2581 subtype
= stream_getc(BGP_INPUT(peer
));
2582 sublength
= stream_getc(BGP_INPUT(peer
));
2584 #ifdef ENABLE_BGP_VNC
2586 subtype
= stream_getw(BGP_INPUT(peer
));
2587 sublength
= stream_getw(BGP_INPUT(peer
));
2592 if (sublength
> length
) {
2594 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2596 bgp_notify_send_with_data(
2597 peer
, BGP_NOTIFY_UPDATE_ERR
,
2598 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2602 /* alloc and copy sub-tlv */
2603 /* TBD make sure these are freed when attributes are released */
2604 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2605 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2606 tlv
->type
= subtype
;
2607 tlv
->length
= sublength
;
2608 stream_get(tlv
->value
, peer
->curr
, sublength
);
2609 length
-= sublength
;
2611 /* attach tlv to encap chain */
2612 if (BGP_ATTR_ENCAP
== type
) {
2613 struct bgp_attr_encap_subtlv
*stlv_last
;
2614 for (stlv_last
= attr
->encap_subtlvs
;
2615 stlv_last
&& stlv_last
->next
;
2616 stlv_last
= stlv_last
->next
)
2619 stlv_last
->next
= tlv
;
2621 attr
->encap_subtlvs
= tlv
;
2623 #ifdef ENABLE_BGP_VNC
2625 struct bgp_attr_encap_subtlv
*stlv_last
;
2626 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2627 bgp_attr_get_vnc_subtlvs(attr
);
2629 for (stlv_last
= vnc_subtlvs
;
2630 stlv_last
&& stlv_last
->next
;
2631 stlv_last
= stlv_last
->next
)
2634 stlv_last
->next
= tlv
;
2636 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2641 if (BGP_ATTR_ENCAP
== type
) {
2642 attr
->encap_tunneltype
= tunneltype
;
2646 /* spurious leftover data */
2648 "Tunnel Encap attribute length is bad: %d leftover octets",
2650 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2651 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2660 /* SRv6 Service Data Sub-Sub-TLV attribute
2661 * draft-ietf-bess-srv6-services-07
2663 static enum bgp_attr_parse_ret
2664 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2666 struct peer
*const peer
= args
->peer
;
2667 struct attr
*const attr
= args
->attr
;
2668 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2669 transposition_len
, transposition_offset
;
2671 size_t headersz
= sizeof(type
) + sizeof(length
);
2673 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2676 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2677 headersz
, STREAM_READABLE(peer
->curr
));
2678 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2682 type
= stream_getc(peer
->curr
);
2683 length
= stream_getw(peer
->curr
);
2685 if (STREAM_READABLE(peer
->curr
) < length
) {
2688 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2689 length
, STREAM_READABLE(peer
->curr
));
2690 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2694 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2697 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2698 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2700 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2704 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2705 loc_block_len
= stream_getc(peer
->curr
);
2706 loc_node_len
= stream_getc(peer
->curr
);
2707 func_len
= stream_getc(peer
->curr
);
2708 arg_len
= stream_getc(peer
->curr
);
2709 transposition_len
= stream_getc(peer
->curr
);
2710 transposition_offset
= stream_getc(peer
->curr
);
2712 /* Log SRv6 Service Data Sub-Sub-TLV */
2713 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2715 "%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",
2716 __func__
, loc_block_len
, loc_node_len
, func_len
,
2717 arg_len
, transposition_len
,
2718 transposition_offset
);
2721 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2722 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2723 attr
->srv6_l3vpn
->func_len
= func_len
;
2724 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2725 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2726 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2730 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2732 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2735 stream_forward_getp(peer
->curr
, length
);
2738 return BGP_ATTR_PARSE_PROCEED
;
2741 /* SRv6 Service Sub-TLV attribute
2742 * draft-ietf-bess-srv6-services-07
2744 static enum bgp_attr_parse_ret
2745 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2747 struct peer
*const peer
= args
->peer
;
2748 struct attr
*const attr
= args
->attr
;
2749 struct in6_addr ipv6_sid
;
2750 uint8_t type
, sid_flags
;
2751 uint16_t length
, endpoint_behavior
;
2752 size_t headersz
= sizeof(type
) + sizeof(length
);
2753 enum bgp_attr_parse_ret err
;
2755 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2758 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2759 headersz
, STREAM_READABLE(peer
->curr
));
2760 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2764 type
= stream_getc(peer
->curr
);
2765 length
= stream_getw(peer
->curr
);
2767 if (STREAM_READABLE(peer
->curr
) < length
) {
2770 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2771 length
, STREAM_READABLE(peer
->curr
));
2772 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2776 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2777 stream_getc(peer
->curr
);
2778 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2779 sid_flags
= stream_getc(peer
->curr
);
2780 endpoint_behavior
= stream_getw(peer
->curr
);
2781 stream_getc(peer
->curr
);
2783 /* Log SRv6 Service Sub-TLV */
2784 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
2786 "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2787 __func__
, &ipv6_sid
, sid_flags
,
2790 /* Configure from Info */
2791 if (attr
->srv6_l3vpn
) {
2792 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2793 "Prefix SID SRv6 L3VPN field repeated");
2794 return bgp_attr_malformed(
2795 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2797 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2798 sizeof(struct bgp_attr_srv6_l3vpn
));
2799 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2800 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2801 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2802 attr
->srv6_l3vpn
->loc_block_len
= 0;
2803 attr
->srv6_l3vpn
->loc_node_len
= 0;
2804 attr
->srv6_l3vpn
->func_len
= 0;
2805 attr
->srv6_l3vpn
->arg_len
= 0;
2806 attr
->srv6_l3vpn
->transposition_len
= 0;
2807 attr
->srv6_l3vpn
->transposition_offset
= 0;
2809 // Sub-Sub-TLV found
2810 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2811 err
= bgp_attr_srv6_service_data(args
);
2813 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2817 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2820 /* Placeholder code for unsupported type */
2822 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2824 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2827 stream_forward_getp(peer
->curr
, length
);
2830 return BGP_ATTR_PARSE_PROCEED
;
2834 * Read an individual SID value returning how much data we have read
2835 * Returns 0 if there was an error that needs to be passed up the stack
2837 static enum bgp_attr_parse_ret
2838 bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2839 struct bgp_attr_parser_args
*args
)
2841 struct peer
*const peer
= args
->peer
;
2842 struct attr
*const attr
= args
->attr
;
2843 uint32_t label_index
;
2844 struct in6_addr ipv6_sid
;
2846 uint32_t srgb_range
;
2848 uint8_t sid_type
, sid_flags
;
2850 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2851 if (STREAM_READABLE(peer
->curr
) < length
2852 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2853 flog_err(EC_BGP_ATTR_LEN
,
2854 "Prefix SID label index length is %hu instead of %u",
2855 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2856 return bgp_attr_malformed(args
,
2857 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2861 /* Ignore flags and reserved */
2862 stream_getc(peer
->curr
);
2863 stream_getw(peer
->curr
);
2865 /* Fetch the label index and see if it is valid. */
2866 label_index
= stream_getl(peer
->curr
);
2867 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2868 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2871 /* Store label index; subsequently, we'll check on
2873 attr
->label_index
= label_index
;
2876 /* Placeholder code for the IPv6 SID type */
2877 else if (type
== BGP_PREFIX_SID_IPV6
) {
2878 if (STREAM_READABLE(peer
->curr
) < length
2879 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2880 flog_err(EC_BGP_ATTR_LEN
,
2881 "Prefix SID IPv6 length is %hu instead of %u",
2882 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2883 return bgp_attr_malformed(args
,
2884 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2888 /* Ignore reserved */
2889 stream_getc(peer
->curr
);
2890 stream_getw(peer
->curr
);
2892 stream_get(&ipv6_sid
, peer
->curr
, 16);
2895 /* Placeholder code for the Originator SRGB type */
2896 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2898 * ietf-idr-bgp-prefix-sid-05:
2899 * Length is the total length of the value portion of the
2900 * TLV: 2 + multiple of 6.
2902 * peer->curr stream readp should be at the beginning of the 16
2903 * bit flag field at this point in the code.
2907 * Check that the TLV length field is sane: at least 2 bytes of
2908 * flag, and at least 1 SRGB (these are 6 bytes each)
2910 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2913 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2915 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2916 return bgp_attr_malformed(
2917 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2922 * Check that we actually have at least as much data as
2923 * specified by the length field
2925 if (STREAM_READABLE(peer
->curr
) < length
) {
2926 flog_err(EC_BGP_ATTR_LEN
,
2927 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2928 length
, STREAM_READABLE(peer
->curr
));
2929 return bgp_attr_malformed(
2930 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2935 * Check that the portion of the TLV containing the sequence of
2936 * SRGBs corresponds to a multiple of the SRGB size; to get
2937 * that length, we skip the 16 bit flags field
2939 stream_getw(peer
->curr
);
2941 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2944 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2945 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2946 return bgp_attr_malformed(
2947 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2951 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2953 for (int i
= 0; i
< srgb_count
; i
++) {
2954 stream_get(&srgb_base
, peer
->curr
, 3);
2955 stream_get(&srgb_range
, peer
->curr
, 3);
2959 /* Placeholder code for the VPN-SID Service type */
2960 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2961 if (STREAM_READABLE(peer
->curr
) < length
2962 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2963 flog_err(EC_BGP_ATTR_LEN
,
2964 "Prefix SID VPN SID length is %hu instead of %u",
2965 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2966 return bgp_attr_malformed(args
,
2967 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2971 /* Parse VPN-SID Sub-TLV */
2972 stream_getc(peer
->curr
); /* reserved */
2973 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2974 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2975 stream_get(&ipv6_sid
, peer
->curr
,
2976 sizeof(ipv6_sid
)); /* sid_value */
2978 /* Log VPN-SID Sub-TLV */
2979 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
2981 "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
2982 __func__
, &ipv6_sid
, sid_type
, sid_flags
);
2984 /* Configure from Info */
2985 if (attr
->srv6_vpn
) {
2986 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2987 "Prefix SID SRv6 VPN field repeated");
2988 return bgp_attr_malformed(
2989 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2991 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2992 sizeof(struct bgp_attr_srv6_vpn
));
2993 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2994 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2995 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2998 /* Placeholder code for the SRv6 L3 Service type */
2999 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
3000 if (STREAM_READABLE(peer
->curr
) < length
) {
3003 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
3004 length
, STREAM_READABLE(peer
->curr
));
3005 return bgp_attr_malformed(args
,
3006 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3010 /* ignore reserved */
3011 stream_getc(peer
->curr
);
3013 return bgp_attr_srv6_service(args
);
3016 /* Placeholder code for Unsupported TLV */
3019 if (STREAM_READABLE(peer
->curr
) < length
) {
3022 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
3023 length
, STREAM_READABLE(peer
->curr
));
3024 return bgp_attr_malformed(
3025 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3029 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3031 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3034 stream_forward_getp(peer
->curr
, length
);
3037 return BGP_ATTR_PARSE_PROCEED
;
3040 /* Prefix SID attribute
3041 * draft-ietf-idr-bgp-prefix-sid-05
3043 enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
3045 struct peer
*const peer
= args
->peer
;
3046 struct attr
*const attr
= args
->attr
;
3047 enum bgp_attr_parse_ret ret
;
3049 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3053 size_t headersz
= sizeof(type
) + sizeof(length
);
3054 size_t psid_parsed_length
= 0;
3056 while (STREAM_READABLE(peer
->curr
) > 0
3057 && psid_parsed_length
< args
->length
) {
3059 if (STREAM_READABLE(peer
->curr
) < headersz
) {
3062 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3063 headersz
, STREAM_READABLE(peer
->curr
));
3064 return bgp_attr_malformed(
3065 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3069 type
= stream_getc(peer
->curr
);
3070 length
= stream_getw(peer
->curr
);
3072 if (STREAM_READABLE(peer
->curr
) < length
) {
3075 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3076 length
, STREAM_READABLE(peer
->curr
));
3077 return bgp_attr_malformed(args
,
3078 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3082 ret
= bgp_attr_psid_sub(type
, length
, args
);
3084 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3087 psid_parsed_length
+= length
+ headersz
;
3089 if (psid_parsed_length
> args
->length
) {
3092 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
3093 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
3094 return bgp_attr_malformed(
3095 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3100 return BGP_ATTR_PARSE_PROCEED
;
3103 /* PMSI tunnel attribute (RFC 6514)
3104 * Basic validation checks done here.
3106 static enum bgp_attr_parse_ret
3107 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
3109 struct peer
*const peer
= args
->peer
;
3110 struct attr
*const attr
= args
->attr
;
3111 const bgp_size_t length
= args
->length
;
3113 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
3115 /* Verify that the receiver is expecting "ingress replication" as we
3116 * can only support that.
3118 if (length
< attr_parse_len
) {
3119 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
3121 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3124 stream_getc(peer
->curr
); /* Flags */
3125 tnl_type
= stream_getc(peer
->curr
);
3126 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3127 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3128 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3129 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3132 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3134 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3135 "Bad PMSI tunnel attribute length %d for IR",
3137 return bgp_attr_malformed(
3138 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3143 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3144 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3145 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3147 /* Forward read pointer of input stream. */
3148 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3150 return BGP_ATTR_PARSE_PROCEED
;
3153 /* AIGP attribute (rfc7311) */
3154 static enum bgp_attr_parse_ret
bgp_attr_aigp(struct bgp_attr_parser_args
*args
)
3156 struct peer
*const peer
= args
->peer
;
3157 struct attr
*const attr
= args
->attr
;
3158 const bgp_size_t length
= args
->length
;
3159 uint8_t *s
= stream_pnt(peer
->curr
);
3162 /* If an AIGP attribute is received on a BGP session for which
3163 * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3164 * as if it were an unrecognized non-transitive attribute.
3165 * That is, it "MUST be quietly ignored and not passed along to
3167 * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3168 * sessions between members of the same BGP Confederation,
3169 * the default value of AIGP_SESSION SHOULD be "enabled".
3171 if (peer
->sort
== BGP_PEER_EBGP
&&
3172 !CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
)) {
3174 "%pBP received AIGP attribute, but eBGP peer do not support it",
3179 if (!bgp_attr_aigp_valid(s
, length
))
3182 /* Extract AIGP Metric TLV */
3183 if (bgp_attr_aigp_get_tlv_metric(s
, length
, &aigp
))
3184 bgp_attr_set_aigp_metric(attr
, aigp
);
3187 stream_forward_getp(peer
->curr
, length
);
3189 return BGP_ATTR_PARSE_PROCEED
;
3192 /* OTC attribute. */
3193 static enum bgp_attr_parse_ret
bgp_attr_otc(struct bgp_attr_parser_args
*args
)
3195 struct peer
*const peer
= args
->peer
;
3196 struct attr
*const attr
= args
->attr
;
3197 const bgp_size_t length
= args
->length
;
3201 flog_err(EC_BGP_ATTR_LEN
, "OTC attribute length isn't 4 [%u]",
3203 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3207 attr
->otc
= stream_getl(peer
->curr
);
3209 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "OTC attribute value is 0");
3210 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
3214 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
3216 return BGP_ATTR_PARSE_PROCEED
;
3219 /* BGP unknown attribute treatment. */
3220 static enum bgp_attr_parse_ret
3221 bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3223 bgp_size_t total
= args
->total
;
3224 struct transit
*transit
;
3225 struct peer
*const peer
= args
->peer
;
3226 struct attr
*const attr
= args
->attr
;
3227 uint8_t *const startp
= args
->startp
;
3228 const uint8_t type
= args
->type
;
3229 const uint8_t flag
= args
->flags
;
3230 const bgp_size_t length
= args
->length
;
3232 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3234 "%s Unknown attribute is received (type %d, length %d)",
3235 peer
->host
, type
, length
);
3237 /* Forward read pointer of input stream. */
3238 stream_forward_getp(peer
->curr
, length
);
3240 /* If any of the mandatory well-known attributes are not recognized,
3241 then the Error Subcode is set to Unrecognized Well-known
3242 Attribute. The Data field contains the unrecognized attribute
3243 (type, length and value). */
3244 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3245 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3249 /* Unrecognized non-transitive optional attributes must be quietly
3250 ignored and not passed along to other BGP peers. */
3251 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3252 return BGP_ATTR_PARSE_PROCEED
;
3254 /* If a path with recognized transitive optional attribute is
3255 accepted and passed along to other BGP peers and the Partial bit
3256 in the Attribute Flags octet is set to 1 by some previous AS, it
3257 is not set back to 0 by the current AS. */
3258 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3260 /* Store transitive attribute to the end of attr->transit. */
3261 transit
= bgp_attr_get_transit(attr
);
3263 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3265 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3266 transit
->length
+ total
);
3268 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3269 transit
->length
+= total
;
3270 bgp_attr_set_transit(attr
, transit
);
3272 return BGP_ATTR_PARSE_PROCEED
;
3275 /* Well-known attribute check. */
3276 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3280 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3282 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3283 return BGP_ATTR_PARSE_PROCEED
;
3285 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3286 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3287 are present, it should. Check for any other attribute being present
3290 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3291 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3292 return BGP_ATTR_PARSE_PROCEED
;
3294 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3295 type
= BGP_ATTR_ORIGIN
;
3297 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3298 type
= BGP_ATTR_AS_PATH
;
3300 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3302 * NLRI is empty. We can't easily check NLRI empty here though.
3304 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3305 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3306 type
= BGP_ATTR_NEXT_HOP
;
3308 if (peer
->sort
== BGP_PEER_IBGP
3309 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3310 type
= BGP_ATTR_LOCAL_PREF
;
3312 /* If any of the well-known mandatory attributes are not present
3313 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3316 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3317 "%s Missing well-known attribute %s.", peer
->host
,
3318 lookup_msg(attr_str
, type
, NULL
));
3319 return BGP_ATTR_PARSE_WITHDRAW
;
3321 return BGP_ATTR_PARSE_PROCEED
;
3324 /* Read attribute of update packet. This function is called from
3325 bgp_update_receive() in bgp_packet.c. */
3326 enum bgp_attr_parse_ret
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3328 struct bgp_nlri
*mp_update
,
3329 struct bgp_nlri
*mp_withdraw
)
3331 enum bgp_attr_parse_ret ret
;
3335 uint8_t *startp
, *endp
;
3337 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3338 /* we need the as4_path only until we have synthesized the as_path with
3340 /* same goes for as4_aggregator */
3341 struct aspath
*as4_path
= NULL
;
3342 as_t as4_aggregator
= 0;
3343 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3344 struct transit
*transit
;
3346 /* Initialize bitmap. */
3347 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3349 /* End pointer of BGP attribute. */
3350 endp
= BGP_INPUT_PNT(peer
) + size
;
3352 /* Get attributes to the end of attribute length. */
3353 while (BGP_INPUT_PNT(peer
) < endp
) {
3354 /* Check remaining length check.*/
3355 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3356 /* XXX warning: long int format, int arg (arg 5) */
3358 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3359 "%s: error BGP attribute length %lu is smaller than min len",
3361 (unsigned long)(endp
3362 - stream_pnt(BGP_INPUT(peer
))));
3364 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3365 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3366 ret
= BGP_ATTR_PARSE_ERROR
;
3370 /* Fetch attribute flag and type. */
3371 startp
= BGP_INPUT_PNT(peer
);
3372 /* "The lower-order four bits of the Attribute Flags octet are
3373 unused. They MUST be zero when sent and MUST be ignored when
3375 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3376 type
= stream_getc(BGP_INPUT(peer
));
3378 /* Check whether Extended-Length applies and is in bounds */
3379 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3380 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3382 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3383 "%s: Extended length set, but just %lu bytes of attr header",
3385 (unsigned long)(endp
3386 - stream_pnt(BGP_INPUT(peer
))));
3388 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3389 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3390 ret
= BGP_ATTR_PARSE_ERROR
;
3394 /* Check extended attribue length bit. */
3395 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3396 length
= stream_getw(BGP_INPUT(peer
));
3398 length
= stream_getc(BGP_INPUT(peer
));
3400 /* If any attribute appears more than once in the UPDATE
3401 message, then the Error Subcode is set to Malformed Attribute
3404 if (CHECK_BITMAP(seen
, type
)) {
3406 EC_BGP_ATTRIBUTE_REPEATED
,
3407 "%s: error BGP attribute type %d appears twice in a message",
3410 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3411 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3412 ret
= BGP_ATTR_PARSE_ERROR
;
3416 /* Set type to bitmap to check duplicate attribute. `type' is
3417 unsigned char so it never overflow bitmap range. */
3419 SET_BITMAP(seen
, type
);
3421 /* Overflow check. */
3422 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3424 if (attr_endp
> endp
) {
3426 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3427 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3428 peer
->host
, type
, length
, size
, attr_endp
,
3432 * If any recognized attribute has an Attribute
3433 * Length that conflicts with the expected length
3434 * (based on the attribute type code), then the
3435 * Error Subcode MUST be set to Attribute Length
3436 * Error. The Data field MUST contain the erroneous
3437 * attribute (type, length, and value).
3439 * We do not currently have a good way to determine the
3440 * length of the attribute independent of the length
3441 * received in the message. Instead we send the
3442 * minimum between the amount of data we have and the
3443 * amount specified by the attribute length field.
3445 * Instead of directly passing in the packet buffer and
3446 * offset we use the stream_get* functions to read into
3447 * a stack buffer, since they perform bounds checking
3448 * and we are working with untrusted data.
3450 unsigned char ndata
[peer
->max_packet_size
];
3451 memset(ndata
, 0x00, sizeof(ndata
));
3453 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3454 /* Rewind to end of flag field */
3455 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3457 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3459 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3461 size_t atl
= attr_endp
- startp
;
3462 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3463 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3465 bgp_notify_send_with_data(
3466 peer
, BGP_NOTIFY_UPDATE_ERR
,
3467 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3470 ret
= BGP_ATTR_PARSE_ERROR
;
3474 struct bgp_attr_parser_args attr_args
= {
3481 .total
= attr_endp
- startp
,
3485 /* If any recognized attribute has Attribute Flags that conflict
3486 with the Attribute Type Code, then the Error Subcode is set
3488 Attribute Flags Error. The Data field contains the erroneous
3489 attribute (type, length and value). */
3490 if (bgp_attr_flag_invalid(&attr_args
)) {
3491 ret
= bgp_attr_malformed(
3492 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3494 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3499 /* OK check attribute and store it's value. */
3501 case BGP_ATTR_ORIGIN
:
3502 ret
= bgp_attr_origin(&attr_args
);
3504 case BGP_ATTR_AS_PATH
:
3505 ret
= bgp_attr_aspath(&attr_args
);
3507 case BGP_ATTR_AS4_PATH
:
3508 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3510 case BGP_ATTR_NEXT_HOP
:
3511 ret
= bgp_attr_nexthop(&attr_args
);
3513 case BGP_ATTR_MULTI_EXIT_DISC
:
3514 ret
= bgp_attr_med(&attr_args
);
3516 case BGP_ATTR_LOCAL_PREF
:
3517 ret
= bgp_attr_local_pref(&attr_args
);
3519 case BGP_ATTR_ATOMIC_AGGREGATE
:
3520 ret
= bgp_attr_atomic(&attr_args
);
3522 case BGP_ATTR_AGGREGATOR
:
3523 ret
= bgp_attr_aggregator(&attr_args
);
3525 case BGP_ATTR_AS4_AGGREGATOR
:
3526 ret
= bgp_attr_as4_aggregator(&attr_args
,
3528 &as4_aggregator_addr
);
3530 case BGP_ATTR_COMMUNITIES
:
3531 ret
= bgp_attr_community(&attr_args
);
3533 case BGP_ATTR_LARGE_COMMUNITIES
:
3534 ret
= bgp_attr_large_community(&attr_args
);
3536 case BGP_ATTR_ORIGINATOR_ID
:
3537 ret
= bgp_attr_originator_id(&attr_args
);
3539 case BGP_ATTR_CLUSTER_LIST
:
3540 ret
= bgp_attr_cluster_list(&attr_args
);
3542 case BGP_ATTR_MP_REACH_NLRI
:
3543 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3545 case BGP_ATTR_MP_UNREACH_NLRI
:
3546 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3548 case BGP_ATTR_EXT_COMMUNITIES
:
3549 ret
= bgp_attr_ext_communities(&attr_args
);
3551 #ifdef ENABLE_BGP_VNC_ATTR
3554 case BGP_ATTR_ENCAP
:
3555 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3558 case BGP_ATTR_PREFIX_SID
:
3559 ret
= bgp_attr_prefix_sid(&attr_args
);
3561 case BGP_ATTR_PMSI_TUNNEL
:
3562 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3564 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3565 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3568 ret
= bgp_attr_otc(&attr_args
);
3571 ret
= bgp_attr_aigp(&attr_args
);
3574 ret
= bgp_attr_unknown(&attr_args
);
3578 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3579 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3580 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3581 ret
= BGP_ATTR_PARSE_ERROR
;
3585 if (ret
== BGP_ATTR_PARSE_EOR
) {
3589 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3590 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3591 "%s: Attribute %s, parse error", peer
->host
,
3592 lookup_msg(attr_str
, type
, NULL
));
3595 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3597 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3598 "%s: Attribute %s, parse error - treating as withdrawal",
3599 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3603 /* Check the fetched length. */
3604 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3605 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3606 "%s: BGP attribute %s, fetch error",
3607 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3608 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3609 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3610 ret
= BGP_ATTR_PARSE_ERROR
;
3616 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3617 * About Prefix-SID path attribute,
3618 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3619 * may only appear in a BGP Prefix-SID attribute attached to
3620 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3621 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3623 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3624 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3626 /* Check final read pointer is same as end pointer. */
3627 if (BGP_INPUT_PNT(peer
) != endp
) {
3628 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3629 "%s: BGP attribute %s, length mismatch", peer
->host
,
3630 lookup_msg(attr_str
, type
, NULL
));
3631 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3632 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3634 ret
= BGP_ATTR_PARSE_ERROR
;
3639 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3640 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3641 * This is implemented below and will result in a NOTIFICATION. If the
3642 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3643 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3644 * message SHOULD NOT be sent. This is implemented elsewhere.
3646 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3647 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3648 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3649 * speaker that receives the message SHOULD ignore this attribute.
3651 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3652 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3653 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3654 ret
= BGP_ATTR_PARSE_ERROR
;
3659 /* Check all mandatory well-known attributes are present */
3660 ret
= bgp_attr_check(peer
, attr
);
3665 * At this place we can see whether we got AS4_PATH and/or
3666 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3667 * We can not do this before we've read all attributes because
3668 * the as4 handling does not say whether AS4_PATH has to be sent
3669 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3670 * in relationship to AGGREGATOR.
3671 * So, to be defensive, we are not relying on any order and read
3672 * all attributes first, including these 32bit ones, and now,
3673 * afterwards, we look what and if something is to be done for as4.
3675 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3678 /* actually... this doesn't ever return failure currently, but
3679 * better safe than sorry */
3680 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3681 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3682 &as4_aggregator_addr
)) {
3683 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3684 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3685 ret
= BGP_ATTR_PARSE_ERROR
;
3690 * Finally do the checks on the aspath we did not do yet
3691 * because we waited for a potentially synthesized aspath.
3693 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3694 ret
= bgp_attr_aspath_check(peer
, attr
);
3695 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3699 ret
= BGP_ATTR_PARSE_PROCEED
;
3703 * At this stage, we have done all fiddling with as4, and the
3704 * resulting info is in attr->aggregator resp. attr->aspath so
3705 * we can chuck as4_aggregator and as4_path alltogether in order
3709 * unintern - it is in the hash
3710 * The flag that we got this is still there, but that
3711 * does not do any trouble
3713 aspath_unintern(&as4_path
);
3715 transit
= bgp_attr_get_transit(attr
);
3716 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3717 /* Finally intern unknown attribute. */
3719 bgp_attr_set_transit(attr
, transit_intern(transit
));
3720 if (attr
->encap_subtlvs
)
3721 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3723 #ifdef ENABLE_BGP_VNC
3724 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3725 bgp_attr_get_vnc_subtlvs(attr
);
3728 bgp_attr_set_vnc_subtlvs(
3730 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3734 transit_free(transit
);
3735 bgp_attr_set_transit(attr
, NULL
);
3738 bgp_attr_flush_encap(attr
);
3742 transit
= bgp_attr_get_transit(attr
);
3744 assert(transit
->refcnt
> 0);
3745 if (attr
->encap_subtlvs
)
3746 assert(attr
->encap_subtlvs
->refcnt
> 0);
3747 #ifdef ENABLE_BGP_VNC
3748 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3749 bgp_attr_get_vnc_subtlvs(attr
);
3752 assert(vnc_subtlvs
->refcnt
> 0);
3759 * Extract the tunnel type from extended community
3761 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3762 bgp_encap_types
*tunnel_type
)
3764 struct ecommunity
*ecom
;
3770 ecom
= bgp_attr_get_ecommunity(attr
);
3771 if (!ecom
|| !ecom
->size
)
3774 for (i
= 0; i
< ecom
->size
; i
++) {
3776 uint8_t type
, sub_type
;
3778 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3781 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3782 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3784 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3791 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3792 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3796 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
3797 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
3800 /* Set extended bit always to encode the attribute length as 2 bytes */
3801 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3802 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3803 sizep
= stream_get_endp(s
);
3804 stream_putw(s
, 0); /* Marker: Attribute length. */
3807 /* Convert AFI, SAFI to values for packet. */
3808 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3810 stream_putw(s
, pkt_afi
); /* AFI */
3811 stream_putc(s
, pkt_safi
); /* SAFI */
3815 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3816 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3817 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3818 else if (safi
== SAFI_FLOWSPEC
)
3821 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3824 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3829 case SAFI_MULTICAST
:
3830 case SAFI_LABELED_UNICAST
:
3832 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3836 stream_putl(s
, 0); /* RD = 0, per RFC */
3838 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3843 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3846 if (attr
->mp_nexthop_len
== 0)
3847 stream_putc(s
, 0); /* no nexthop for flowspec */
3849 stream_putc(s
, attr
->mp_nexthop_len
);
3850 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3859 case SAFI_MULTICAST
:
3860 case SAFI_LABELED_UNICAST
:
3862 if (attr
->mp_nexthop_len
3863 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3865 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3866 stream_put(s
, &attr
->mp_nexthop_global
,
3868 stream_put(s
, &attr
->mp_nexthop_local
,
3871 stream_putc(s
, IPV6_MAX_BYTELEN
);
3872 stream_put(s
, &attr
->mp_nexthop_global
,
3876 case SAFI_MPLS_VPN
: {
3877 if (attr
->mp_nexthop_len
3878 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3880 stream_putl(s
, 0); /* RD = 0, per RFC */
3882 stream_put(s
, &attr
->mp_nexthop_global
,
3884 stream_putl(s
, 0); /* RD = 0, per RFC */
3886 stream_put(s
, &attr
->mp_nexthop_local
,
3890 stream_putl(s
, 0); /* RD = 0, per RFC */
3892 stream_put(s
, &attr
->mp_nexthop_global
,
3897 stream_putc(s
, IPV6_MAX_BYTELEN
);
3898 stream_put(s
, &attr
->mp_nexthop_global
,
3902 stream_putc(s
, 0); /* no nexthop for flowspec */
3908 if (safi
!= SAFI_FLOWSPEC
)
3910 EC_BGP_ATTR_NH_SEND_LEN
,
3911 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3912 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3921 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3922 const struct prefix
*p
,
3923 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3924 uint32_t num_labels
, bool addpath_capable
,
3925 uint32_t addpath_tx_id
, struct attr
*attr
)
3927 if (safi
== SAFI_MPLS_VPN
) {
3928 if (addpath_capable
)
3929 stream_putl(s
, addpath_tx_id
);
3930 /* Label, RD, Prefix write. */
3931 stream_putc(s
, p
->prefixlen
+ 88);
3932 stream_put(s
, label
, BGP_LABEL_BYTES
);
3933 stream_put(s
, prd
->val
, 8);
3934 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3935 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3936 /* EVPN prefix - contents depend on type */
3937 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3938 addpath_capable
, addpath_tx_id
);
3939 } else if (safi
== SAFI_LABELED_UNICAST
) {
3940 /* Prefix write with label. */
3941 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3943 } else if (safi
== SAFI_FLOWSPEC
) {
3944 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3945 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3946 p
->u
.prefix_flowspec
.prefixlen
);
3948 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
3951 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3952 const struct prefix
*p
)
3954 int size
= PSIZE(p
->prefixlen
);
3955 if (safi
== SAFI_MPLS_VPN
)
3957 else if (safi
== SAFI_LABELED_UNICAST
)
3958 size
+= BGP_LABEL_BYTES
;
3959 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3960 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3966 * Encodes the tunnel encapsulation attribute,
3967 * and with ENABLE_BGP_VNC the VNC attribute which uses
3968 * almost the same TLV format
3970 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3971 struct stream
*s
, struct attr
*attr
,
3974 unsigned int attrlenfield
= 0;
3975 unsigned int attrhdrlen
= 0;
3976 struct bgp_attr_encap_subtlv
*subtlvs
;
3977 struct bgp_attr_encap_subtlv
*st
;
3978 const char *attrname
;
3980 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3981 && (!attr
->encap_tunneltype
3982 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3986 case BGP_ATTR_ENCAP
:
3987 attrname
= "Tunnel Encap";
3988 subtlvs
= attr
->encap_subtlvs
;
3989 if (subtlvs
== NULL
) /* nothing to do */
3992 * The tunnel encap attr has an "outer" tlv.
3994 * L = total length of subtlvs,
3995 * V = concatenated subtlvs.
3997 attrlenfield
= 2 + 2; /* T + L */
3998 attrhdrlen
= 1 + 1; /* subTLV T + L */
4001 #ifdef ENABLE_BGP_VNC_ATTR
4004 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
4005 if (subtlvs
== NULL
) /* nothing to do */
4007 attrlenfield
= 0; /* no outer T + L */
4008 attrhdrlen
= 2 + 2; /* subTLV T + L */
4016 /* compute attr length */
4017 for (st
= subtlvs
; st
; st
= st
->next
) {
4018 attrlenfield
+= (attrhdrlen
+ st
->length
);
4021 if (attrlenfield
> 0xffff) {
4022 zlog_info("%s attribute is too long (length=%d), can't send it",
4023 attrname
, attrlenfield
);
4027 if (attrlenfield
> 0xff) {
4028 /* 2-octet length field */
4030 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4031 | BGP_ATTR_FLAG_EXTLEN
);
4032 stream_putc(s
, attrtype
);
4033 stream_putw(s
, attrlenfield
& 0xffff);
4035 /* 1-octet length field */
4036 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
4037 stream_putc(s
, attrtype
);
4038 stream_putc(s
, attrlenfield
& 0xff);
4041 if (attrtype
== BGP_ATTR_ENCAP
) {
4042 /* write outer T+L */
4043 stream_putw(s
, attr
->encap_tunneltype
);
4044 stream_putw(s
, attrlenfield
- 4);
4047 /* write each sub-tlv */
4048 for (st
= subtlvs
; st
; st
= st
->next
) {
4049 if (attrtype
== BGP_ATTR_ENCAP
) {
4050 stream_putc(s
, st
->type
);
4051 stream_putc(s
, st
->length
);
4052 #ifdef ENABLE_BGP_VNC
4054 stream_putw(s
, st
->type
);
4055 stream_putw(s
, st
->length
);
4058 stream_put(s
, st
->value
, st
->length
);
4062 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
4064 /* Set MP attribute length. Don't count the (2) bytes used to encode
4066 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
4069 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
4071 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
4072 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
4073 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4074 PEER_FLAG_REMOVE_PRIVATE_AS
)
4075 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4076 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
4077 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4078 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
4079 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4080 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
4085 /* Make attribute packet. */
4086 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
4087 struct stream
*s
, struct attr
*attr
,
4088 struct bpacket_attr_vec_arr
*vecarr
,
4089 struct prefix
*p
, afi_t afi
, safi_t safi
,
4090 struct peer
*from
, struct prefix_rd
*prd
,
4091 mpls_label_t
*label
, uint32_t num_labels
,
4092 bool addpath_capable
, uint32_t addpath_tx_id
,
4093 struct bgp_path_info
*bpi
)
4096 size_t aspath_sizep
;
4097 struct aspath
*aspath
;
4098 int send_as4_path
= 0;
4099 int send_as4_aggregator
= 0;
4100 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
4101 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
4106 /* Remember current pointer. */
4107 cp
= stream_get_endp(s
);
4110 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
4111 && !peer_cap_enhe(peer
, afi
, safi
))) {
4112 size_t mpattrlen_pos
= 0;
4114 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
4116 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
4117 num_labels
, addpath_capable
,
4118 addpath_tx_id
, attr
);
4119 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
4122 /* Origin attribute. */
4123 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4124 stream_putc(s
, BGP_ATTR_ORIGIN
);
4126 stream_putc(s
, attr
->origin
);
4128 /* AS path attribute. */
4130 /* If remote-peer is EBGP */
4131 if (peer
->sort
== BGP_PEER_EBGP
4132 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4133 PEER_FLAG_AS_PATH_UNCHANGED
)
4134 || attr
->aspath
->segments
== NULL
)
4135 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4136 PEER_FLAG_RSERVER_CLIENT
))) {
4137 aspath
= aspath_dup(attr
->aspath
);
4139 /* Even though we may not be configured for confederations we
4141 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4142 aspath
= aspath_delete_confed_seq(aspath
);
4144 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
4145 /* Stuff our path CONFED_ID on the front */
4146 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
4148 if (peer
->change_local_as
) {
4149 /* If replace-as is specified, we only use the
4150 change_local_as when
4151 advertising routes. */
4152 if (!CHECK_FLAG(peer
->flags
,
4153 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
4154 if (bgp_append_local_as(peer
, afi
,
4156 aspath
= aspath_add_seq(
4157 aspath
, peer
->local_as
);
4158 aspath
= aspath_add_seq(aspath
,
4159 peer
->change_local_as
);
4161 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
4164 } else if (peer
->sort
== BGP_PEER_CONFED
) {
4165 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4167 aspath
= aspath_dup(attr
->aspath
);
4168 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
4170 aspath
= attr
->aspath
;
4172 /* If peer is not AS4 capable, then:
4173 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4174 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4176 * types are in it (i.e. exclude them if they are there)
4177 * AND do this only if there is at least one asnum > 65535 in the
4179 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4181 * all ASnums > 65535 to BGP_AS_TRANS
4184 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4185 stream_putc(s
, BGP_ATTR_AS_PATH
);
4186 aspath_sizep
= stream_get_endp(s
);
4188 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4190 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4193 if (!use32bit
&& aspath_has_as4(aspath
))
4195 1; /* we'll do this later, at the correct place */
4197 /* Nexthop attribute. */
4198 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4199 && !peer_cap_enhe(peer
, afi
, safi
)) {
4200 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4202 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4203 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4204 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4205 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4208 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4209 } else if (peer_cap_enhe(from
, afi
, safi
)
4210 || (nh_afi
== AFI_IP6
)) {
4212 * Likely this is the case when an IPv4 prefix was
4213 * received with Extended Next-hop capability in this
4214 * or another vrf and is now being advertised to
4215 * non-ENHE peers. Since peer_cap_enhe only checks
4216 * peers in this vrf, also check the nh_afi to catch
4217 * the case where the originator was in another vrf.
4218 * Setting the mandatory (ipv4) next-hop attribute here
4219 * to enable implicit next-hop self with correct A-F
4220 * (ipv4 address family).
4222 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4223 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4224 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4227 stream_put_ipv4(s
, 0);
4231 /* MED attribute. */
4232 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4233 || bgp
->maxmed_active
) {
4234 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4235 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4237 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4241 /* Local preference. */
4242 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4243 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4244 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4246 stream_putl(s
, attr
->local_pref
);
4249 /* Atomic aggregate. */
4250 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4251 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4252 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4257 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4258 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4259 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4260 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4263 /* AS4 capable peer */
4265 stream_putl(s
, attr
->aggregator_as
);
4267 /* 2-byte AS peer */
4270 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4272 if (attr
->aggregator_as
> UINT16_MAX
) {
4273 stream_putw(s
, BGP_AS_TRANS
);
4275 /* we have to send AS4_AGGREGATOR, too.
4276 * we'll do that later in order to send
4277 * attributes in ascending
4280 send_as4_aggregator
= 1;
4282 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4284 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4287 /* Community attribute. */
4288 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4289 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4290 struct community
*comm
= NULL
;
4292 comm
= bgp_attr_get_community(attr
);
4293 if (comm
->size
* 4 > 255) {
4295 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4296 | BGP_ATTR_FLAG_EXTLEN
);
4297 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4298 stream_putw(s
, comm
->size
* 4);
4301 BGP_ATTR_FLAG_OPTIONAL
4302 | BGP_ATTR_FLAG_TRANS
);
4303 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4304 stream_putc(s
, comm
->size
* 4);
4306 stream_put(s
, comm
->val
, comm
->size
* 4);
4310 * Large Community attribute.
4312 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4313 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4314 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4315 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4317 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4318 | BGP_ATTR_FLAG_EXTLEN
);
4319 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4321 lcom_length(bgp_attr_get_lcommunity(attr
)));
4324 BGP_ATTR_FLAG_OPTIONAL
4325 | BGP_ATTR_FLAG_TRANS
);
4326 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4328 lcom_length(bgp_attr_get_lcommunity(attr
)));
4330 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4331 lcom_length(bgp_attr_get_lcommunity(attr
)));
4334 /* Route Reflector. */
4335 if (peer
->sort
== BGP_PEER_IBGP
&& from
4336 && from
->sort
== BGP_PEER_IBGP
) {
4337 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4339 /* Originator ID. */
4340 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4341 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4344 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4345 stream_put_in_addr(s
, &attr
->originator_id
);
4347 stream_put_in_addr(s
, &from
->remote_id
);
4350 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4351 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4354 stream_putc(s
, cluster
->length
+ 4);
4355 /* If this peer configuration's parent BGP has
4357 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4358 stream_put_in_addr(s
, &bgp
->cluster_id
);
4360 stream_put_in_addr(s
, &bgp
->router_id
);
4361 stream_put(s
, cluster
->list
, cluster
->length
);
4364 /* If this peer configuration's parent BGP has
4366 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4367 stream_put_in_addr(s
, &bgp
->cluster_id
);
4369 stream_put_in_addr(s
, &bgp
->router_id
);
4373 /* Extended Communities attribute. */
4374 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4375 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4376 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4377 bool transparent
= CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4378 PEER_FLAG_RSERVER_CLIENT
) &&
4380 CHECK_FLAG(from
->af_flags
[afi
][safi
],
4381 PEER_FLAG_RSERVER_CLIENT
);
4383 if (peer
->sort
== BGP_PEER_IBGP
||
4384 peer
->sort
== BGP_PEER_CONFED
|| transparent
) {
4385 if (ecomm
->size
* 8 > 255) {
4387 BGP_ATTR_FLAG_OPTIONAL
4388 | BGP_ATTR_FLAG_TRANS
4389 | BGP_ATTR_FLAG_EXTLEN
);
4390 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4391 stream_putw(s
, ecomm
->size
* 8);
4394 BGP_ATTR_FLAG_OPTIONAL
4395 | BGP_ATTR_FLAG_TRANS
);
4396 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4397 stream_putc(s
, ecomm
->size
* 8);
4399 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4403 int ecom_tr_size
= 0;
4406 for (i
= 0; i
< ecomm
->size
; i
++) {
4407 pnt
= ecomm
->val
+ (i
* 8);
4410 if (CHECK_FLAG(tbit
,
4411 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4418 if (ecom_tr_size
* 8 > 255) {
4421 BGP_ATTR_FLAG_OPTIONAL
4422 | BGP_ATTR_FLAG_TRANS
4423 | BGP_ATTR_FLAG_EXTLEN
);
4425 BGP_ATTR_EXT_COMMUNITIES
);
4426 stream_putw(s
, ecom_tr_size
* 8);
4430 BGP_ATTR_FLAG_OPTIONAL
4431 | BGP_ATTR_FLAG_TRANS
);
4433 BGP_ATTR_EXT_COMMUNITIES
);
4434 stream_putc(s
, ecom_tr_size
* 8);
4437 for (i
= 0; i
< ecomm
->size
; i
++) {
4438 pnt
= ecomm
->val
+ (i
* 8);
4443 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4446 stream_put(s
, pnt
, 8);
4452 /* Label index attribute. */
4453 if (safi
== SAFI_LABELED_UNICAST
) {
4454 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4455 uint32_t label_index
;
4457 label_index
= attr
->label_index
;
4459 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4461 BGP_ATTR_FLAG_OPTIONAL
4462 | BGP_ATTR_FLAG_TRANS
);
4463 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4465 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4467 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4468 stream_putc(s
, 0); // reserved
4469 stream_putw(s
, 0); // flags
4470 stream_putl(s
, label_index
);
4475 /* SRv6 Service Information Attribute. */
4476 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4477 if (attr
->srv6_l3vpn
) {
4478 uint8_t subtlv_len
=
4479 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4481 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4482 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4483 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4484 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4485 | BGP_ATTR_FLAG_TRANS
);
4486 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4487 stream_putc(s
, attr_len
);
4488 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4489 stream_putw(s
, tlv_len
);
4490 stream_putc(s
, 0); /* reserved */
4491 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4492 stream_putw(s
, subtlv_len
);
4493 stream_putc(s
, 0); /* reserved */
4494 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4495 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4496 stream_putc(s
, 0); /* sid_flags */
4499 ->endpoint_behavior
); /* endpoint */
4500 stream_putc(s
, 0); /* reserved */
4503 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4506 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4507 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4508 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4509 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4510 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4511 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4512 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4513 } else if (attr
->srv6_vpn
) {
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
, 22); /* tlv len */
4518 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4519 stream_putw(s
, 0x13); /* tlv len */
4520 stream_putc(s
, 0x00); /* reserved */
4521 stream_putc(s
, 0x01); /* sid_type */
4522 stream_putc(s
, 0x00); /* sif_flags */
4523 stream_put(s
, &attr
->srv6_vpn
->sid
,
4524 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4528 if (send_as4_path
) {
4529 /* If the peer is NOT As4 capable, AND */
4530 /* there are ASnums > 65535 in path THEN
4531 * give out AS4_PATH */
4533 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4535 * Hm, I wonder... confederation things *should* only be at
4536 * the beginning of an aspath, right? Then we should use
4537 * aspath_delete_confed_seq for this, because it is already
4539 * Folks, talk to me: what is reasonable here!?
4541 aspath
= aspath_delete_confed_seq(aspath
);
4544 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4545 | BGP_ATTR_FLAG_EXTLEN
);
4546 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4547 aspath_sizep
= stream_get_endp(s
);
4549 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4552 if (aspath
!= attr
->aspath
)
4553 aspath_free(aspath
);
4555 if (send_as4_aggregator
) {
4556 /* send AS4_AGGREGATOR, at this place */
4557 /* this section of code moved here in order to ensure the
4559 * *ascending* order of attributes
4561 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4562 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4564 stream_putl(s
, attr
->aggregator_as
);
4565 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4568 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4569 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4570 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4571 /* Tunnel Encap attribute */
4572 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4574 #ifdef ENABLE_BGP_VNC_ATTR
4576 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4581 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4582 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4583 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4584 stream_putc(s
, 9); // Length
4585 stream_putc(s
, 0); // Flags
4586 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4587 stream_put(s
, &(attr
->label
),
4588 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4589 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4590 // Unicast tunnel endpoint IP address
4594 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4595 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4596 stream_putc(s
, BGP_ATTR_OTC
);
4598 stream_putl(s
, attr
->otc
);
4602 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
) &&
4603 (CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
) ||
4604 peer
->sort
!= BGP_PEER_EBGP
)) {
4605 /* At the moment only AIGP Metric TLV exists for AIGP
4606 * attribute. If more comes in, do not forget to update
4607 * attr_len variable to include new ones.
4609 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4611 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4612 stream_putc(s
, BGP_ATTR_AIGP
);
4613 stream_putc(s
, attr_len
);
4614 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4617 /* Unknown transit attribute. */
4618 struct transit
*transit
= bgp_attr_get_transit(attr
);
4621 stream_put(s
, transit
->val
, transit
->length
);
4623 /* Return total size of attribute. */
4624 return stream_get_endp(s
) - cp
;
4627 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4629 unsigned long attrlen_pnt
;
4630 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
4631 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
4633 /* Set extended bit always to encode the attribute length as 2 bytes */
4634 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4635 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4637 attrlen_pnt
= stream_get_endp(s
);
4638 stream_putw(s
, 0); /* Length of this attribute. */
4640 /* Convert AFI, SAFI to values for packet. */
4641 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4643 stream_putw(s
, pkt_afi
);
4644 stream_putc(s
, pkt_safi
);
4649 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4650 afi_t afi
, safi_t safi
,
4651 const struct prefix_rd
*prd
,
4652 mpls_label_t
*label
, uint32_t num_labels
,
4653 bool addpath_capable
, uint32_t addpath_tx_id
,
4656 uint8_t wlabel
[4] = {0x80, 0x00, 0x00};
4658 if (safi
== SAFI_LABELED_UNICAST
) {
4659 label
= (mpls_label_t
*)wlabel
;
4663 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4664 addpath_capable
, addpath_tx_id
, attr
);
4667 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4669 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4672 /* Initialization of attribute. */
4673 void bgp_attr_init(void)
4686 void bgp_attr_finish(void)
4691 ecommunity_finish();
4692 lcommunity_finish();
4699 /* Make attribute packet. */
4700 void bgp_dump_routes_attr(struct stream
*s
, struct bgp_path_info
*bpi
,
4701 const struct prefix
*prefix
)
4706 struct aspath
*aspath
;
4707 bool addpath_capable
= false;
4708 uint32_t addpath_tx_id
= 0;
4709 struct attr
*attr
= bpi
->attr
;
4711 /* Remember current pointer. */
4712 cp
= stream_get_endp(s
);
4714 /* Place holder of length. */
4717 /* Origin attribute. */
4718 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4719 stream_putc(s
, BGP_ATTR_ORIGIN
);
4721 stream_putc(s
, attr
->origin
);
4723 aspath
= attr
->aspath
;
4725 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4726 stream_putc(s
, BGP_ATTR_AS_PATH
);
4727 aspath_lenp
= stream_get_endp(s
);
4730 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4732 /* Nexthop attribute. */
4733 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4734 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4735 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4736 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4738 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4741 /* MED attribute. */
4742 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4743 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4744 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4746 stream_putl(s
, attr
->med
);
4749 /* Local preference. */
4750 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4751 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4752 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4754 stream_putl(s
, attr
->local_pref
);
4757 /* Atomic aggregate. */
4758 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4759 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4760 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4765 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4766 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4767 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4769 stream_putl(s
, attr
->aggregator_as
);
4770 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4773 /* Community attribute. */
4774 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4775 struct community
*comm
= NULL
;
4777 comm
= bgp_attr_get_community(attr
);
4778 if (comm
->size
* 4 > 255) {
4780 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4781 | BGP_ATTR_FLAG_EXTLEN
);
4782 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4783 stream_putw(s
, comm
->size
* 4);
4786 BGP_ATTR_FLAG_OPTIONAL
4787 | BGP_ATTR_FLAG_TRANS
);
4788 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4789 stream_putc(s
, comm
->size
* 4);
4791 stream_put(s
, comm
->val
, comm
->size
* 4);
4794 /* Large Community attribute. */
4795 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4796 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4798 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4799 | BGP_ATTR_FLAG_EXTLEN
);
4800 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4802 lcom_length(bgp_attr_get_lcommunity(attr
)));
4805 BGP_ATTR_FLAG_OPTIONAL
4806 | BGP_ATTR_FLAG_TRANS
);
4807 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4809 lcom_length(bgp_attr_get_lcommunity(attr
)));
4812 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4813 lcom_length(bgp_attr_get_lcommunity(attr
)));
4816 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4817 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4818 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4819 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4822 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4823 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4824 sizep
= stream_get_endp(s
);
4827 stream_putc(s
, 0); /* Marker: Attribute length. */
4828 stream_putw(s
, AFI_IP6
); /* AFI */
4829 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4832 stream_putc(s
, attr
->mp_nexthop_len
);
4833 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4834 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4835 stream_put(s
, &attr
->mp_nexthop_local
,
4842 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4845 /* Set MP attribute length. */
4846 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4850 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4851 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4853 BGP_ATTR_FLAG_OPTIONAL
4854 | BGP_ATTR_FLAG_TRANS
);
4855 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4857 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4858 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4859 stream_putc(s
, 0); // reserved
4860 stream_putw(s
, 0); // flags
4861 stream_putl(s
, attr
->label_index
);
4866 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4867 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4868 stream_putc(s
, BGP_ATTR_OTC
);
4870 stream_putl(s
, attr
->otc
);
4874 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
4875 /* At the moment only AIGP Metric TLV exists for AIGP
4876 * attribute. If more comes in, do not forget to update
4877 * attr_len variable to include new ones.
4879 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4881 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4882 stream_putc(s
, BGP_ATTR_AIGP
);
4883 stream_putc(s
, attr_len
);
4884 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4887 /* Return total size of attribute. */
4888 len
= stream_get_endp(s
) - cp
- 2;
4889 stream_putw_at(s
, cp
, len
);