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_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
77 {BGP_ATTR_ENCAP
, "ENCAP"},
78 {BGP_ATTR_OTC
, "OTC"},
79 #ifdef ENABLE_BGP_VNC_ATTR
80 {BGP_ATTR_VNC
, "VNC"},
82 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
83 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
84 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
85 {BGP_ATTR_AIGP
, "AIGP"},
88 static const struct message attr_flag_str
[] = {
89 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
90 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
91 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
92 /* bgp_attr_flags_diagnose() relies on this bit being last in
94 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
97 static struct hash
*cluster_hash
;
99 static void *cluster_hash_alloc(void *p
)
101 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
102 struct cluster_list
*cluster
;
104 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
105 cluster
->length
= val
->length
;
107 if (cluster
->length
) {
108 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
109 memcpy(cluster
->list
, val
->list
, val
->length
);
111 cluster
->list
= NULL
;
118 /* Cluster list related functions. */
119 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
121 struct cluster_list tmp
= {};
122 struct cluster_list
*cluster
;
125 tmp
.list
= length
== 0 ? NULL
: pnt
;
127 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
132 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
136 for (i
= 0; i
< cluster
->length
/ 4; i
++)
137 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
142 static unsigned int cluster_hash_key_make(const void *p
)
144 const struct cluster_list
*cluster
= p
;
146 return jhash(cluster
->list
, cluster
->length
, 0);
149 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
151 const struct cluster_list
*cluster1
= p1
;
152 const struct cluster_list
*cluster2
= p2
;
154 if (cluster1
->list
== cluster2
->list
)
157 if (!cluster1
->list
|| !cluster2
->list
)
160 if (cluster1
->length
!= cluster2
->length
)
163 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
166 static void cluster_free(struct cluster_list
*cluster
)
168 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
169 XFREE(MTYPE_CLUSTER
, cluster
);
172 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
174 struct cluster_list
*find
;
176 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
182 static void cluster_unintern(struct cluster_list
**cluster
)
184 if ((*cluster
)->refcnt
)
185 (*cluster
)->refcnt
--;
187 if ((*cluster
)->refcnt
== 0) {
188 void *p
= hash_release(cluster_hash
, *cluster
);
189 assert(p
== *cluster
);
190 cluster_free(*cluster
);
195 static void cluster_init(void)
197 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
201 static void cluster_finish(void)
203 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
204 hash_free(cluster_hash
);
208 static struct hash
*encap_hash
= NULL
;
209 #ifdef ENABLE_BGP_VNC
210 static struct hash
*vnc_hash
= NULL
;
212 static struct hash
*srv6_l3vpn_hash
;
213 static struct hash
*srv6_vpn_hash
;
215 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
217 struct bgp_attr_encap_subtlv
*new;
218 struct bgp_attr_encap_subtlv
*tail
;
219 struct bgp_attr_encap_subtlv
*p
;
221 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
222 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
224 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
227 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
230 memcpy(tail
, p
, size
);
237 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
239 struct bgp_attr_encap_subtlv
*next
;
243 XFREE(MTYPE_ENCAP_TLV
, p
);
248 void bgp_attr_flush_encap(struct attr
*attr
)
253 if (attr
->encap_subtlvs
) {
254 encap_free(attr
->encap_subtlvs
);
255 attr
->encap_subtlvs
= NULL
;
257 #ifdef ENABLE_BGP_VNC
258 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
259 bgp_attr_get_vnc_subtlvs(attr
);
262 encap_free(vnc_subtlvs
);
263 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
269 * Compare encap sub-tlv chains
274 * This algorithm could be made faster if needed
276 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
277 const struct bgp_attr_encap_subtlv
*h2
)
279 const struct bgp_attr_encap_subtlv
*p
;
280 const struct bgp_attr_encap_subtlv
*q
;
284 if (h1
== NULL
|| h2
== NULL
)
287 for (p
= h1
; p
; p
= p
->next
) {
288 for (q
= h2
; q
; q
= q
->next
) {
289 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
290 && !memcmp(p
->value
, q
->value
, p
->length
)) {
299 for (p
= h2
; p
; p
= p
->next
) {
300 for (q
= h1
; q
; q
= q
->next
) {
301 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
302 && !memcmp(p
->value
, q
->value
, p
->length
)) {
314 static void *encap_hash_alloc(void *p
)
316 /* Encap structure is already allocated. */
322 #ifdef ENABLE_BGP_VNC
327 static struct bgp_attr_encap_subtlv
*
328 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
330 struct bgp_attr_encap_subtlv
*find
;
331 struct hash
*hash
= encap_hash
;
332 #ifdef ENABLE_BGP_VNC
333 if (type
== VNC_SUBTLV_TYPE
)
337 find
= hash_get(hash
, encap
, encap_hash_alloc
);
345 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
346 encap_subtlv_type type
)
348 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
352 if (encap
->refcnt
== 0) {
353 struct hash
*hash
= encap_hash
;
354 #ifdef ENABLE_BGP_VNC
355 if (type
== VNC_SUBTLV_TYPE
)
358 hash_release(hash
, encap
);
364 static unsigned int encap_hash_key_make(const void *p
)
366 const struct bgp_attr_encap_subtlv
*encap
= p
;
368 return jhash(encap
->value
, encap
->length
, 0);
371 static bool encap_hash_cmp(const void *p1
, const void *p2
)
373 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
374 (const struct bgp_attr_encap_subtlv
*)p2
);
377 static void encap_init(void)
379 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
381 #ifdef ENABLE_BGP_VNC
382 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
387 static void encap_finish(void)
389 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
390 hash_free(encap_hash
);
392 #ifdef ENABLE_BGP_VNC
393 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
399 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
408 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
409 bgp_attr_get_evpn_overlay(a2
));
412 /* Unknown transit attribute. */
413 static struct hash
*transit_hash
;
415 static void transit_free(struct transit
*transit
)
417 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
418 XFREE(MTYPE_TRANSIT
, transit
);
421 static void *transit_hash_alloc(void *p
)
423 /* Transit structure is already allocated. */
427 static struct transit
*transit_intern(struct transit
*transit
)
429 struct transit
*find
;
431 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
433 transit_free(transit
);
439 static void transit_unintern(struct transit
**transit
)
441 if ((*transit
)->refcnt
)
442 (*transit
)->refcnt
--;
444 if ((*transit
)->refcnt
== 0) {
445 hash_release(transit_hash
, *transit
);
446 transit_free(*transit
);
451 static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt
, int length
,
460 ptr_get_be16(data
+ 1, &tlv_length
);
463 /* The value field of the AIGP TLV is always 8 octets
464 * long and its value is interpreted as an unsigned 64-bit
467 if (tlv_type
== BGP_AIGP_TLV_METRIC
) {
468 (void)ptr_get_be64(data
+ 3, aigp
);
470 /* If an AIGP attribute is received and its first AIGP
471 * TLV contains the maximum value 0xffffffffffffffff,
472 * the attribute SHOULD be considered to be malformed
473 * and SHOULD be discarded as specified in this section.
475 if (*aigp
== BGP_AIGP_TLV_METRIC_MAX
) {
476 zlog_err("Bad AIGP TLV (%s) length: %llu",
477 BGP_AIGP_TLV_METRIC_DESC
,
478 BGP_AIGP_TLV_METRIC_MAX
);
486 length
-= tlv_length
;
492 static uint64_t bgp_aigp_metric_total(struct bgp_path_info
*bpi
)
494 uint64_t aigp
= bgp_attr_get_aigp_metric(bpi
->attr
);
497 return aigp
+ bpi
->nexthop
->metric
;
502 static void stream_put_bgp_aigp_tlv_metric(struct stream
*s
,
503 struct bgp_path_info
*bpi
)
505 stream_putc(s
, BGP_AIGP_TLV_METRIC
);
506 stream_putw(s
, BGP_AIGP_TLV_METRIC_LEN
);
507 stream_putq(s
, bgp_aigp_metric_total(bpi
));
510 static bool bgp_attr_aigp_valid(uint8_t *pnt
, int length
)
517 zlog_err("Bad AIGP attribute length (MUST be minimum 3): %u",
524 ptr_get_be16(data
+ 1, &tlv_length
);
527 if (length
< tlv_length
) {
529 "Bad AIGP attribute length: %u, but TLV length: %u",
534 if (tlv_length
< 3) {
535 zlog_err("Bad AIGP TLV length (MUST be minimum 3): %u",
540 /* AIGP TLV, Length: 11 */
541 if (tlv_type
== BGP_AIGP_TLV_METRIC
&&
542 tlv_length
!= BGP_AIGP_TLV_METRIC_LEN
) {
543 zlog_err("Bad AIGP TLV (%s) length: %u",
544 BGP_AIGP_TLV_METRIC_DESC
, tlv_length
);
549 length
-= tlv_length
;
555 static void *srv6_l3vpn_hash_alloc(void *p
)
560 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
562 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
565 static struct bgp_attr_srv6_l3vpn
*
566 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
568 struct bgp_attr_srv6_l3vpn
*find
;
570 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
572 srv6_l3vpn_free(l3vpn
);
577 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
579 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
584 if (l3vpn
->refcnt
== 0) {
585 hash_release(srv6_l3vpn_hash
, l3vpn
);
586 srv6_l3vpn_free(l3vpn
);
591 static void *srv6_vpn_hash_alloc(void *p
)
596 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
598 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
601 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
603 struct bgp_attr_srv6_vpn
*find
;
605 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
612 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
614 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
619 if (vpn
->refcnt
== 0) {
620 hash_release(srv6_vpn_hash
, vpn
);
626 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
628 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
631 key
= jhash(&l3vpn
->sid
, 16, key
);
632 key
= jhash_1word(l3vpn
->sid_flags
, key
);
633 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
634 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
635 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
636 key
= jhash_1word(l3vpn
->func_len
, key
);
637 key
= jhash_1word(l3vpn
->arg_len
, key
);
638 key
= jhash_1word(l3vpn
->transposition_len
, key
);
639 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
643 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
645 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
646 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
648 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
649 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
650 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
651 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
652 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
653 && l3vpn1
->func_len
== l3vpn2
->func_len
654 && l3vpn1
->arg_len
== l3vpn2
->arg_len
655 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
656 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
659 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
660 const struct bgp_attr_srv6_l3vpn
*h2
)
664 else if (h1
== NULL
|| h2
== NULL
)
667 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
670 static unsigned int srv6_vpn_hash_key_make(const void *p
)
672 const struct bgp_attr_srv6_vpn
*vpn
= p
;
675 key
= jhash(&vpn
->sid
, 16, key
);
676 key
= jhash_1word(vpn
->sid_flags
, key
);
680 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
682 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
683 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
685 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
686 && vpn1
->sid_flags
== vpn2
->sid_flags
;
689 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
690 const struct bgp_attr_srv6_vpn
*h2
)
694 else if (h1
== NULL
|| h2
== NULL
)
697 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
700 static void srv6_init(void)
703 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
704 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
705 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
706 "BGP Prefix-SID SRv6-VPN-Service-TLV");
709 static void srv6_finish(void)
711 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
712 hash_free(srv6_l3vpn_hash
);
713 srv6_l3vpn_hash
= NULL
;
714 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
715 hash_free(srv6_vpn_hash
);
716 srv6_vpn_hash
= NULL
;
719 static unsigned int transit_hash_key_make(const void *p
)
721 const struct transit
*transit
= p
;
723 return jhash(transit
->val
, transit
->length
, 0);
726 static bool transit_hash_cmp(const void *p1
, const void *p2
)
728 const struct transit
*transit1
= p1
;
729 const struct transit
*transit2
= p2
;
731 return (transit1
->length
== transit2
->length
732 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
735 static void transit_init(void)
737 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
741 static void transit_finish(void)
743 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
744 hash_free(transit_hash
);
748 /* Attribute hash routines. */
749 static struct hash
*attrhash
;
751 unsigned long int attr_count(void)
753 return attrhash
->count
;
756 unsigned long int attr_unknown_count(void)
758 return transit_hash
->count
;
761 unsigned int attrhash_key_make(const void *p
)
763 const struct attr
*attr
= (struct attr
*)p
;
765 #define MIX(val) key = jhash_1word(val, key)
766 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
768 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
769 MIX3(attr
->local_pref
, attr
->aggregator_as
,
770 attr
->aggregator_addr
.s_addr
);
771 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
772 attr
->originator_id
.s_addr
);
773 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
776 MIX(aspath_key_make(attr
->aspath
));
777 if (bgp_attr_get_community(attr
))
778 MIX(community_hash_make(bgp_attr_get_community(attr
)));
779 if (bgp_attr_get_lcommunity(attr
))
780 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
781 if (bgp_attr_get_ecommunity(attr
))
782 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
783 if (bgp_attr_get_ipv6_ecommunity(attr
))
784 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
785 if (bgp_attr_get_cluster(attr
))
786 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
787 if (bgp_attr_get_transit(attr
))
788 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
789 if (attr
->encap_subtlvs
)
790 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
791 if (attr
->srv6_l3vpn
)
792 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
794 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
795 #ifdef ENABLE_BGP_VNC
796 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
797 bgp_attr_get_vnc_subtlvs(attr
);
799 MIX(encap_hash_key_make(vnc_subtlvs
));
801 MIX(attr
->mp_nexthop_len
);
802 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
803 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
804 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
805 MIX(attr
->rmap_table_id
);
809 MIX(bgp_attr_get_aigp_metric(attr
));
814 bool attrhash_cmp(const void *p1
, const void *p2
)
816 const struct attr
*attr1
= p1
;
817 const struct attr
*attr2
= p2
;
819 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
820 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
821 && attr1
->aspath
== attr2
->aspath
822 && bgp_attr_get_community(attr1
)
823 == bgp_attr_get_community(attr2
)
824 && attr1
->med
== attr2
->med
825 && attr1
->local_pref
== attr2
->local_pref
826 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
827 if (attr1
->aggregator_as
== attr2
->aggregator_as
&&
828 attr1
->aggregator_addr
.s_addr
==
829 attr2
->aggregator_addr
.s_addr
&&
830 attr1
->weight
== attr2
->weight
&&
831 attr1
->tag
== attr2
->tag
&&
832 attr1
->label_index
== attr2
->label_index
&&
833 attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
&&
834 bgp_attr_get_ecommunity(attr1
) ==
835 bgp_attr_get_ecommunity(attr2
) &&
836 bgp_attr_get_ipv6_ecommunity(attr1
) ==
837 bgp_attr_get_ipv6_ecommunity(attr2
) &&
838 bgp_attr_get_lcommunity(attr1
) ==
839 bgp_attr_get_lcommunity(attr2
) &&
840 bgp_attr_get_cluster(attr1
) ==
841 bgp_attr_get_cluster(attr2
) &&
842 bgp_attr_get_transit(attr1
) ==
843 bgp_attr_get_transit(attr2
) &&
844 bgp_attr_get_aigp_metric(attr1
) ==
845 bgp_attr_get_aigp_metric(attr2
) &&
846 attr1
->rmap_table_id
== attr2
->rmap_table_id
&&
847 (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
) &&
848 encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
849 #ifdef ENABLE_BGP_VNC
850 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
851 bgp_attr_get_vnc_subtlvs(attr2
))
853 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
854 &attr2
->mp_nexthop_global
) &&
855 IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
856 &attr2
->mp_nexthop_local
) &&
857 IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
858 &attr2
->mp_nexthop_global_in
) &&
859 IPV4_ADDR_SAME(&attr1
->originator_id
,
860 &attr2
->originator_id
) &&
861 overlay_index_same(attr1
, attr2
) &&
862 !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
)) &&
863 attr1
->es_flags
== attr2
->es_flags
&&
864 attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
&&
865 attr1
->df_pref
== attr2
->df_pref
&&
866 attr1
->df_alg
== attr2
->df_alg
&&
867 attr1
->nh_ifindex
== attr2
->nh_ifindex
&&
868 attr1
->nh_flag
== attr2
->nh_flag
&&
869 attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
&&
870 attr1
->distance
== attr2
->distance
&&
871 srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
) &&
872 srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
) &&
873 attr1
->srte_color
== attr2
->srte_color
&&
874 attr1
->nh_type
== attr2
->nh_type
&&
875 attr1
->bh_type
== attr2
->bh_type
&&
876 attr1
->otc
== attr2
->otc
)
883 static void attrhash_init(void)
886 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
890 * special for hash_clean below
892 static void attr_vfree(void *attr
)
894 XFREE(MTYPE_ATTR
, attr
);
897 static void attrhash_finish(void)
899 hash_clean(attrhash
, attr_vfree
);
904 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
906 struct attr
*attr
= bucket
->data
;
907 struct in6_addr
*sid
= NULL
;
909 if (attr
->srv6_l3vpn
)
910 sid
= &attr
->srv6_l3vpn
->sid
;
911 else if (attr
->srv6_vpn
)
912 sid
= &attr
->srv6_vpn
->sid
;
914 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
918 " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6\n",
919 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
920 attr
->origin
, attr
->weight
, attr
->label
, sid
);
923 void attr_show_all(struct vty
*vty
)
925 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
926 void *))attr_show_all_iterator
,
930 static void *bgp_attr_hash_alloc(void *p
)
932 struct attr
*val
= (struct attr
*)p
;
935 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
937 if (val
->encap_subtlvs
) {
938 val
->encap_subtlvs
= NULL
;
940 #ifdef ENABLE_BGP_VNC
941 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
942 bgp_attr_get_vnc_subtlvs(val
);
945 bgp_attr_set_vnc_subtlvs(val
, NULL
);
952 /* Internet argument attribute. */
953 struct attr
*bgp_attr_intern(struct attr
*attr
)
956 struct ecommunity
*ecomm
= NULL
;
957 struct ecommunity
*ipv6_ecomm
= NULL
;
958 struct lcommunity
*lcomm
= NULL
;
959 struct community
*comm
= NULL
;
961 /* Intern referenced structure. */
963 if (!attr
->aspath
->refcnt
)
964 attr
->aspath
= aspath_intern(attr
->aspath
);
966 attr
->aspath
->refcnt
++;
969 comm
= bgp_attr_get_community(attr
);
972 bgp_attr_set_community(attr
, community_intern(comm
));
977 ecomm
= bgp_attr_get_ecommunity(attr
);
980 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
985 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
987 if (!ipv6_ecomm
->refcnt
)
988 bgp_attr_set_ipv6_ecommunity(
989 attr
, ecommunity_intern(ipv6_ecomm
));
991 ipv6_ecomm
->refcnt
++;
994 lcomm
= bgp_attr_get_lcommunity(attr
);
997 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
1002 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1005 if (!cluster
->refcnt
)
1006 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
1011 struct transit
*transit
= bgp_attr_get_transit(attr
);
1014 if (!transit
->refcnt
)
1015 bgp_attr_set_transit(attr
, transit_intern(transit
));
1019 if (attr
->encap_subtlvs
) {
1020 if (!attr
->encap_subtlvs
->refcnt
)
1021 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
1024 attr
->encap_subtlvs
->refcnt
++;
1026 if (attr
->srv6_l3vpn
) {
1027 if (!attr
->srv6_l3vpn
->refcnt
)
1028 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
1030 attr
->srv6_l3vpn
->refcnt
++;
1032 if (attr
->srv6_vpn
) {
1033 if (!attr
->srv6_vpn
->refcnt
)
1034 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
1036 attr
->srv6_vpn
->refcnt
++;
1038 #ifdef ENABLE_BGP_VNC
1039 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1040 bgp_attr_get_vnc_subtlvs(attr
);
1043 if (!vnc_subtlvs
->refcnt
)
1044 bgp_attr_set_vnc_subtlvs(
1046 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
1048 vnc_subtlvs
->refcnt
++;
1052 /* At this point, attr only contains intern'd pointers. that means
1053 * if we find it in attrhash, it has all the same pointers and we
1054 * correctly updated the refcounts on these.
1055 * If we don't find it, we need to allocate a one because in all
1056 * cases this returns a new reference to a hashed attr, but the input
1057 * wasn't on hash. */
1058 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
1064 /* Make network statement's attribute. */
1065 struct attr
*bgp_attr_default_set(struct attr
*attr
, struct bgp
*bgp
,
1068 memset(attr
, 0, sizeof(struct attr
));
1070 attr
->origin
= origin
;
1071 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1072 attr
->aspath
= aspath_empty();
1073 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1074 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1076 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
1077 attr
->label
= MPLS_INVALID_LABEL
;
1078 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1079 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1080 attr
->local_pref
= bgp
->default_local_pref
;
1085 /* Create the attributes for an aggregate */
1086 struct attr
*bgp_attr_aggregate_intern(
1087 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
1088 struct community
*community
, struct ecommunity
*ecommunity
,
1089 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
1090 uint8_t atomic_aggregate
, const struct prefix
*p
)
1094 route_map_result_t ret
;
1096 memset(&attr
, 0, sizeof(attr
));
1098 /* Origin attribute. */
1099 attr
.origin
= origin
;
1100 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1104 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1106 /* AS path attribute. */
1108 attr
.aspath
= aspath_intern(aspath
);
1110 attr
.aspath
= aspath_empty();
1111 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1113 /* Next hop attribute. */
1114 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1117 uint32_t gshut
= COMMUNITY_GSHUT
;
1119 /* If we are not shutting down ourselves and we are
1120 * aggregating a route that contains the GSHUT community we
1121 * need to remove that community when creating the aggregate */
1122 if (!bgp_in_graceful_shutdown(bgp
)
1123 && community_include(community
, gshut
)) {
1124 community_del_val(community
, &gshut
);
1127 bgp_attr_set_community(&attr
, community
);
1131 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1134 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1136 if (bgp_in_graceful_shutdown(bgp
))
1137 bgp_attr_add_gshut_community(&attr
);
1139 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1140 attr
.label
= MPLS_INVALID_LABEL
;
1141 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1142 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1143 if (!aggregate
->as_set
|| atomic_aggregate
)
1144 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1145 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1146 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1147 attr
.aggregator_as
= bgp
->confed_id
;
1149 attr
.aggregator_as
= bgp
->as
;
1150 attr
.aggregator_addr
= bgp
->router_id
;
1152 /* Apply route-map */
1153 if (aggregate
->rmap
.name
) {
1154 struct attr attr_tmp
= attr
;
1155 struct bgp_path_info rmap_path
;
1157 memset(&rmap_path
, 0, sizeof(rmap_path
));
1158 rmap_path
.peer
= bgp
->peer_self
;
1159 rmap_path
.attr
= &attr_tmp
;
1161 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1163 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1165 bgp
->peer_self
->rmap_type
= 0;
1167 if (ret
== RMAP_DENYMATCH
) {
1168 /* Free uninterned attribute. */
1169 bgp_attr_flush(&attr_tmp
);
1171 /* Unintern original. */
1172 aspath_unintern(&attr
.aspath
);
1176 if (bgp_in_graceful_shutdown(bgp
))
1177 bgp_attr_add_gshut_community(&attr_tmp
);
1179 new = bgp_attr_intern(&attr_tmp
);
1182 if (bgp_in_graceful_shutdown(bgp
))
1183 bgp_attr_add_gshut_community(&attr
);
1185 new = bgp_attr_intern(&attr
);
1188 /* Always release the 'intern()'ed AS Path. */
1189 aspath_unintern(&attr
.aspath
);
1194 /* Unintern just the sub-components of the attr, but not the attr */
1195 void bgp_attr_unintern_sub(struct attr
*attr
)
1197 struct ecommunity
*ecomm
= NULL
;
1198 struct ecommunity
*ipv6_ecomm
= NULL
;
1199 struct cluster_list
*cluster
;
1200 struct lcommunity
*lcomm
= NULL
;
1201 struct community
*comm
= NULL
;
1203 /* aspath refcount shoud be decrement. */
1204 aspath_unintern(&attr
->aspath
);
1205 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1207 comm
= bgp_attr_get_community(attr
);
1208 community_unintern(&comm
);
1209 bgp_attr_set_community(attr
, NULL
);
1211 ecomm
= bgp_attr_get_ecommunity(attr
);
1212 ecommunity_unintern(&ecomm
);
1213 bgp_attr_set_ecommunity(attr
, NULL
);
1215 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1216 ecommunity_unintern(&ipv6_ecomm
);
1217 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1219 lcomm
= bgp_attr_get_lcommunity(attr
);
1220 lcommunity_unintern(&lcomm
);
1221 bgp_attr_set_lcommunity(attr
, NULL
);
1223 cluster
= bgp_attr_get_cluster(attr
);
1225 cluster_unintern(&cluster
);
1226 bgp_attr_set_cluster(attr
, cluster
);
1228 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1230 struct transit
*transit
= bgp_attr_get_transit(attr
);
1233 transit_unintern(&transit
);
1234 bgp_attr_set_transit(attr
, transit
);
1237 if (attr
->encap_subtlvs
)
1238 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1240 #ifdef ENABLE_BGP_VNC
1241 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1242 bgp_attr_get_vnc_subtlvs(attr
);
1245 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1246 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1250 if (attr
->srv6_l3vpn
)
1251 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1254 srv6_vpn_unintern(&attr
->srv6_vpn
);
1257 /* Free bgp attribute and aspath. */
1258 void bgp_attr_unintern(struct attr
**pattr
)
1260 struct attr
*attr
= *pattr
;
1264 /* Decrement attribute reference. */
1269 /* If reference becomes zero then free attribute object. */
1270 if (attr
->refcnt
== 0) {
1271 ret
= hash_release(attrhash
, attr
);
1272 assert(ret
!= NULL
);
1273 XFREE(MTYPE_ATTR
, attr
);
1277 bgp_attr_unintern_sub(&tmp
);
1280 void bgp_attr_flush(struct attr
*attr
)
1282 struct ecommunity
*ecomm
;
1283 struct ecommunity
*ipv6_ecomm
;
1284 struct cluster_list
*cluster
;
1285 struct lcommunity
*lcomm
;
1286 struct community
*comm
;
1288 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1289 aspath_free(attr
->aspath
);
1290 attr
->aspath
= NULL
;
1292 comm
= bgp_attr_get_community(attr
);
1293 if (comm
&& !comm
->refcnt
)
1294 community_free(&comm
);
1295 bgp_attr_set_community(attr
, NULL
);
1297 ecomm
= bgp_attr_get_ecommunity(attr
);
1298 if (ecomm
&& !ecomm
->refcnt
)
1299 ecommunity_free(&ecomm
);
1300 bgp_attr_set_ecommunity(attr
, NULL
);
1302 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1303 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1304 ecommunity_free(&ipv6_ecomm
);
1305 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1307 lcomm
= bgp_attr_get_lcommunity(attr
);
1308 if (lcomm
&& !lcomm
->refcnt
)
1309 lcommunity_free(&lcomm
);
1310 bgp_attr_set_lcommunity(attr
, NULL
);
1312 cluster
= bgp_attr_get_cluster(attr
);
1313 if (cluster
&& !cluster
->refcnt
) {
1314 cluster_free(cluster
);
1315 bgp_attr_set_cluster(attr
, NULL
);
1318 struct transit
*transit
= bgp_attr_get_transit(attr
);
1320 if (transit
&& !transit
->refcnt
) {
1321 transit_free(transit
);
1322 bgp_attr_set_transit(attr
, NULL
);
1324 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1325 encap_free(attr
->encap_subtlvs
);
1326 attr
->encap_subtlvs
= NULL
;
1328 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1329 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1330 attr
->srv6_l3vpn
= NULL
;
1332 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1333 srv6_vpn_free(attr
->srv6_vpn
);
1334 attr
->srv6_vpn
= NULL
;
1336 #ifdef ENABLE_BGP_VNC
1337 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1338 bgp_attr_get_vnc_subtlvs(attr
);
1340 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1341 encap_free(vnc_subtlvs
);
1342 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1347 /* Implement draft-scudder-idr-optional-transitive behaviour and
1348 * avoid resetting sessions for malformed attributes which are
1349 * are partial/optional and hence where the error likely was not
1350 * introduced by the sending neighbour.
1352 static enum bgp_attr_parse_ret
1353 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1356 struct peer
*const peer
= args
->peer
;
1357 struct attr
*const attr
= args
->attr
;
1358 const uint8_t flags
= args
->flags
;
1359 /* startp and length must be special-cased, as whether or not to
1360 * send the attribute data with the NOTIFY depends on the error,
1361 * the caller therefore signals this with the seperate length argument
1363 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1365 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1366 char attr_str
[BUFSIZ
] = {0};
1368 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1370 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1373 /* Only relax error handling for eBGP peers */
1374 if (peer
->sort
!= BGP_PEER_EBGP
) {
1375 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1376 notify_datap
, length
);
1377 return BGP_ATTR_PARSE_ERROR
;
1380 /* Adjust the stream getp to the end of the attribute, in case we can
1381 * still proceed but the caller hasn't read all the attribute.
1383 stream_set_getp(BGP_INPUT(peer
),
1384 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1387 switch (args
->type
) {
1388 /* where an attribute is relatively inconsequential, e.g. it does not
1389 * affect route selection, and can be safely ignored, then any such
1390 * attributes which are malformed should just be ignored and the route
1391 * processed as normal.
1393 case BGP_ATTR_AS4_AGGREGATOR
:
1394 case BGP_ATTR_AGGREGATOR
:
1395 case BGP_ATTR_ATOMIC_AGGREGATE
:
1396 return BGP_ATTR_PARSE_PROCEED
;
1398 /* Core attributes, particularly ones which may influence route
1399 * selection, should be treat-as-withdraw.
1401 case BGP_ATTR_ORIGIN
:
1402 case BGP_ATTR_AS_PATH
:
1403 case BGP_ATTR_NEXT_HOP
:
1404 case BGP_ATTR_MULTI_EXIT_DISC
:
1405 case BGP_ATTR_LOCAL_PREF
:
1406 case BGP_ATTR_COMMUNITIES
:
1407 case BGP_ATTR_EXT_COMMUNITIES
:
1408 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1409 case BGP_ATTR_LARGE_COMMUNITIES
:
1410 case BGP_ATTR_ORIGINATOR_ID
:
1411 case BGP_ATTR_CLUSTER_LIST
:
1413 return BGP_ATTR_PARSE_WITHDRAW
;
1414 case BGP_ATTR_MP_REACH_NLRI
:
1415 case BGP_ATTR_MP_UNREACH_NLRI
:
1416 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1417 notify_datap
, length
);
1418 return BGP_ATTR_PARSE_ERROR
;
1421 /* Partial optional attributes that are malformed should not cause
1422 * the whole session to be reset. Instead treat it as a withdrawal
1423 * of the routes, if possible.
1425 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1426 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1427 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1428 return BGP_ATTR_PARSE_WITHDRAW
;
1430 /* default to reset */
1431 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1434 /* Find out what is wrong with the path attribute flag bits and log the error.
1435 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1436 Extended Length. Checking O/T/P bits at once implies, that the attribute
1437 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1438 non-transitive" attribute. */
1440 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1441 uint8_t desired_flags
/* how RFC says it must be */
1444 uint8_t seen
= 0, i
;
1445 uint8_t real_flags
= args
->flags
;
1446 const uint8_t attr_code
= args
->type
;
1448 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1449 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1450 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1451 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1452 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1453 flog_err(EC_BGP_ATTR_FLAG
,
1454 "%s attribute must%s be flagged as \"%s\"",
1455 lookup_msg(attr_str
, attr_code
, NULL
),
1456 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1459 attr_flag_str
[i
].str
);
1464 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1465 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1466 real_flags
, desired_flags
);
1470 /* Required flags for attributes. EXTLEN will be masked off when testing,
1471 * as will PARTIAL for optional+transitive attributes.
1473 const uint8_t attr_flags_values
[] = {
1474 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1475 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1476 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1477 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1478 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1479 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1480 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1481 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1482 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1483 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1484 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1485 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1486 [BGP_ATTR_EXT_COMMUNITIES
] =
1487 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1488 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1489 [BGP_ATTR_AS4_AGGREGATOR
] =
1490 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1491 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1492 [BGP_ATTR_LARGE_COMMUNITIES
] =
1493 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1494 [BGP_ATTR_OTC
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1495 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1496 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1497 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1498 [BGP_ATTR_AIGP
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1500 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1502 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1504 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1505 const uint8_t flags
= args
->flags
;
1506 const uint8_t attr_code
= args
->type
;
1508 /* there may be attributes we don't know about */
1509 if (attr_code
> attr_flags_values_max
)
1511 if (attr_flags_values
[attr_code
] == 0)
1514 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1518 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1519 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1522 "%s well-known attributes must have transitive flag set (%x)",
1523 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1527 /* "For well-known attributes and for optional non-transitive
1529 * the Partial bit MUST be set to 0."
1531 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1532 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1533 flog_err(EC_BGP_ATTR_FLAG
,
1534 "%s well-known attribute must NOT have the partial flag set (%x)",
1535 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1538 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1539 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1540 flog_err(EC_BGP_ATTR_FLAG
,
1541 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1542 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1547 /* Optional transitive attributes may go through speakers that don't
1548 * reocgnise them and set the Partial bit.
1550 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1551 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1552 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1554 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1557 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1561 /* Get origin attribute of the update message. */
1562 static enum bgp_attr_parse_ret
1563 bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1565 struct peer
*const peer
= args
->peer
;
1566 struct attr
*const attr
= args
->attr
;
1567 const bgp_size_t length
= args
->length
;
1569 /* If any recognized attribute has Attribute Length that conflicts
1570 with the expected length (based on the attribute type code), then
1571 the Error Subcode is set to Attribute Length Error. The Data
1572 field contains the erroneous attribute (type, length and
1575 flog_err(EC_BGP_ATTR_LEN
,
1576 "Origin attribute length is not one %d", length
);
1577 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1581 /* Fetch origin attribute. */
1582 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1584 /* If the ORIGIN attribute has an undefined value, then the Error
1585 Subcode is set to Invalid Origin Attribute. The Data field
1586 contains the unrecognized attribute (type, length and value). */
1587 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1588 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1589 flog_err(EC_BGP_ATTR_ORIGIN
,
1590 "Origin attribute value is invalid %d", attr
->origin
);
1591 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1595 /* Set oring attribute flag. */
1596 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1601 /* Parse AS path information. This function is wrapper of
1603 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1605 struct attr
*const attr
= args
->attr
;
1606 struct peer
*const peer
= args
->peer
;
1607 const bgp_size_t length
= args
->length
;
1610 * peer with AS4 => will get 4Byte ASnums
1611 * otherwise, will get 16 Bit
1613 attr
->aspath
= aspath_parse(
1615 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1616 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1618 /* In case of IBGP, length will be zero. */
1619 if (!attr
->aspath
) {
1620 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1621 "Malformed AS path from %s, length is %d", peer
->host
,
1623 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1627 /* Conformant BGP speakers SHOULD NOT send BGP
1628 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1629 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1630 * withdraw" error handling behavior as per [RFC7606].
1632 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1633 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1634 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1636 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1640 /* Set aspath attribute flag. */
1641 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1643 return BGP_ATTR_PARSE_PROCEED
;
1646 static enum bgp_attr_parse_ret
bgp_attr_aspath_check(struct peer
*const peer
,
1647 struct attr
*const attr
)
1649 /* These checks were part of bgp_attr_aspath, but with
1650 * as4 we should to check aspath things when
1651 * aspath synthesizing with as4_path has already taken place.
1652 * Otherwise we check ASPATH and use the synthesized thing, and that is
1654 * So do the checks later, i.e. here
1656 struct aspath
*aspath
;
1658 /* Confederation sanity check. */
1659 if ((peer
->sort
== BGP_PEER_CONFED
1660 && !aspath_left_confed_check(attr
->aspath
))
1661 || (peer
->sort
== BGP_PEER_EBGP
1662 && aspath_confed_check(attr
->aspath
))) {
1663 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1665 return BGP_ATTR_PARSE_WITHDRAW
;
1668 /* First AS check for EBGP. */
1669 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1670 if (peer
->sort
== BGP_PEER_EBGP
1671 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1672 flog_err(EC_BGP_ATTR_FIRST_AS
,
1673 "%s incorrect first AS (must be %u)",
1674 peer
->host
, peer
->as
);
1675 return BGP_ATTR_PARSE_WITHDRAW
;
1679 /* Codification of AS 0 Processing */
1680 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1682 EC_BGP_ATTR_MAL_AS_PATH
,
1683 "Malformed AS path, AS number is 0 in the path from %s",
1685 return BGP_ATTR_PARSE_WITHDRAW
;
1688 /* local-as prepend */
1689 if (peer
->change_local_as
1690 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1691 aspath
= aspath_dup(attr
->aspath
);
1692 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1693 aspath_unintern(&attr
->aspath
);
1694 attr
->aspath
= aspath_intern(aspath
);
1697 return BGP_ATTR_PARSE_PROCEED
;
1700 /* Parse AS4 path information. This function is another wrapper of
1702 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1703 struct aspath
**as4_path
)
1705 struct peer
*const peer
= args
->peer
;
1706 struct attr
*const attr
= args
->attr
;
1707 const bgp_size_t length
= args
->length
;
1709 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1711 /* In case of IBGP, length will be zero. */
1713 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1714 "Malformed AS4 path from %s, length is %d", peer
->host
,
1716 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1720 /* Conformant BGP speakers SHOULD NOT send BGP
1721 * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
1722 * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1723 * withdraw" error handling behavior as per [RFC7606].
1725 if (peer
->bgp
->reject_as_sets
&& aspath_check_as_sets(attr
->aspath
)) {
1726 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1727 "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1729 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1733 /* Set aspath attribute flag. */
1734 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1736 return BGP_ATTR_PARSE_PROCEED
;
1740 * Check that the nexthop attribute is valid.
1742 enum bgp_attr_parse_ret
bgp_attr_nexthop_valid(struct peer
*peer
,
1745 struct bgp
*bgp
= peer
->bgp
;
1747 if (ipv4_martian(&attr
->nexthop
) && !bgp
->allow_martian
) {
1748 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1750 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %pI4",
1752 data
[0] = BGP_ATTR_FLAG_TRANS
;
1753 data
[1] = BGP_ATTR_NEXT_HOP
;
1754 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1755 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1756 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1757 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1759 return BGP_ATTR_PARSE_ERROR
;
1762 return BGP_ATTR_PARSE_PROCEED
;
1765 /* Nexthop attribute. */
1766 static enum bgp_attr_parse_ret
1767 bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1769 struct peer
*const peer
= args
->peer
;
1770 struct attr
*const attr
= args
->attr
;
1771 const bgp_size_t length
= args
->length
;
1773 /* Check nexthop attribute length. */
1775 flog_err(EC_BGP_ATTR_LEN
,
1776 "Nexthop attribute length isn't four [%d]", length
);
1778 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1782 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1783 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1785 return BGP_ATTR_PARSE_PROCEED
;
1788 /* MED atrribute. */
1789 static enum bgp_attr_parse_ret
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1791 struct peer
*const peer
= args
->peer
;
1792 struct attr
*const attr
= args
->attr
;
1793 const bgp_size_t length
= args
->length
;
1797 flog_err(EC_BGP_ATTR_LEN
,
1798 "MED attribute length isn't four [%d]", length
);
1800 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1804 attr
->med
= stream_getl(peer
->curr
);
1806 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1808 return BGP_ATTR_PARSE_PROCEED
;
1811 /* Local preference attribute. */
1812 static enum bgp_attr_parse_ret
1813 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1815 struct peer
*const peer
= args
->peer
;
1816 struct attr
*const attr
= args
->attr
;
1817 const bgp_size_t length
= args
->length
;
1819 /* if received from an internal neighbor, it SHALL be considered
1820 * malformed if its length is not equal to 4. If malformed, the
1821 * UPDATE message SHALL be handled using the approach of "treat-as-
1824 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1825 flog_err(EC_BGP_ATTR_LEN
,
1826 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1827 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1831 /* If it is contained in an UPDATE message that is received from an
1832 external peer, then this attribute MUST be ignored by the
1833 receiving speaker. */
1834 if (peer
->sort
== BGP_PEER_EBGP
) {
1835 STREAM_FORWARD_GETP(peer
->curr
, length
);
1836 return BGP_ATTR_PARSE_PROCEED
;
1839 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1841 /* Set the local-pref flag. */
1842 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1844 return BGP_ATTR_PARSE_PROCEED
;
1847 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1851 /* Atomic aggregate. */
1852 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1854 struct attr
*const attr
= args
->attr
;
1855 const bgp_size_t length
= args
->length
;
1859 flog_err(EC_BGP_ATTR_LEN
,
1860 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1862 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1866 /* Set atomic aggregate flag. */
1867 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1869 return BGP_ATTR_PARSE_PROCEED
;
1872 /* Aggregator attribute */
1873 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1875 struct peer
*const peer
= args
->peer
;
1876 struct attr
*const attr
= args
->attr
;
1877 const bgp_size_t length
= args
->length
;
1882 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1883 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1884 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1887 if (length
!= wantedlen
) {
1888 flog_err(EC_BGP_ATTR_LEN
,
1889 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1891 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1895 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1896 aggregator_as
= stream_getl(peer
->curr
);
1898 aggregator_as
= stream_getw(peer
->curr
);
1900 attr
->aggregator_as
= aggregator_as
;
1901 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1903 /* Codification of AS 0 Processing */
1904 if (aggregator_as
== BGP_AS_ZERO
) {
1905 flog_err(EC_BGP_ATTR_LEN
,
1906 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1907 peer
->host
, aspath_print(attr
->aspath
));
1909 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1910 char attr_str
[BUFSIZ
] = {0};
1912 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1914 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1917 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1920 return BGP_ATTR_PARSE_PROCEED
;
1923 /* New Aggregator attribute */
1924 static enum bgp_attr_parse_ret
1925 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1926 as_t
*as4_aggregator_as
,
1927 struct in_addr
*as4_aggregator_addr
)
1929 struct peer
*const peer
= args
->peer
;
1930 struct attr
*const attr
= args
->attr
;
1931 const bgp_size_t length
= args
->length
;
1935 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1937 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1941 aggregator_as
= stream_getl(peer
->curr
);
1943 *as4_aggregator_as
= aggregator_as
;
1944 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1946 /* Codification of AS 0 Processing */
1947 if (aggregator_as
== BGP_AS_ZERO
) {
1948 flog_err(EC_BGP_ATTR_LEN
,
1949 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1950 peer
->host
, aspath_print(attr
->aspath
));
1952 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1953 char attr_str
[BUFSIZ
] = {0};
1955 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1957 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1960 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1963 return BGP_ATTR_PARSE_PROCEED
;
1966 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1968 static enum bgp_attr_parse_ret
1969 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1970 struct aspath
*as4_path
, as_t as4_aggregator
,
1971 struct in_addr
*as4_aggregator_addr
)
1973 int ignore_as4_path
= 0;
1974 struct aspath
*newpath
;
1976 if (!attr
->aspath
) {
1977 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1979 * checked that all well-known, mandatory attributes were
1982 * Can only be a problem with peer itself - hard error
1984 return BGP_ATTR_PARSE_ERROR
;
1987 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1988 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1990 * It is worth a warning though, because the peer really
1991 * should not send them
1993 if (BGP_DEBUG(as4
, AS4
)) {
1994 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1995 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1996 "AS4 capable peer, yet it sent");
1999 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
2000 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
2002 "AS4 capable peer, yet it sent");
2005 return BGP_ATTR_PARSE_PROCEED
;
2008 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
2009 * because that may override AS4_PATH
2011 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
2012 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
2014 * if the as_number in aggregator is not AS_TRANS,
2015 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
2016 * and the Aggregator shall be taken as
2017 * info on the aggregating node, and the AS_PATH
2018 * shall be taken as the AS_PATH
2020 * the Aggregator shall be ignored and the
2021 * AS4_AGGREGATOR shall be taken as the
2022 * Aggregating node and the AS_PATH is to be
2023 * constructed "as in all other cases"
2025 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
2027 if (BGP_DEBUG(as4
, AS4
))
2029 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
2031 ignore_as4_path
= 1;
2033 /* "New_aggregator shall be taken as aggregator"
2035 attr
->aggregator_as
= as4_aggregator
;
2036 attr
->aggregator_addr
.s_addr
=
2037 as4_aggregator_addr
->s_addr
;
2040 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2041 * That is bogus - but reading the conditions
2042 * we have to handle AS4_AGGREGATOR as if it were
2043 * AGGREGATOR in that case
2045 if (BGP_DEBUG(as4
, AS4
))
2047 "[AS4] %s BGP not AS4 capable peer send AS4_AGGREGATOR but no AGGREGATOR, will take it as if AGGREGATOR with AS_TRANS had been there",
2049 attr
->aggregator_as
= as4_aggregator
;
2050 /* sweep it under the carpet and simulate a "good"
2052 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
2056 /* need to reconcile NEW_AS_PATH and AS_PATH */
2057 if (!ignore_as4_path
2058 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
2059 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
2061 return BGP_ATTR_PARSE_ERROR
;
2063 aspath_unintern(&attr
->aspath
);
2064 attr
->aspath
= aspath_intern(newpath
);
2066 return BGP_ATTR_PARSE_PROCEED
;
2069 /* Community attribute. */
2070 static enum bgp_attr_parse_ret
2071 bgp_attr_community(struct bgp_attr_parser_args
*args
)
2073 struct peer
*const peer
= args
->peer
;
2074 struct attr
*const attr
= args
->attr
;
2075 const bgp_size_t length
= args
->length
;
2078 bgp_attr_set_community(attr
, NULL
);
2079 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2083 bgp_attr_set_community(
2085 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
2087 /* XXX: fix community_parse to use stream API and remove this */
2088 stream_forward_getp(peer
->curr
, length
);
2090 /* The Community attribute SHALL be considered malformed if its
2091 * length is not a non-zero multiple of 4.
2093 if (!bgp_attr_get_community(attr
))
2094 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2097 return BGP_ATTR_PARSE_PROCEED
;
2100 /* Originator ID attribute. */
2101 static enum bgp_attr_parse_ret
2102 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
2104 struct peer
*const peer
= args
->peer
;
2105 struct attr
*const attr
= args
->attr
;
2106 const bgp_size_t length
= args
->length
;
2108 /* if received from an internal neighbor, it SHALL be considered
2109 * malformed if its length is not equal to 4. If malformed, the
2110 * UPDATE message SHALL be handled using the approach of "treat-as-
2114 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
2117 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2121 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
2123 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2125 return BGP_ATTR_PARSE_PROCEED
;
2128 /* Cluster list attribute. */
2129 static enum bgp_attr_parse_ret
2130 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2132 struct peer
*const peer
= args
->peer
;
2133 struct attr
*const attr
= args
->attr
;
2134 const bgp_size_t length
= args
->length
;
2136 /* if received from an internal neighbor, it SHALL be considered
2137 * malformed if its length is not a non-zero multiple of 4. If
2138 * malformed, the UPDATE message SHALL be handled using the approach
2139 * of "treat-as-withdraw".
2141 if (length
== 0 || length
% 4) {
2142 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2144 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2148 bgp_attr_set_cluster(
2149 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2152 /* XXX: Fix cluster_parse to use stream API and then remove this */
2153 stream_forward_getp(peer
->curr
, length
);
2155 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2157 return BGP_ATTR_PARSE_PROCEED
;
2160 /* Multiprotocol reachability information parse. */
2161 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2162 struct bgp_nlri
*mp_update
)
2166 iana_safi_t pkt_safi
;
2168 bgp_size_t nlri_len
;
2171 struct peer
*const peer
= args
->peer
;
2172 struct attr
*const attr
= args
->attr
;
2173 const bgp_size_t length
= args
->length
;
2175 /* Set end of packet. */
2176 s
= BGP_INPUT(peer
);
2177 start
= stream_get_getp(s
);
2179 /* safe to read statically sized header? */
2180 #define BGP_MP_REACH_MIN_SIZE 5
2181 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2182 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2183 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2184 __func__
, peer
->host
, (unsigned long)length
);
2185 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2188 /* Load AFI, SAFI. */
2189 pkt_afi
= stream_getw(s
);
2190 pkt_safi
= stream_getc(s
);
2192 /* Convert AFI, SAFI to internal values, check. */
2193 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2194 /* Log if AFI or SAFI is unrecognized. This is not an error
2196 * the attribute is otherwise malformed.
2198 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2200 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2201 peer
->host
, iana_afi2str(pkt_afi
),
2202 iana_safi2str(pkt_safi
));
2203 return BGP_ATTR_PARSE_ERROR
;
2206 /* Get nexthop length. */
2207 attr
->mp_nexthop_len
= stream_getc(s
);
2209 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2211 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2212 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2213 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2216 /* Nexthop length check. */
2217 switch (attr
->mp_nexthop_len
) {
2219 if (safi
!= SAFI_FLOWSPEC
) {
2220 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2221 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2222 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2225 case BGP_ATTR_NHLEN_VPNV4
:
2226 stream_getl(s
); /* RD high */
2227 stream_getl(s
); /* RD low */
2229 * NOTE: intentional fall through
2230 * - for consistency in rx processing
2232 * The following comment is to signal GCC this intention
2233 * and suppress the warning
2236 case BGP_ATTR_NHLEN_IPV4
:
2237 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2238 /* Probably needed for RFC 2283 */
2239 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2240 memcpy(&attr
->nexthop
.s_addr
,
2241 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2243 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2244 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2245 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2246 stream_getl(s
); /* RD high */
2247 stream_getl(s
); /* RD low */
2249 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2250 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2251 if (!peer
->nexthop
.ifp
) {
2252 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2254 return BGP_ATTR_PARSE_WITHDRAW
;
2256 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2257 if (if_is_operative(peer
->nexthop
.ifp
))
2258 SET_FLAG(attr
->nh_flag
,
2259 BGP_ATTR_NH_IF_OPERSTATE
);
2261 UNSET_FLAG(attr
->nh_flag
,
2262 BGP_ATTR_NH_IF_OPERSTATE
);
2265 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2266 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2267 if (attr
->mp_nexthop_len
2268 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2269 stream_getl(s
); /* RD high */
2270 stream_getl(s
); /* RD low */
2272 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2273 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2274 if (!peer
->nexthop
.ifp
) {
2275 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",
2277 return BGP_ATTR_PARSE_WITHDRAW
;
2279 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2280 if (if_is_operative(peer
->nexthop
.ifp
))
2281 SET_FLAG(attr
->nh_flag
,
2282 BGP_ATTR_NH_IF_OPERSTATE
);
2284 UNSET_FLAG(attr
->nh_flag
,
2285 BGP_ATTR_NH_IF_OPERSTATE
);
2287 if (attr
->mp_nexthop_len
2288 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2289 stream_getl(s
); /* RD high */
2290 stream_getl(s
); /* RD low */
2292 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2293 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2294 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2296 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2297 peer
->host
, &attr
->mp_nexthop_global
,
2298 &attr
->mp_nexthop_local
);
2300 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2302 if (!peer
->nexthop
.ifp
) {
2303 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2305 return BGP_ATTR_PARSE_WITHDRAW
;
2307 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2310 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2311 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2312 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2316 zlog_info("%s: %s sent SNPA which couldn't be read",
2317 __func__
, peer
->host
);
2318 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2323 if ((val
= stream_getc(s
)))
2325 EC_BGP_DEFUNCT_SNPA_LEN
,
2326 "%s sent non-zero value, %u, for defunct SNPA-length field",
2330 /* must have nrli_len, what is left of the attribute */
2331 nlri_len
= LEN_LEFT
;
2332 if (nlri_len
> STREAM_READABLE(s
)) {
2333 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2334 __func__
, peer
->host
);
2335 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2339 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2340 __func__
, peer
->host
);
2342 mp_update
->afi
= afi
;
2343 mp_update
->safi
= safi
;
2344 return BGP_ATTR_PARSE_EOR
;
2347 mp_update
->afi
= afi
;
2348 mp_update
->safi
= safi
;
2349 mp_update
->nlri
= stream_pnt(s
);
2350 mp_update
->length
= nlri_len
;
2352 stream_forward_getp(s
, nlri_len
);
2354 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2356 return BGP_ATTR_PARSE_PROCEED
;
2360 /* Multiprotocol unreachable parse */
2361 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2362 struct bgp_nlri
*mp_withdraw
)
2367 iana_safi_t pkt_safi
;
2369 uint16_t withdraw_len
;
2370 struct peer
*const peer
= args
->peer
;
2371 struct attr
*const attr
= args
->attr
;
2372 const bgp_size_t length
= args
->length
;
2376 #define BGP_MP_UNREACH_MIN_SIZE 3
2377 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2378 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2380 pkt_afi
= stream_getw(s
);
2381 pkt_safi
= stream_getc(s
);
2383 /* Convert AFI, SAFI to internal values, check. */
2384 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2385 /* Log if AFI or SAFI is unrecognized. This is not an error
2387 * the attribute is otherwise malformed.
2389 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2391 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2392 peer
->host
, iana_afi2str(pkt_afi
),
2393 iana_safi2str(pkt_safi
));
2394 return BGP_ATTR_PARSE_ERROR
;
2397 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2399 mp_withdraw
->afi
= afi
;
2400 mp_withdraw
->safi
= safi
;
2401 mp_withdraw
->nlri
= stream_pnt(s
);
2402 mp_withdraw
->length
= withdraw_len
;
2404 stream_forward_getp(s
, withdraw_len
);
2406 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2408 return BGP_ATTR_PARSE_PROCEED
;
2411 /* Large Community attribute. */
2412 static enum bgp_attr_parse_ret
2413 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2415 struct peer
*const peer
= args
->peer
;
2416 struct attr
*const attr
= args
->attr
;
2417 const bgp_size_t length
= args
->length
;
2420 * Large community follows new attribute format.
2423 bgp_attr_set_lcommunity(attr
, NULL
);
2424 /* Empty extcomm doesn't seem to be invalid per se */
2425 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2429 bgp_attr_set_lcommunity(
2430 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2431 /* XXX: fix ecommunity_parse to use stream API */
2432 stream_forward_getp(peer
->curr
, length
);
2434 if (!bgp_attr_get_lcommunity(attr
))
2435 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2438 return BGP_ATTR_PARSE_PROCEED
;
2441 /* Extended Community attribute. */
2442 static enum bgp_attr_parse_ret
2443 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2445 struct peer
*const peer
= args
->peer
;
2446 struct attr
*const attr
= args
->attr
;
2447 const bgp_size_t length
= args
->length
;
2450 struct ecommunity
*ecomm
;
2453 bgp_attr_set_ecommunity(attr
, NULL
);
2454 /* Empty extcomm doesn't seem to be invalid per se */
2455 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2459 ecomm
= ecommunity_parse(
2460 stream_pnt(peer
->curr
), length
,
2461 CHECK_FLAG(peer
->flags
,
2462 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2463 bgp_attr_set_ecommunity(attr
, ecomm
);
2464 /* XXX: fix ecommunity_parse to use stream API */
2465 stream_forward_getp(peer
->curr
, length
);
2467 /* The Extended Community attribute SHALL be considered malformed if
2468 * its length is not a non-zero multiple of 8.
2470 if (!bgp_attr_get_ecommunity(attr
))
2471 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2474 /* Extract DF election preference and mobility sequence number */
2475 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2477 /* Extract MAC mobility sequence number, if any. */
2478 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2479 attr
->sticky
= sticky
;
2481 /* Check if this is a Gateway MAC-IP advertisement */
2482 attr
->default_gw
= bgp_attr_default_gw(attr
);
2484 /* Handle scenario where router flag ecommunity is not
2485 * set but default gw ext community is present.
2486 * Use default gateway, set and propogate R-bit.
2488 if (attr
->default_gw
)
2489 attr
->router_flag
= 1;
2491 /* Check EVPN Neighbor advertisement flags, R-bit */
2492 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2494 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2496 /* Extract the Rmac, if any */
2497 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2498 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2499 && bgp_mac_exist(&attr
->rmac
))
2500 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2504 /* Get the tunnel type from encap extended community */
2505 bgp_attr_extcom_tunnel_type(attr
,
2506 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2508 /* Extract link bandwidth, if any. */
2509 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2512 return BGP_ATTR_PARSE_PROCEED
;
2515 /* IPv6 Extended Community attribute. */
2516 static enum bgp_attr_parse_ret
2517 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2519 struct peer
*const peer
= args
->peer
;
2520 struct attr
*const attr
= args
->attr
;
2521 const bgp_size_t length
= args
->length
;
2522 struct ecommunity
*ipv6_ecomm
= NULL
;
2525 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2526 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2530 ipv6_ecomm
= ecommunity_parse_ipv6(
2531 stream_pnt(peer
->curr
), length
,
2532 CHECK_FLAG(peer
->flags
,
2533 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2534 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2536 /* XXX: fix ecommunity_parse to use stream API */
2537 stream_forward_getp(peer
->curr
, length
);
2540 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2543 return BGP_ATTR_PARSE_PROCEED
;
2546 /* Parse Tunnel Encap attribute in an UPDATE */
2547 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2548 bgp_size_t length
, /* IN: attr's length field */
2549 struct attr
*attr
, /* IN: caller already allocated */
2550 uint8_t flag
, /* IN: attr's flags field */
2554 uint16_t tunneltype
= 0;
2556 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2558 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2559 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2561 "Tunnel Encap attribute flag isn't optional and transitive %d",
2563 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2564 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2569 if (BGP_ATTR_ENCAP
== type
) {
2570 /* read outer TLV type and length */
2571 uint16_t tlv_length
;
2575 "Tunnel Encap attribute not long enough to contain outer T,L");
2576 bgp_notify_send_with_data(
2577 peer
, BGP_NOTIFY_UPDATE_ERR
,
2578 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2581 tunneltype
= stream_getw(BGP_INPUT(peer
));
2582 tlv_length
= stream_getw(BGP_INPUT(peer
));
2585 if (tlv_length
!= length
) {
2586 zlog_info("%s: tlv_length(%d) != length(%d)",
2587 __func__
, tlv_length
, length
);
2591 while (length
>= 4) {
2592 uint16_t subtype
= 0;
2593 uint16_t sublength
= 0;
2594 struct bgp_attr_encap_subtlv
*tlv
;
2596 if (BGP_ATTR_ENCAP
== type
) {
2597 subtype
= stream_getc(BGP_INPUT(peer
));
2598 sublength
= stream_getc(BGP_INPUT(peer
));
2600 #ifdef ENABLE_BGP_VNC
2602 subtype
= stream_getw(BGP_INPUT(peer
));
2603 sublength
= stream_getw(BGP_INPUT(peer
));
2608 if (sublength
> length
) {
2610 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2612 bgp_notify_send_with_data(
2613 peer
, BGP_NOTIFY_UPDATE_ERR
,
2614 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2618 /* alloc and copy sub-tlv */
2619 /* TBD make sure these are freed when attributes are released */
2620 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2621 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2622 tlv
->type
= subtype
;
2623 tlv
->length
= sublength
;
2624 stream_get(tlv
->value
, peer
->curr
, sublength
);
2625 length
-= sublength
;
2627 /* attach tlv to encap chain */
2628 if (BGP_ATTR_ENCAP
== type
) {
2629 struct bgp_attr_encap_subtlv
*stlv_last
;
2630 for (stlv_last
= attr
->encap_subtlvs
;
2631 stlv_last
&& stlv_last
->next
;
2632 stlv_last
= stlv_last
->next
)
2635 stlv_last
->next
= tlv
;
2637 attr
->encap_subtlvs
= tlv
;
2639 #ifdef ENABLE_BGP_VNC
2641 struct bgp_attr_encap_subtlv
*stlv_last
;
2642 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2643 bgp_attr_get_vnc_subtlvs(attr
);
2645 for (stlv_last
= vnc_subtlvs
;
2646 stlv_last
&& stlv_last
->next
;
2647 stlv_last
= stlv_last
->next
)
2650 stlv_last
->next
= tlv
;
2652 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2657 if (BGP_ATTR_ENCAP
== type
) {
2658 attr
->encap_tunneltype
= tunneltype
;
2662 /* spurious leftover data */
2664 "Tunnel Encap attribute length is bad: %d leftover octets",
2666 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2667 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2676 /* SRv6 Service Data Sub-Sub-TLV attribute
2677 * draft-ietf-bess-srv6-services-07
2679 static enum bgp_attr_parse_ret
2680 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2682 struct peer
*const peer
= args
->peer
;
2683 struct attr
*const attr
= args
->attr
;
2684 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2685 transposition_len
, transposition_offset
;
2687 size_t headersz
= sizeof(type
) + sizeof(length
);
2689 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2692 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2693 headersz
, STREAM_READABLE(peer
->curr
));
2694 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2698 type
= stream_getc(peer
->curr
);
2699 length
= stream_getw(peer
->curr
);
2701 if (STREAM_READABLE(peer
->curr
) < length
) {
2704 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2705 length
, STREAM_READABLE(peer
->curr
));
2706 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2710 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2713 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2714 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2716 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2720 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2721 if (STREAM_READABLE(peer
->curr
) <
2722 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2725 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
2726 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2727 STREAM_READABLE(peer
->curr
));
2728 return bgp_attr_malformed(
2729 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2733 loc_block_len
= stream_getc(peer
->curr
);
2734 loc_node_len
= stream_getc(peer
->curr
);
2735 func_len
= stream_getc(peer
->curr
);
2736 arg_len
= stream_getc(peer
->curr
);
2737 transposition_len
= stream_getc(peer
->curr
);
2738 transposition_offset
= stream_getc(peer
->curr
);
2740 /* Log SRv6 Service Data Sub-Sub-TLV */
2741 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2743 "%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",
2744 __func__
, loc_block_len
, loc_node_len
, func_len
,
2745 arg_len
, transposition_len
,
2746 transposition_offset
);
2749 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2750 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2751 attr
->srv6_l3vpn
->func_len
= func_len
;
2752 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2753 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2754 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2758 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2760 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2763 stream_forward_getp(peer
->curr
, length
);
2766 return BGP_ATTR_PARSE_PROCEED
;
2769 /* SRv6 Service Sub-TLV attribute
2770 * draft-ietf-bess-srv6-services-07
2772 static enum bgp_attr_parse_ret
2773 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2775 struct peer
*const peer
= args
->peer
;
2776 struct attr
*const attr
= args
->attr
;
2777 struct in6_addr ipv6_sid
;
2778 uint8_t type
, sid_flags
;
2779 uint16_t length
, endpoint_behavior
;
2780 size_t headersz
= sizeof(type
) + sizeof(length
);
2781 enum bgp_attr_parse_ret err
;
2783 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2786 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2787 headersz
, STREAM_READABLE(peer
->curr
));
2788 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2792 type
= stream_getc(peer
->curr
);
2793 length
= stream_getw(peer
->curr
);
2795 if (STREAM_READABLE(peer
->curr
) < length
) {
2798 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2799 length
, STREAM_READABLE(peer
->curr
));
2800 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2804 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2805 if (STREAM_READABLE(peer
->curr
) <
2806 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2809 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
2810 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
,
2811 STREAM_READABLE(peer
->curr
));
2812 return bgp_attr_malformed(
2813 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2816 stream_getc(peer
->curr
);
2817 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2818 sid_flags
= stream_getc(peer
->curr
);
2819 endpoint_behavior
= stream_getw(peer
->curr
);
2820 stream_getc(peer
->curr
);
2822 /* Log SRv6 Service Sub-TLV */
2823 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
2825 "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2826 __func__
, &ipv6_sid
, sid_flags
,
2829 /* Configure from Info */
2830 if (attr
->srv6_l3vpn
) {
2831 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2832 "Prefix SID SRv6 L3VPN field repeated");
2833 return bgp_attr_malformed(
2834 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2836 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2837 sizeof(struct bgp_attr_srv6_l3vpn
));
2838 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2839 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2840 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2841 attr
->srv6_l3vpn
->loc_block_len
= 0;
2842 attr
->srv6_l3vpn
->loc_node_len
= 0;
2843 attr
->srv6_l3vpn
->func_len
= 0;
2844 attr
->srv6_l3vpn
->arg_len
= 0;
2845 attr
->srv6_l3vpn
->transposition_len
= 0;
2846 attr
->srv6_l3vpn
->transposition_offset
= 0;
2848 // Sub-Sub-TLV found
2849 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2850 err
= bgp_attr_srv6_service_data(args
);
2852 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2856 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2859 /* Placeholder code for unsupported type */
2861 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2863 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2866 stream_forward_getp(peer
->curr
, length
);
2869 return BGP_ATTR_PARSE_PROCEED
;
2873 * Read an individual SID value returning how much data we have read
2874 * Returns 0 if there was an error that needs to be passed up the stack
2876 static enum bgp_attr_parse_ret
2877 bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2878 struct bgp_attr_parser_args
*args
)
2880 struct peer
*const peer
= args
->peer
;
2881 struct attr
*const attr
= args
->attr
;
2882 uint32_t label_index
;
2883 struct in6_addr ipv6_sid
;
2885 uint32_t srgb_range
;
2887 uint8_t sid_type
, sid_flags
;
2889 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2890 if (STREAM_READABLE(peer
->curr
) < length
2891 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2892 flog_err(EC_BGP_ATTR_LEN
,
2893 "Prefix SID label index length is %hu instead of %u",
2894 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2895 return bgp_attr_malformed(args
,
2896 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2900 /* Ignore flags and reserved */
2901 stream_getc(peer
->curr
);
2902 stream_getw(peer
->curr
);
2904 /* Fetch the label index and see if it is valid. */
2905 label_index
= stream_getl(peer
->curr
);
2906 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2907 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2910 /* Store label index; subsequently, we'll check on
2912 attr
->label_index
= label_index
;
2915 /* Placeholder code for the IPv6 SID type */
2916 else if (type
== BGP_PREFIX_SID_IPV6
) {
2917 if (STREAM_READABLE(peer
->curr
) < length
2918 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2919 flog_err(EC_BGP_ATTR_LEN
,
2920 "Prefix SID IPv6 length is %hu instead of %u",
2921 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2922 return bgp_attr_malformed(args
,
2923 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2927 /* Ignore reserved */
2928 stream_getc(peer
->curr
);
2929 stream_getw(peer
->curr
);
2931 stream_get(&ipv6_sid
, peer
->curr
, 16);
2934 /* Placeholder code for the Originator SRGB type */
2935 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2937 * ietf-idr-bgp-prefix-sid-05:
2938 * Length is the total length of the value portion of the
2939 * TLV: 2 + multiple of 6.
2941 * peer->curr stream readp should be at the beginning of the 16
2942 * bit flag field at this point in the code.
2946 * Check that the TLV length field is sane: at least 2 bytes of
2947 * flag, and at least 1 SRGB (these are 6 bytes each)
2949 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2952 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2954 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2955 return bgp_attr_malformed(
2956 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2961 * Check that we actually have at least as much data as
2962 * specified by the length field
2964 if (STREAM_READABLE(peer
->curr
) < length
) {
2965 flog_err(EC_BGP_ATTR_LEN
,
2966 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2967 length
, STREAM_READABLE(peer
->curr
));
2968 return bgp_attr_malformed(
2969 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2974 * Check that the portion of the TLV containing the sequence of
2975 * SRGBs corresponds to a multiple of the SRGB size; to get
2976 * that length, we skip the 16 bit flags field
2978 stream_getw(peer
->curr
);
2980 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2983 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2984 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2985 return bgp_attr_malformed(
2986 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2990 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2992 for (int i
= 0; i
< srgb_count
; i
++) {
2993 stream_get(&srgb_base
, peer
->curr
, 3);
2994 stream_get(&srgb_range
, peer
->curr
, 3);
2998 /* Placeholder code for the VPN-SID Service type */
2999 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
3000 if (STREAM_READABLE(peer
->curr
) < length
3001 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
3002 flog_err(EC_BGP_ATTR_LEN
,
3003 "Prefix SID VPN SID length is %hu instead of %u",
3004 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
3005 return bgp_attr_malformed(args
,
3006 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3010 /* Parse VPN-SID Sub-TLV */
3011 stream_getc(peer
->curr
); /* reserved */
3012 sid_type
= stream_getc(peer
->curr
); /* sid_type */
3013 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
3014 stream_get(&ipv6_sid
, peer
->curr
,
3015 sizeof(ipv6_sid
)); /* sid_value */
3017 /* Log VPN-SID Sub-TLV */
3018 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
))
3020 "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
3021 __func__
, &ipv6_sid
, sid_type
, sid_flags
);
3023 /* Configure from Info */
3024 if (attr
->srv6_vpn
) {
3025 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
3026 "Prefix SID SRv6 VPN field repeated");
3027 return bgp_attr_malformed(
3028 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
3030 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
3031 sizeof(struct bgp_attr_srv6_vpn
));
3032 attr
->srv6_vpn
->sid_flags
= sid_flags
;
3033 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
3034 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
3037 /* Placeholder code for the SRv6 L3 Service type */
3038 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
3039 if (STREAM_READABLE(peer
->curr
) < length
) {
3042 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
3043 length
, STREAM_READABLE(peer
->curr
));
3044 return bgp_attr_malformed(args
,
3045 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3049 /* ignore reserved */
3050 stream_getc(peer
->curr
);
3052 return bgp_attr_srv6_service(args
);
3055 /* Placeholder code for Unsupported TLV */
3058 if (STREAM_READABLE(peer
->curr
) < length
) {
3061 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
3062 length
, STREAM_READABLE(peer
->curr
));
3063 return bgp_attr_malformed(
3064 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3068 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3070 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3073 stream_forward_getp(peer
->curr
, length
);
3076 return BGP_ATTR_PARSE_PROCEED
;
3079 /* Prefix SID attribute
3080 * draft-ietf-idr-bgp-prefix-sid-05
3082 enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
3084 struct peer
*const peer
= args
->peer
;
3085 struct attr
*const attr
= args
->attr
;
3086 enum bgp_attr_parse_ret ret
;
3088 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3092 size_t headersz
= sizeof(type
) + sizeof(length
);
3093 size_t psid_parsed_length
= 0;
3095 while (STREAM_READABLE(peer
->curr
) > 0
3096 && psid_parsed_length
< args
->length
) {
3098 if (STREAM_READABLE(peer
->curr
) < headersz
) {
3101 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3102 headersz
, STREAM_READABLE(peer
->curr
));
3103 return bgp_attr_malformed(
3104 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3108 type
= stream_getc(peer
->curr
);
3109 length
= stream_getw(peer
->curr
);
3111 if (STREAM_READABLE(peer
->curr
) < length
) {
3114 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3115 length
, STREAM_READABLE(peer
->curr
));
3116 return bgp_attr_malformed(args
,
3117 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3121 ret
= bgp_attr_psid_sub(type
, length
, args
);
3123 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3126 psid_parsed_length
+= length
+ headersz
;
3128 if (psid_parsed_length
> args
->length
) {
3131 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
3132 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
3133 return bgp_attr_malformed(
3134 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3139 return BGP_ATTR_PARSE_PROCEED
;
3142 /* PMSI tunnel attribute (RFC 6514)
3143 * Basic validation checks done here.
3145 static enum bgp_attr_parse_ret
3146 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
3148 struct peer
*const peer
= args
->peer
;
3149 struct attr
*const attr
= args
->attr
;
3150 const bgp_size_t length
= args
->length
;
3152 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
3154 /* Verify that the receiver is expecting "ingress replication" as we
3155 * can only support that.
3157 if (length
< attr_parse_len
) {
3158 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
3160 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3163 stream_getc(peer
->curr
); /* Flags */
3164 tnl_type
= stream_getc(peer
->curr
);
3165 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3166 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3167 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3168 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3171 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3173 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3174 "Bad PMSI tunnel attribute length %d for IR",
3176 return bgp_attr_malformed(
3177 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3182 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3183 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3184 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3186 /* Forward read pointer of input stream. */
3187 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3189 return BGP_ATTR_PARSE_PROCEED
;
3192 /* AIGP attribute (rfc7311) */
3193 static enum bgp_attr_parse_ret
bgp_attr_aigp(struct bgp_attr_parser_args
*args
)
3195 struct peer
*const peer
= args
->peer
;
3196 struct attr
*const attr
= args
->attr
;
3197 const bgp_size_t length
= args
->length
;
3198 uint8_t *s
= stream_pnt(peer
->curr
);
3201 /* If an AIGP attribute is received on a BGP session for which
3202 * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3203 * as if it were an unrecognized non-transitive attribute.
3204 * That is, it "MUST be quietly ignored and not passed along to
3206 * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3207 * sessions between members of the same BGP Confederation,
3208 * the default value of AIGP_SESSION SHOULD be "enabled".
3210 if (peer
->sort
== BGP_PEER_EBGP
&&
3211 !CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
)) {
3213 "%pBP received AIGP attribute, but eBGP peer do not support it",
3218 if (!bgp_attr_aigp_valid(s
, length
))
3221 /* Extract AIGP Metric TLV */
3222 if (bgp_attr_aigp_get_tlv_metric(s
, length
, &aigp
))
3223 bgp_attr_set_aigp_metric(attr
, aigp
);
3226 stream_forward_getp(peer
->curr
, length
);
3228 return BGP_ATTR_PARSE_PROCEED
;
3231 /* OTC attribute. */
3232 static enum bgp_attr_parse_ret
bgp_attr_otc(struct bgp_attr_parser_args
*args
)
3234 struct peer
*const peer
= args
->peer
;
3235 struct attr
*const attr
= args
->attr
;
3236 const bgp_size_t length
= args
->length
;
3240 flog_err(EC_BGP_ATTR_LEN
, "OTC attribute length isn't 4 [%u]",
3242 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3246 attr
->otc
= stream_getl(peer
->curr
);
3248 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "OTC attribute value is 0");
3249 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
3253 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
3255 return BGP_ATTR_PARSE_PROCEED
;
3258 /* BGP unknown attribute treatment. */
3259 static enum bgp_attr_parse_ret
3260 bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3262 bgp_size_t total
= args
->total
;
3263 struct transit
*transit
;
3264 struct peer
*const peer
= args
->peer
;
3265 struct attr
*const attr
= args
->attr
;
3266 uint8_t *const startp
= args
->startp
;
3267 const uint8_t type
= args
->type
;
3268 const uint8_t flag
= args
->flags
;
3269 const bgp_size_t length
= args
->length
;
3271 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3273 "%s Unknown attribute is received (type %d, length %d)",
3274 peer
->host
, type
, length
);
3276 /* Forward read pointer of input stream. */
3277 stream_forward_getp(peer
->curr
, length
);
3279 /* If any of the mandatory well-known attributes are not recognized,
3280 then the Error Subcode is set to Unrecognized Well-known
3281 Attribute. The Data field contains the unrecognized attribute
3282 (type, length and value). */
3283 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3284 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3288 /* Unrecognized non-transitive optional attributes must be quietly
3289 ignored and not passed along to other BGP peers. */
3290 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3291 return BGP_ATTR_PARSE_PROCEED
;
3293 /* If a path with recognized transitive optional attribute is
3294 accepted and passed along to other BGP peers and the Partial bit
3295 in the Attribute Flags octet is set to 1 by some previous AS, it
3296 is not set back to 0 by the current AS. */
3297 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3299 /* Store transitive attribute to the end of attr->transit. */
3300 transit
= bgp_attr_get_transit(attr
);
3302 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3304 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3305 transit
->length
+ total
);
3307 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3308 transit
->length
+= total
;
3309 bgp_attr_set_transit(attr
, transit
);
3311 return BGP_ATTR_PARSE_PROCEED
;
3314 /* Well-known attribute check. */
3315 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3319 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3321 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3322 return BGP_ATTR_PARSE_PROCEED
;
3324 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3325 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3326 are present, it should. Check for any other attribute being present
3329 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3330 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3331 return BGP_ATTR_PARSE_PROCEED
;
3333 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3334 type
= BGP_ATTR_ORIGIN
;
3336 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3337 type
= BGP_ATTR_AS_PATH
;
3339 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3341 * NLRI is empty. We can't easily check NLRI empty here though.
3343 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3344 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3345 type
= BGP_ATTR_NEXT_HOP
;
3347 if (peer
->sort
== BGP_PEER_IBGP
3348 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3349 type
= BGP_ATTR_LOCAL_PREF
;
3351 /* If any of the well-known mandatory attributes are not present
3352 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3355 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3356 "%s Missing well-known attribute %s.", peer
->host
,
3357 lookup_msg(attr_str
, type
, NULL
));
3358 return BGP_ATTR_PARSE_WITHDRAW
;
3360 return BGP_ATTR_PARSE_PROCEED
;
3363 /* Read attribute of update packet. This function is called from
3364 bgp_update_receive() in bgp_packet.c. */
3365 enum bgp_attr_parse_ret
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3367 struct bgp_nlri
*mp_update
,
3368 struct bgp_nlri
*mp_withdraw
)
3370 enum bgp_attr_parse_ret ret
;
3374 uint8_t *startp
, *endp
;
3376 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3377 /* we need the as4_path only until we have synthesized the as_path with
3379 /* same goes for as4_aggregator */
3380 struct aspath
*as4_path
= NULL
;
3381 as_t as4_aggregator
= 0;
3382 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3383 struct transit
*transit
;
3385 /* Initialize bitmap. */
3386 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3388 /* End pointer of BGP attribute. */
3389 endp
= BGP_INPUT_PNT(peer
) + size
;
3391 /* Get attributes to the end of attribute length. */
3392 while (BGP_INPUT_PNT(peer
) < endp
) {
3393 /* Check remaining length check.*/
3394 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3395 /* XXX warning: long int format, int arg (arg 5) */
3397 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3398 "%s: error BGP attribute length %lu is smaller than min len",
3400 (unsigned long)(endp
3401 - stream_pnt(BGP_INPUT(peer
))));
3403 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3404 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3405 ret
= BGP_ATTR_PARSE_ERROR
;
3409 /* Fetch attribute flag and type. */
3410 startp
= BGP_INPUT_PNT(peer
);
3411 /* "The lower-order four bits of the Attribute Flags octet are
3412 unused. They MUST be zero when sent and MUST be ignored when
3414 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3415 type
= stream_getc(BGP_INPUT(peer
));
3417 /* Check whether Extended-Length applies and is in bounds */
3418 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3419 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3421 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3422 "%s: Extended length set, but just %lu bytes of attr header",
3424 (unsigned long)(endp
3425 - stream_pnt(BGP_INPUT(peer
))));
3427 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3428 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3429 ret
= BGP_ATTR_PARSE_ERROR
;
3433 /* Check extended attribue length bit. */
3434 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3435 length
= stream_getw(BGP_INPUT(peer
));
3437 length
= stream_getc(BGP_INPUT(peer
));
3439 /* If any attribute appears more than once in the UPDATE
3440 message, then the Error Subcode is set to Malformed Attribute
3443 if (CHECK_BITMAP(seen
, type
)) {
3445 EC_BGP_ATTRIBUTE_REPEATED
,
3446 "%s: error BGP attribute type %d appears twice in a message",
3449 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3450 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3451 ret
= BGP_ATTR_PARSE_ERROR
;
3455 /* Set type to bitmap to check duplicate attribute. `type' is
3456 unsigned char so it never overflow bitmap range. */
3458 SET_BITMAP(seen
, type
);
3460 /* Overflow check. */
3461 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3463 if (attr_endp
> endp
) {
3465 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3466 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3467 peer
->host
, type
, length
, size
, attr_endp
,
3471 * If any recognized attribute has an Attribute
3472 * Length that conflicts with the expected length
3473 * (based on the attribute type code), then the
3474 * Error Subcode MUST be set to Attribute Length
3475 * Error. The Data field MUST contain the erroneous
3476 * attribute (type, length, and value).
3478 * We do not currently have a good way to determine the
3479 * length of the attribute independent of the length
3480 * received in the message. Instead we send the
3481 * minimum between the amount of data we have and the
3482 * amount specified by the attribute length field.
3484 * Instead of directly passing in the packet buffer and
3485 * offset we use the stream_get* functions to read into
3486 * a stack buffer, since they perform bounds checking
3487 * and we are working with untrusted data.
3489 unsigned char ndata
[peer
->max_packet_size
];
3490 memset(ndata
, 0x00, sizeof(ndata
));
3492 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3493 /* Rewind to end of flag field */
3494 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3496 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3498 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3500 size_t atl
= attr_endp
- startp
;
3501 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3502 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3504 bgp_notify_send_with_data(
3505 peer
, BGP_NOTIFY_UPDATE_ERR
,
3506 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3509 ret
= BGP_ATTR_PARSE_ERROR
;
3513 struct bgp_attr_parser_args attr_args
= {
3520 .total
= attr_endp
- startp
,
3524 /* If any recognized attribute has Attribute Flags that conflict
3525 with the Attribute Type Code, then the Error Subcode is set
3527 Attribute Flags Error. The Data field contains the erroneous
3528 attribute (type, length and value). */
3529 if (bgp_attr_flag_invalid(&attr_args
)) {
3530 ret
= bgp_attr_malformed(
3531 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3533 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3538 /* OK check attribute and store it's value. */
3540 case BGP_ATTR_ORIGIN
:
3541 ret
= bgp_attr_origin(&attr_args
);
3543 case BGP_ATTR_AS_PATH
:
3544 ret
= bgp_attr_aspath(&attr_args
);
3546 case BGP_ATTR_AS4_PATH
:
3547 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3549 case BGP_ATTR_NEXT_HOP
:
3550 ret
= bgp_attr_nexthop(&attr_args
);
3552 case BGP_ATTR_MULTI_EXIT_DISC
:
3553 ret
= bgp_attr_med(&attr_args
);
3555 case BGP_ATTR_LOCAL_PREF
:
3556 ret
= bgp_attr_local_pref(&attr_args
);
3558 case BGP_ATTR_ATOMIC_AGGREGATE
:
3559 ret
= bgp_attr_atomic(&attr_args
);
3561 case BGP_ATTR_AGGREGATOR
:
3562 ret
= bgp_attr_aggregator(&attr_args
);
3564 case BGP_ATTR_AS4_AGGREGATOR
:
3565 ret
= bgp_attr_as4_aggregator(&attr_args
,
3567 &as4_aggregator_addr
);
3569 case BGP_ATTR_COMMUNITIES
:
3570 ret
= bgp_attr_community(&attr_args
);
3572 case BGP_ATTR_LARGE_COMMUNITIES
:
3573 ret
= bgp_attr_large_community(&attr_args
);
3575 case BGP_ATTR_ORIGINATOR_ID
:
3576 ret
= bgp_attr_originator_id(&attr_args
);
3578 case BGP_ATTR_CLUSTER_LIST
:
3579 ret
= bgp_attr_cluster_list(&attr_args
);
3581 case BGP_ATTR_MP_REACH_NLRI
:
3582 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3584 case BGP_ATTR_MP_UNREACH_NLRI
:
3585 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3587 case BGP_ATTR_EXT_COMMUNITIES
:
3588 ret
= bgp_attr_ext_communities(&attr_args
);
3590 #ifdef ENABLE_BGP_VNC_ATTR
3593 case BGP_ATTR_ENCAP
:
3594 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3597 case BGP_ATTR_PREFIX_SID
:
3598 ret
= bgp_attr_prefix_sid(&attr_args
);
3600 case BGP_ATTR_PMSI_TUNNEL
:
3601 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3603 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3604 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3607 ret
= bgp_attr_otc(&attr_args
);
3610 ret
= bgp_attr_aigp(&attr_args
);
3613 ret
= bgp_attr_unknown(&attr_args
);
3617 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3618 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3619 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3620 ret
= BGP_ATTR_PARSE_ERROR
;
3624 if (ret
== BGP_ATTR_PARSE_EOR
) {
3628 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3629 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3630 "%s: Attribute %s, parse error", peer
->host
,
3631 lookup_msg(attr_str
, type
, NULL
));
3634 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3636 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3637 "%s: Attribute %s, parse error - treating as withdrawal",
3638 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3642 /* Check the fetched length. */
3643 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3644 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3645 "%s: BGP attribute %s, fetch error",
3646 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3647 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3648 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3649 ret
= BGP_ATTR_PARSE_ERROR
;
3655 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3656 * About Prefix-SID path attribute,
3657 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3658 * may only appear in a BGP Prefix-SID attribute attached to
3659 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3660 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3662 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3663 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3665 /* Check final read pointer is same as end pointer. */
3666 if (BGP_INPUT_PNT(peer
) != endp
) {
3667 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3668 "%s: BGP attribute %s, length mismatch", peer
->host
,
3669 lookup_msg(attr_str
, type
, NULL
));
3670 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3671 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3673 ret
= BGP_ATTR_PARSE_ERROR
;
3678 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3679 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3680 * This is implemented below and will result in a NOTIFICATION. If the
3681 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3682 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3683 * message SHOULD NOT be sent. This is implemented elsewhere.
3685 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3686 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3687 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3688 * speaker that receives the message SHOULD ignore this attribute.
3690 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3691 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3692 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3693 ret
= BGP_ATTR_PARSE_ERROR
;
3698 /* Check all mandatory well-known attributes are present */
3699 ret
= bgp_attr_check(peer
, attr
);
3704 * At this place we can see whether we got AS4_PATH and/or
3705 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3706 * We can not do this before we've read all attributes because
3707 * the as4 handling does not say whether AS4_PATH has to be sent
3708 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3709 * in relationship to AGGREGATOR.
3710 * So, to be defensive, we are not relying on any order and read
3711 * all attributes first, including these 32bit ones, and now,
3712 * afterwards, we look what and if something is to be done for as4.
3714 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3717 /* actually... this doesn't ever return failure currently, but
3718 * better safe than sorry */
3719 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3720 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3721 &as4_aggregator_addr
)) {
3722 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3723 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3724 ret
= BGP_ATTR_PARSE_ERROR
;
3729 * Finally do the checks on the aspath we did not do yet
3730 * because we waited for a potentially synthesized aspath.
3732 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3733 ret
= bgp_attr_aspath_check(peer
, attr
);
3734 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3738 ret
= BGP_ATTR_PARSE_PROCEED
;
3742 * At this stage, we have done all fiddling with as4, and the
3743 * resulting info is in attr->aggregator resp. attr->aspath so
3744 * we can chuck as4_aggregator and as4_path alltogether in order
3748 * unintern - it is in the hash
3749 * The flag that we got this is still there, but that
3750 * does not do any trouble
3752 aspath_unintern(&as4_path
);
3754 transit
= bgp_attr_get_transit(attr
);
3755 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3756 /* Finally intern unknown attribute. */
3758 bgp_attr_set_transit(attr
, transit_intern(transit
));
3759 if (attr
->encap_subtlvs
)
3760 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3762 #ifdef ENABLE_BGP_VNC
3763 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3764 bgp_attr_get_vnc_subtlvs(attr
);
3767 bgp_attr_set_vnc_subtlvs(
3769 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3773 transit_free(transit
);
3774 bgp_attr_set_transit(attr
, NULL
);
3777 bgp_attr_flush_encap(attr
);
3781 transit
= bgp_attr_get_transit(attr
);
3783 assert(transit
->refcnt
> 0);
3784 if (attr
->encap_subtlvs
)
3785 assert(attr
->encap_subtlvs
->refcnt
> 0);
3786 #ifdef ENABLE_BGP_VNC
3787 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3788 bgp_attr_get_vnc_subtlvs(attr
);
3791 assert(vnc_subtlvs
->refcnt
> 0);
3798 * Extract the tunnel type from extended community
3800 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3801 bgp_encap_types
*tunnel_type
)
3803 struct ecommunity
*ecom
;
3809 ecom
= bgp_attr_get_ecommunity(attr
);
3810 if (!ecom
|| !ecom
->size
)
3813 for (i
= 0; i
< ecom
->size
; i
++) {
3815 uint8_t type
, sub_type
;
3817 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3820 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3821 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3823 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3830 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3831 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3835 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
3836 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
3839 /* Set extended bit always to encode the attribute length as 2 bytes */
3840 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3841 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3842 sizep
= stream_get_endp(s
);
3843 stream_putw(s
, 0); /* Marker: Attribute length. */
3846 /* Convert AFI, SAFI to values for packet. */
3847 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3849 stream_putw(s
, pkt_afi
); /* AFI */
3850 stream_putc(s
, pkt_safi
); /* SAFI */
3854 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3855 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3856 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3857 else if (safi
== SAFI_FLOWSPEC
)
3860 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3863 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3868 case SAFI_MULTICAST
:
3869 case SAFI_LABELED_UNICAST
:
3871 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3875 stream_putl(s
, 0); /* RD = 0, per RFC */
3877 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3882 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3885 if (attr
->mp_nexthop_len
== 0)
3886 stream_putc(s
, 0); /* no nexthop for flowspec */
3888 stream_putc(s
, attr
->mp_nexthop_len
);
3889 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3894 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
3901 case SAFI_MULTICAST
:
3902 case SAFI_LABELED_UNICAST
:
3904 if (attr
->mp_nexthop_len
3905 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3907 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3908 stream_put(s
, &attr
->mp_nexthop_global
,
3910 stream_put(s
, &attr
->mp_nexthop_local
,
3913 stream_putc(s
, IPV6_MAX_BYTELEN
);
3914 stream_put(s
, &attr
->mp_nexthop_global
,
3918 case SAFI_MPLS_VPN
: {
3919 if (attr
->mp_nexthop_len
3920 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3922 stream_putl(s
, 0); /* RD = 0, per RFC */
3924 stream_put(s
, &attr
->mp_nexthop_global
,
3926 stream_putl(s
, 0); /* RD = 0, per RFC */
3928 stream_put(s
, &attr
->mp_nexthop_local
,
3932 stream_putl(s
, 0); /* RD = 0, per RFC */
3934 stream_put(s
, &attr
->mp_nexthop_global
,
3939 stream_putc(s
, IPV6_MAX_BYTELEN
);
3940 stream_put(s
, &attr
->mp_nexthop_global
,
3944 stream_putc(s
, 0); /* no nexthop for flowspec */
3948 assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
3953 if (safi
!= SAFI_FLOWSPEC
)
3955 EC_BGP_ATTR_NH_SEND_LEN
,
3956 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3957 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3961 assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here");
3970 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3971 const struct prefix
*p
,
3972 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3973 uint32_t num_labels
, bool addpath_capable
,
3974 uint32_t addpath_tx_id
, struct attr
*attr
)
3979 assert(!"Dev escape usage of SAFI_UNSPEC or MAX");
3982 if (addpath_capable
)
3983 stream_putl(s
, addpath_tx_id
);
3984 /* Label, RD, Prefix write. */
3985 stream_putc(s
, p
->prefixlen
+ 88);
3986 stream_put(s
, label
, BGP_LABEL_BYTES
);
3987 stream_put(s
, prd
->val
, 8);
3988 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3991 if (afi
== AFI_L2VPN
)
3992 /* EVPN prefix - contents depend on type */
3993 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
,
3994 attr
, addpath_capable
,
3997 assert(!"Add encoding bits here for other AFI's");
3999 case SAFI_LABELED_UNICAST
:
4000 /* Prefix write with label. */
4001 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
4005 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
4006 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
4007 p
->u
.prefix_flowspec
.prefixlen
);
4011 case SAFI_MULTICAST
:
4012 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
4015 assert(!"Please add proper encoding of SAFI_ENCAP");
4020 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
4021 const struct prefix
*p
)
4023 int size
= PSIZE(p
->prefixlen
);
4028 assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE");
4031 case SAFI_MULTICAST
:
4037 /* This has to be wrong, but I don't know what to put here */
4038 assert(!"Do we try to use this?");
4040 case SAFI_LABELED_UNICAST
:
4041 size
+= BGP_LABEL_BYTES
;
4045 * TODO: Maximum possible for type-2, type-3 and type-5
4047 if (afi
== AFI_L2VPN
)
4050 assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values");
4053 size
= ((struct prefix_fs
*)p
)->prefix
.prefixlen
;
4061 * Encodes the tunnel encapsulation attribute,
4062 * and with ENABLE_BGP_VNC the VNC attribute which uses
4063 * almost the same TLV format
4065 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
4066 struct stream
*s
, struct attr
*attr
,
4069 unsigned int attrlenfield
= 0;
4070 unsigned int attrhdrlen
= 0;
4071 struct bgp_attr_encap_subtlv
*subtlvs
;
4072 struct bgp_attr_encap_subtlv
*st
;
4073 const char *attrname
;
4075 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
4076 && (!attr
->encap_tunneltype
4077 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
4081 case BGP_ATTR_ENCAP
:
4082 attrname
= "Tunnel Encap";
4083 subtlvs
= attr
->encap_subtlvs
;
4084 if (subtlvs
== NULL
) /* nothing to do */
4087 * The tunnel encap attr has an "outer" tlv.
4089 * L = total length of subtlvs,
4090 * V = concatenated subtlvs.
4092 attrlenfield
= 2 + 2; /* T + L */
4093 attrhdrlen
= 1 + 1; /* subTLV T + L */
4096 #ifdef ENABLE_BGP_VNC_ATTR
4099 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
4100 if (subtlvs
== NULL
) /* nothing to do */
4102 attrlenfield
= 0; /* no outer T + L */
4103 attrhdrlen
= 2 + 2; /* subTLV T + L */
4111 /* compute attr length */
4112 for (st
= subtlvs
; st
; st
= st
->next
) {
4113 attrlenfield
+= (attrhdrlen
+ st
->length
);
4116 if (attrlenfield
> 0xffff) {
4117 zlog_info("%s attribute is too long (length=%d), can't send it",
4118 attrname
, attrlenfield
);
4122 if (attrlenfield
> 0xff) {
4123 /* 2-octet length field */
4125 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4126 | BGP_ATTR_FLAG_EXTLEN
);
4127 stream_putc(s
, attrtype
);
4128 stream_putw(s
, attrlenfield
& 0xffff);
4130 /* 1-octet length field */
4131 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
4132 stream_putc(s
, attrtype
);
4133 stream_putc(s
, attrlenfield
& 0xff);
4136 if (attrtype
== BGP_ATTR_ENCAP
) {
4137 /* write outer T+L */
4138 stream_putw(s
, attr
->encap_tunneltype
);
4139 stream_putw(s
, attrlenfield
- 4);
4142 /* write each sub-tlv */
4143 for (st
= subtlvs
; st
; st
= st
->next
) {
4144 if (attrtype
== BGP_ATTR_ENCAP
) {
4145 stream_putc(s
, st
->type
);
4146 stream_putc(s
, st
->length
);
4147 #ifdef ENABLE_BGP_VNC
4149 stream_putw(s
, st
->type
);
4150 stream_putw(s
, st
->length
);
4153 stream_put(s
, st
->value
, st
->length
);
4157 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
4159 /* Set MP attribute length. Don't count the (2) bytes used to encode
4161 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
4164 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
4166 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
4167 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
4168 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4169 PEER_FLAG_REMOVE_PRIVATE_AS
)
4170 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4171 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
4172 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4173 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
4174 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4175 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
4180 /* Make attribute packet. */
4181 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
4182 struct stream
*s
, struct attr
*attr
,
4183 struct bpacket_attr_vec_arr
*vecarr
,
4184 struct prefix
*p
, afi_t afi
, safi_t safi
,
4185 struct peer
*from
, struct prefix_rd
*prd
,
4186 mpls_label_t
*label
, uint32_t num_labels
,
4187 bool addpath_capable
, uint32_t addpath_tx_id
,
4188 struct bgp_path_info
*bpi
)
4191 size_t aspath_sizep
;
4192 struct aspath
*aspath
;
4193 int send_as4_path
= 0;
4194 int send_as4_aggregator
= 0;
4195 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
4196 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
4201 /* Remember current pointer. */
4202 cp
= stream_get_endp(s
);
4205 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
4206 && !peer_cap_enhe(peer
, afi
, safi
))) {
4207 size_t mpattrlen_pos
= 0;
4209 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
4211 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
4212 num_labels
, addpath_capable
,
4213 addpath_tx_id
, attr
);
4214 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
4217 /* Origin attribute. */
4218 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4219 stream_putc(s
, BGP_ATTR_ORIGIN
);
4221 stream_putc(s
, attr
->origin
);
4223 /* AS path attribute. */
4225 /* If remote-peer is EBGP */
4226 if (peer
->sort
== BGP_PEER_EBGP
4227 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4228 PEER_FLAG_AS_PATH_UNCHANGED
)
4229 || attr
->aspath
->segments
== NULL
)
4230 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4231 PEER_FLAG_RSERVER_CLIENT
))) {
4232 aspath
= aspath_dup(attr
->aspath
);
4234 /* Even though we may not be configured for confederations we
4236 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4237 aspath
= aspath_delete_confed_seq(aspath
);
4239 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
4240 /* Stuff our path CONFED_ID on the front */
4241 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
4243 if (peer
->change_local_as
) {
4244 /* If replace-as is specified, we only use the
4245 change_local_as when
4246 advertising routes. */
4247 if (!CHECK_FLAG(peer
->flags
,
4248 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
4249 if (bgp_append_local_as(peer
, afi
,
4251 aspath
= aspath_add_seq(
4252 aspath
, peer
->local_as
);
4253 aspath
= aspath_add_seq(aspath
,
4254 peer
->change_local_as
);
4256 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
4259 } else if (peer
->sort
== BGP_PEER_CONFED
) {
4260 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4262 aspath
= aspath_dup(attr
->aspath
);
4263 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
4265 aspath
= attr
->aspath
;
4267 /* If peer is not AS4 capable, then:
4268 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4269 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4271 * types are in it (i.e. exclude them if they are there)
4272 * AND do this only if there is at least one asnum > 65535 in the
4274 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4276 * all ASnums > 65535 to BGP_AS_TRANS
4279 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4280 stream_putc(s
, BGP_ATTR_AS_PATH
);
4281 aspath_sizep
= stream_get_endp(s
);
4283 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4285 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4288 if (!use32bit
&& aspath_has_as4(aspath
))
4290 1; /* we'll do this later, at the correct place */
4292 /* Nexthop attribute. */
4293 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4294 && !peer_cap_enhe(peer
, afi
, safi
)) {
4295 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4297 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4298 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4299 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4300 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4303 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4304 } else if (peer_cap_enhe(from
, afi
, safi
)
4305 || (nh_afi
== AFI_IP6
)) {
4307 * Likely this is the case when an IPv4 prefix was
4308 * received with Extended Next-hop capability in this
4309 * or another vrf and is now being advertised to
4310 * non-ENHE peers. Since peer_cap_enhe only checks
4311 * peers in this vrf, also check the nh_afi to catch
4312 * the case where the originator was in another vrf.
4313 * Setting the mandatory (ipv4) next-hop attribute here
4314 * to enable implicit next-hop self with correct A-F
4315 * (ipv4 address family).
4317 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4318 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4319 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4322 stream_put_ipv4(s
, 0);
4326 /* MED attribute. */
4327 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4328 || bgp
->maxmed_active
) {
4329 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4330 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4332 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4336 /* Local preference. */
4337 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4338 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4339 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4341 stream_putl(s
, attr
->local_pref
);
4344 /* Atomic aggregate. */
4345 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4346 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4347 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4352 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4353 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4354 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4355 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4358 /* AS4 capable peer */
4360 stream_putl(s
, attr
->aggregator_as
);
4362 /* 2-byte AS peer */
4365 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4367 if (attr
->aggregator_as
> UINT16_MAX
) {
4368 stream_putw(s
, BGP_AS_TRANS
);
4370 /* we have to send AS4_AGGREGATOR, too.
4371 * we'll do that later in order to send
4372 * attributes in ascending
4375 send_as4_aggregator
= 1;
4377 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4379 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4382 /* Community attribute. */
4383 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4384 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4385 struct community
*comm
= NULL
;
4387 comm
= bgp_attr_get_community(attr
);
4388 if (comm
->size
* 4 > 255) {
4390 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4391 | BGP_ATTR_FLAG_EXTLEN
);
4392 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4393 stream_putw(s
, comm
->size
* 4);
4396 BGP_ATTR_FLAG_OPTIONAL
4397 | BGP_ATTR_FLAG_TRANS
);
4398 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4399 stream_putc(s
, comm
->size
* 4);
4401 stream_put(s
, comm
->val
, comm
->size
* 4);
4405 * Large Community attribute.
4407 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4408 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4409 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4410 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4412 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4413 | BGP_ATTR_FLAG_EXTLEN
);
4414 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4416 lcom_length(bgp_attr_get_lcommunity(attr
)));
4419 BGP_ATTR_FLAG_OPTIONAL
4420 | BGP_ATTR_FLAG_TRANS
);
4421 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4423 lcom_length(bgp_attr_get_lcommunity(attr
)));
4425 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4426 lcom_length(bgp_attr_get_lcommunity(attr
)));
4429 /* Route Reflector. */
4430 if (peer
->sort
== BGP_PEER_IBGP
&& from
4431 && from
->sort
== BGP_PEER_IBGP
) {
4432 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4434 /* Originator ID. */
4435 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4436 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4439 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4440 stream_put_in_addr(s
, &attr
->originator_id
);
4442 stream_put_in_addr(s
, &from
->remote_id
);
4445 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4446 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4449 stream_putc(s
, cluster
->length
+ 4);
4450 /* If this peer configuration's parent BGP has
4452 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4453 stream_put_in_addr(s
, &bgp
->cluster_id
);
4455 stream_put_in_addr(s
, &bgp
->router_id
);
4456 stream_put(s
, cluster
->list
, cluster
->length
);
4459 /* If this peer configuration's parent BGP has
4461 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4462 stream_put_in_addr(s
, &bgp
->cluster_id
);
4464 stream_put_in_addr(s
, &bgp
->router_id
);
4468 /* Extended Communities attribute. */
4469 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4470 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4471 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4472 bool transparent
= CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4473 PEER_FLAG_RSERVER_CLIENT
) &&
4475 CHECK_FLAG(from
->af_flags
[afi
][safi
],
4476 PEER_FLAG_RSERVER_CLIENT
);
4478 if (peer
->sort
== BGP_PEER_IBGP
||
4479 peer
->sort
== BGP_PEER_CONFED
|| transparent
) {
4480 if (ecomm
->size
* 8 > 255) {
4482 BGP_ATTR_FLAG_OPTIONAL
4483 | BGP_ATTR_FLAG_TRANS
4484 | BGP_ATTR_FLAG_EXTLEN
);
4485 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4486 stream_putw(s
, ecomm
->size
* 8);
4489 BGP_ATTR_FLAG_OPTIONAL
4490 | BGP_ATTR_FLAG_TRANS
);
4491 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4492 stream_putc(s
, ecomm
->size
* 8);
4494 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4498 int ecom_tr_size
= 0;
4501 for (i
= 0; i
< ecomm
->size
; i
++) {
4502 pnt
= ecomm
->val
+ (i
* 8);
4505 if (CHECK_FLAG(tbit
,
4506 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4513 if (ecom_tr_size
* 8 > 255) {
4516 BGP_ATTR_FLAG_OPTIONAL
4517 | BGP_ATTR_FLAG_TRANS
4518 | BGP_ATTR_FLAG_EXTLEN
);
4520 BGP_ATTR_EXT_COMMUNITIES
);
4521 stream_putw(s
, ecom_tr_size
* 8);
4525 BGP_ATTR_FLAG_OPTIONAL
4526 | BGP_ATTR_FLAG_TRANS
);
4528 BGP_ATTR_EXT_COMMUNITIES
);
4529 stream_putc(s
, ecom_tr_size
* 8);
4532 for (i
= 0; i
< ecomm
->size
; i
++) {
4533 pnt
= ecomm
->val
+ (i
* 8);
4538 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4541 stream_put(s
, pnt
, 8);
4547 /* Label index attribute. */
4548 if (safi
== SAFI_LABELED_UNICAST
) {
4549 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4550 uint32_t label_index
;
4552 label_index
= attr
->label_index
;
4554 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4556 BGP_ATTR_FLAG_OPTIONAL
4557 | BGP_ATTR_FLAG_TRANS
);
4558 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4560 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4562 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4563 stream_putc(s
, 0); // reserved
4564 stream_putw(s
, 0); // flags
4565 stream_putl(s
, label_index
);
4570 /* SRv6 Service Information Attribute. */
4571 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4572 if (attr
->srv6_l3vpn
) {
4573 uint8_t subtlv_len
=
4574 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4576 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4577 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4578 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4579 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4580 | BGP_ATTR_FLAG_TRANS
);
4581 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4582 stream_putc(s
, attr_len
);
4583 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4584 stream_putw(s
, tlv_len
);
4585 stream_putc(s
, 0); /* reserved */
4586 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4587 stream_putw(s
, subtlv_len
);
4588 stream_putc(s
, 0); /* reserved */
4589 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4590 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4591 stream_putc(s
, 0); /* sid_flags */
4594 ->endpoint_behavior
); /* endpoint */
4595 stream_putc(s
, 0); /* reserved */
4598 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4601 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4602 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4603 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4604 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4605 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4606 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4607 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4608 } else if (attr
->srv6_vpn
) {
4609 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4610 | BGP_ATTR_FLAG_TRANS
);
4611 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4612 stream_putc(s
, 22); /* tlv len */
4613 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4614 stream_putw(s
, 0x13); /* tlv len */
4615 stream_putc(s
, 0x00); /* reserved */
4616 stream_putc(s
, 0x01); /* sid_type */
4617 stream_putc(s
, 0x00); /* sif_flags */
4618 stream_put(s
, &attr
->srv6_vpn
->sid
,
4619 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4623 if (send_as4_path
) {
4624 /* If the peer is NOT As4 capable, AND */
4625 /* there are ASnums > 65535 in path THEN
4626 * give out AS4_PATH */
4628 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4630 * Hm, I wonder... confederation things *should* only be at
4631 * the beginning of an aspath, right? Then we should use
4632 * aspath_delete_confed_seq for this, because it is already
4634 * Folks, talk to me: what is reasonable here!?
4636 aspath
= aspath_delete_confed_seq(aspath
);
4639 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4640 | BGP_ATTR_FLAG_EXTLEN
);
4641 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4642 aspath_sizep
= stream_get_endp(s
);
4644 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4647 if (aspath
!= attr
->aspath
)
4648 aspath_free(aspath
);
4650 if (send_as4_aggregator
) {
4651 /* send AS4_AGGREGATOR, at this place */
4652 /* this section of code moved here in order to ensure the
4654 * *ascending* order of attributes
4656 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4657 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4659 stream_putl(s
, attr
->aggregator_as
);
4660 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4663 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4664 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4665 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4666 /* Tunnel Encap attribute */
4667 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4669 #ifdef ENABLE_BGP_VNC_ATTR
4671 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4676 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4677 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4678 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4679 stream_putc(s
, 9); // Length
4680 stream_putc(s
, 0); // Flags
4681 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4682 stream_put(s
, &(attr
->label
),
4683 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4684 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4685 // Unicast tunnel endpoint IP address
4689 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4690 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4691 stream_putc(s
, BGP_ATTR_OTC
);
4693 stream_putl(s
, attr
->otc
);
4697 if (bpi
&& attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
) &&
4698 (CHECK_FLAG(peer
->flags
, PEER_FLAG_AIGP
) ||
4699 peer
->sort
!= BGP_PEER_EBGP
)) {
4700 /* At the moment only AIGP Metric TLV exists for AIGP
4701 * attribute. If more comes in, do not forget to update
4702 * attr_len variable to include new ones.
4704 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4706 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4707 stream_putc(s
, BGP_ATTR_AIGP
);
4708 stream_putc(s
, attr_len
);
4709 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4712 /* Unknown transit attribute. */
4713 struct transit
*transit
= bgp_attr_get_transit(attr
);
4716 stream_put(s
, transit
->val
, transit
->length
);
4718 /* Return total size of attribute. */
4719 return stream_get_endp(s
) - cp
;
4722 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4724 unsigned long attrlen_pnt
;
4725 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
4726 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
4728 /* Set extended bit always to encode the attribute length as 2 bytes */
4729 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4730 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4732 attrlen_pnt
= stream_get_endp(s
);
4733 stream_putw(s
, 0); /* Length of this attribute. */
4735 /* Convert AFI, SAFI to values for packet. */
4736 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4738 stream_putw(s
, pkt_afi
);
4739 stream_putc(s
, pkt_safi
);
4744 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4745 afi_t afi
, safi_t safi
,
4746 const struct prefix_rd
*prd
,
4747 mpls_label_t
*label
, uint32_t num_labels
,
4748 bool addpath_capable
, uint32_t addpath_tx_id
,
4751 uint8_t wlabel
[4] = {0x80, 0x00, 0x00};
4753 if (safi
== SAFI_LABELED_UNICAST
) {
4754 label
= (mpls_label_t
*)wlabel
;
4758 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4759 addpath_capable
, addpath_tx_id
, attr
);
4762 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4764 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4767 /* Initialization of attribute. */
4768 void bgp_attr_init(void)
4781 void bgp_attr_finish(void)
4786 ecommunity_finish();
4787 lcommunity_finish();
4794 /* Make attribute packet. */
4795 void bgp_dump_routes_attr(struct stream
*s
, struct bgp_path_info
*bpi
,
4796 const struct prefix
*prefix
)
4801 struct aspath
*aspath
;
4802 bool addpath_capable
= false;
4803 uint32_t addpath_tx_id
= 0;
4804 struct attr
*attr
= bpi
->attr
;
4806 /* Remember current pointer. */
4807 cp
= stream_get_endp(s
);
4809 /* Place holder of length. */
4812 /* Origin attribute. */
4813 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4814 stream_putc(s
, BGP_ATTR_ORIGIN
);
4816 stream_putc(s
, attr
->origin
);
4818 aspath
= attr
->aspath
;
4820 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4821 stream_putc(s
, BGP_ATTR_AS_PATH
);
4822 aspath_lenp
= stream_get_endp(s
);
4825 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4827 /* Nexthop attribute. */
4828 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4829 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4830 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4831 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4833 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4836 /* MED attribute. */
4837 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4838 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4839 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4841 stream_putl(s
, attr
->med
);
4844 /* Local preference. */
4845 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4846 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4847 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4849 stream_putl(s
, attr
->local_pref
);
4852 /* Atomic aggregate. */
4853 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4854 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4855 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4860 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4861 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4862 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4864 stream_putl(s
, attr
->aggregator_as
);
4865 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4868 /* Community attribute. */
4869 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4870 struct community
*comm
= NULL
;
4872 comm
= bgp_attr_get_community(attr
);
4873 if (comm
->size
* 4 > 255) {
4875 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4876 | BGP_ATTR_FLAG_EXTLEN
);
4877 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4878 stream_putw(s
, comm
->size
* 4);
4881 BGP_ATTR_FLAG_OPTIONAL
4882 | BGP_ATTR_FLAG_TRANS
);
4883 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4884 stream_putc(s
, comm
->size
* 4);
4886 stream_put(s
, comm
->val
, comm
->size
* 4);
4889 /* Large Community attribute. */
4890 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4891 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4893 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4894 | BGP_ATTR_FLAG_EXTLEN
);
4895 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4897 lcom_length(bgp_attr_get_lcommunity(attr
)));
4900 BGP_ATTR_FLAG_OPTIONAL
4901 | BGP_ATTR_FLAG_TRANS
);
4902 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4904 lcom_length(bgp_attr_get_lcommunity(attr
)));
4907 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4908 lcom_length(bgp_attr_get_lcommunity(attr
)));
4911 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4912 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4913 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4914 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4917 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4918 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4919 sizep
= stream_get_endp(s
);
4922 stream_putc(s
, 0); /* Marker: Attribute length. */
4923 stream_putw(s
, AFI_IP6
); /* AFI */
4924 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4927 stream_putc(s
, attr
->mp_nexthop_len
);
4928 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4929 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4930 stream_put(s
, &attr
->mp_nexthop_local
,
4937 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4940 /* Set MP attribute length. */
4941 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4945 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4946 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4948 BGP_ATTR_FLAG_OPTIONAL
4949 | BGP_ATTR_FLAG_TRANS
);
4950 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4952 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4953 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4954 stream_putc(s
, 0); // reserved
4955 stream_putw(s
, 0); // flags
4956 stream_putl(s
, attr
->label_index
);
4961 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4962 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4963 stream_putc(s
, BGP_ATTR_OTC
);
4965 stream_putl(s
, attr
->otc
);
4969 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AIGP
)) {
4970 /* At the moment only AIGP Metric TLV exists for AIGP
4971 * attribute. If more comes in, do not forget to update
4972 * attr_len variable to include new ones.
4974 uint8_t attr_len
= BGP_AIGP_TLV_METRIC_LEN
;
4976 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4977 stream_putc(s
, BGP_ATTR_AIGP
);
4978 stream_putc(s
, attr_len
);
4979 stream_put_bgp_aigp_tlv_metric(s
, bpi
);
4982 /* Return total size of attribute. */
4983 len
= stream_get_endp(s
) - cp
- 2;
4984 stream_putw_at(s
, cp
, len
);