1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_aspath.h"
41 #include "bgpd/bgp_community.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_errors.h"
44 #include "bgpd/bgp_label.h"
45 #include "bgpd/bgp_packet.h"
46 #include "bgpd/bgp_ecommunity.h"
47 #include "bgpd/bgp_lcommunity.h"
48 #include "bgpd/bgp_updgrp.h"
49 #include "bgpd/bgp_encap_types.h"
51 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
52 #include "bgp_encap_types.h"
53 #include "bgp_vnc_types.h"
56 #include "bgp_flowspec_private.h"
59 /* Attribute strings for logging. */
60 static const struct message attr_str
[] = {
61 {BGP_ATTR_ORIGIN
, "ORIGIN"},
62 {BGP_ATTR_AS_PATH
, "AS_PATH"},
63 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
64 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
65 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
66 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
67 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
68 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
69 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
70 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
71 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
72 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
73 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
74 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
75 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
76 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
77 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
78 {BGP_ATTR_ENCAP
, "ENCAP"},
79 {BGP_ATTR_OTC
, "OTC"},
80 #ifdef ENABLE_BGP_VNC_ATTR
81 {BGP_ATTR_VNC
, "VNC"},
83 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
84 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
85 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
86 {BGP_ATTR_AIGP
, "AIGP"},
89 static const struct message attr_flag_str
[] = {
90 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
91 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
92 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
93 /* bgp_attr_flags_diagnose() relies on this bit being last in
95 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
98 static struct hash
*cluster_hash
;
100 static void *cluster_hash_alloc(void *p
)
102 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
103 struct cluster_list
*cluster
;
105 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
106 cluster
->length
= val
->length
;
108 if (cluster
->length
) {
109 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
110 memcpy(cluster
->list
, val
->list
, val
->length
);
112 cluster
->list
= NULL
;
119 /* Cluster list related functions. */
120 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
122 struct cluster_list tmp
= {};
123 struct cluster_list
*cluster
;
126 tmp
.list
= length
== 0 ? NULL
: pnt
;
128 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
133 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
137 for (i
= 0; i
< cluster
->length
/ 4; i
++)
138 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
143 static unsigned int cluster_hash_key_make(const void *p
)
145 const struct cluster_list
*cluster
= p
;
147 return jhash(cluster
->list
, cluster
->length
, 0);
150 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
152 const struct cluster_list
*cluster1
= p1
;
153 const struct cluster_list
*cluster2
= p2
;
155 if (cluster1
->list
== cluster2
->list
)
158 if (!cluster1
->list
|| !cluster2
->list
)
161 if (cluster1
->length
!= cluster2
->length
)
164 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
167 static void cluster_free(struct cluster_list
*cluster
)
169 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
170 XFREE(MTYPE_CLUSTER
, cluster
);
173 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
175 struct cluster_list
*find
;
177 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
183 static void cluster_unintern(struct cluster_list
**cluster
)
185 if ((*cluster
)->refcnt
)
186 (*cluster
)->refcnt
--;
188 if ((*cluster
)->refcnt
== 0) {
189 void *p
= hash_release(cluster_hash
, *cluster
);
190 assert(p
== *cluster
);
191 cluster_free(*cluster
);
196 static void cluster_init(void)
198 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
202 static void cluster_finish(void)
204 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
205 hash_free(cluster_hash
);
209 static struct hash
*encap_hash
= NULL
;
210 #ifdef ENABLE_BGP_VNC
211 static struct hash
*vnc_hash
= NULL
;
213 static struct hash
*srv6_l3vpn_hash
;
214 static struct hash
*srv6_vpn_hash
;
216 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
218 struct bgp_attr_encap_subtlv
*new;
219 struct bgp_attr_encap_subtlv
*tail
;
220 struct bgp_attr_encap_subtlv
*p
;
222 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
223 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
225 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
228 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
231 memcpy(tail
, p
, size
);
238 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
240 struct bgp_attr_encap_subtlv
*next
;
244 XFREE(MTYPE_ENCAP_TLV
, p
);
249 void bgp_attr_flush_encap(struct attr
*attr
)
254 if (attr
->encap_subtlvs
) {
255 encap_free(attr
->encap_subtlvs
);
256 attr
->encap_subtlvs
= NULL
;
258 #ifdef ENABLE_BGP_VNC
259 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
260 bgp_attr_get_vnc_subtlvs(attr
);
263 encap_free(vnc_subtlvs
);
264 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
270 * Compare encap sub-tlv chains
275 * This algorithm could be made faster if needed
277 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
278 const struct bgp_attr_encap_subtlv
*h2
)
280 const struct bgp_attr_encap_subtlv
*p
;
281 const struct bgp_attr_encap_subtlv
*q
;
285 if (h1
== NULL
|| h2
== NULL
)
288 for (p
= h1
; p
; p
= p
->next
) {
289 for (q
= h2
; q
; q
= q
->next
) {
290 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
291 && !memcmp(p
->value
, q
->value
, p
->length
)) {
300 for (p
= h2
; p
; p
= p
->next
) {
301 for (q
= h1
; q
; q
= q
->next
) {
302 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
303 && !memcmp(p
->value
, q
->value
, p
->length
)) {
315 static void *encap_hash_alloc(void *p
)
317 /* Encap structure is already allocated. */
323 #ifdef ENABLE_BGP_VNC
328 static struct bgp_attr_encap_subtlv
*
329 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
331 struct bgp_attr_encap_subtlv
*find
;
332 struct hash
*hash
= encap_hash
;
333 #ifdef ENABLE_BGP_VNC
334 if (type
== VNC_SUBTLV_TYPE
)
338 find
= hash_get(hash
, encap
, encap_hash_alloc
);
346 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
347 encap_subtlv_type type
)
349 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
353 if (encap
->refcnt
== 0) {
354 struct hash
*hash
= encap_hash
;
355 #ifdef ENABLE_BGP_VNC
356 if (type
== VNC_SUBTLV_TYPE
)
359 hash_release(hash
, encap
);
365 static unsigned int encap_hash_key_make(const void *p
)
367 const struct bgp_attr_encap_subtlv
*encap
= p
;
369 return jhash(encap
->value
, encap
->length
, 0);
372 static bool encap_hash_cmp(const void *p1
, const void *p2
)
374 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
375 (const struct bgp_attr_encap_subtlv
*)p2
);
378 static void encap_init(void)
380 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
382 #ifdef ENABLE_BGP_VNC
383 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
388 static void encap_finish(void)
390 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
391 hash_free(encap_hash
);
393 #ifdef ENABLE_BGP_VNC
394 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
400 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
409 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
410 bgp_attr_get_evpn_overlay(a2
));
413 /* Unknown transit attribute. */
414 static struct hash
*transit_hash
;
416 static void transit_free(struct transit
*transit
)
418 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
419 XFREE(MTYPE_TRANSIT
, transit
);
422 static void *transit_hash_alloc(void *p
)
424 /* Transit structure is already allocated. */
428 static struct transit
*transit_intern(struct transit
*transit
)
430 struct transit
*find
;
432 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
434 transit_free(transit
);
440 static void transit_unintern(struct transit
**transit
)
442 if ((*transit
)->refcnt
)
443 (*transit
)->refcnt
--;
445 if ((*transit
)->refcnt
== 0) {
446 hash_release(transit_hash
, *transit
);
447 transit_free(*transit
);
452 static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt
, int length
,
461 ptr_get_be16(data
+ 1, &tlv_length
);
464 /* The value field of the AIGP TLV is always 8 octets
465 * long and its value is interpreted as an unsigned 64-bit
468 if (tlv_type
== BGP_AIGP_TLV_METRIC
) {
469 (void)ptr_get_be64(data
+ 3, aigp
);
471 /* If an AIGP attribute is received and its first AIGP
472 * TLV contains the maximum value 0xffffffffffffffff,
473 * the attribute SHOULD be considered to be malformed
474 * and SHOULD be discarded as specified in this section.
476 if (*aigp
== BGP_AIGP_TLV_METRIC_MAX
) {
477 zlog_err("Bad AIGP TLV (%s) length: %llu",
478 BGP_AIGP_TLV_METRIC_DESC
,
479 BGP_AIGP_TLV_METRIC_MAX
);
487 length
-= tlv_length
;
493 static uint64_t bgp_aigp_metric_total(struct bgp_path_info
*bpi
)
495 uint64_t aigp
= bgp_attr_get_aigp_metric(bpi
->attr
);
498 return aigp
+ bpi
->nexthop
->metric
;
503 static void stream_put_bgp_aigp_tlv_metric(struct stream
*s
,
504 struct bgp_path_info
*bpi
)
506 stream_putc(s
, BGP_AIGP_TLV_METRIC
);
507 stream_putw(s
, BGP_AIGP_TLV_METRIC_LEN
);
508 stream_putq(s
, bgp_aigp_metric_total(bpi
));
511 static bool bgp_attr_aigp_valid(uint8_t *pnt
, int length
)
518 zlog_err("Bad AIGP attribute length (MUST be minimum 3): %u",
525 ptr_get_be16(data
+ 1, &tlv_length
);
528 if (length
< tlv_length
) {
530 "Bad AIGP attribute length: %u, but TLV length: %u",
535 if (tlv_length
< 3) {
536 zlog_err("Bad AIGP TLV length (MUST be minimum 3): %u",
541 /* AIGP TLV, Length: 11 */
542 if (tlv_type
== BGP_AIGP_TLV_METRIC
&&
543 tlv_length
!= BGP_AIGP_TLV_METRIC_LEN
) {
544 zlog_err("Bad AIGP TLV (%s) length: %u",
545 BGP_AIGP_TLV_METRIC_DESC
, tlv_length
);
550 length
-= tlv_length
;
556 static void *srv6_l3vpn_hash_alloc(void *p
)
561 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
563 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
566 static struct bgp_attr_srv6_l3vpn
*
567 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
569 struct bgp_attr_srv6_l3vpn
*find
;
571 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
573 srv6_l3vpn_free(l3vpn
);
578 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
580 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
585 if (l3vpn
->refcnt
== 0) {
586 hash_release(srv6_l3vpn_hash
, l3vpn
);
587 srv6_l3vpn_free(l3vpn
);
592 static void *srv6_vpn_hash_alloc(void *p
)
597 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
599 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
602 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
604 struct bgp_attr_srv6_vpn
*find
;
606 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
613 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
615 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
620 if (vpn
->refcnt
== 0) {
621 hash_release(srv6_vpn_hash
, vpn
);
627 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
629 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
632 key
= jhash(&l3vpn
->sid
, 16, key
);
633 key
= jhash_1word(l3vpn
->sid_flags
, key
);
634 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
635 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
636 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
637 key
= jhash_1word(l3vpn
->func_len
, key
);
638 key
= jhash_1word(l3vpn
->arg_len
, key
);
639 key
= jhash_1word(l3vpn
->transposition_len
, key
);
640 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
644 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
646 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
647 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
649 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
650 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
651 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
652 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
653 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
654 && l3vpn1
->func_len
== l3vpn2
->func_len
655 && l3vpn1
->arg_len
== l3vpn2
->arg_len
656 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
657 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
660 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
661 const struct bgp_attr_srv6_l3vpn
*h2
)
665 else if (h1
== NULL
|| h2
== NULL
)
668 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
671 static unsigned int srv6_vpn_hash_key_make(const void *p
)
673 const struct bgp_attr_srv6_vpn
*vpn
= p
;
676 key
= jhash(&vpn
->sid
, 16, key
);
677 key
= jhash_1word(vpn
->sid_flags
, key
);
681 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
683 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
684 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
686 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
687 && vpn1
->sid_flags
== vpn2
->sid_flags
;
690 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
691 const struct bgp_attr_srv6_vpn
*h2
)
695 else if (h1
== NULL
|| h2
== NULL
)
698 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
701 static void srv6_init(void)
704 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
705 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
706 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
707 "BGP Prefix-SID SRv6-VPN-Service-TLV");
710 static void srv6_finish(void)
712 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
713 hash_free(srv6_l3vpn_hash
);
714 srv6_l3vpn_hash
= NULL
;
715 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
716 hash_free(srv6_vpn_hash
);
717 srv6_vpn_hash
= NULL
;
720 static unsigned int transit_hash_key_make(const void *p
)
722 const struct transit
*transit
= p
;
724 return jhash(transit
->val
, transit
->length
, 0);
727 static bool transit_hash_cmp(const void *p1
, const void *p2
)
729 const struct transit
*transit1
= p1
;
730 const struct transit
*transit2
= p2
;
732 return (transit1
->length
== transit2
->length
733 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
736 static void transit_init(void)
738 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
742 static void transit_finish(void)
744 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
745 hash_free(transit_hash
);
749 /* Attribute hash routines. */
750 static struct hash
*attrhash
;
752 unsigned long int attr_count(void)
754 return attrhash
->count
;
757 unsigned long int attr_unknown_count(void)
759 return transit_hash
->count
;
762 unsigned int attrhash_key_make(const void *p
)
764 const struct attr
*attr
= (struct attr
*)p
;
766 #define MIX(val) key = jhash_1word(val, key)
767 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
769 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
770 MIX3(attr
->local_pref
, attr
->aggregator_as
,
771 attr
->aggregator_addr
.s_addr
);
772 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
773 attr
->originator_id
.s_addr
);
774 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
777 MIX(aspath_key_make(attr
->aspath
));
778 if (bgp_attr_get_community(attr
))
779 MIX(community_hash_make(bgp_attr_get_community(attr
)));
780 if (bgp_attr_get_lcommunity(attr
))
781 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
782 if (bgp_attr_get_ecommunity(attr
))
783 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
784 if (bgp_attr_get_ipv6_ecommunity(attr
))
785 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
786 if (bgp_attr_get_cluster(attr
))
787 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
788 if (bgp_attr_get_transit(attr
))
789 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
790 if (attr
->encap_subtlvs
)
791 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
792 if (attr
->srv6_l3vpn
)
793 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
795 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
796 #ifdef ENABLE_BGP_VNC
797 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
798 bgp_attr_get_vnc_subtlvs(attr
);
800 MIX(encap_hash_key_make(vnc_subtlvs
));
802 MIX(attr
->mp_nexthop_len
);
803 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
804 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
805 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
806 MIX(attr
->rmap_table_id
);
810 MIX(bgp_attr_get_aigp_metric(attr
));
815 bool attrhash_cmp(const void *p1
, const void *p2
)
817 const struct attr
*attr1
= p1
;
818 const struct attr
*attr2
= p2
;
820 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
821 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
822 && attr1
->aspath
== attr2
->aspath
823 && bgp_attr_get_community(attr1
)
824 == bgp_attr_get_community(attr2
)
825 && attr1
->med
== attr2
->med
826 && attr1
->local_pref
== attr2
->local_pref
827 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
828 if (attr1
->aggregator_as
== attr2
->aggregator_as
829 && attr1
->aggregator_addr
.s_addr
830 == attr2
->aggregator_addr
.s_addr
831 && attr1
->weight
== attr2
->weight
832 && attr1
->tag
== attr2
->tag
833 && attr1
->label_index
== attr2
->label_index
834 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
835 && bgp_attr_get_ecommunity(attr1
)
836 == bgp_attr_get_ecommunity(attr2
)
837 && bgp_attr_get_ipv6_ecommunity(attr1
)
838 == bgp_attr_get_ipv6_ecommunity(attr2
)
839 && bgp_attr_get_lcommunity(attr1
)
840 == bgp_attr_get_lcommunity(attr2
)
841 && bgp_attr_get_cluster(attr1
)
842 == bgp_attr_get_cluster(attr2
)
843 && bgp_attr_get_transit(attr1
)
844 == bgp_attr_get_transit(attr2
)
845 && bgp_attr_get_aigp_metric(attr1
)
846 == bgp_attr_get_aigp_metric(attr2
)
847 && attr1
->rmap_table_id
== attr2
->rmap_table_id
848 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
849 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
850 #ifdef ENABLE_BGP_VNC
851 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
852 bgp_attr_get_vnc_subtlvs(attr2
))
854 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
855 &attr2
->mp_nexthop_global
)
856 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
857 &attr2
->mp_nexthop_local
)
858 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
859 &attr2
->mp_nexthop_global_in
)
860 && IPV4_ADDR_SAME(&attr1
->originator_id
,
861 &attr2
->originator_id
)
862 && overlay_index_same(attr1
, attr2
)
863 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
864 && attr1
->es_flags
== attr2
->es_flags
865 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
866 && attr1
->df_pref
== attr2
->df_pref
867 && attr1
->df_alg
== attr2
->df_alg
868 && attr1
->nh_ifindex
== attr2
->nh_ifindex
869 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
870 && attr1
->distance
== attr2
->distance
871 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
872 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
873 && attr1
->srte_color
== attr2
->srte_color
874 && attr1
->nh_type
== attr2
->nh_type
875 && attr1
->bh_type
== attr2
->bh_type
876 && attr1
->otc
== attr2
->otc
)
883 static void attrhash_init(void)
886 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
890 * special for hash_clean below
892 static void attr_vfree(void *attr
)
894 XFREE(MTYPE_ATTR
, attr
);
897 static void attrhash_finish(void)
899 hash_clean(attrhash
, attr_vfree
);
904 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
906 struct attr
*attr
= bucket
->data
;
907 char sid_str
[BUFSIZ
];
909 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
912 if (attr
->srv6_l3vpn
)
913 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
914 else if (attr
->srv6_vpn
)
915 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
918 "\tflags: %" PRIu64
" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
919 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
920 attr
->origin
, attr
->weight
, attr
->label
, sid_str
);
923 void attr_show_all(struct vty
*vty
)
925 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
926 void *))attr_show_all_iterator
,
930 static void *bgp_attr_hash_alloc(void *p
)
932 struct attr
*val
= (struct attr
*)p
;
935 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
937 if (val
->encap_subtlvs
) {
938 val
->encap_subtlvs
= NULL
;
940 #ifdef ENABLE_BGP_VNC
941 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
942 bgp_attr_get_vnc_subtlvs(val
);
945 bgp_attr_set_vnc_subtlvs(val
, NULL
);
952 /* Internet argument attribute. */
953 struct attr
*bgp_attr_intern(struct attr
*attr
)
956 struct ecommunity
*ecomm
= NULL
;
957 struct ecommunity
*ipv6_ecomm
= NULL
;
958 struct lcommunity
*lcomm
= NULL
;
959 struct community
*comm
= NULL
;
961 /* Intern referenced structure. */
963 if (!attr
->aspath
->refcnt
)
964 attr
->aspath
= aspath_intern(attr
->aspath
);
966 attr
->aspath
->refcnt
++;
969 comm
= bgp_attr_get_community(attr
);
972 bgp_attr_set_community(attr
, community_intern(comm
));
977 ecomm
= bgp_attr_get_ecommunity(attr
);
980 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
985 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
987 if (!ipv6_ecomm
->refcnt
)
988 bgp_attr_set_ipv6_ecommunity(
989 attr
, ecommunity_intern(ipv6_ecomm
));
991 ipv6_ecomm
->refcnt
++;
994 lcomm
= bgp_attr_get_lcommunity(attr
);
997 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
1002 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1005 if (!cluster
->refcnt
)
1006 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
1011 struct transit
*transit
= bgp_attr_get_transit(attr
);
1014 if (!transit
->refcnt
)
1015 bgp_attr_set_transit(attr
, transit_intern(transit
));
1019 if (attr
->encap_subtlvs
) {
1020 if (!attr
->encap_subtlvs
->refcnt
)
1021 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
1024 attr
->encap_subtlvs
->refcnt
++;
1026 if (attr
->srv6_l3vpn
) {
1027 if (!attr
->srv6_l3vpn
->refcnt
)
1028 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
1030 attr
->srv6_l3vpn
->refcnt
++;
1032 if (attr
->srv6_vpn
) {
1033 if (!attr
->srv6_vpn
->refcnt
)
1034 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
1036 attr
->srv6_vpn
->refcnt
++;
1038 #ifdef ENABLE_BGP_VNC
1039 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1040 bgp_attr_get_vnc_subtlvs(attr
);
1043 if (!vnc_subtlvs
->refcnt
)
1044 bgp_attr_set_vnc_subtlvs(
1046 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
1048 vnc_subtlvs
->refcnt
++;
1052 /* At this point, attr only contains intern'd pointers. that means
1053 * if we find it in attrhash, it has all the same pointers and we
1054 * correctly updated the refcounts on these.
1055 * If we don't find it, we need to allocate a one because in all
1056 * cases this returns a new reference to a hashed attr, but the input
1057 * wasn't on hash. */
1058 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
1064 /* Make network statement's attribute. */
1065 struct attr
*bgp_attr_default_set(struct attr
*attr
, struct bgp
*bgp
,
1068 memset(attr
, 0, sizeof(struct attr
));
1070 attr
->origin
= origin
;
1071 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1072 attr
->aspath
= aspath_empty();
1073 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1074 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1076 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
1077 attr
->label
= MPLS_INVALID_LABEL
;
1078 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1079 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1080 attr
->local_pref
= bgp
->default_local_pref
;
1085 /* Create the attributes for an aggregate */
1086 struct attr
*bgp_attr_aggregate_intern(
1087 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
1088 struct community
*community
, struct ecommunity
*ecommunity
,
1089 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
1090 uint8_t atomic_aggregate
, const struct prefix
*p
)
1094 route_map_result_t ret
;
1096 memset(&attr
, 0, sizeof(attr
));
1098 /* Origin attribute. */
1099 attr
.origin
= origin
;
1100 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1104 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1106 /* AS path attribute. */
1108 attr
.aspath
= aspath_intern(aspath
);
1110 attr
.aspath
= aspath_empty();
1111 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1113 /* Next hop attribute. */
1114 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1117 uint32_t gshut
= COMMUNITY_GSHUT
;
1119 /* If we are not shutting down ourselves and we are
1120 * aggregating a route that contains the GSHUT community we
1121 * need to remove that community when creating the aggregate */
1122 if (!bgp_in_graceful_shutdown(bgp
)
1123 && community_include(community
, gshut
)) {
1124 community_del_val(community
, &gshut
);
1127 bgp_attr_set_community(&attr
, community
);
1131 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1134 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1136 if (bgp_in_graceful_shutdown(bgp
))
1137 bgp_attr_add_gshut_community(&attr
);
1139 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1140 attr
.label
= MPLS_INVALID_LABEL
;
1141 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1142 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1143 if (!aggregate
->as_set
|| atomic_aggregate
)
1144 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1145 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1146 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1147 attr
.aggregator_as
= bgp
->confed_id
;
1149 attr
.aggregator_as
= bgp
->as
;
1150 attr
.aggregator_addr
= bgp
->router_id
;
1152 /* Apply route-map */
1153 if (aggregate
->rmap
.name
) {
1154 struct attr attr_tmp
= attr
;
1155 struct bgp_path_info rmap_path
;
1157 memset(&rmap_path
, 0, sizeof(rmap_path
));
1158 rmap_path
.peer
= bgp
->peer_self
;
1159 rmap_path
.attr
= &attr_tmp
;
1161 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1163 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1165 bgp
->peer_self
->rmap_type
= 0;
1167 if (ret
== RMAP_DENYMATCH
) {
1168 /* Free uninterned attribute. */
1169 bgp_attr_flush(&attr_tmp
);
1171 /* Unintern original. */
1172 aspath_unintern(&attr
.aspath
);
1176 if (bgp_in_graceful_shutdown(bgp
))
1177 bgp_attr_add_gshut_community(&attr_tmp
);
1179 new = bgp_attr_intern(&attr_tmp
);
1182 if (bgp_in_graceful_shutdown(bgp
))
1183 bgp_attr_add_gshut_community(&attr
);
1185 new = bgp_attr_intern(&attr
);
1188 /* Always release the 'intern()'ed AS Path. */
1189 aspath_unintern(&attr
.aspath
);
1194 /* Unintern just the sub-components of the attr, but not the attr */
1195 void bgp_attr_unintern_sub(struct attr
*attr
)
1197 struct ecommunity
*ecomm
= NULL
;
1198 struct ecommunity
*ipv6_ecomm
= NULL
;
1199 struct cluster_list
*cluster
;
1200 struct lcommunity
*lcomm
= NULL
;
1201 struct community
*comm
= NULL
;
1203 /* aspath refcount shoud be decrement. */
1204 aspath_unintern(&attr
->aspath
);
1205 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1207 comm
= bgp_attr_get_community(attr
);
1208 community_unintern(&comm
);
1209 bgp_attr_set_community(attr
, NULL
);
1211 ecomm
= bgp_attr_get_ecommunity(attr
);
1212 ecommunity_unintern(&ecomm
);
1213 bgp_attr_set_ecommunity(attr
, NULL
);
1215 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1216 ecommunity_unintern(&ipv6_ecomm
);
1217 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1219 lcomm
= bgp_attr_get_lcommunity(attr
);
1220 lcommunity_unintern(&lcomm
);
1221 bgp_attr_set_lcommunity(attr
, NULL
);
1223 cluster
= bgp_attr_get_cluster(attr
);
1225 cluster_unintern(&cluster
);
1226 bgp_attr_set_cluster(attr
, cluster
);
1228 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1230 struct transit
*transit
= bgp_attr_get_transit(attr
);
1233 transit_unintern(&transit
);
1234 bgp_attr_set_transit(attr
, transit
);
1237 if (attr
->encap_subtlvs
)
1238 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1240 #ifdef ENABLE_BGP_VNC
1241 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1242 bgp_attr_get_vnc_subtlvs(attr
);
1245 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1246 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1250 if (attr
->srv6_l3vpn
)
1251 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1254 srv6_vpn_unintern(&attr
->srv6_vpn
);
1257 /* Free bgp attribute and aspath. */
1258 void bgp_attr_unintern(struct attr
**pattr
)
1260 struct attr
*attr
= *pattr
;
1264 /* Decrement attribute reference. */
1269 /* If reference becomes zero then free attribute object. */
1270 if (attr
->refcnt
== 0) {
1271 ret
= hash_release(attrhash
, attr
);
1272 assert(ret
!= NULL
);
1273 XFREE(MTYPE_ATTR
, attr
);
1277 bgp_attr_unintern_sub(&tmp
);
1280 void bgp_attr_flush(struct attr
*attr
)
1282 struct ecommunity
*ecomm
;
1283 struct ecommunity
*ipv6_ecomm
;
1284 struct cluster_list
*cluster
;
1285 struct lcommunity
*lcomm
;
1286 struct community
*comm
;
1288 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1289 aspath_free(attr
->aspath
);
1290 attr
->aspath
= NULL
;
1292 comm
= bgp_attr_get_community(attr
);
1293 if (comm
&& !comm
->refcnt
)
1294 community_free(&comm
);
1295 bgp_attr_set_community(attr
, NULL
);
1297 ecomm
= bgp_attr_get_ecommunity(attr
);
1298 if (ecomm
&& !ecomm
->refcnt
)
1299 ecommunity_free(&ecomm
);
1300 bgp_attr_set_ecommunity(attr
, NULL
);
1302 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1303 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1304 ecommunity_free(&ipv6_ecomm
);
1305 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1307 lcomm
= bgp_attr_get_lcommunity(attr
);
1308 if (lcomm
&& !lcomm
->refcnt
)
1309 lcommunity_free(&lcomm
);
1310 bgp_attr_set_lcommunity(attr
, NULL
);
1312 cluster
= bgp_attr_get_cluster(attr
);
1313 if (cluster
&& !cluster
->refcnt
) {
1314 cluster_free(cluster
);
1315 bgp_attr_set_cluster(attr
, NULL
);
1318 struct transit
*transit
= bgp_attr_get_transit(attr
);
1320 if (transit
&& !transit
->refcnt
) {
1321 transit_free(transit
);
1322 bgp_attr_set_transit(attr
, NULL
);
1324 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1325 encap_free(attr
->encap_subtlvs
);
1326 attr
->encap_subtlvs
= NULL
;
1328 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1329 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1330 attr
->srv6_l3vpn
= NULL
;
1332 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1333 srv6_vpn_free(attr
->srv6_vpn
);
1334 attr
->srv6_vpn
= NULL
;
1336 #ifdef ENABLE_BGP_VNC
1337 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1338 bgp_attr_get_vnc_subtlvs(attr
);
1340 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1341 encap_free(vnc_subtlvs
);
1342 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1347 /* Implement draft-scudder-idr-optional-transitive behaviour and
1348 * avoid resetting sessions for malformed attributes which are
1349 * are partial/optional and hence where the error likely was not
1350 * introduced by the sending neighbour.
1352 static enum bgp_attr_parse_ret
1353 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1356 struct peer
*const peer
= args
->peer
;
1357 struct attr
*const attr
= args
->attr
;
1358 const uint8_t flags
= args
->flags
;
1359 /* startp and length must be special-cased, as whether or not to
1360 * send the attribute data with the NOTIFY depends on the error,
1361 * the caller therefore signals this with the seperate length argument
1363 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1365 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1366 char attr_str
[BUFSIZ
] = {0};
1368 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1370 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1373 /* Only relax error handling for eBGP peers */
1374 if (peer
->sort
!= BGP_PEER_EBGP
) {
1375 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1376 notify_datap
, length
);
1377 return BGP_ATTR_PARSE_ERROR
;
1380 /* Adjust the stream getp to the end of the attribute, in case we can
1381 * still proceed but the caller hasn't read all the attribute.
1383 stream_set_getp(BGP_INPUT(peer
),
1384 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1387 switch (args
->type
) {
1388 /* where an attribute is relatively inconsequential, e.g. it does not
1389 * affect route selection, and can be safely ignored, then any such
1390 * attributes which are malformed should just be ignored and the route
1391 * processed as normal.
1393 case BGP_ATTR_AS4_AGGREGATOR
:
1394 case BGP_ATTR_AGGREGATOR
:
1395 case BGP_ATTR_ATOMIC_AGGREGATE
:
1396 return BGP_ATTR_PARSE_PROCEED
;
1398 /* Core attributes, particularly ones which may influence route
1399 * selection, should be treat-as-withdraw.
1401 case BGP_ATTR_ORIGIN
:
1402 case BGP_ATTR_AS_PATH
:
1403 case BGP_ATTR_NEXT_HOP
:
1404 case BGP_ATTR_MULTI_EXIT_DISC
:
1405 case BGP_ATTR_LOCAL_PREF
:
1406 case BGP_ATTR_COMMUNITIES
:
1407 case BGP_ATTR_EXT_COMMUNITIES
:
1408 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1409 case BGP_ATTR_LARGE_COMMUNITIES
:
1410 case BGP_ATTR_ORIGINATOR_ID
:
1411 case BGP_ATTR_CLUSTER_LIST
:
1413 return BGP_ATTR_PARSE_WITHDRAW
;
1414 case BGP_ATTR_MP_REACH_NLRI
:
1415 case BGP_ATTR_MP_UNREACH_NLRI
:
1416 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1417 notify_datap
, length
);
1418 return BGP_ATTR_PARSE_ERROR
;
1421 /* Partial optional attributes that are malformed should not cause
1422 * the whole session to be reset. Instead treat it as a withdrawal
1423 * of the routes, if possible.
1425 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1426 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1427 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1428 return BGP_ATTR_PARSE_WITHDRAW
;
1430 /* default to reset */
1431 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1434 /* Find out what is wrong with the path attribute flag bits and log the error.
1435 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1436 Extended Length. Checking O/T/P bits at once implies, that the attribute
1437 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1438 non-transitive" attribute. */
1440 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1441 uint8_t desired_flags
/* how RFC says it must be */
1444 uint8_t seen
= 0, i
;
1445 uint8_t real_flags
= args
->flags
;
1446 const uint8_t attr_code
= args
->type
;
1448 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1449 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1450 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1451 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1452 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1453 flog_err(EC_BGP_ATTR_FLAG
,
1454 "%s attribute must%s be flagged as \"%s\"",
1455 lookup_msg(attr_str
, attr_code
, NULL
),
1456 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1459 attr_flag_str
[i
].str
);
1464 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1465 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1466 real_flags
, desired_flags
);
1470 /* Required flags for attributes. EXTLEN will be masked off when testing,
1471 * as will PARTIAL for optional+transitive attributes.
1473 const uint8_t attr_flags_values
[] = {
1474 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1475 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1476 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1477 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1478 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1479 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1480 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1481 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1482 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1483 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1484 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1485 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1486 [BGP_ATTR_EXT_COMMUNITIES
] =
1487 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1488 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1489 [BGP_ATTR_AS4_AGGREGATOR
] =
1490 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1491 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1492 [BGP_ATTR_LARGE_COMMUNITIES
] =
1493 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1494 [BGP_ATTR_OTC
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1495 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1496 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1497 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1498 [BGP_ATTR_AIGP
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1500 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1502 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1504 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1505 const uint8_t flags
= args
->flags
;
1506 const uint8_t attr_code
= args
->type
;
1508 /* there may be attributes we don't know about */
1509 if (attr_code
> attr_flags_values_max
)
1511 if (attr_flags_values
[attr_code
] == 0)
1514 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1518 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1519 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1522 "%s well-known attributes must have transitive flag set (%x)",
1523 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1527 /* "For well-known attributes and for optional non-transitive
1529 * the Partial bit MUST be set to 0."
1531 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1532 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1533 flog_err(EC_BGP_ATTR_FLAG
,
1534 "%s well-known attribute must NOT have the partial flag set (%x)",
1535 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1538 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1539 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1540 flog_err(EC_BGP_ATTR_FLAG
,
1541 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1542 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1547 /* Optional transitive attributes may go through speakers that don't
1548 * reocgnise them and set the Partial bit.
1550 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1551 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1552 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1554 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1557 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1561 /* Get origin attribute of the update message. */
1562 static enum bgp_attr_parse_ret
1563 bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1565 struct peer
*const peer
= args
->peer
;
1566 struct attr
*const attr
= args
->attr
;
1567 const bgp_size_t length
= args
->length
;
1569 /* If any recognized attribute has Attribute Length that conflicts
1570 with the expected length (based on the attribute type code), then
1571 the Error Subcode is set to Attribute Length Error. The Data
1572 field contains the erroneous attribute (type, length and
1575 flog_err(EC_BGP_ATTR_LEN
,
1576 "Origin attribute length is not one %d", length
);
1577 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1581 /* Fetch origin attribute. */
1582 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1584 /* If the ORIGIN attribute has an undefined value, then the Error
1585 Subcode is set to Invalid Origin Attribute. The Data field
1586 contains the unrecognized attribute (type, length and value). */
1587 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1588 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1589 flog_err(EC_BGP_ATTR_ORIGIN
,
1590 "Origin attribute value is invalid %d", attr
->origin
);
1591 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1595 /* Set oring attribute flag. */
1596 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1601 /* Parse AS path information. This function is wrapper of
1603 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1605 struct attr
*const attr
= args
->attr
;
1606 struct peer
*const peer
= args
->peer
;
1607 const bgp_size_t length
= args
->length
;
1610 * peer with AS4 => will get 4Byte ASnums
1611 * otherwise, will get 16 Bit
1613 attr
->aspath
= aspath_parse(
1615 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1616 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1618 /* In case of IBGP, length will be zero. */
1619 if (!attr
->aspath
) {
1620 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1621 "Malformed AS path from %s, length is %d", peer
->host
,
1623 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1627 /* Conformant BGP speakers SHOULD NOT send BGP
1628 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1629 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1630 * withdraw" error handling behavior as per [RFC7606].
1632 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1633 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1634 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1636 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1640 /* Set aspath attribute flag. */
1641 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1643 return BGP_ATTR_PARSE_PROCEED
;
1646 static enum bgp_attr_parse_ret
bgp_attr_aspath_check(struct peer
*const peer
,
1647 struct attr
*const attr
)
1649 /* These checks were part of bgp_attr_aspath, but with
1650 * as4 we should to check aspath things when
1651 * aspath synthesizing with as4_path has already taken place.
1652 * Otherwise we check ASPATH and use the synthesized thing, and that is
1654 * So do the checks later, i.e. here
1656 struct aspath
*aspath
;
1658 /* Confederation sanity check. */
1659 if ((peer
->sort
== BGP_PEER_CONFED
1660 && !aspath_left_confed_check(attr
->aspath
))
1661 || (peer
->sort
== BGP_PEER_EBGP
1662 && aspath_confed_check(attr
->aspath
))) {
1663 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1665 return BGP_ATTR_PARSE_WITHDRAW
;
1668 /* First AS check for EBGP. */
1669 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1670 if (peer
->sort
== BGP_PEER_EBGP
1671 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1672 flog_err(EC_BGP_ATTR_FIRST_AS
,
1673 "%s incorrect first AS (must be %u)",
1674 peer
->host
, peer
->as
);
1675 return BGP_ATTR_PARSE_WITHDRAW
;
1679 /* Codification of AS 0 Processing */
1680 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1682 EC_BGP_ATTR_MAL_AS_PATH
,
1683 "Malformed AS path, AS number is 0 in the path from %s",
1685 return BGP_ATTR_PARSE_WITHDRAW
;
1688 /* local-as prepend */
1689 if (peer
->change_local_as
1690 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1691 aspath
= aspath_dup(attr
->aspath
);
1692 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1693 aspath_unintern(&attr
->aspath
);
1694 attr
->aspath
= aspath_intern(aspath
);
1697 return BGP_ATTR_PARSE_PROCEED
;
1700 /* Parse AS4 path information. This function is another wrapper of
1702 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1703 struct aspath
**as4_path
)
1705 struct peer
*const peer
= args
->peer
;
1706 struct attr
*const attr
= args
->attr
;
1707 const bgp_size_t length
= args
->length
;
1709 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1711 /* In case of IBGP, length will be zero. */
1713 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1714 "Malformed AS4 path from %s, length is %d", peer
->host
,
1716 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1720 /* Conformant BGP speakers SHOULD NOT send BGP
1721 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1722 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1723 * withdraw" error handling behavior as per [RFC7606].
1725 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1726 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1727 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1729 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1733 /* Set aspath attribute flag. */
1734 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1736 return BGP_ATTR_PARSE_PROCEED
;
1740 * Check that the nexthop attribute is valid.
1742 enum bgp_attr_parse_ret
bgp_attr_nexthop_valid(struct peer
*peer
,
1745 struct bgp
*bgp
= peer
->bgp
;
1747 if (ipv4_martian(&attr
->nexthop
) && !bgp
->allow_martian
) {
1748 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1749 char buf
[INET_ADDRSTRLEN
];
1751 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1753 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1755 data
[0] = BGP_ATTR_FLAG_TRANS
;
1756 data
[1] = BGP_ATTR_NEXT_HOP
;
1757 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1758 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1759 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1760 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1762 return BGP_ATTR_PARSE_ERROR
;
1765 return BGP_ATTR_PARSE_PROCEED
;
1768 /* Nexthop attribute. */
1769 static enum bgp_attr_parse_ret
1770 bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1772 struct peer
*const peer
= args
->peer
;
1773 struct attr
*const attr
= args
->attr
;
1774 const bgp_size_t length
= args
->length
;
1776 /* Check nexthop attribute length. */
1778 flog_err(EC_BGP_ATTR_LEN
,
1779 "Nexthop attribute length isn't four [%d]", length
);
1781 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1785 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1786 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1788 return BGP_ATTR_PARSE_PROCEED
;
1791 /* MED atrribute. */
1792 static enum bgp_attr_parse_ret
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1794 struct peer
*const peer
= args
->peer
;
1795 struct attr
*const attr
= args
->attr
;
1796 const bgp_size_t length
= args
->length
;
1800 flog_err(EC_BGP_ATTR_LEN
,
1801 "MED attribute length isn't four [%d]", length
);
1803 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1807 attr
->med
= stream_getl(peer
->curr
);
1809 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1811 return BGP_ATTR_PARSE_PROCEED
;
1814 /* Local preference attribute. */
1815 static enum bgp_attr_parse_ret
1816 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1818 struct peer
*const peer
= args
->peer
;
1819 struct attr
*const attr
= args
->attr
;
1820 const bgp_size_t length
= args
->length
;
1822 /* if received from an internal neighbor, it SHALL be considered
1823 * malformed if its length is not equal to 4. If malformed, the
1824 * UPDATE message SHALL be handled using the approach of "treat-as-
1827 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1828 flog_err(EC_BGP_ATTR_LEN
,
1829 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1830 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1834 /* If it is contained in an UPDATE message that is received from an
1835 external peer, then this attribute MUST be ignored by the
1836 receiving speaker. */
1837 if (peer
->sort
== BGP_PEER_EBGP
) {
1838 STREAM_FORWARD_GETP(peer
->curr
, length
);
1839 return BGP_ATTR_PARSE_PROCEED
;
1842 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1844 /* Set the local-pref flag. */
1845 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1847 return BGP_ATTR_PARSE_PROCEED
;
1850 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1854 /* Atomic aggregate. */
1855 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1857 struct attr
*const attr
= args
->attr
;
1858 const bgp_size_t length
= args
->length
;
1862 flog_err(EC_BGP_ATTR_LEN
,
1863 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1865 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1869 /* Set atomic aggregate flag. */
1870 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1872 return BGP_ATTR_PARSE_PROCEED
;
1875 /* Aggregator attribute */
1876 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1878 struct peer
*const peer
= args
->peer
;
1879 struct attr
*const attr
= args
->attr
;
1880 const bgp_size_t length
= args
->length
;
1885 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1886 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1887 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1890 if (length
!= wantedlen
) {
1891 flog_err(EC_BGP_ATTR_LEN
,
1892 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1894 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1898 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1899 aggregator_as
= stream_getl(peer
->curr
);
1901 aggregator_as
= stream_getw(peer
->curr
);
1903 attr
->aggregator_as
= aggregator_as
;
1904 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1906 /* Codification of AS 0 Processing */
1907 if (aggregator_as
== BGP_AS_ZERO
) {
1908 flog_err(EC_BGP_ATTR_LEN
,
1909 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1910 peer
->host
, aspath_print(attr
->aspath
));
1912 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1913 char attr_str
[BUFSIZ
] = {0};
1915 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1917 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1920 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1923 return BGP_ATTR_PARSE_PROCEED
;
1926 /* New Aggregator attribute */
1927 static enum bgp_attr_parse_ret
1928 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1929 as_t
*as4_aggregator_as
,
1930 struct in_addr
*as4_aggregator_addr
)
1932 struct peer
*const peer
= args
->peer
;
1933 struct attr
*const attr
= args
->attr
;
1934 const bgp_size_t length
= args
->length
;
1938 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1940 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1944 aggregator_as
= stream_getl(peer
->curr
);
1946 *as4_aggregator_as
= aggregator_as
;
1947 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1949 /* Codification of AS 0 Processing */
1950 if (aggregator_as
== BGP_AS_ZERO
) {
1951 flog_err(EC_BGP_ATTR_LEN
,
1952 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1953 peer
->host
, aspath_print(attr
->aspath
));
1955 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1956 char attr_str
[BUFSIZ
] = {0};
1958 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1960 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1963 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1966 return BGP_ATTR_PARSE_PROCEED
;
1969 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1971 static enum bgp_attr_parse_ret
1972 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1973 struct aspath
*as4_path
, as_t as4_aggregator
,
1974 struct in_addr
*as4_aggregator_addr
)
1976 int ignore_as4_path
= 0;
1977 struct aspath
*newpath
;
1979 if (!attr
->aspath
) {
1980 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1982 * checked that all well-known, mandatory attributes were
1985 * Can only be a problem with peer itself - hard error
1987 return BGP_ATTR_PARSE_ERROR
;
1990 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1991 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1993 * It is worth a warning though, because the peer really
1994 * should not send them
1996 if (BGP_DEBUG(as4
, AS4
)) {
1997 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1998 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1999 "AS4 capable peer, yet it sent");
2002 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
2003 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
2005 "AS4 capable peer, yet it sent");
2008 return BGP_ATTR_PARSE_PROCEED
;
2011 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
2012 * because that may override AS4_PATH
2014 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
2015 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
2017 * if the as_number in aggregator is not AS_TRANS,
2018 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
2019 * and the Aggregator shall be taken as
2020 * info on the aggregating node, and the AS_PATH
2021 * shall be taken as the AS_PATH
2023 * the Aggregator shall be ignored and the
2024 * AS4_AGGREGATOR shall be taken as the
2025 * Aggregating node and the AS_PATH is to be
2026 * constructed "as in all other cases"
2028 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
2030 if (BGP_DEBUG(as4
, AS4
))
2032 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
2034 ignore_as4_path
= 1;
2036 /* "New_aggregator shall be taken as aggregator"
2038 attr
->aggregator_as
= as4_aggregator
;
2039 attr
->aggregator_addr
.s_addr
=
2040 as4_aggregator_addr
->s_addr
;
2043 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2044 * That is bogus - but reading the conditions
2045 * we have to handle AS4_AGGREGATOR as if it were
2046 * AGGREGATOR in that case
2048 if (BGP_DEBUG(as4
, AS4
))
2050 "[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",
2052 attr
->aggregator_as
= as4_aggregator
;
2053 /* sweep it under the carpet and simulate a "good"
2055 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
2059 /* need to reconcile NEW_AS_PATH and AS_PATH */
2060 if (!ignore_as4_path
2061 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
2062 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
2064 return BGP_ATTR_PARSE_ERROR
;
2066 aspath_unintern(&attr
->aspath
);
2067 attr
->aspath
= aspath_intern(newpath
);
2069 return BGP_ATTR_PARSE_PROCEED
;
2072 /* Community attribute. */
2073 static enum bgp_attr_parse_ret
2074 bgp_attr_community(struct bgp_attr_parser_args
*args
)
2076 struct peer
*const peer
= args
->peer
;
2077 struct attr
*const attr
= args
->attr
;
2078 const bgp_size_t length
= args
->length
;
2081 bgp_attr_set_community(attr
, NULL
);
2082 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2086 bgp_attr_set_community(
2088 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
2090 /* XXX: fix community_parse to use stream API and remove this */
2091 stream_forward_getp(peer
->curr
, length
);
2093 /* The Community attribute SHALL be considered malformed if its
2094 * length is not a non-zero multiple of 4.
2096 if (!bgp_attr_get_community(attr
))
2097 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2100 return BGP_ATTR_PARSE_PROCEED
;
2103 /* Originator ID attribute. */
2104 static enum bgp_attr_parse_ret
2105 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
2107 struct peer
*const peer
= args
->peer
;
2108 struct attr
*const attr
= args
->attr
;
2109 const bgp_size_t length
= args
->length
;
2111 /* if received from an internal neighbor, it SHALL be considered
2112 * malformed if its length is not equal to 4. If malformed, the
2113 * UPDATE message SHALL be handled using the approach of "treat-as-
2117 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
2120 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2124 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
2126 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2128 return BGP_ATTR_PARSE_PROCEED
;
2131 /* Cluster list attribute. */
2132 static enum bgp_attr_parse_ret
2133 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2135 struct peer
*const peer
= args
->peer
;
2136 struct attr
*const attr
= args
->attr
;
2137 const bgp_size_t length
= args
->length
;
2139 /* if received from an internal neighbor, it SHALL be considered
2140 * malformed if its length is not a non-zero multiple of 4. If
2141 * malformed, the UPDATE message SHALL be handled using the approach
2142 * of "treat-as-withdraw".
2144 if (length
== 0 || length
% 4) {
2145 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2147 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2151 bgp_attr_set_cluster(
2152 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2155 /* XXX: Fix cluster_parse to use stream API and then remove this */
2156 stream_forward_getp(peer
->curr
, length
);
2158 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2160 return BGP_ATTR_PARSE_PROCEED
;
2163 /* Multiprotocol reachability information parse. */
2164 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2165 struct bgp_nlri
*mp_update
)
2169 iana_safi_t pkt_safi
;
2171 bgp_size_t nlri_len
;
2174 struct peer
*const peer
= args
->peer
;
2175 struct attr
*const attr
= args
->attr
;
2176 const bgp_size_t length
= args
->length
;
2178 /* Set end of packet. */
2179 s
= BGP_INPUT(peer
);
2180 start
= stream_get_getp(s
);
2182 /* safe to read statically sized header? */
2183 #define BGP_MP_REACH_MIN_SIZE 5
2184 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2185 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2186 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2187 __func__
, peer
->host
, (unsigned long)length
);
2188 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2191 /* Load AFI, SAFI. */
2192 pkt_afi
= stream_getw(s
);
2193 pkt_safi
= stream_getc(s
);
2195 /* Convert AFI, SAFI to internal values, check. */
2196 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2197 /* Log if AFI or SAFI is unrecognized. This is not an error
2199 * the attribute is otherwise malformed.
2201 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2203 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2204 peer
->host
, iana_afi2str(pkt_afi
),
2205 iana_safi2str(pkt_safi
));
2206 return BGP_ATTR_PARSE_ERROR
;
2209 /* Get nexthop length. */
2210 attr
->mp_nexthop_len
= stream_getc(s
);
2212 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2214 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2215 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2216 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2219 /* Nexthop length check. */
2220 switch (attr
->mp_nexthop_len
) {
2222 if (safi
!= SAFI_FLOWSPEC
) {
2223 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2224 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2225 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2228 case BGP_ATTR_NHLEN_VPNV4
:
2229 stream_getl(s
); /* RD high */
2230 stream_getl(s
); /* RD low */
2232 * NOTE: intentional fall through
2233 * - for consistency in rx processing
2235 * The following comment is to signal GCC this intention
2236 * and suppress the warning
2239 case BGP_ATTR_NHLEN_IPV4
:
2240 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2241 /* Probably needed for RFC 2283 */
2242 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2243 memcpy(&attr
->nexthop
.s_addr
,
2244 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2246 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2247 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2248 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2249 stream_getl(s
); /* RD high */
2250 stream_getl(s
); /* RD low */
2252 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2253 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2254 if (!peer
->nexthop
.ifp
) {
2255 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2257 return BGP_ATTR_PARSE_WITHDRAW
;
2259 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2262 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2263 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2264 if (attr
->mp_nexthop_len
2265 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2266 stream_getl(s
); /* RD high */
2267 stream_getl(s
); /* RD low */
2269 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2270 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2271 if (!peer
->nexthop
.ifp
) {
2272 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",
2274 return BGP_ATTR_PARSE_WITHDRAW
;
2276 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2278 if (attr
->mp_nexthop_len
2279 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2280 stream_getl(s
); /* RD high */
2281 stream_getl(s
); /* RD low */
2283 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2284 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2285 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2287 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2288 peer
->host
, &attr
->mp_nexthop_global
,
2289 &attr
->mp_nexthop_local
);
2291 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2293 if (!peer
->nexthop
.ifp
) {
2294 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2296 return BGP_ATTR_PARSE_WITHDRAW
;
2298 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2301 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2302 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2303 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2307 zlog_info("%s: %s sent SNPA which couldn't be read",
2308 __func__
, peer
->host
);
2309 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2314 if ((val
= stream_getc(s
)))
2316 EC_BGP_DEFUNCT_SNPA_LEN
,
2317 "%s sent non-zero value, %u, for defunct SNPA-length field",
2321 /* must have nrli_len, what is left of the attribute */
2322 nlri_len
= LEN_LEFT
;
2323 if (nlri_len
> STREAM_READABLE(s
)) {
2324 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2325 __func__
, peer
->host
);
2326 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2330 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2331 __func__
, peer
->host
);
2333 mp_update
->afi
= afi
;
2334 mp_update
->safi
= safi
;
2335 return BGP_ATTR_PARSE_EOR
;
2338 mp_update
->afi
= afi
;
2339 mp_update
->safi
= safi
;
2340 mp_update
->nlri
= stream_pnt(s
);
2341 mp_update
->length
= nlri_len
;
2343 stream_forward_getp(s
, nlri_len
);
2345 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2347 return BGP_ATTR_PARSE_PROCEED
;
2351 /* Multiprotocol unreachable parse */
2352 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2353 struct bgp_nlri
*mp_withdraw
)
2358 iana_safi_t pkt_safi
;
2360 uint16_t withdraw_len
;
2361 struct peer
*const peer
= args
->peer
;
2362 struct attr
*const attr
= args
->attr
;
2363 const bgp_size_t length
= args
->length
;
2367 #define BGP_MP_UNREACH_MIN_SIZE 3
2368 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2369 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2371 pkt_afi
= stream_getw(s
);
2372 pkt_safi
= stream_getc(s
);
2374 /* Convert AFI, SAFI to internal values, check. */
2375 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2376 /* Log if AFI or SAFI is unrecognized. This is not an error
2378 * the attribute is otherwise malformed.
2380 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2382 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2383 peer
->host
, iana_afi2str(pkt_afi
),
2384 iana_safi2str(pkt_safi
));
2385 return BGP_ATTR_PARSE_ERROR
;
2388 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2390 mp_withdraw
->afi
= afi
;
2391 mp_withdraw
->safi
= safi
;
2392 mp_withdraw
->nlri
= stream_pnt(s
);
2393 mp_withdraw
->length
= withdraw_len
;
2395 stream_forward_getp(s
, withdraw_len
);
2397 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2399 return BGP_ATTR_PARSE_PROCEED
;
2402 /* Large Community attribute. */
2403 static enum bgp_attr_parse_ret
2404 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2406 struct peer
*const peer
= args
->peer
;
2407 struct attr
*const attr
= args
->attr
;
2408 const bgp_size_t length
= args
->length
;
2411 * Large community follows new attribute format.
2414 bgp_attr_set_lcommunity(attr
, NULL
);
2415 /* Empty extcomm doesn't seem to be invalid per se */
2416 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2420 bgp_attr_set_lcommunity(
2421 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2422 /* XXX: fix ecommunity_parse to use stream API */
2423 stream_forward_getp(peer
->curr
, length
);
2425 if (!bgp_attr_get_lcommunity(attr
))
2426 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2429 return BGP_ATTR_PARSE_PROCEED
;
2432 /* Extended Community attribute. */
2433 static enum bgp_attr_parse_ret
2434 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2436 struct peer
*const peer
= args
->peer
;
2437 struct attr
*const attr
= args
->attr
;
2438 const bgp_size_t length
= args
->length
;
2441 struct ecommunity
*ecomm
;
2444 bgp_attr_set_ecommunity(attr
, NULL
);
2445 /* Empty extcomm doesn't seem to be invalid per se */
2446 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2450 ecomm
= ecommunity_parse(
2451 stream_pnt(peer
->curr
), length
,
2452 CHECK_FLAG(peer
->flags
,
2453 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2454 bgp_attr_set_ecommunity(attr
, ecomm
);
2455 /* XXX: fix ecommunity_parse to use stream API */
2456 stream_forward_getp(peer
->curr
, length
);
2458 /* The Extended Community attribute SHALL be considered malformed if
2459 * its length is not a non-zero multiple of 8.
2461 if (!bgp_attr_get_ecommunity(attr
))
2462 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2465 /* Extract DF election preference and mobility sequence number */
2466 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2468 /* Extract MAC mobility sequence number, if any. */
2469 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2470 attr
->sticky
= sticky
;
2472 /* Check if this is a Gateway MAC-IP advertisement */
2473 attr
->default_gw
= bgp_attr_default_gw(attr
);
2475 /* Handle scenario where router flag ecommunity is not
2476 * set but default gw ext community is present.
2477 * Use default gateway, set and propogate R-bit.
2479 if (attr
->default_gw
)
2480 attr
->router_flag
= 1;
2482 /* Check EVPN Neighbor advertisement flags, R-bit */
2483 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2485 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2487 /* Extract the Rmac, if any */
2488 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2489 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2490 && bgp_mac_exist(&attr
->rmac
))
2491 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2495 /* Get the tunnel type from encap extended community */
2496 bgp_attr_extcom_tunnel_type(attr
,
2497 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2499 /* Extract link bandwidth, if any. */
2500 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2503 return BGP_ATTR_PARSE_PROCEED
;
2506 /* IPv6 Extended Community attribute. */
2507 static enum bgp_attr_parse_ret
2508 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2510 struct peer
*const peer
= args
->peer
;
2511 struct attr
*const attr
= args
->attr
;
2512 const bgp_size_t length
= args
->length
;
2513 struct ecommunity
*ipv6_ecomm
= NULL
;
2516 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2517 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2521 ipv6_ecomm
= ecommunity_parse_ipv6(
2522 stream_pnt(peer
->curr
), length
,
2523 CHECK_FLAG(peer
->flags
,
2524 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2525 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2527 /* XXX: fix ecommunity_parse to use stream API */
2528 stream_forward_getp(peer
->curr
, length
);
2531 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2534 return BGP_ATTR_PARSE_PROCEED
;
2537 /* Parse Tunnel Encap attribute in an UPDATE */
2538 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2539 bgp_size_t length
, /* IN: attr's length field */
2540 struct attr
*attr
, /* IN: caller already allocated */
2541 uint8_t flag
, /* IN: attr's flags field */
2545 uint16_t tunneltype
= 0;
2547 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2549 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2550 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2552 "Tunnel Encap attribute flag isn't optional and transitive %d",
2554 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2555 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2560 if (BGP_ATTR_ENCAP
== type
) {
2561 /* read outer TLV type and length */
2562 uint16_t tlv_length
;
2566 "Tunnel Encap attribute not long enough to contain outer T,L");
2567 bgp_notify_send_with_data(
2568 peer
, BGP_NOTIFY_UPDATE_ERR
,
2569 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2572 tunneltype
= stream_getw(BGP_INPUT(peer
));
2573 tlv_length
= stream_getw(BGP_INPUT(peer
));
2576 if (tlv_length
!= length
) {
2577 zlog_info("%s: tlv_length(%d) != length(%d)",
2578 __func__
, tlv_length
, length
);
2582 while (length
>= 4) {
2583 uint16_t subtype
= 0;
2584 uint16_t sublength
= 0;
2585 struct bgp_attr_encap_subtlv
*tlv
;
2587 if (BGP_ATTR_ENCAP
== type
) {
2588 subtype
= stream_getc(BGP_INPUT(peer
));
2589 sublength
= stream_getc(BGP_INPUT(peer
));
2591 #ifdef ENABLE_BGP_VNC
2593 subtype
= stream_getw(BGP_INPUT(peer
));
2594 sublength
= stream_getw(BGP_INPUT(peer
));
2599 if (sublength
> length
) {
2601 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2603 bgp_notify_send_with_data(
2604 peer
, BGP_NOTIFY_UPDATE_ERR
,
2605 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2609 /* alloc and copy sub-tlv */
2610 /* TBD make sure these are freed when attributes are released */
2611 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2612 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2613 tlv
->type
= subtype
;
2614 tlv
->length
= sublength
;
2615 stream_get(tlv
->value
, peer
->curr
, sublength
);
2616 length
-= sublength
;
2618 /* attach tlv to encap chain */
2619 if (BGP_ATTR_ENCAP
== type
) {
2620 struct bgp_attr_encap_subtlv
*stlv_last
;
2621 for (stlv_last
= attr
->encap_subtlvs
;
2622 stlv_last
&& stlv_last
->next
;
2623 stlv_last
= stlv_last
->next
)
2626 stlv_last
->next
= tlv
;
2628 attr
->encap_subtlvs
= tlv
;
2630 #ifdef ENABLE_BGP_VNC
2632 struct bgp_attr_encap_subtlv
*stlv_last
;
2633 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2634 bgp_attr_get_vnc_subtlvs(attr
);
2636 for (stlv_last
= vnc_subtlvs
;
2637 stlv_last
&& stlv_last
->next
;
2638 stlv_last
= stlv_last
->next
)
2641 stlv_last
->next
= tlv
;
2643 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2648 if (BGP_ATTR_ENCAP
== type
) {
2649 attr
->encap_tunneltype
= tunneltype
;
2653 /* spurious leftover data */
2655 "Tunnel Encap attribute length is bad: %d leftover octets",
2657 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2658 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2667 /* SRv6 Service Data Sub-Sub-TLV attribute
2668 * draft-ietf-bess-srv6-services-07
2670 static enum bgp_attr_parse_ret
2671 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2673 struct peer
*const peer
= args
->peer
;
2674 struct attr
*const attr
= args
->attr
;
2675 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2676 transposition_len
, transposition_offset
;
2678 size_t headersz
= sizeof(type
) + sizeof(length
);
2680 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2683 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2684 headersz
, STREAM_READABLE(peer
->curr
));
2685 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2689 type
= stream_getc(peer
->curr
);
2690 length
= stream_getw(peer
->curr
);
2692 if (STREAM_READABLE(peer
->curr
) < length
) {
2695 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2696 length
, STREAM_READABLE(peer
->curr
));
2697 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2701 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2704 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2705 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2707 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2711 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2712 loc_block_len
= stream_getc(peer
->curr
);
2713 loc_node_len
= stream_getc(peer
->curr
);
2714 func_len
= stream_getc(peer
->curr
);
2715 arg_len
= stream_getc(peer
->curr
);
2716 transposition_len
= stream_getc(peer
->curr
);
2717 transposition_offset
= stream_getc(peer
->curr
);
2719 /* Log SRv6 Service Data Sub-Sub-TLV */
2720 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2722 "%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",
2723 __func__
, loc_block_len
, loc_node_len
, func_len
,
2724 arg_len
, transposition_len
,
2725 transposition_offset
);
2728 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2729 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2730 attr
->srv6_l3vpn
->func_len
= func_len
;
2731 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2732 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2733 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2737 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2739 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2742 stream_forward_getp(peer
->curr
, length
);
2745 return BGP_ATTR_PARSE_PROCEED
;
2748 /* SRv6 Service Sub-TLV attribute
2749 * draft-ietf-bess-srv6-services-07
2751 static enum bgp_attr_parse_ret
2752 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2754 struct peer
*const peer
= args
->peer
;
2755 struct attr
*const attr
= args
->attr
;
2756 struct in6_addr ipv6_sid
;
2757 uint8_t type
, sid_flags
;
2758 uint16_t length
, endpoint_behavior
;
2759 size_t headersz
= sizeof(type
) + sizeof(length
);
2760 enum bgp_attr_parse_ret err
;
2763 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2766 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2767 headersz
, STREAM_READABLE(peer
->curr
));
2768 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2772 type
= stream_getc(peer
->curr
);
2773 length
= stream_getw(peer
->curr
);
2775 if (STREAM_READABLE(peer
->curr
) < length
) {
2778 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2779 length
, STREAM_READABLE(peer
->curr
));
2780 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2784 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2785 stream_getc(peer
->curr
);
2786 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2787 sid_flags
= stream_getc(peer
->curr
);
2788 endpoint_behavior
= stream_getw(peer
->curr
);
2789 stream_getc(peer
->curr
);
2791 /* Log SRv6 Service Sub-TLV */
2792 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2793 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2795 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2796 __func__
, buf
, sid_flags
, endpoint_behavior
);
2799 /* Configure from Info */
2800 if (attr
->srv6_l3vpn
) {
2801 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2802 "Prefix SID SRv6 L3VPN field repeated");
2803 return bgp_attr_malformed(
2804 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2806 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2807 sizeof(struct bgp_attr_srv6_l3vpn
));
2808 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2809 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2810 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2811 attr
->srv6_l3vpn
->loc_block_len
= 0;
2812 attr
->srv6_l3vpn
->loc_node_len
= 0;
2813 attr
->srv6_l3vpn
->func_len
= 0;
2814 attr
->srv6_l3vpn
->arg_len
= 0;
2815 attr
->srv6_l3vpn
->transposition_len
= 0;
2816 attr
->srv6_l3vpn
->transposition_offset
= 0;
2818 // Sub-Sub-TLV found
2819 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2820 err
= bgp_attr_srv6_service_data(args
);
2822 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2826 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2829 /* Placeholder code for unsupported type */
2831 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2833 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2836 stream_forward_getp(peer
->curr
, length
);
2839 return BGP_ATTR_PARSE_PROCEED
;
2843 * Read an individual SID value returning how much data we have read
2844 * Returns 0 if there was an error that needs to be passed up the stack
2846 static enum bgp_attr_parse_ret
2847 bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2848 struct bgp_attr_parser_args
*args
)
2850 struct peer
*const peer
= args
->peer
;
2851 struct attr
*const attr
= args
->attr
;
2852 uint32_t label_index
;
2853 struct in6_addr ipv6_sid
;
2855 uint32_t srgb_range
;
2857 uint8_t sid_type
, sid_flags
;
2860 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2861 if (STREAM_READABLE(peer
->curr
) < length
2862 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2863 flog_err(EC_BGP_ATTR_LEN
,
2864 "Prefix SID label index length is %hu instead of %u",
2865 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2866 return bgp_attr_malformed(args
,
2867 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2871 /* Ignore flags and reserved */
2872 stream_getc(peer
->curr
);
2873 stream_getw(peer
->curr
);
2875 /* Fetch the label index and see if it is valid. */
2876 label_index
= stream_getl(peer
->curr
);
2877 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2878 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2881 /* Store label index; subsequently, we'll check on
2883 attr
->label_index
= label_index
;
2886 /* Placeholder code for the IPv6 SID type */
2887 else if (type
== BGP_PREFIX_SID_IPV6
) {
2888 if (STREAM_READABLE(peer
->curr
) < length
2889 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2890 flog_err(EC_BGP_ATTR_LEN
,
2891 "Prefix SID IPv6 length is %hu instead of %u",
2892 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2893 return bgp_attr_malformed(args
,
2894 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2898 /* Ignore reserved */
2899 stream_getc(peer
->curr
);
2900 stream_getw(peer
->curr
);
2902 stream_get(&ipv6_sid
, peer
->curr
, 16);
2905 /* Placeholder code for the Originator SRGB type */
2906 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2908 * ietf-idr-bgp-prefix-sid-05:
2909 * Length is the total length of the value portion of the
2910 * TLV: 2 + multiple of 6.
2912 * peer->curr stream readp should be at the beginning of the 16
2913 * bit flag field at this point in the code.
2917 * Check that the TLV length field is sane: at least 2 bytes of
2918 * flag, and at least 1 SRGB (these are 6 bytes each)
2920 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2923 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2925 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2926 return bgp_attr_malformed(
2927 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2932 * Check that we actually have at least as much data as
2933 * specified by the length field
2935 if (STREAM_READABLE(peer
->curr
) < length
) {
2936 flog_err(EC_BGP_ATTR_LEN
,
2937 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2938 length
, STREAM_READABLE(peer
->curr
));
2939 return bgp_attr_malformed(
2940 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2945 * Check that the portion of the TLV containing the sequence of
2946 * SRGBs corresponds to a multiple of the SRGB size; to get
2947 * that length, we skip the 16 bit flags field
2949 stream_getw(peer
->curr
);
2951 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2954 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2955 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2956 return bgp_attr_malformed(
2957 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2961 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2963 for (int i
= 0; i
< srgb_count
; i
++) {
2964 stream_get(&srgb_base
, peer
->curr
, 3);
2965 stream_get(&srgb_range
, peer
->curr
, 3);
2969 /* Placeholder code for the VPN-SID Service type */
2970 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2971 if (STREAM_READABLE(peer
->curr
) < length
2972 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2973 flog_err(EC_BGP_ATTR_LEN
,
2974 "Prefix SID VPN SID length is %hu instead of %u",
2975 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2976 return bgp_attr_malformed(args
,
2977 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2981 /* Parse VPN-SID Sub-TLV */
2982 stream_getc(peer
->curr
); /* reserved */
2983 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2984 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2985 stream_get(&ipv6_sid
, peer
->curr
,
2986 sizeof(ipv6_sid
)); /* sid_value */
2988 /* Log VPN-SID Sub-TLV */
2989 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2990 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2992 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2993 __func__
, buf
, sid_type
, sid_flags
);
2996 /* Configure from Info */
2997 if (attr
->srv6_vpn
) {
2998 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2999 "Prefix SID SRv6 VPN field repeated");
3000 return bgp_attr_malformed(
3001 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
3003 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
3004 sizeof(struct bgp_attr_srv6_vpn
));
3005 attr
->srv6_vpn
->sid_flags
= sid_flags
;
3006 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
3007 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
3010 /* Placeholder code for the SRv6 L3 Service type */
3011 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
3012 if (STREAM_READABLE(peer
->curr
) < length
) {
3015 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
3016 length
, STREAM_READABLE(peer
->curr
));
3017 return bgp_attr_malformed(args
,
3018 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3022 /* ignore reserved */
3023 stream_getc(peer
->curr
);
3025 return bgp_attr_srv6_service(args
);
3028 /* Placeholder code for Unsupported TLV */
3031 if (STREAM_READABLE(peer
->curr
) < length
) {
3034 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
3035 length
, STREAM_READABLE(peer
->curr
));
3036 return bgp_attr_malformed(
3037 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3041 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3043 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3046 stream_forward_getp(peer
->curr
, length
);
3049 return BGP_ATTR_PARSE_PROCEED
;
3052 /* Prefix SID attribute
3053 * draft-ietf-idr-bgp-prefix-sid-05
3055 enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
3057 struct peer
*const peer
= args
->peer
;
3058 struct attr
*const attr
= args
->attr
;
3059 enum bgp_attr_parse_ret ret
;
3061 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3065 size_t headersz
= sizeof(type
) + sizeof(length
);
3066 size_t psid_parsed_length
= 0;
3068 while (STREAM_READABLE(peer
->curr
) > 0
3069 && psid_parsed_length
< args
->length
) {
3071 if (STREAM_READABLE(peer
->curr
) < headersz
) {
3074 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3075 headersz
, STREAM_READABLE(peer
->curr
));
3076 return bgp_attr_malformed(
3077 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3081 type
= stream_getc(peer
->curr
);
3082 length
= stream_getw(peer
->curr
);
3084 if (STREAM_READABLE(peer
->curr
) < length
) {
3087 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3088 length
, STREAM_READABLE(peer
->curr
));
3089 return bgp_attr_malformed(args
,
3090 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3094 ret
= bgp_attr_psid_sub(type
, length
, args
);
3096 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3099 psid_parsed_length
+= length
+ headersz
;
3101 if (psid_parsed_length
> args
->length
) {
3104 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
3105 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
3106 return bgp_attr_malformed(
3107 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3112 return BGP_ATTR_PARSE_PROCEED
;
3115 /* PMSI tunnel attribute (RFC 6514)
3116 * Basic validation checks done here.
3118 static enum bgp_attr_parse_ret
3119 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
3121 struct peer
*const peer
= args
->peer
;
3122 struct attr
*const attr
= args
->attr
;
3123 const bgp_size_t length
= args
->length
;
3125 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
3127 /* Verify that the receiver is expecting "ingress replication" as we
3128 * can only support that.
3130 if (length
< attr_parse_len
) {
3131 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
3133 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3136 stream_getc(peer
->curr
); /* Flags */
3137 tnl_type
= stream_getc(peer
->curr
);
3138 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3139 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3140 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3141 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3144 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3146 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3147 "Bad PMSI tunnel attribute length %d for IR",
3149 return bgp_attr_malformed(
3150 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3155 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3156 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3157 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3159 /* Forward read pointer of input stream. */
3160 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3162 return BGP_ATTR_PARSE_PROCEED
;
3165 /* AIGP attribute (rfc7311) */
3166 static enum bgp_attr_parse_ret
bgp_attr_aigp(struct bgp_attr_parser_args
*args
)
3168 struct peer
*const peer
= args
->peer
;
3169 struct attr
*const attr
= args
->attr
;
3170 const bgp_size_t length
= args
->length
;
3171 uint8_t *s
= stream_pnt(peer
->curr
);
3174 /* If an AIGP attribute is received on a BGP session for which
3175 * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3176 * as if it were an unrecognized non-transitive attribute.
3177 * That is, it "MUST be quietly ignored and not passed along to
3179 * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3180 * sessions between members of the same BGP Confederation,
3181 * the default value of AIGP_SESSION SHOULD be "enabled".
3183 if (peer
->sort
== BGP_PEER_EBGP
&&
3184 !CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
)) {
3186 "%pBP received AIGP attribute, but eBGP peer do not support it",
3191 if (!bgp_attr_aigp_valid(s
, length
))
3194 /* Extract AIGP Metric TLV */
3195 if (bgp_attr_aigp_get_tlv_metric(s
, length
, &aigp
))
3196 bgp_attr_set_aigp_metric(attr
, aigp
);
3199 stream_forward_getp(peer
->curr
, length
);
3201 return BGP_ATTR_PARSE_PROCEED
;
3204 /* OTC attribute. */
3205 static enum bgp_attr_parse_ret
bgp_attr_otc(struct bgp_attr_parser_args
*args
)
3207 struct peer
*const peer
= args
->peer
;
3208 struct attr
*const attr
= args
->attr
;
3209 const bgp_size_t length
= args
->length
;
3213 flog_err(EC_BGP_ATTR_LEN
, "OTC attribute length isn't 4 [%u]",
3215 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3219 attr
->otc
= stream_getl(peer
->curr
);
3221 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "OTC attribute value is 0");
3222 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
3226 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
3228 return BGP_ATTR_PARSE_PROCEED
;
3231 /* BGP unknown attribute treatment. */
3232 static enum bgp_attr_parse_ret
3233 bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3235 bgp_size_t total
= args
->total
;
3236 struct transit
*transit
;
3237 struct peer
*const peer
= args
->peer
;
3238 struct attr
*const attr
= args
->attr
;
3239 uint8_t *const startp
= args
->startp
;
3240 const uint8_t type
= args
->type
;
3241 const uint8_t flag
= args
->flags
;
3242 const bgp_size_t length
= args
->length
;
3244 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3246 "%s Unknown attribute is received (type %d, length %d)",
3247 peer
->host
, type
, length
);
3249 /* Forward read pointer of input stream. */
3250 stream_forward_getp(peer
->curr
, length
);
3252 /* If any of the mandatory well-known attributes are not recognized,
3253 then the Error Subcode is set to Unrecognized Well-known
3254 Attribute. The Data field contains the unrecognized attribute
3255 (type, length and value). */
3256 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3257 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3261 /* Unrecognized non-transitive optional attributes must be quietly
3262 ignored and not passed along to other BGP peers. */
3263 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3264 return BGP_ATTR_PARSE_PROCEED
;
3266 /* If a path with recognized transitive optional attribute is
3267 accepted and passed along to other BGP peers and the Partial bit
3268 in the Attribute Flags octet is set to 1 by some previous AS, it
3269 is not set back to 0 by the current AS. */
3270 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3272 /* Store transitive attribute to the end of attr->transit. */
3273 transit
= bgp_attr_get_transit(attr
);
3275 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3277 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3278 transit
->length
+ total
);
3280 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3281 transit
->length
+= total
;
3282 bgp_attr_set_transit(attr
, transit
);
3284 return BGP_ATTR_PARSE_PROCEED
;
3287 /* Well-known attribute check. */
3288 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3292 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3294 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3295 return BGP_ATTR_PARSE_PROCEED
;
3297 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3298 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3299 are present, it should. Check for any other attribute being present
3302 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3303 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3304 return BGP_ATTR_PARSE_PROCEED
;
3306 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3307 type
= BGP_ATTR_ORIGIN
;
3309 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3310 type
= BGP_ATTR_AS_PATH
;
3312 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3314 * NLRI is empty. We can't easily check NLRI empty here though.
3316 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3317 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3318 type
= BGP_ATTR_NEXT_HOP
;
3320 if (peer
->sort
== BGP_PEER_IBGP
3321 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3322 type
= BGP_ATTR_LOCAL_PREF
;
3324 /* If any of the well-known mandatory attributes are not present
3325 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3328 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3329 "%s Missing well-known attribute %s.", peer
->host
,
3330 lookup_msg(attr_str
, type
, NULL
));
3331 return BGP_ATTR_PARSE_WITHDRAW
;
3333 return BGP_ATTR_PARSE_PROCEED
;
3336 /* Read attribute of update packet. This function is called from
3337 bgp_update_receive() in bgp_packet.c. */
3338 enum bgp_attr_parse_ret
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3340 struct bgp_nlri
*mp_update
,
3341 struct bgp_nlri
*mp_withdraw
)
3343 enum bgp_attr_parse_ret ret
;
3347 uint8_t *startp
, *endp
;
3349 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3350 /* we need the as4_path only until we have synthesized the as_path with
3352 /* same goes for as4_aggregator */
3353 struct aspath
*as4_path
= NULL
;
3354 as_t as4_aggregator
= 0;
3355 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3356 struct transit
*transit
;
3358 /* Initialize bitmap. */
3359 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3361 /* End pointer of BGP attribute. */
3362 endp
= BGP_INPUT_PNT(peer
) + size
;
3364 /* Get attributes to the end of attribute length. */
3365 while (BGP_INPUT_PNT(peer
) < endp
) {
3366 /* Check remaining length check.*/
3367 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3368 /* XXX warning: long int format, int arg (arg 5) */
3370 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3371 "%s: error BGP attribute length %lu is smaller than min len",
3373 (unsigned long)(endp
3374 - stream_pnt(BGP_INPUT(peer
))));
3376 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3377 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3378 ret
= BGP_ATTR_PARSE_ERROR
;
3382 /* Fetch attribute flag and type. */
3383 startp
= BGP_INPUT_PNT(peer
);
3384 /* "The lower-order four bits of the Attribute Flags octet are
3385 unused. They MUST be zero when sent and MUST be ignored when
3387 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3388 type
= stream_getc(BGP_INPUT(peer
));
3390 /* Check whether Extended-Length applies and is in bounds */
3391 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3392 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3394 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3395 "%s: Extended length set, but just %lu bytes of attr header",
3397 (unsigned long)(endp
3398 - stream_pnt(BGP_INPUT(peer
))));
3400 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3401 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3402 ret
= BGP_ATTR_PARSE_ERROR
;
3406 /* Check extended attribue length bit. */
3407 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3408 length
= stream_getw(BGP_INPUT(peer
));
3410 length
= stream_getc(BGP_INPUT(peer
));
3412 /* If any attribute appears more than once in the UPDATE
3413 message, then the Error Subcode is set to Malformed Attribute
3416 if (CHECK_BITMAP(seen
, type
)) {
3418 EC_BGP_ATTRIBUTE_REPEATED
,
3419 "%s: error BGP attribute type %d appears twice in a message",
3422 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3423 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3424 ret
= BGP_ATTR_PARSE_ERROR
;
3428 /* Set type to bitmap to check duplicate attribute. `type' is
3429 unsigned char so it never overflow bitmap range. */
3431 SET_BITMAP(seen
, type
);
3433 /* Overflow check. */
3434 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3436 if (attr_endp
> endp
) {
3438 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3439 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3440 peer
->host
, type
, length
, size
, attr_endp
,
3444 * If any recognized attribute has an Attribute
3445 * Length that conflicts with the expected length
3446 * (based on the attribute type code), then the
3447 * Error Subcode MUST be set to Attribute Length
3448 * Error. The Data field MUST contain the erroneous
3449 * attribute (type, length, and value).
3451 * We do not currently have a good way to determine the
3452 * length of the attribute independent of the length
3453 * received in the message. Instead we send the
3454 * minimum between the amount of data we have and the
3455 * amount specified by the attribute length field.
3457 * Instead of directly passing in the packet buffer and
3458 * offset we use the stream_get* functions to read into
3459 * a stack buffer, since they perform bounds checking
3460 * and we are working with untrusted data.
3462 unsigned char ndata
[peer
->max_packet_size
];
3463 memset(ndata
, 0x00, sizeof(ndata
));
3465 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3466 /* Rewind to end of flag field */
3467 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3469 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3471 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3473 size_t atl
= attr_endp
- startp
;
3474 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3475 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3477 bgp_notify_send_with_data(
3478 peer
, BGP_NOTIFY_UPDATE_ERR
,
3479 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3482 ret
= BGP_ATTR_PARSE_ERROR
;
3486 struct bgp_attr_parser_args attr_args
= {
3493 .total
= attr_endp
- startp
,
3497 /* If any recognized attribute has Attribute Flags that conflict
3498 with the Attribute Type Code, then the Error Subcode is set
3500 Attribute Flags Error. The Data field contains the erroneous
3501 attribute (type, length and value). */
3502 if (bgp_attr_flag_invalid(&attr_args
)) {
3503 ret
= bgp_attr_malformed(
3504 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3506 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3511 /* OK check attribute and store it's value. */
3513 case BGP_ATTR_ORIGIN
:
3514 ret
= bgp_attr_origin(&attr_args
);
3516 case BGP_ATTR_AS_PATH
:
3517 ret
= bgp_attr_aspath(&attr_args
);
3519 case BGP_ATTR_AS4_PATH
:
3520 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3522 case BGP_ATTR_NEXT_HOP
:
3523 ret
= bgp_attr_nexthop(&attr_args
);
3525 case BGP_ATTR_MULTI_EXIT_DISC
:
3526 ret
= bgp_attr_med(&attr_args
);
3528 case BGP_ATTR_LOCAL_PREF
:
3529 ret
= bgp_attr_local_pref(&attr_args
);
3531 case BGP_ATTR_ATOMIC_AGGREGATE
:
3532 ret
= bgp_attr_atomic(&attr_args
);
3534 case BGP_ATTR_AGGREGATOR
:
3535 ret
= bgp_attr_aggregator(&attr_args
);
3537 case BGP_ATTR_AS4_AGGREGATOR
:
3538 ret
= bgp_attr_as4_aggregator(&attr_args
,
3540 &as4_aggregator_addr
);
3542 case BGP_ATTR_COMMUNITIES
:
3543 ret
= bgp_attr_community(&attr_args
);
3545 case BGP_ATTR_LARGE_COMMUNITIES
:
3546 ret
= bgp_attr_large_community(&attr_args
);
3548 case BGP_ATTR_ORIGINATOR_ID
:
3549 ret
= bgp_attr_originator_id(&attr_args
);
3551 case BGP_ATTR_CLUSTER_LIST
:
3552 ret
= bgp_attr_cluster_list(&attr_args
);
3554 case BGP_ATTR_MP_REACH_NLRI
:
3555 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3557 case BGP_ATTR_MP_UNREACH_NLRI
:
3558 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3560 case BGP_ATTR_EXT_COMMUNITIES
:
3561 ret
= bgp_attr_ext_communities(&attr_args
);
3563 #ifdef ENABLE_BGP_VNC_ATTR
3566 case BGP_ATTR_ENCAP
:
3567 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3570 case BGP_ATTR_PREFIX_SID
:
3571 ret
= bgp_attr_prefix_sid(&attr_args
);
3573 case BGP_ATTR_PMSI_TUNNEL
:
3574 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3576 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3577 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3580 ret
= bgp_attr_otc(&attr_args
);
3583 ret
= bgp_attr_aigp(&attr_args
);
3586 ret
= bgp_attr_unknown(&attr_args
);
3590 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3591 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3592 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3593 ret
= BGP_ATTR_PARSE_ERROR
;
3597 if (ret
== BGP_ATTR_PARSE_EOR
) {
3601 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3602 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3603 "%s: Attribute %s, parse error", peer
->host
,
3604 lookup_msg(attr_str
, type
, NULL
));
3607 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3609 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3610 "%s: Attribute %s, parse error - treating as withdrawal",
3611 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3615 /* Check the fetched length. */
3616 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3617 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3618 "%s: BGP attribute %s, fetch error",
3619 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3620 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3621 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3622 ret
= BGP_ATTR_PARSE_ERROR
;
3628 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3629 * About Prefix-SID path attribute,
3630 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3631 * may only appear in a BGP Prefix-SID attribute attached to
3632 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3633 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3635 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3636 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3638 /* Check final read pointer is same as end pointer. */
3639 if (BGP_INPUT_PNT(peer
) != endp
) {
3640 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3641 "%s: BGP attribute %s, length mismatch", peer
->host
,
3642 lookup_msg(attr_str
, type
, NULL
));
3643 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3644 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3646 ret
= BGP_ATTR_PARSE_ERROR
;
3651 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3652 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3653 * This is implemented below and will result in a NOTIFICATION. If the
3654 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3655 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3656 * message SHOULD NOT be sent. This is implemented elsewhere.
3658 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3659 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3660 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3661 * speaker that receives the message SHOULD ignore this attribute.
3663 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3664 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3665 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3666 ret
= BGP_ATTR_PARSE_ERROR
;
3671 /* Check all mandatory well-known attributes are present */
3672 ret
= bgp_attr_check(peer
, attr
);
3677 * At this place we can see whether we got AS4_PATH and/or
3678 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3679 * We can not do this before we've read all attributes because
3680 * the as4 handling does not say whether AS4_PATH has to be sent
3681 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3682 * in relationship to AGGREGATOR.
3683 * So, to be defensive, we are not relying on any order and read
3684 * all attributes first, including these 32bit ones, and now,
3685 * afterwards, we look what and if something is to be done for as4.
3687 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3690 /* actually... this doesn't ever return failure currently, but
3691 * better safe than sorry */
3692 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3693 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3694 &as4_aggregator_addr
)) {
3695 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3696 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3697 ret
= BGP_ATTR_PARSE_ERROR
;
3702 * Finally do the checks on the aspath we did not do yet
3703 * because we waited for a potentially synthesized aspath.
3705 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3706 ret
= bgp_attr_aspath_check(peer
, attr
);
3707 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3711 ret
= BGP_ATTR_PARSE_PROCEED
;
3715 * At this stage, we have done all fiddling with as4, and the
3716 * resulting info is in attr->aggregator resp. attr->aspath so
3717 * we can chuck as4_aggregator and as4_path alltogether in order
3721 * unintern - it is in the hash
3722 * The flag that we got this is still there, but that
3723 * does not do any trouble
3725 aspath_unintern(&as4_path
);
3727 transit
= bgp_attr_get_transit(attr
);
3728 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3729 /* Finally intern unknown attribute. */
3731 bgp_attr_set_transit(attr
, transit_intern(transit
));
3732 if (attr
->encap_subtlvs
)
3733 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3735 #ifdef ENABLE_BGP_VNC
3736 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3737 bgp_attr_get_vnc_subtlvs(attr
);
3740 bgp_attr_set_vnc_subtlvs(
3742 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3746 transit_free(transit
);
3747 bgp_attr_set_transit(attr
, NULL
);
3750 bgp_attr_flush_encap(attr
);
3754 transit
= bgp_attr_get_transit(attr
);
3756 assert(transit
->refcnt
> 0);
3757 if (attr
->encap_subtlvs
)
3758 assert(attr
->encap_subtlvs
->refcnt
> 0);
3759 #ifdef ENABLE_BGP_VNC
3760 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3761 bgp_attr_get_vnc_subtlvs(attr
);
3764 assert(vnc_subtlvs
->refcnt
> 0);
3771 * Extract the tunnel type from extended community
3773 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3774 bgp_encap_types
*tunnel_type
)
3776 struct ecommunity
*ecom
;
3782 ecom
= bgp_attr_get_ecommunity(attr
);
3783 if (!ecom
|| !ecom
->size
)
3786 for (i
= 0; i
< ecom
->size
; i
++) {
3788 uint8_t type
, sub_type
;
3790 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3793 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3794 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3796 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3803 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3804 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3808 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
3809 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
3812 /* Set extended bit always to encode the attribute length as 2 bytes */
3813 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3814 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3815 sizep
= stream_get_endp(s
);
3816 stream_putw(s
, 0); /* Marker: Attribute length. */
3819 /* Convert AFI, SAFI to values for packet. */
3820 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3822 stream_putw(s
, pkt_afi
); /* AFI */
3823 stream_putc(s
, pkt_safi
); /* SAFI */
3827 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3828 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3829 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3830 else if (safi
== SAFI_FLOWSPEC
)
3833 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3836 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3841 case SAFI_MULTICAST
:
3842 case SAFI_LABELED_UNICAST
:
3844 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3848 stream_putl(s
, 0); /* RD = 0, per RFC */
3850 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3855 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3858 if (attr
->mp_nexthop_len
== 0)
3859 stream_putc(s
, 0); /* no nexthop for flowspec */
3861 stream_putc(s
, attr
->mp_nexthop_len
);
3862 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3871 case SAFI_MULTICAST
:
3872 case SAFI_LABELED_UNICAST
:
3874 if (attr
->mp_nexthop_len
3875 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3877 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3878 stream_put(s
, &attr
->mp_nexthop_global
,
3880 stream_put(s
, &attr
->mp_nexthop_local
,
3883 stream_putc(s
, IPV6_MAX_BYTELEN
);
3884 stream_put(s
, &attr
->mp_nexthop_global
,
3888 case SAFI_MPLS_VPN
: {
3889 if (attr
->mp_nexthop_len
3890 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3892 stream_putl(s
, 0); /* RD = 0, per RFC */
3894 stream_put(s
, &attr
->mp_nexthop_global
,
3896 } else if (attr
->mp_nexthop_len
3897 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3899 stream_putl(s
, 0); /* RD = 0, per RFC */
3901 stream_put(s
, &attr
->mp_nexthop_global
,
3903 stream_putl(s
, 0); /* RD = 0, per RFC */
3905 stream_put(s
, &attr
->mp_nexthop_local
,
3910 stream_putc(s
, IPV6_MAX_BYTELEN
);
3911 stream_put(s
, &attr
->mp_nexthop_global
,
3915 stream_putc(s
, 0); /* no nexthop for flowspec */
3921 if (safi
!= SAFI_FLOWSPEC
)
3923 EC_BGP_ATTR_NH_SEND_LEN
,
3924 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3925 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3934 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3935 const struct prefix
*p
,
3936 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3937 uint32_t num_labels
, bool addpath_capable
,
3938 uint32_t addpath_tx_id
, struct attr
*attr
)
3940 if (safi
== SAFI_MPLS_VPN
) {
3941 if (addpath_capable
)
3942 stream_putl(s
, addpath_tx_id
);
3943 /* Label, RD, Prefix write. */
3944 stream_putc(s
, p
->prefixlen
+ 88);
3945 stream_put(s
, label
, BGP_LABEL_BYTES
);
3946 stream_put(s
, prd
->val
, 8);
3947 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3948 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3949 /* EVPN prefix - contents depend on type */
3950 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3951 addpath_capable
, addpath_tx_id
);
3952 } else if (safi
== SAFI_LABELED_UNICAST
) {
3953 /* Prefix write with label. */
3954 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3956 } else if (safi
== SAFI_FLOWSPEC
) {
3957 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3958 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3959 p
->u
.prefix_flowspec
.prefixlen
);
3961 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
3964 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3965 const struct prefix
*p
)
3967 int size
= PSIZE(p
->prefixlen
);
3968 if (safi
== SAFI_MPLS_VPN
)
3970 else if (safi
== SAFI_LABELED_UNICAST
)
3971 size
+= BGP_LABEL_BYTES
;
3972 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3973 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3979 * Encodes the tunnel encapsulation attribute,
3980 * and with ENABLE_BGP_VNC the VNC attribute which uses
3981 * almost the same TLV format
3983 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3984 struct stream
*s
, struct attr
*attr
,
3987 unsigned int attrlenfield
= 0;
3988 unsigned int attrhdrlen
= 0;
3989 struct bgp_attr_encap_subtlv
*subtlvs
;
3990 struct bgp_attr_encap_subtlv
*st
;
3991 const char *attrname
;
3993 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3994 && (!attr
->encap_tunneltype
3995 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3999 case BGP_ATTR_ENCAP
:
4000 attrname
= "Tunnel Encap";
4001 subtlvs
= attr
->encap_subtlvs
;
4002 if (subtlvs
== NULL
) /* nothing to do */
4005 * The tunnel encap attr has an "outer" tlv.
4007 * L = total length of subtlvs,
4008 * V = concatenated subtlvs.
4010 attrlenfield
= 2 + 2; /* T + L */
4011 attrhdrlen
= 1 + 1; /* subTLV T + L */
4014 #ifdef ENABLE_BGP_VNC_ATTR
4017 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
4018 if (subtlvs
== NULL
) /* nothing to do */
4020 attrlenfield
= 0; /* no outer T + L */
4021 attrhdrlen
= 2 + 2; /* subTLV T + L */
4029 /* compute attr length */
4030 for (st
= subtlvs
; st
; st
= st
->next
) {
4031 attrlenfield
+= (attrhdrlen
+ st
->length
);
4034 if (attrlenfield
> 0xffff) {
4035 zlog_info("%s attribute is too long (length=%d), can't send it",
4036 attrname
, attrlenfield
);
4040 if (attrlenfield
> 0xff) {
4041 /* 2-octet length field */
4043 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4044 | BGP_ATTR_FLAG_EXTLEN
);
4045 stream_putc(s
, attrtype
);
4046 stream_putw(s
, attrlenfield
& 0xffff);
4048 /* 1-octet length field */
4049 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
4050 stream_putc(s
, attrtype
);
4051 stream_putc(s
, attrlenfield
& 0xff);
4054 if (attrtype
== BGP_ATTR_ENCAP
) {
4055 /* write outer T+L */
4056 stream_putw(s
, attr
->encap_tunneltype
);
4057 stream_putw(s
, attrlenfield
- 4);
4060 /* write each sub-tlv */
4061 for (st
= subtlvs
; st
; st
= st
->next
) {
4062 if (attrtype
== BGP_ATTR_ENCAP
) {
4063 stream_putc(s
, st
->type
);
4064 stream_putc(s
, st
->length
);
4065 #ifdef ENABLE_BGP_VNC
4067 stream_putw(s
, st
->type
);
4068 stream_putw(s
, st
->length
);
4071 stream_put(s
, st
->value
, st
->length
);
4075 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
4077 /* Set MP attribute length. Don't count the (2) bytes used to encode
4079 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
4082 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
4084 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
4085 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
4086 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4087 PEER_FLAG_REMOVE_PRIVATE_AS
)
4088 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4089 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
4090 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4091 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
4092 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4093 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
4098 /* Make attribute packet. */
4099 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
4100 struct stream
*s
, struct attr
*attr
,
4101 struct bpacket_attr_vec_arr
*vecarr
,
4102 struct prefix
*p
, afi_t afi
, safi_t safi
,
4103 struct peer
*from
, struct prefix_rd
*prd
,
4104 mpls_label_t
*label
, uint32_t num_labels
,
4105 bool addpath_capable
, uint32_t addpath_tx_id
,
4106 struct bgp_path_info
*bpi
)
4109 size_t aspath_sizep
;
4110 struct aspath
*aspath
;
4111 int send_as4_path
= 0;
4112 int send_as4_aggregator
= 0;
4113 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
4114 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
4119 /* Remember current pointer. */
4120 cp
= stream_get_endp(s
);
4123 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
4124 && !peer_cap_enhe(peer
, afi
, safi
))) {
4125 size_t mpattrlen_pos
= 0;
4127 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
4129 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
4130 num_labels
, addpath_capable
,
4131 addpath_tx_id
, attr
);
4132 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
4135 /* Origin attribute. */
4136 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4137 stream_putc(s
, BGP_ATTR_ORIGIN
);
4139 stream_putc(s
, attr
->origin
);
4141 /* AS path attribute. */
4143 /* If remote-peer is EBGP */
4144 if (peer
->sort
== BGP_PEER_EBGP
4145 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4146 PEER_FLAG_AS_PATH_UNCHANGED
)
4147 || attr
->aspath
->segments
== NULL
)
4148 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4149 PEER_FLAG_RSERVER_CLIENT
))) {
4150 aspath
= aspath_dup(attr
->aspath
);
4152 /* Even though we may not be configured for confederations we
4154 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4155 aspath
= aspath_delete_confed_seq(aspath
);
4157 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
4158 /* Stuff our path CONFED_ID on the front */
4159 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
4161 if (peer
->change_local_as
) {
4162 /* If replace-as is specified, we only use the
4163 change_local_as when
4164 advertising routes. */
4165 if (!CHECK_FLAG(peer
->flags
,
4166 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
4167 if (bgp_append_local_as(peer
, afi
,
4169 aspath
= aspath_add_seq(
4170 aspath
, peer
->local_as
);
4171 aspath
= aspath_add_seq(aspath
,
4172 peer
->change_local_as
);
4174 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
4177 } else if (peer
->sort
== BGP_PEER_CONFED
) {
4178 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4180 aspath
= aspath_dup(attr
->aspath
);
4181 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
4183 aspath
= attr
->aspath
;
4185 /* If peer is not AS4 capable, then:
4186 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4187 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4189 * types are in it (i.e. exclude them if they are there)
4190 * AND do this only if there is at least one asnum > 65535 in the
4192 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4194 * all ASnums > 65535 to BGP_AS_TRANS
4197 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4198 stream_putc(s
, BGP_ATTR_AS_PATH
);
4199 aspath_sizep
= stream_get_endp(s
);
4201 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4203 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4206 if (!use32bit
&& aspath_has_as4(aspath
))
4208 1; /* we'll do this later, at the correct place */
4210 /* Nexthop attribute. */
4211 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4212 && !peer_cap_enhe(peer
, afi
, safi
)) {
4213 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4215 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4216 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4217 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4218 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4221 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4222 } else if (peer_cap_enhe(from
, afi
, safi
)
4223 || (nh_afi
== AFI_IP6
)) {
4225 * Likely this is the case when an IPv4 prefix was
4226 * received with Extended Next-hop capability in this
4227 * or another vrf and is now being advertised to
4228 * non-ENHE peers. Since peer_cap_enhe only checks
4229 * peers in this vrf, also check the nh_afi to catch
4230 * the case where the originator was in another vrf.
4231 * Setting the mandatory (ipv4) next-hop attribute here
4232 * to enable implicit next-hop self with correct A-F
4233 * (ipv4 address family).
4235 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4236 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4237 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4240 stream_put_ipv4(s
, 0);
4244 /* MED attribute. */
4245 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4246 || bgp
->maxmed_active
) {
4247 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4248 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4250 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4254 /* Local preference. */
4255 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4256 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4257 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4259 stream_putl(s
, attr
->local_pref
);
4262 /* Atomic aggregate. */
4263 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4264 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4265 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4270 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4271 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4272 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4273 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4276 /* AS4 capable peer */
4278 stream_putl(s
, attr
->aggregator_as
);
4280 /* 2-byte AS peer */
4283 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4285 if (attr
->aggregator_as
> UINT16_MAX
) {
4286 stream_putw(s
, BGP_AS_TRANS
);
4288 /* we have to send AS4_AGGREGATOR, too.
4289 * we'll do that later in order to send
4290 * attributes in ascending
4293 send_as4_aggregator
= 1;
4295 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4297 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4300 /* Community attribute. */
4301 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4302 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4303 struct community
*comm
= NULL
;
4305 comm
= bgp_attr_get_community(attr
);
4306 if (comm
->size
* 4 > 255) {
4308 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4309 | BGP_ATTR_FLAG_EXTLEN
);
4310 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4311 stream_putw(s
, comm
->size
* 4);
4314 BGP_ATTR_FLAG_OPTIONAL
4315 | BGP_ATTR_FLAG_TRANS
);
4316 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4317 stream_putc(s
, comm
->size
* 4);
4319 stream_put(s
, comm
->val
, comm
->size
* 4);
4323 * Large Community attribute.
4325 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4326 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4327 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4328 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4330 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4331 | BGP_ATTR_FLAG_EXTLEN
);
4332 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4334 lcom_length(bgp_attr_get_lcommunity(attr
)));
4337 BGP_ATTR_FLAG_OPTIONAL
4338 | BGP_ATTR_FLAG_TRANS
);
4339 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4341 lcom_length(bgp_attr_get_lcommunity(attr
)));
4343 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4344 lcom_length(bgp_attr_get_lcommunity(attr
)));
4347 /* Route Reflector. */
4348 if (peer
->sort
== BGP_PEER_IBGP
&& from
4349 && from
->sort
== BGP_PEER_IBGP
) {
4350 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4352 /* Originator ID. */
4353 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4354 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4357 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4358 stream_put_in_addr(s
, &attr
->originator_id
);
4360 stream_put_in_addr(s
, &from
->remote_id
);
4363 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4364 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4367 stream_putc(s
, cluster
->length
+ 4);
4368 /* If this peer configuration's parent BGP has
4370 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4371 stream_put_in_addr(s
, &bgp
->cluster_id
);
4373 stream_put_in_addr(s
, &bgp
->router_id
);
4374 stream_put(s
, cluster
->list
, cluster
->length
);
4377 /* If this peer configuration's parent BGP has
4379 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4380 stream_put_in_addr(s
, &bgp
->cluster_id
);
4382 stream_put_in_addr(s
, &bgp
->router_id
);
4386 /* Extended Communities attribute. */
4387 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4388 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4389 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4390 bool transparent
= CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4391 PEER_FLAG_RSERVER_CLIENT
) &&
4393 CHECK_FLAG(from
->af_flags
[afi
][safi
],
4394 PEER_FLAG_RSERVER_CLIENT
);
4396 if (peer
->sort
== BGP_PEER_IBGP
||
4397 peer
->sort
== BGP_PEER_CONFED
|| transparent
) {
4398 if (ecomm
->size
* 8 > 255) {
4400 BGP_ATTR_FLAG_OPTIONAL
4401 | BGP_ATTR_FLAG_TRANS
4402 | BGP_ATTR_FLAG_EXTLEN
);
4403 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4404 stream_putw(s
, ecomm
->size
* 8);
4407 BGP_ATTR_FLAG_OPTIONAL
4408 | BGP_ATTR_FLAG_TRANS
);
4409 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4410 stream_putc(s
, ecomm
->size
* 8);
4412 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4416 int ecom_tr_size
= 0;
4419 for (i
= 0; i
< ecomm
->size
; i
++) {
4420 pnt
= ecomm
->val
+ (i
* 8);
4423 if (CHECK_FLAG(tbit
,
4424 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4431 if (ecom_tr_size
* 8 > 255) {
4434 BGP_ATTR_FLAG_OPTIONAL
4435 | BGP_ATTR_FLAG_TRANS
4436 | BGP_ATTR_FLAG_EXTLEN
);
4438 BGP_ATTR_EXT_COMMUNITIES
);
4439 stream_putw(s
, ecom_tr_size
* 8);
4443 BGP_ATTR_FLAG_OPTIONAL
4444 | BGP_ATTR_FLAG_TRANS
);
4446 BGP_ATTR_EXT_COMMUNITIES
);
4447 stream_putc(s
, ecom_tr_size
* 8);
4450 for (i
= 0; i
< ecomm
->size
; i
++) {
4451 pnt
= ecomm
->val
+ (i
* 8);
4456 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4459 stream_put(s
, pnt
, 8);
4465 /* Label index attribute. */
4466 if (safi
== SAFI_LABELED_UNICAST
) {
4467 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4468 uint32_t label_index
;
4470 label_index
= attr
->label_index
;
4472 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4474 BGP_ATTR_FLAG_OPTIONAL
4475 | BGP_ATTR_FLAG_TRANS
);
4476 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4478 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4480 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4481 stream_putc(s
, 0); // reserved
4482 stream_putw(s
, 0); // flags
4483 stream_putl(s
, label_index
);
4488 /* SRv6 Service Information Attribute. */
4489 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4490 if (attr
->srv6_l3vpn
) {
4491 uint8_t subtlv_len
=
4492 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4494 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4495 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4496 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4497 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4498 | BGP_ATTR_FLAG_TRANS
);
4499 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4500 stream_putc(s
, attr_len
);
4501 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4502 stream_putw(s
, tlv_len
);
4503 stream_putc(s
, 0); /* reserved */
4504 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4505 stream_putw(s
, subtlv_len
);
4506 stream_putc(s
, 0); /* reserved */
4507 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4508 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4509 stream_putc(s
, 0); /* sid_flags */
4510 stream_putw(s
, 0xffff); /* endpoint */
4511 stream_putc(s
, 0); /* reserved */
4514 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4517 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4518 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4519 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4520 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4521 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4522 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4523 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4524 } else if (attr
->srv6_vpn
) {
4525 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4526 | BGP_ATTR_FLAG_TRANS
);
4527 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4528 stream_putc(s
, 22); /* tlv len */
4529 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4530 stream_putw(s
, 0x13); /* tlv len */
4531 stream_putc(s
, 0x00); /* reserved */
4532 stream_putc(s
, 0x01); /* sid_type */
4533 stream_putc(s
, 0x00); /* sif_flags */
4534 stream_put(s
, &attr
->srv6_vpn
->sid
,
4535 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4539 if (send_as4_path
) {
4540 /* If the peer is NOT As4 capable, AND */
4541 /* there are ASnums > 65535 in path THEN
4542 * give out AS4_PATH */
4544 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4546 * Hm, I wonder... confederation things *should* only be at
4547 * the beginning of an aspath, right? Then we should use
4548 * aspath_delete_confed_seq for this, because it is already
4550 * Folks, talk to me: what is reasonable here!?
4552 aspath
= aspath_delete_confed_seq(aspath
);
4555 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4556 | BGP_ATTR_FLAG_EXTLEN
);
4557 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4558 aspath_sizep
= stream_get_endp(s
);
4560 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4563 if (aspath
!= attr
->aspath
)
4564 aspath_free(aspath
);
4566 if (send_as4_aggregator
) {
4567 /* send AS4_AGGREGATOR, at this place */
4568 /* this section of code moved here in order to ensure the
4570 * *ascending* order of attributes
4572 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4573 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4575 stream_putl(s
, attr
->aggregator_as
);
4576 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4579 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4580 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4581 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4582 /* Tunnel Encap attribute */
4583 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4585 #ifdef ENABLE_BGP_VNC_ATTR
4587 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4592 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4593 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4594 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4595 stream_putc(s
, 9); // Length
4596 stream_putc(s
, 0); // Flags
4597 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4598 stream_put(s
, &(attr
->label
),
4599 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4600 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4601 // Unicast tunnel endpoint IP address
4605 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4606 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4607 stream_putc(s
, BGP_ATTR_OTC
);
4609 stream_putl(s
, attr
->otc
);
4613 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
) &&
4614 (CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
) ||
4615 peer
->sort
!= BGP_PEER_EBGP
)) {
4616 /* At the moment only AIGP Metric TLV exists for AIGP
4617 * attribute. If more comes in, do not forget to update
4618 * attr_len variable to include new ones.
4620 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4622 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4623 stream_putc(s
, BGP_ATTR_AIGP
);
4624 stream_putc(s
, attr_len
);
4625 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4628 /* Unknown transit attribute. */
4629 struct transit
*transit
= bgp_attr_get_transit(attr
);
4632 stream_put(s
, transit
->val
, transit
->length
);
4634 /* Return total size of attribute. */
4635 return stream_get_endp(s
) - cp
;
4638 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4640 unsigned long attrlen_pnt
;
4641 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
4642 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
4644 /* Set extended bit always to encode the attribute length as 2 bytes */
4645 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4646 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4648 attrlen_pnt
= stream_get_endp(s
);
4649 stream_putw(s
, 0); /* Length of this attribute. */
4651 /* Convert AFI, SAFI to values for packet. */
4652 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4654 stream_putw(s
, pkt_afi
);
4655 stream_putc(s
, pkt_safi
);
4660 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4661 afi_t afi
, safi_t safi
,
4662 const struct prefix_rd
*prd
,
4663 mpls_label_t
*label
, uint32_t num_labels
,
4664 bool addpath_capable
, uint32_t addpath_tx_id
,
4667 uint8_t wlabel
[4] = {0x80, 0x00, 0x00};
4669 if (safi
== SAFI_LABELED_UNICAST
) {
4670 label
= (mpls_label_t
*)wlabel
;
4674 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4675 addpath_capable
, addpath_tx_id
, attr
);
4678 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4680 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4683 /* Initialization of attribute. */
4684 void bgp_attr_init(void)
4697 void bgp_attr_finish(void)
4702 ecommunity_finish();
4703 lcommunity_finish();
4710 /* Make attribute packet. */
4711 void bgp_dump_routes_attr(struct stream
*s
, struct bgp_path_info
*bpi
,
4712 const struct prefix
*prefix
)
4717 struct aspath
*aspath
;
4718 bool addpath_capable
= false;
4719 uint32_t addpath_tx_id
= 0;
4720 struct attr
*attr
= bpi
->attr
;
4722 /* Remember current pointer. */
4723 cp
= stream_get_endp(s
);
4725 /* Place holder of length. */
4728 /* Origin attribute. */
4729 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4730 stream_putc(s
, BGP_ATTR_ORIGIN
);
4732 stream_putc(s
, attr
->origin
);
4734 aspath
= attr
->aspath
;
4736 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4737 stream_putc(s
, BGP_ATTR_AS_PATH
);
4738 aspath_lenp
= stream_get_endp(s
);
4741 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4743 /* Nexthop attribute. */
4744 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4745 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4746 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4747 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4749 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4752 /* MED attribute. */
4753 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4754 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4755 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4757 stream_putl(s
, attr
->med
);
4760 /* Local preference. */
4761 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4762 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4763 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4765 stream_putl(s
, attr
->local_pref
);
4768 /* Atomic aggregate. */
4769 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4770 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4771 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4776 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4777 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4778 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4780 stream_putl(s
, attr
->aggregator_as
);
4781 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4784 /* Community attribute. */
4785 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4786 struct community
*comm
= NULL
;
4788 comm
= bgp_attr_get_community(attr
);
4789 if (comm
->size
* 4 > 255) {
4791 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4792 | BGP_ATTR_FLAG_EXTLEN
);
4793 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4794 stream_putw(s
, comm
->size
* 4);
4797 BGP_ATTR_FLAG_OPTIONAL
4798 | BGP_ATTR_FLAG_TRANS
);
4799 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4800 stream_putc(s
, comm
->size
* 4);
4802 stream_put(s
, comm
->val
, comm
->size
* 4);
4805 /* Large Community attribute. */
4806 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4807 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4809 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4810 | BGP_ATTR_FLAG_EXTLEN
);
4811 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4813 lcom_length(bgp_attr_get_lcommunity(attr
)));
4816 BGP_ATTR_FLAG_OPTIONAL
4817 | BGP_ATTR_FLAG_TRANS
);
4818 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4820 lcom_length(bgp_attr_get_lcommunity(attr
)));
4823 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4824 lcom_length(bgp_attr_get_lcommunity(attr
)));
4827 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4828 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4829 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4830 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4833 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4834 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4835 sizep
= stream_get_endp(s
);
4838 stream_putc(s
, 0); /* Marker: Attribute length. */
4839 stream_putw(s
, AFI_IP6
); /* AFI */
4840 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4843 stream_putc(s
, attr
->mp_nexthop_len
);
4844 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4845 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4846 stream_put(s
, &attr
->mp_nexthop_local
,
4853 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4856 /* Set MP attribute length. */
4857 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4861 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4862 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4864 BGP_ATTR_FLAG_OPTIONAL
4865 | BGP_ATTR_FLAG_TRANS
);
4866 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4868 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4869 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4870 stream_putc(s
, 0); // reserved
4871 stream_putw(s
, 0); // flags
4872 stream_putl(s
, attr
->label_index
);
4877 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4878 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4879 stream_putc(s
, BGP_ATTR_OTC
);
4881 stream_putl(s
, attr
->otc
);
4885 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
4886 /* At the moment only AIGP Metric TLV exists for AIGP
4887 * attribute. If more comes in, do not forget to update
4888 * attr_len variable to include new ones.
4890 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4892 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4893 stream_putc(s
, BGP_ATTR_AIGP
);
4894 stream_putc(s
, attr_len
);
4895 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4898 /* Return total size of attribute. */
4899 len
= stream_get_endp(s
) - cp
- 2;
4900 stream_putw_at(s
, cp
, len
);