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_DPA
, "DPA"},
72 {BGP_ATTR_ADVERTISER
, "ADVERTISER"},
73 {BGP_ATTR_RCID_PATH
, "RCID_PATH"},
74 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
75 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
76 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
77 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
78 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
79 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
80 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
81 {BGP_ATTR_ENCAP
, "ENCAP"},
82 #ifdef ENABLE_BGP_VNC_ATTR
83 {BGP_ATTR_VNC
, "VNC"},
85 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
86 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
87 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
90 static const struct message attr_flag_str
[] = {
91 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
92 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
93 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
94 /* bgp_attr_flags_diagnose() relies on this bit being last in
96 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
99 static struct hash
*cluster_hash
;
101 static void *cluster_hash_alloc(void *p
)
103 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
104 struct cluster_list
*cluster
;
106 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
107 cluster
->length
= val
->length
;
109 if (cluster
->length
) {
110 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
111 memcpy(cluster
->list
, val
->list
, val
->length
);
113 cluster
->list
= NULL
;
120 /* Cluster list related functions. */
121 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
123 struct cluster_list tmp
= {};
124 struct cluster_list
*cluster
;
127 tmp
.list
= length
== 0 ? NULL
: pnt
;
129 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
134 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
138 for (i
= 0; i
< cluster
->length
/ 4; i
++)
139 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
144 static unsigned int cluster_hash_key_make(const void *p
)
146 const struct cluster_list
*cluster
= p
;
148 return jhash(cluster
->list
, cluster
->length
, 0);
151 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
153 const struct cluster_list
*cluster1
= p1
;
154 const struct cluster_list
*cluster2
= p2
;
156 if (cluster1
->list
== cluster2
->list
)
159 if (!cluster1
->list
|| !cluster2
->list
)
162 if (cluster1
->length
!= cluster2
->length
)
165 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
168 static void cluster_free(struct cluster_list
*cluster
)
170 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
171 XFREE(MTYPE_CLUSTER
, cluster
);
174 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
176 struct cluster_list
*find
;
178 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
184 static void cluster_unintern(struct cluster_list
**cluster
)
186 if ((*cluster
)->refcnt
)
187 (*cluster
)->refcnt
--;
189 if ((*cluster
)->refcnt
== 0) {
190 void *p
= hash_release(cluster_hash
, *cluster
);
191 assert(p
== *cluster
);
192 cluster_free(*cluster
);
197 static void cluster_init(void)
199 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
203 static void cluster_finish(void)
205 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
206 hash_free(cluster_hash
);
210 static struct hash
*encap_hash
= NULL
;
211 #ifdef ENABLE_BGP_VNC
212 static struct hash
*vnc_hash
= NULL
;
214 static struct hash
*srv6_l3vpn_hash
;
215 static struct hash
*srv6_vpn_hash
;
217 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
219 struct bgp_attr_encap_subtlv
*new;
220 struct bgp_attr_encap_subtlv
*tail
;
221 struct bgp_attr_encap_subtlv
*p
;
223 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
224 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
226 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
229 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
232 memcpy(tail
, p
, size
);
239 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
241 struct bgp_attr_encap_subtlv
*next
;
245 XFREE(MTYPE_ENCAP_TLV
, p
);
250 void bgp_attr_flush_encap(struct attr
*attr
)
255 if (attr
->encap_subtlvs
) {
256 encap_free(attr
->encap_subtlvs
);
257 attr
->encap_subtlvs
= NULL
;
259 #ifdef ENABLE_BGP_VNC
260 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
261 bgp_attr_get_vnc_subtlvs(attr
);
264 encap_free(vnc_subtlvs
);
265 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
271 * Compare encap sub-tlv chains
276 * This algorithm could be made faster if needed
278 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
279 const struct bgp_attr_encap_subtlv
*h2
)
281 const struct bgp_attr_encap_subtlv
*p
;
282 const struct bgp_attr_encap_subtlv
*q
;
286 if (h1
== NULL
|| h2
== NULL
)
289 for (p
= h1
; p
; p
= p
->next
) {
290 for (q
= h2
; q
; q
= q
->next
) {
291 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
292 && !memcmp(p
->value
, q
->value
, p
->length
)) {
301 for (p
= h2
; p
; p
= p
->next
) {
302 for (q
= h1
; q
; q
= q
->next
) {
303 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
304 && !memcmp(p
->value
, q
->value
, p
->length
)) {
316 static void *encap_hash_alloc(void *p
)
318 /* Encap structure is already allocated. */
324 #ifdef ENABLE_BGP_VNC
329 static struct bgp_attr_encap_subtlv
*
330 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
332 struct bgp_attr_encap_subtlv
*find
;
333 struct hash
*hash
= encap_hash
;
334 #ifdef ENABLE_BGP_VNC
335 if (type
== VNC_SUBTLV_TYPE
)
339 find
= hash_get(hash
, encap
, encap_hash_alloc
);
347 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
348 encap_subtlv_type type
)
350 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
354 if (encap
->refcnt
== 0) {
355 struct hash
*hash
= encap_hash
;
356 #ifdef ENABLE_BGP_VNC
357 if (type
== VNC_SUBTLV_TYPE
)
360 hash_release(hash
, encap
);
366 static unsigned int encap_hash_key_make(const void *p
)
368 const struct bgp_attr_encap_subtlv
*encap
= p
;
370 return jhash(encap
->value
, encap
->length
, 0);
373 static bool encap_hash_cmp(const void *p1
, const void *p2
)
375 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
376 (const struct bgp_attr_encap_subtlv
*)p2
);
379 static void encap_init(void)
381 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
383 #ifdef ENABLE_BGP_VNC
384 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
389 static void encap_finish(void)
391 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
392 hash_free(encap_hash
);
394 #ifdef ENABLE_BGP_VNC
395 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
401 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
410 return !memcmp(bgp_attr_get_evpn_overlay(a1
),
411 bgp_attr_get_evpn_overlay(a2
),
412 sizeof(struct bgp_route_evpn
));
415 /* Unknown transit attribute. */
416 static struct hash
*transit_hash
;
418 static void transit_free(struct transit
*transit
)
420 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
421 XFREE(MTYPE_TRANSIT
, transit
);
424 static void *transit_hash_alloc(void *p
)
426 /* Transit structure is already allocated. */
430 static struct transit
*transit_intern(struct transit
*transit
)
432 struct transit
*find
;
434 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
436 transit_free(transit
);
442 static void transit_unintern(struct transit
**transit
)
444 if ((*transit
)->refcnt
)
445 (*transit
)->refcnt
--;
447 if ((*transit
)->refcnt
== 0) {
448 hash_release(transit_hash
, *transit
);
449 transit_free(*transit
);
454 static void *srv6_l3vpn_hash_alloc(void *p
)
459 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
461 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
464 static struct bgp_attr_srv6_l3vpn
*
465 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
467 struct bgp_attr_srv6_l3vpn
*find
;
469 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
471 srv6_l3vpn_free(l3vpn
);
476 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
478 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
483 if (l3vpn
->refcnt
== 0) {
484 hash_release(srv6_l3vpn_hash
, l3vpn
);
485 srv6_l3vpn_free(l3vpn
);
490 static void *srv6_vpn_hash_alloc(void *p
)
495 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
497 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
500 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
502 struct bgp_attr_srv6_vpn
*find
;
504 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
511 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
513 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
518 if (vpn
->refcnt
== 0) {
519 hash_release(srv6_vpn_hash
, vpn
);
525 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
527 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
530 key
= jhash(&l3vpn
->sid
, 16, key
);
531 key
= jhash_1word(l3vpn
->sid_flags
, key
);
532 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
536 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
538 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
539 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
541 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
542 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
543 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
;
546 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
547 const struct bgp_attr_srv6_l3vpn
*h2
)
551 else if (h1
== NULL
|| h2
== NULL
)
554 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
557 static unsigned int srv6_vpn_hash_key_make(const void *p
)
559 const struct bgp_attr_srv6_vpn
*vpn
= p
;
562 key
= jhash(&vpn
->sid
, 16, key
);
563 key
= jhash_1word(vpn
->sid_flags
, key
);
567 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
569 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
570 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
572 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
573 && vpn1
->sid_flags
== vpn2
->sid_flags
;
576 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
577 const struct bgp_attr_srv6_vpn
*h2
)
581 else if (h1
== NULL
|| h2
== NULL
)
584 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
587 static void srv6_init(void)
590 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
591 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
592 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
593 "BGP Prefix-SID SRv6-VPN-Service-TLV");
596 static void srv6_finish(void)
598 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
599 hash_free(srv6_l3vpn_hash
);
600 srv6_l3vpn_hash
= NULL
;
601 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
602 hash_free(srv6_vpn_hash
);
603 srv6_vpn_hash
= NULL
;
606 static unsigned int transit_hash_key_make(const void *p
)
608 const struct transit
*transit
= p
;
610 return jhash(transit
->val
, transit
->length
, 0);
613 static bool transit_hash_cmp(const void *p1
, const void *p2
)
615 const struct transit
*transit1
= p1
;
616 const struct transit
*transit2
= p2
;
618 return (transit1
->length
== transit2
->length
619 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
622 static void transit_init(void)
624 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
628 static void transit_finish(void)
630 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
631 hash_free(transit_hash
);
635 /* Attribute hash routines. */
636 static struct hash
*attrhash
;
638 unsigned long int attr_count(void)
640 return attrhash
->count
;
643 unsigned long int attr_unknown_count(void)
645 return transit_hash
->count
;
648 unsigned int attrhash_key_make(const void *p
)
650 const struct attr
*attr
= (struct attr
*)p
;
652 #define MIX(val) key = jhash_1word(val, key)
653 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
655 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
656 MIX3(attr
->local_pref
, attr
->aggregator_as
,
657 attr
->aggregator_addr
.s_addr
);
658 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
659 attr
->originator_id
.s_addr
);
660 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
663 MIX(aspath_key_make(attr
->aspath
));
665 MIX(community_hash_make(attr
->community
));
667 if (attr
->lcommunity
)
668 MIX(lcommunity_hash_make(attr
->lcommunity
));
669 if (attr
->ecommunity
)
670 MIX(ecommunity_hash_make(attr
->ecommunity
));
671 if (bgp_attr_get_ipv6_ecommunity(attr
))
672 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
673 if (bgp_attr_get_cluster(attr
))
674 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
675 if (bgp_attr_get_transit(attr
))
676 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
677 if (attr
->encap_subtlvs
)
678 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
679 if (attr
->srv6_l3vpn
)
680 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
682 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
683 #ifdef ENABLE_BGP_VNC
684 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
685 bgp_attr_get_vnc_subtlvs(attr
);
687 MIX(encap_hash_key_make(vnc_subtlvs
));
689 MIX(attr
->mp_nexthop_len
);
690 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
691 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
692 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
693 MIX(attr
->rmap_table_id
);
698 bool attrhash_cmp(const void *p1
, const void *p2
)
700 const struct attr
*attr1
= p1
;
701 const struct attr
*attr2
= p2
;
703 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
704 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
705 && attr1
->aspath
== attr2
->aspath
706 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
707 && attr1
->local_pref
== attr2
->local_pref
708 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
709 if (attr1
->aggregator_as
== attr2
->aggregator_as
710 && attr1
->aggregator_addr
.s_addr
711 == attr2
->aggregator_addr
.s_addr
712 && attr1
->weight
== attr2
->weight
713 && attr1
->tag
== attr2
->tag
714 && attr1
->label_index
== attr2
->label_index
715 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
716 && attr1
->ecommunity
== attr2
->ecommunity
717 && bgp_attr_get_ipv6_ecommunity(attr1
)
718 == bgp_attr_get_ipv6_ecommunity(attr2
)
719 && attr1
->lcommunity
== attr2
->lcommunity
720 && bgp_attr_get_cluster(attr1
)
721 == bgp_attr_get_cluster(attr2
)
722 && bgp_attr_get_transit(attr1
)
723 == bgp_attr_get_transit(attr2
)
724 && attr1
->rmap_table_id
== attr2
->rmap_table_id
725 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
726 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
727 #ifdef ENABLE_BGP_VNC
728 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
729 bgp_attr_get_vnc_subtlvs(attr2
))
731 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
732 &attr2
->mp_nexthop_global
)
733 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
734 &attr2
->mp_nexthop_local
)
735 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
736 &attr2
->mp_nexthop_global_in
)
737 && IPV4_ADDR_SAME(&attr1
->originator_id
,
738 &attr2
->originator_id
)
739 && overlay_index_same(attr1
, attr2
)
740 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
741 && attr1
->es_flags
== attr2
->es_flags
742 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
743 && attr1
->df_pref
== attr2
->df_pref
744 && attr1
->df_alg
== attr2
->df_alg
745 && attr1
->nh_ifindex
== attr2
->nh_ifindex
746 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
747 && attr1
->distance
== attr2
->distance
748 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
749 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
750 && attr1
->srte_color
== attr2
->srte_color
)
757 static void attrhash_init(void)
760 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
764 * special for hash_clean below
766 static void attr_vfree(void *attr
)
768 XFREE(MTYPE_ATTR
, attr
);
771 static void attrhash_finish(void)
773 hash_clean(attrhash
, attr_vfree
);
778 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
780 struct attr
*attr
= bucket
->data
;
781 char sid_str
[BUFSIZ
];
783 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
786 if (attr
->srv6_l3vpn
)
787 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
788 else if (attr
->srv6_vpn
)
789 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
792 "\tflags: %" PRIu64
" med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
793 attr
->flag
, attr
->med
, attr
->local_pref
, attr
->origin
,
794 attr
->weight
, attr
->label
, sid_str
);
797 void attr_show_all(struct vty
*vty
)
799 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
800 void *))attr_show_all_iterator
,
804 static void *bgp_attr_hash_alloc(void *p
)
806 struct attr
*val
= (struct attr
*)p
;
809 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
811 if (val
->encap_subtlvs
) {
812 val
->encap_subtlvs
= NULL
;
814 #ifdef ENABLE_BGP_VNC
815 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
816 bgp_attr_get_vnc_subtlvs(val
);
819 bgp_attr_set_vnc_subtlvs(val
, NULL
);
822 val
->srv6_l3vpn
= NULL
;
824 val
->srv6_vpn
= NULL
;
830 /* Internet argument attribute. */
831 struct attr
*bgp_attr_intern(struct attr
*attr
)
834 struct ecommunity
*ecomm
;
836 /* Intern referenced strucutre. */
838 if (!attr
->aspath
->refcnt
)
839 attr
->aspath
= aspath_intern(attr
->aspath
);
841 attr
->aspath
->refcnt
++;
843 if (attr
->community
) {
844 if (!attr
->community
->refcnt
)
845 attr
->community
= community_intern(attr
->community
);
847 attr
->community
->refcnt
++;
850 if (attr
->ecommunity
) {
851 if (!attr
->ecommunity
->refcnt
)
852 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
854 attr
->ecommunity
->refcnt
++;
857 ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
860 bgp_attr_set_ipv6_ecommunity(attr
,
861 ecommunity_intern(ecomm
));
866 if (attr
->lcommunity
) {
867 if (!attr
->lcommunity
->refcnt
)
868 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
870 attr
->lcommunity
->refcnt
++;
873 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
876 if (!cluster
->refcnt
)
877 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
882 struct transit
*transit
= bgp_attr_get_transit(attr
);
885 if (!transit
->refcnt
)
886 bgp_attr_set_transit(attr
, transit_intern(transit
));
890 if (attr
->encap_subtlvs
) {
891 if (!attr
->encap_subtlvs
->refcnt
)
892 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
895 attr
->encap_subtlvs
->refcnt
++;
897 if (attr
->srv6_l3vpn
) {
898 if (!attr
->srv6_l3vpn
->refcnt
)
899 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
901 attr
->srv6_l3vpn
->refcnt
++;
903 if (attr
->srv6_vpn
) {
904 if (!attr
->srv6_vpn
->refcnt
)
905 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
907 attr
->srv6_vpn
->refcnt
++;
909 #ifdef ENABLE_BGP_VNC
910 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
911 bgp_attr_get_vnc_subtlvs(attr
);
914 if (!vnc_subtlvs
->refcnt
)
915 bgp_attr_set_vnc_subtlvs(
917 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
919 vnc_subtlvs
->refcnt
++;
923 /* At this point, attr only contains intern'd pointers. that means
924 * if we find it in attrhash, it has all the same pointers and we
925 * correctly updated the refcounts on these.
926 * If we don't find it, we need to allocate a one because in all
927 * cases this returns a new reference to a hashed attr, but the input
929 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
935 /* Make network statement's attribute. */
936 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
938 memset(attr
, 0, sizeof(struct attr
));
940 attr
->origin
= origin
;
941 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
942 attr
->aspath
= aspath_empty();
943 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
944 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
946 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
947 attr
->label
= MPLS_INVALID_LABEL
;
948 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
949 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
954 /* Create the attributes for an aggregate */
955 struct attr
*bgp_attr_aggregate_intern(
956 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
957 struct community
*community
, struct ecommunity
*ecommunity
,
958 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
959 uint8_t atomic_aggregate
, const struct prefix
*p
)
965 memset(&attr
, 0, sizeof(struct attr
));
967 /* Origin attribute. */
968 attr
.origin
= origin
;
969 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
971 /* AS path attribute. */
973 attr
.aspath
= aspath_intern(aspath
);
975 attr
.aspath
= aspath_empty();
976 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
978 /* Next hop attribute. */
979 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
982 uint32_t gshut
= COMMUNITY_GSHUT
;
984 /* If we are not shutting down ourselves and we are
985 * aggregating a route that contains the GSHUT community we
986 * need to remove that community when creating the aggregate */
987 if (!bgp_in_graceful_shutdown(bgp
)
988 && community_include(community
, gshut
)) {
989 community_del_val(community
, &gshut
);
992 attr
.community
= community
;
993 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
997 attr
.ecommunity
= ecommunity
;
998 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1002 attr
.lcommunity
= lcommunity
;
1003 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1006 if (bgp_in_graceful_shutdown(bgp
))
1007 bgp_attr_add_gshut_community(&attr
);
1009 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1010 attr
.label
= MPLS_INVALID_LABEL
;
1011 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1012 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1013 if (!aggregate
->as_set
|| atomic_aggregate
)
1014 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1015 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1016 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1017 attr
.aggregator_as
= bgp
->confed_id
;
1019 attr
.aggregator_as
= bgp
->as
;
1020 attr
.aggregator_addr
= bgp
->router_id
;
1021 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1022 attr
.label
= MPLS_INVALID_LABEL
;
1024 /* Apply route-map */
1025 if (aggregate
->rmap
.name
) {
1026 struct attr attr_tmp
= attr
;
1027 struct bgp_path_info rmap_path
;
1029 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1030 rmap_path
.peer
= bgp
->peer_self
;
1031 rmap_path
.attr
= &attr_tmp
;
1033 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1035 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1037 bgp
->peer_self
->rmap_type
= 0;
1039 if (ret
== RMAP_DENYMATCH
) {
1040 /* Free uninterned attribute. */
1041 bgp_attr_flush(&attr_tmp
);
1043 /* Unintern original. */
1044 aspath_unintern(&attr
.aspath
);
1048 if (bgp_in_graceful_shutdown(bgp
))
1049 bgp_attr_add_gshut_community(&attr_tmp
);
1051 new = bgp_attr_intern(&attr_tmp
);
1054 if (bgp_in_graceful_shutdown(bgp
))
1055 bgp_attr_add_gshut_community(&attr
);
1057 new = bgp_attr_intern(&attr
);
1060 aspath_unintern(&new->aspath
);
1064 /* Unintern just the sub-components of the attr, but not the attr */
1065 void bgp_attr_unintern_sub(struct attr
*attr
)
1067 struct ecommunity
*ecomm
;
1068 struct cluster_list
*cluster
;
1070 /* aspath refcount shoud be decrement. */
1072 aspath_unintern(&attr
->aspath
);
1073 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1075 if (attr
->community
)
1076 community_unintern(&attr
->community
);
1077 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1079 ecommunity_unintern(&attr
->ecommunity
);
1080 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
1082 ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1083 ecommunity_unintern(&ecomm
);
1084 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
));
1085 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1087 if (attr
->lcommunity
)
1088 lcommunity_unintern(&attr
->lcommunity
);
1089 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1091 cluster
= bgp_attr_get_cluster(attr
);
1093 cluster_unintern(&cluster
);
1094 bgp_attr_set_cluster(attr
, cluster
);
1096 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1098 struct transit
*transit
= bgp_attr_get_transit(attr
);
1101 transit_unintern(&transit
);
1102 bgp_attr_set_transit(attr
, transit
);
1105 if (attr
->encap_subtlvs
)
1106 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1108 #ifdef ENABLE_BGP_VNC
1109 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1110 bgp_attr_get_vnc_subtlvs(attr
);
1113 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1114 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1118 if (attr
->srv6_l3vpn
)
1119 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1122 srv6_vpn_unintern(&attr
->srv6_vpn
);
1126 * We have some show commands that let you experimentally
1127 * apply a route-map. When we apply the route-map
1128 * we are reseting values but not saving them for
1129 * posterity via intern'ing( because route-maps don't
1130 * do that) but at this point in time we need
1131 * to compare the new attr to the old and if the
1132 * routemap has changed it we need to, as Snoop Dog says,
1133 * Drop it like it's hot
1135 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
1137 if (new->aspath
!= old
->aspath
)
1138 aspath_free(new->aspath
);
1140 if (new->community
!= old
->community
)
1141 community_free(&new->community
);
1143 if (new->ecommunity
!= old
->ecommunity
)
1144 ecommunity_free(&new->ecommunity
);
1146 if (new->lcommunity
!= old
->lcommunity
)
1147 lcommunity_free(&new->lcommunity
);
1149 if (new->srv6_l3vpn
!= old
->srv6_l3vpn
) {
1150 srv6_l3vpn_free(new->srv6_l3vpn
);
1151 new->srv6_l3vpn
= NULL
;
1154 if (new->srv6_vpn
!= old
->srv6_vpn
) {
1155 srv6_vpn_free(new->srv6_vpn
);
1156 new->srv6_vpn
= NULL
;
1160 /* Free bgp attribute and aspath. */
1161 void bgp_attr_unintern(struct attr
**pattr
)
1163 struct attr
*attr
= *pattr
;
1167 /* Decrement attribute reference. */
1172 /* If reference becomes zero then free attribute object. */
1173 if (attr
->refcnt
== 0) {
1174 ret
= hash_release(attrhash
, attr
);
1175 assert(ret
!= NULL
);
1176 XFREE(MTYPE_ATTR
, attr
);
1180 bgp_attr_unintern_sub(&tmp
);
1183 void bgp_attr_flush(struct attr
*attr
)
1185 struct ecommunity
*ecomm
;
1186 struct cluster_list
*cluster
;
1188 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1189 aspath_free(attr
->aspath
);
1190 attr
->aspath
= NULL
;
1192 if (attr
->community
&& !attr
->community
->refcnt
)
1193 community_free(&attr
->community
);
1194 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
1195 ecommunity_free(&attr
->ecommunity
);
1196 ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1197 if (ecomm
&& !ecomm
->refcnt
)
1198 ecommunity_free(&ecomm
);
1199 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1200 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
1201 lcommunity_free(&attr
->lcommunity
);
1203 cluster
= bgp_attr_get_cluster(attr
);
1204 if (cluster
&& !cluster
->refcnt
) {
1205 cluster_free(cluster
);
1206 bgp_attr_set_cluster(attr
, NULL
);
1209 struct transit
*transit
= bgp_attr_get_transit(attr
);
1211 if (transit
&& !transit
->refcnt
) {
1212 transit_free(transit
);
1213 bgp_attr_set_transit(attr
, NULL
);
1215 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1216 encap_free(attr
->encap_subtlvs
);
1217 attr
->encap_subtlvs
= NULL
;
1219 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1220 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1221 attr
->srv6_l3vpn
= NULL
;
1223 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1224 srv6_vpn_free(attr
->srv6_vpn
);
1225 attr
->srv6_vpn
= NULL
;
1227 #ifdef ENABLE_BGP_VNC
1228 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1229 bgp_attr_get_vnc_subtlvs(attr
);
1231 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1232 encap_free(vnc_subtlvs
);
1233 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1238 /* Implement draft-scudder-idr-optional-transitive behaviour and
1239 * avoid resetting sessions for malformed attributes which are
1240 * are partial/optional and hence where the error likely was not
1241 * introduced by the sending neighbour.
1243 static bgp_attr_parse_ret_t
1244 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1247 struct peer
*const peer
= args
->peer
;
1248 struct attr
*const attr
= args
->attr
;
1249 const uint8_t flags
= args
->flags
;
1250 /* startp and length must be special-cased, as whether or not to
1251 * send the attribute data with the NOTIFY depends on the error,
1252 * the caller therefore signals this with the seperate length argument
1254 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1256 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1257 char attr_str
[BUFSIZ
] = {0};
1259 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1261 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1264 /* Only relax error handling for eBGP peers */
1265 if (peer
->sort
!= BGP_PEER_EBGP
) {
1266 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1267 notify_datap
, length
);
1268 return BGP_ATTR_PARSE_ERROR
;
1271 /* Adjust the stream getp to the end of the attribute, in case we can
1272 * still proceed but the caller hasn't read all the attribute.
1274 stream_set_getp(BGP_INPUT(peer
),
1275 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1278 switch (args
->type
) {
1279 /* where an attribute is relatively inconsequential, e.g. it does not
1280 * affect route selection, and can be safely ignored, then any such
1281 * attributes which are malformed should just be ignored and the route
1282 * processed as normal.
1284 case BGP_ATTR_AS4_AGGREGATOR
:
1285 case BGP_ATTR_AGGREGATOR
:
1286 case BGP_ATTR_ATOMIC_AGGREGATE
:
1287 return BGP_ATTR_PARSE_PROCEED
;
1289 /* Core attributes, particularly ones which may influence route
1290 * selection, should be treat-as-withdraw.
1292 case BGP_ATTR_ORIGIN
:
1293 case BGP_ATTR_AS_PATH
:
1294 case BGP_ATTR_NEXT_HOP
:
1295 case BGP_ATTR_MULTI_EXIT_DISC
:
1296 case BGP_ATTR_LOCAL_PREF
:
1297 case BGP_ATTR_COMMUNITIES
:
1298 case BGP_ATTR_EXT_COMMUNITIES
:
1299 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1300 case BGP_ATTR_LARGE_COMMUNITIES
:
1301 case BGP_ATTR_ORIGINATOR_ID
:
1302 case BGP_ATTR_CLUSTER_LIST
:
1303 return BGP_ATTR_PARSE_WITHDRAW
;
1304 case BGP_ATTR_MP_REACH_NLRI
:
1305 case BGP_ATTR_MP_UNREACH_NLRI
:
1306 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1307 notify_datap
, length
);
1308 return BGP_ATTR_PARSE_ERROR
;
1311 /* Partial optional attributes that are malformed should not cause
1312 * the whole session to be reset. Instead treat it as a withdrawal
1313 * of the routes, if possible.
1315 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1316 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1317 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1318 return BGP_ATTR_PARSE_WITHDRAW
;
1320 /* default to reset */
1321 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1324 /* Find out what is wrong with the path attribute flag bits and log the error.
1325 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1326 Extended Length. Checking O/T/P bits at once implies, that the attribute
1327 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1328 non-transitive" attribute. */
1330 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1331 uint8_t desired_flags
/* how RFC says it must be */
1334 uint8_t seen
= 0, i
;
1335 uint8_t real_flags
= args
->flags
;
1336 const uint8_t attr_code
= args
->type
;
1338 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1339 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1340 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1341 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1342 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1343 flog_err(EC_BGP_ATTR_FLAG
,
1344 "%s attribute must%s be flagged as \"%s\"",
1345 lookup_msg(attr_str
, attr_code
, NULL
),
1346 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1349 attr_flag_str
[i
].str
);
1354 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1355 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1356 real_flags
, desired_flags
);
1360 /* Required flags for attributes. EXTLEN will be masked off when testing,
1361 * as will PARTIAL for optional+transitive attributes.
1363 const uint8_t attr_flags_values
[] = {
1364 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1365 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1366 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1367 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1368 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1369 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1370 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1371 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1372 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1373 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1374 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1375 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1376 [BGP_ATTR_EXT_COMMUNITIES
] =
1377 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1378 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1379 [BGP_ATTR_AS4_AGGREGATOR
] =
1380 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1381 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1382 [BGP_ATTR_LARGE_COMMUNITIES
] =
1383 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1384 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1385 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1386 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1388 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1390 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1392 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1393 const uint8_t flags
= args
->flags
;
1394 const uint8_t attr_code
= args
->type
;
1396 /* there may be attributes we don't know about */
1397 if (attr_code
> attr_flags_values_max
)
1399 if (attr_flags_values
[attr_code
] == 0)
1402 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1406 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1407 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1410 "%s well-known attributes must have transitive flag set (%x)",
1411 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1415 /* "For well-known attributes and for optional non-transitive
1417 * the Partial bit MUST be set to 0."
1419 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1420 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1421 flog_err(EC_BGP_ATTR_FLAG
,
1422 "%s well-known attribute must NOT have the partial flag set (%x)",
1423 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1426 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1427 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1428 flog_err(EC_BGP_ATTR_FLAG
,
1429 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1430 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1435 /* Optional transitive attributes may go through speakers that don't
1436 * reocgnise them and set the Partial bit.
1438 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1439 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1440 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1442 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1445 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1449 /* Get origin attribute of the update message. */
1450 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1452 struct peer
*const peer
= args
->peer
;
1453 struct attr
*const attr
= args
->attr
;
1454 const bgp_size_t length
= args
->length
;
1456 /* If any recognized attribute has Attribute Length that conflicts
1457 with the expected length (based on the attribute type code), then
1458 the Error Subcode is set to Attribute Length Error. The Data
1459 field contains the erroneous attribute (type, length and
1462 flog_err(EC_BGP_ATTR_LEN
,
1463 "Origin attribute length is not one %d", length
);
1464 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1468 /* Fetch origin attribute. */
1469 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1471 /* If the ORIGIN attribute has an undefined value, then the Error
1472 Subcode is set to Invalid Origin Attribute. The Data field
1473 contains the unrecognized attribute (type, length and value). */
1474 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1475 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1476 flog_err(EC_BGP_ATTR_ORIGIN
,
1477 "Origin attribute value is invalid %d", attr
->origin
);
1478 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1482 /* Set oring attribute flag. */
1483 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1488 /* Parse AS path information. This function is wrapper of
1490 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1492 struct attr
*const attr
= args
->attr
;
1493 struct peer
*const peer
= args
->peer
;
1494 const bgp_size_t length
= args
->length
;
1497 * peer with AS4 => will get 4Byte ASnums
1498 * otherwise, will get 16 Bit
1500 attr
->aspath
= aspath_parse(peer
->curr
, length
,
1501 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1503 /* In case of IBGP, length will be zero. */
1504 if (!attr
->aspath
) {
1505 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1506 "Malformed AS path from %s, length is %d", peer
->host
,
1508 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1512 /* Set aspath attribute flag. */
1513 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1515 return BGP_ATTR_PARSE_PROCEED
;
1518 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1519 struct attr
*const attr
)
1521 /* These checks were part of bgp_attr_aspath, but with
1522 * as4 we should to check aspath things when
1523 * aspath synthesizing with as4_path has already taken place.
1524 * Otherwise we check ASPATH and use the synthesized thing, and that is
1526 * So do the checks later, i.e. here
1528 struct aspath
*aspath
;
1530 /* Confederation sanity check. */
1531 if ((peer
->sort
== BGP_PEER_CONFED
1532 && !aspath_left_confed_check(attr
->aspath
))
1533 || (peer
->sort
== BGP_PEER_EBGP
1534 && aspath_confed_check(attr
->aspath
))) {
1535 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1537 return BGP_ATTR_PARSE_WITHDRAW
;
1540 /* First AS check for EBGP. */
1541 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1542 if (peer
->sort
== BGP_PEER_EBGP
1543 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1544 flog_err(EC_BGP_ATTR_FIRST_AS
,
1545 "%s incorrect first AS (must be %u)",
1546 peer
->host
, peer
->as
);
1547 return BGP_ATTR_PARSE_WITHDRAW
;
1551 /* Codification of AS 0 Processing */
1552 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1554 EC_BGP_ATTR_MAL_AS_PATH
,
1555 "Malformed AS path, AS number is 0 in the path from %s",
1557 return BGP_ATTR_PARSE_WITHDRAW
;
1560 /* local-as prepend */
1561 if (peer
->change_local_as
1562 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1563 aspath
= aspath_dup(attr
->aspath
);
1564 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1565 aspath_unintern(&attr
->aspath
);
1566 attr
->aspath
= aspath_intern(aspath
);
1569 return BGP_ATTR_PARSE_PROCEED
;
1572 /* Parse AS4 path information. This function is another wrapper of
1574 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1575 struct aspath
**as4_path
)
1577 struct peer
*const peer
= args
->peer
;
1578 struct attr
*const attr
= args
->attr
;
1579 const bgp_size_t length
= args
->length
;
1581 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1583 /* In case of IBGP, length will be zero. */
1585 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1586 "Malformed AS4 path from %s, length is %d", peer
->host
,
1588 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1592 /* Set aspath attribute flag. */
1593 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1595 return BGP_ATTR_PARSE_PROCEED
;
1599 * Check that the nexthop attribute is valid.
1601 bgp_attr_parse_ret_t
1602 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1604 in_addr_t nexthop_h
;
1606 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1607 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1608 || IPV4_CLASS_DE(nexthop_h
))
1609 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1610 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1611 char buf
[INET_ADDRSTRLEN
];
1613 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1615 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1617 data
[0] = BGP_ATTR_FLAG_TRANS
;
1618 data
[1] = BGP_ATTR_NEXT_HOP
;
1619 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1620 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1621 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1622 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1624 return BGP_ATTR_PARSE_ERROR
;
1627 return BGP_ATTR_PARSE_PROCEED
;
1630 /* Nexthop attribute. */
1631 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1633 struct peer
*const peer
= args
->peer
;
1634 struct attr
*const attr
= args
->attr
;
1635 const bgp_size_t length
= args
->length
;
1637 /* Check nexthop attribute length. */
1639 flog_err(EC_BGP_ATTR_LEN
,
1640 "Nexthop attribute length isn't four [%d]", length
);
1642 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1646 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1647 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1649 return BGP_ATTR_PARSE_PROCEED
;
1652 /* MED atrribute. */
1653 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1655 struct peer
*const peer
= args
->peer
;
1656 struct attr
*const attr
= args
->attr
;
1657 const bgp_size_t length
= args
->length
;
1661 flog_err(EC_BGP_ATTR_LEN
,
1662 "MED attribute length isn't four [%d]", length
);
1664 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1668 attr
->med
= stream_getl(peer
->curr
);
1670 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1672 return BGP_ATTR_PARSE_PROCEED
;
1675 /* Local preference attribute. */
1676 static bgp_attr_parse_ret_t
1677 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1679 struct peer
*const peer
= args
->peer
;
1680 struct attr
*const attr
= args
->attr
;
1681 const bgp_size_t length
= args
->length
;
1683 /* if received from an internal neighbor, it SHALL be considered
1684 * malformed if its length is not equal to 4. If malformed, the
1685 * UPDATE message SHALL be handled using the approach of "treat-as-
1688 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1689 flog_err(EC_BGP_ATTR_LEN
,
1690 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1691 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1695 /* If it is contained in an UPDATE message that is received from an
1696 external peer, then this attribute MUST be ignored by the
1697 receiving speaker. */
1698 if (peer
->sort
== BGP_PEER_EBGP
) {
1699 STREAM_FORWARD_GETP(peer
->curr
, length
);
1700 return BGP_ATTR_PARSE_PROCEED
;
1703 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1705 /* Set the local-pref flag. */
1706 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1708 return BGP_ATTR_PARSE_PROCEED
;
1711 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1715 /* Atomic aggregate. */
1716 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1718 struct attr
*const attr
= args
->attr
;
1719 const bgp_size_t length
= args
->length
;
1723 flog_err(EC_BGP_ATTR_LEN
,
1724 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1726 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1730 /* Set atomic aggregate flag. */
1731 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1733 return BGP_ATTR_PARSE_PROCEED
;
1736 /* Aggregator attribute */
1737 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1739 struct peer
*const peer
= args
->peer
;
1740 struct attr
*const attr
= args
->attr
;
1741 const bgp_size_t length
= args
->length
;
1746 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1747 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1748 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1751 if (length
!= wantedlen
) {
1752 flog_err(EC_BGP_ATTR_LEN
,
1753 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1755 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1759 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1760 aggregator_as
= stream_getl(peer
->curr
);
1762 aggregator_as
= stream_getw(peer
->curr
);
1764 attr
->aggregator_as
= aggregator_as
;
1765 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1767 /* Codification of AS 0 Processing */
1768 if (aggregator_as
== BGP_AS_ZERO
) {
1769 flog_err(EC_BGP_ATTR_LEN
,
1770 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1771 peer
->host
, aspath_print(attr
->aspath
));
1773 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1774 char attr_str
[BUFSIZ
] = {0};
1776 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1778 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1781 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1784 return BGP_ATTR_PARSE_PROCEED
;
1787 /* New Aggregator attribute */
1788 static bgp_attr_parse_ret_t
1789 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1790 as_t
*as4_aggregator_as
,
1791 struct in_addr
*as4_aggregator_addr
)
1793 struct peer
*const peer
= args
->peer
;
1794 struct attr
*const attr
= args
->attr
;
1795 const bgp_size_t length
= args
->length
;
1799 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1801 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1805 aggregator_as
= stream_getl(peer
->curr
);
1807 *as4_aggregator_as
= aggregator_as
;
1808 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1810 /* Codification of AS 0 Processing */
1811 if (aggregator_as
== BGP_AS_ZERO
) {
1812 flog_err(EC_BGP_ATTR_LEN
,
1813 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1814 peer
->host
, aspath_print(attr
->aspath
));
1816 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1817 char attr_str
[BUFSIZ
] = {0};
1819 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1821 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1824 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1827 return BGP_ATTR_PARSE_PROCEED
;
1830 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1832 static bgp_attr_parse_ret_t
1833 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1834 struct aspath
*as4_path
, as_t as4_aggregator
,
1835 struct in_addr
*as4_aggregator_addr
)
1837 int ignore_as4_path
= 0;
1838 struct aspath
*newpath
;
1840 if (!attr
->aspath
) {
1841 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1843 * checked that all well-known, mandatory attributes were
1846 * Can only be a problem with peer itself - hard error
1848 return BGP_ATTR_PARSE_ERROR
;
1851 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1852 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1854 * It is worth a warning though, because the peer really
1855 * should not send them
1857 if (BGP_DEBUG(as4
, AS4
)) {
1858 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1859 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1860 "AS4 capable peer, yet it sent");
1863 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1864 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1866 "AS4 capable peer, yet it sent");
1869 return BGP_ATTR_PARSE_PROCEED
;
1872 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1873 * because that may override AS4_PATH
1875 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1876 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1878 * if the as_number in aggregator is not AS_TRANS,
1879 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1880 * and the Aggregator shall be taken as
1881 * info on the aggregating node, and the AS_PATH
1882 * shall be taken as the AS_PATH
1884 * the Aggregator shall be ignored and the
1885 * AS4_AGGREGATOR shall be taken as the
1886 * Aggregating node and the AS_PATH is to be
1887 * constructed "as in all other cases"
1889 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1891 if (BGP_DEBUG(as4
, AS4
))
1893 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1895 ignore_as4_path
= 1;
1897 /* "New_aggregator shall be taken as aggregator"
1899 attr
->aggregator_as
= as4_aggregator
;
1900 attr
->aggregator_addr
.s_addr
=
1901 as4_aggregator_addr
->s_addr
;
1904 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1905 * That is bogus - but reading the conditions
1906 * we have to handle AS4_AGGREGATOR as if it were
1907 * AGGREGATOR in that case
1909 if (BGP_DEBUG(as4
, AS4
))
1911 "[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",
1913 attr
->aggregator_as
= as4_aggregator
;
1914 /* sweep it under the carpet and simulate a "good"
1916 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1920 /* need to reconcile NEW_AS_PATH and AS_PATH */
1921 if (!ignore_as4_path
1922 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1923 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1925 return BGP_ATTR_PARSE_ERROR
;
1927 aspath_unintern(&attr
->aspath
);
1928 attr
->aspath
= aspath_intern(newpath
);
1930 return BGP_ATTR_PARSE_PROCEED
;
1933 /* Community attribute. */
1934 static bgp_attr_parse_ret_t
1935 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1937 struct peer
*const peer
= args
->peer
;
1938 struct attr
*const attr
= args
->attr
;
1939 const bgp_size_t length
= args
->length
;
1942 attr
->community
= NULL
;
1943 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1948 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1950 /* XXX: fix community_parse to use stream API and remove this */
1951 stream_forward_getp(peer
->curr
, length
);
1953 /* The Community attribute SHALL be considered malformed if its
1954 * length is not a non-zero multiple of 4.
1956 if (!attr
->community
)
1957 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1960 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1962 return BGP_ATTR_PARSE_PROCEED
;
1965 /* Originator ID attribute. */
1966 static bgp_attr_parse_ret_t
1967 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1969 struct peer
*const peer
= args
->peer
;
1970 struct attr
*const attr
= args
->attr
;
1971 const bgp_size_t length
= args
->length
;
1973 /* if received from an internal neighbor, it SHALL be considered
1974 * malformed if its length is not equal to 4. If malformed, the
1975 * UPDATE message SHALL be handled using the approach of "treat-as-
1979 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1982 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1986 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1988 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1990 return BGP_ATTR_PARSE_PROCEED
;
1993 /* Cluster list attribute. */
1994 static bgp_attr_parse_ret_t
1995 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1997 struct peer
*const peer
= args
->peer
;
1998 struct attr
*const attr
= args
->attr
;
1999 const bgp_size_t length
= args
->length
;
2001 /* if received from an internal neighbor, it SHALL be considered
2002 * malformed if its length is not a non-zero multiple of 4. If
2003 * malformed, the UPDATE message SHALL be handled using the approach
2004 * of "treat-as-withdraw".
2006 if (length
== 0 || length
% 4) {
2007 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2009 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2013 bgp_attr_set_cluster(
2014 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2017 /* XXX: Fix cluster_parse to use stream API and then remove this */
2018 stream_forward_getp(peer
->curr
, length
);
2020 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2022 return BGP_ATTR_PARSE_PROCEED
;
2025 /* Multiprotocol reachability information parse. */
2026 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2027 struct bgp_nlri
*mp_update
)
2031 iana_safi_t pkt_safi
;
2033 bgp_size_t nlri_len
;
2036 struct peer
*const peer
= args
->peer
;
2037 struct attr
*const attr
= args
->attr
;
2038 const bgp_size_t length
= args
->length
;
2040 /* Set end of packet. */
2041 s
= BGP_INPUT(peer
);
2042 start
= stream_get_getp(s
);
2044 /* safe to read statically sized header? */
2045 #define BGP_MP_REACH_MIN_SIZE 5
2046 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2047 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2048 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2049 __func__
, peer
->host
, (unsigned long)length
);
2050 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2053 /* Load AFI, SAFI. */
2054 pkt_afi
= stream_getw(s
);
2055 pkt_safi
= stream_getc(s
);
2057 /* Convert AFI, SAFI to internal values, check. */
2058 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2059 /* Log if AFI or SAFI is unrecognized. This is not an error
2061 * the attribute is otherwise malformed.
2063 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2065 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2066 peer
->host
, iana_afi2str(pkt_afi
),
2067 iana_safi2str(pkt_safi
));
2068 return BGP_ATTR_PARSE_ERROR
;
2071 /* Get nexthop length. */
2072 attr
->mp_nexthop_len
= stream_getc(s
);
2074 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2076 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2077 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2078 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2081 /* Nexthop length check. */
2082 switch (attr
->mp_nexthop_len
) {
2084 if (safi
!= SAFI_FLOWSPEC
) {
2085 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2086 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2087 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2090 case BGP_ATTR_NHLEN_VPNV4
:
2091 stream_getl(s
); /* RD high */
2092 stream_getl(s
); /* RD low */
2094 * NOTE: intentional fall through
2095 * - for consistency in rx processing
2097 * The following comment is to signal GCC this intention
2098 * and suppress the warning
2101 case BGP_ATTR_NHLEN_IPV4
:
2102 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2103 /* Probably needed for RFC 2283 */
2104 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2105 memcpy(&attr
->nexthop
.s_addr
,
2106 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2108 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2109 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2110 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2111 stream_getl(s
); /* RD high */
2112 stream_getl(s
); /* RD low */
2114 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2115 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2116 if (!peer
->nexthop
.ifp
) {
2117 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2119 return BGP_ATTR_PARSE_WITHDRAW
;
2121 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2124 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2125 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2126 if (attr
->mp_nexthop_len
2127 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2128 stream_getl(s
); /* RD high */
2129 stream_getl(s
); /* RD low */
2131 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2132 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2133 if (!peer
->nexthop
.ifp
) {
2134 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",
2136 return BGP_ATTR_PARSE_WITHDRAW
;
2138 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2140 if (attr
->mp_nexthop_len
2141 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2142 stream_getl(s
); /* RD high */
2143 stream_getl(s
); /* RD low */
2145 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2146 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2147 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2149 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2150 peer
->host
, &attr
->mp_nexthop_global
,
2151 &attr
->mp_nexthop_local
);
2153 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2155 if (!peer
->nexthop
.ifp
) {
2156 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2158 return BGP_ATTR_PARSE_WITHDRAW
;
2160 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2163 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2164 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2165 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2169 zlog_info("%s: %s sent SNPA which couldn't be read",
2170 __func__
, peer
->host
);
2171 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2176 if ((val
= stream_getc(s
)))
2178 EC_BGP_DEFUNCT_SNPA_LEN
,
2179 "%s sent non-zero value, %u, for defunct SNPA-length field",
2183 /* must have nrli_len, what is left of the attribute */
2184 nlri_len
= LEN_LEFT
;
2185 if (nlri_len
> STREAM_READABLE(s
)) {
2186 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2187 __func__
, peer
->host
);
2188 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2192 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2193 __func__
, peer
->host
);
2195 mp_update
->afi
= afi
;
2196 mp_update
->safi
= safi
;
2197 return BGP_ATTR_PARSE_EOR
;
2200 mp_update
->afi
= afi
;
2201 mp_update
->safi
= safi
;
2202 mp_update
->nlri
= stream_pnt(s
);
2203 mp_update
->length
= nlri_len
;
2205 stream_forward_getp(s
, nlri_len
);
2207 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2209 return BGP_ATTR_PARSE_PROCEED
;
2213 /* Multiprotocol unreachable parse */
2214 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2215 struct bgp_nlri
*mp_withdraw
)
2220 iana_safi_t pkt_safi
;
2222 uint16_t withdraw_len
;
2223 struct peer
*const peer
= args
->peer
;
2224 struct attr
*const attr
= args
->attr
;
2225 const bgp_size_t length
= args
->length
;
2229 #define BGP_MP_UNREACH_MIN_SIZE 3
2230 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2231 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2233 pkt_afi
= stream_getw(s
);
2234 pkt_safi
= stream_getc(s
);
2236 /* Convert AFI, SAFI to internal values, check. */
2237 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2238 /* Log if AFI or SAFI is unrecognized. This is not an error
2240 * the attribute is otherwise malformed.
2242 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2244 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2245 peer
->host
, iana_afi2str(pkt_afi
),
2246 iana_safi2str(pkt_safi
));
2247 return BGP_ATTR_PARSE_ERROR
;
2250 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2252 mp_withdraw
->afi
= afi
;
2253 mp_withdraw
->safi
= safi
;
2254 mp_withdraw
->nlri
= stream_pnt(s
);
2255 mp_withdraw
->length
= withdraw_len
;
2257 stream_forward_getp(s
, withdraw_len
);
2259 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2261 return BGP_ATTR_PARSE_PROCEED
;
2264 /* Large Community attribute. */
2265 static bgp_attr_parse_ret_t
2266 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2268 struct peer
*const peer
= args
->peer
;
2269 struct attr
*const attr
= args
->attr
;
2270 const bgp_size_t length
= args
->length
;
2273 * Large community follows new attribute format.
2276 attr
->lcommunity
= NULL
;
2277 /* Empty extcomm doesn't seem to be invalid per se */
2278 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2282 attr
->lcommunity
= lcommunity_parse(stream_pnt(peer
->curr
), length
);
2283 /* XXX: fix ecommunity_parse to use stream API */
2284 stream_forward_getp(peer
->curr
, length
);
2286 if (!attr
->lcommunity
)
2287 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2290 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2292 return BGP_ATTR_PARSE_PROCEED
;
2295 /* Extended Community attribute. */
2296 static bgp_attr_parse_ret_t
2297 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2299 struct peer
*const peer
= args
->peer
;
2300 struct attr
*const attr
= args
->attr
;
2301 const bgp_size_t length
= args
->length
;
2306 attr
->ecommunity
= NULL
;
2307 /* Empty extcomm doesn't seem to be invalid per se */
2308 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2313 ecommunity_parse(stream_pnt(peer
->curr
), length
);
2314 /* XXX: fix ecommunity_parse to use stream API */
2315 stream_forward_getp(peer
->curr
, length
);
2317 /* The Extended Community attribute SHALL be considered malformed if
2318 * its length is not a non-zero multiple of 8.
2320 if (!attr
->ecommunity
)
2321 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2324 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2326 /* Extract DF election preference and mobility sequence number */
2327 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2329 /* Extract MAC mobility sequence number, if any. */
2330 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2331 attr
->sticky
= sticky
;
2333 /* Check if this is a Gateway MAC-IP advertisement */
2334 attr
->default_gw
= bgp_attr_default_gw(attr
);
2336 /* Handle scenario where router flag ecommunity is not
2337 * set but default gw ext community is present.
2338 * Use default gateway, set and propogate R-bit.
2340 if (attr
->default_gw
)
2341 attr
->router_flag
= 1;
2343 /* Check EVPN Neighbor advertisement flags, R-bit */
2344 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2346 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2348 /* Extract the Rmac, if any */
2349 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2350 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2351 && bgp_mac_exist(&attr
->rmac
))
2352 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2356 /* Get the tunnel type from encap extended community */
2357 bgp_attr_extcom_tunnel_type(attr
,
2358 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2360 /* Extract link bandwidth, if any. */
2361 (void)ecommunity_linkbw_present(attr
->ecommunity
, &attr
->link_bw
);
2363 return BGP_ATTR_PARSE_PROCEED
;
2366 /* IPv6 Extended Community attribute. */
2367 static bgp_attr_parse_ret_t
2368 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2370 struct peer
*const peer
= args
->peer
;
2371 struct attr
*const attr
= args
->attr
;
2372 const bgp_size_t length
= args
->length
;
2373 struct ecommunity
*ipv6_ecomm
= NULL
;
2376 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2377 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2381 ipv6_ecomm
= ecommunity_parse_ipv6(stream_pnt(peer
->curr
), length
);
2382 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2384 /* XXX: fix ecommunity_parse to use stream API */
2385 stream_forward_getp(peer
->curr
, length
);
2388 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2391 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
);
2393 return BGP_ATTR_PARSE_PROCEED
;
2396 /* Parse Tunnel Encap attribute in an UPDATE */
2397 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2398 bgp_size_t length
, /* IN: attr's length field */
2399 struct attr
*attr
, /* IN: caller already allocated */
2400 uint8_t flag
, /* IN: attr's flags field */
2404 uint16_t tunneltype
= 0;
2406 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2408 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2409 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2411 "Tunnel Encap attribute flag isn't optional and transitive %d",
2413 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2414 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2419 if (BGP_ATTR_ENCAP
== type
) {
2420 /* read outer TLV type and length */
2421 uint16_t tlv_length
;
2425 "Tunnel Encap attribute not long enough to contain outer T,L");
2426 bgp_notify_send_with_data(
2427 peer
, BGP_NOTIFY_UPDATE_ERR
,
2428 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2431 tunneltype
= stream_getw(BGP_INPUT(peer
));
2432 tlv_length
= stream_getw(BGP_INPUT(peer
));
2435 if (tlv_length
!= length
) {
2436 zlog_info("%s: tlv_length(%d) != length(%d)",
2437 __func__
, tlv_length
, length
);
2441 while (length
>= 4) {
2442 uint16_t subtype
= 0;
2443 uint16_t sublength
= 0;
2444 struct bgp_attr_encap_subtlv
*tlv
;
2446 if (BGP_ATTR_ENCAP
== type
) {
2447 subtype
= stream_getc(BGP_INPUT(peer
));
2448 sublength
= stream_getc(BGP_INPUT(peer
));
2450 #ifdef ENABLE_BGP_VNC
2452 subtype
= stream_getw(BGP_INPUT(peer
));
2453 sublength
= stream_getw(BGP_INPUT(peer
));
2458 if (sublength
> length
) {
2460 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2462 bgp_notify_send_with_data(
2463 peer
, BGP_NOTIFY_UPDATE_ERR
,
2464 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2468 /* alloc and copy sub-tlv */
2469 /* TBD make sure these are freed when attributes are released */
2470 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2471 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2472 tlv
->type
= subtype
;
2473 tlv
->length
= sublength
;
2474 stream_get(tlv
->value
, peer
->curr
, sublength
);
2475 length
-= sublength
;
2477 /* attach tlv to encap chain */
2478 if (BGP_ATTR_ENCAP
== type
) {
2479 struct bgp_attr_encap_subtlv
*stlv_last
;
2480 for (stlv_last
= attr
->encap_subtlvs
;
2481 stlv_last
&& stlv_last
->next
;
2482 stlv_last
= stlv_last
->next
)
2485 stlv_last
->next
= tlv
;
2487 attr
->encap_subtlvs
= tlv
;
2489 #ifdef ENABLE_BGP_VNC
2491 struct bgp_attr_encap_subtlv
*stlv_last
;
2492 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2493 bgp_attr_get_vnc_subtlvs(attr
);
2495 for (stlv_last
= vnc_subtlvs
;
2496 stlv_last
&& stlv_last
->next
;
2497 stlv_last
= stlv_last
->next
)
2500 stlv_last
->next
= tlv
;
2502 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2507 if (BGP_ATTR_ENCAP
== type
) {
2508 attr
->encap_tunneltype
= tunneltype
;
2512 /* spurious leftover data */
2514 "Tunnel Encap attribute length is bad: %d leftover octets",
2516 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2517 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2526 * Read an individual SID value returning how much data we have read
2527 * Returns 0 if there was an error that needs to be passed up the stack
2529 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2530 struct bgp_attr_parser_args
*args
)
2532 struct peer
*const peer
= args
->peer
;
2533 struct attr
*const attr
= args
->attr
;
2534 uint32_t label_index
;
2535 struct in6_addr ipv6_sid
;
2537 uint32_t srgb_range
;
2539 uint8_t sid_type
, sid_flags
;
2540 uint16_t endpoint_behavior
;
2543 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2544 if (STREAM_READABLE(peer
->curr
) < length
2545 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2546 flog_err(EC_BGP_ATTR_LEN
,
2547 "Prefix SID label index length is %hu instead of %u",
2548 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2549 return bgp_attr_malformed(args
,
2550 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2554 /* Ignore flags and reserved */
2555 stream_getc(peer
->curr
);
2556 stream_getw(peer
->curr
);
2558 /* Fetch the label index and see if it is valid. */
2559 label_index
= stream_getl(peer
->curr
);
2560 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2561 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2564 /* Store label index; subsequently, we'll check on
2566 attr
->label_index
= label_index
;
2569 /* Placeholder code for the IPv6 SID type */
2570 else if (type
== BGP_PREFIX_SID_IPV6
) {
2571 if (STREAM_READABLE(peer
->curr
) < length
2572 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2573 flog_err(EC_BGP_ATTR_LEN
,
2574 "Prefix SID IPv6 length is %hu instead of %u",
2575 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2576 return bgp_attr_malformed(args
,
2577 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2581 /* Ignore reserved */
2582 stream_getc(peer
->curr
);
2583 stream_getw(peer
->curr
);
2585 stream_get(&ipv6_sid
, peer
->curr
, 16);
2588 /* Placeholder code for the Originator SRGB type */
2589 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2591 * ietf-idr-bgp-prefix-sid-05:
2592 * Length is the total length of the value portion of the
2593 * TLV: 2 + multiple of 6.
2595 * peer->curr stream readp should be at the beginning of the 16
2596 * bit flag field at this point in the code.
2600 * Check that the TLV length field is sane: at least 2 bytes of
2601 * flag, and at least 1 SRGB (these are 6 bytes each)
2603 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2606 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2608 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2609 return bgp_attr_malformed(
2610 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2615 * Check that we actually have at least as much data as
2616 * specified by the length field
2618 if (STREAM_READABLE(peer
->curr
) < length
) {
2619 flog_err(EC_BGP_ATTR_LEN
,
2620 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2621 length
, STREAM_READABLE(peer
->curr
));
2622 return bgp_attr_malformed(
2623 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2628 * Check that the portion of the TLV containing the sequence of
2629 * SRGBs corresponds to a multiple of the SRGB size; to get
2630 * that length, we skip the 16 bit flags field
2632 stream_getw(peer
->curr
);
2634 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2637 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2638 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2639 return bgp_attr_malformed(
2640 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2644 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2646 for (int i
= 0; i
< srgb_count
; i
++) {
2647 stream_get(&srgb_base
, peer
->curr
, 3);
2648 stream_get(&srgb_range
, peer
->curr
, 3);
2652 /* Placeholder code for the VPN-SID Service type */
2653 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2654 if (STREAM_READABLE(peer
->curr
) < length
2655 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2656 flog_err(EC_BGP_ATTR_LEN
,
2657 "Prefix SID VPN SID length is %hu instead of %u",
2658 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2659 return bgp_attr_malformed(args
,
2660 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2664 /* Parse VPN-SID Sub-TLV */
2665 stream_getc(peer
->curr
); /* reserved */
2666 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2667 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2668 stream_get(&ipv6_sid
, peer
->curr
,
2669 sizeof(ipv6_sid
)); /* sid_value */
2671 /* Log VPN-SID Sub-TLV */
2672 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2673 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2675 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2676 __func__
, buf
, sid_type
, sid_flags
);
2679 /* Configure from Info */
2680 if (attr
->srv6_vpn
) {
2681 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2682 "Prefix SID SRv6 VPN field repeated");
2683 return bgp_attr_malformed(
2684 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2686 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2687 sizeof(struct bgp_attr_srv6_vpn
));
2688 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2689 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2690 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2693 /* Placeholder code for the SRv6 L3 Service type */
2694 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2695 if (STREAM_READABLE(peer
->curr
) < length
2696 || length
!= BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
) {
2697 flog_err(EC_BGP_ATTR_LEN
,
2698 "Prefix SID SRv6 L3-Service length is %hu instead of %u",
2699 length
, BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
);
2700 return bgp_attr_malformed(args
,
2701 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2705 /* Parse L3-SERVICE Sub-TLV */
2706 stream_getc(peer
->curr
); /* reserved */
2707 stream_get(&ipv6_sid
, peer
->curr
,
2708 sizeof(ipv6_sid
)); /* sid_value */
2709 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2710 endpoint_behavior
= stream_getw(peer
->curr
); /* endpoint */
2711 stream_getc(peer
->curr
); /* reserved */
2713 /* Log L3-SERVICE Sub-TLV */
2714 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2715 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2717 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2718 __func__
, buf
, sid_flags
, endpoint_behavior
);
2721 /* Configure from Info */
2722 if (attr
->srv6_l3vpn
) {
2723 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2724 "Prefix SID SRv6 L3VPN field repeated");
2725 return bgp_attr_malformed(
2726 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2728 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2729 sizeof(struct bgp_attr_srv6_l3vpn
));
2730 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2731 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2732 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2733 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2736 /* Placeholder code for Unsupported TLV */
2739 if (STREAM_READABLE(peer
->curr
) < length
) {
2742 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2743 length
, STREAM_READABLE(peer
->curr
));
2744 return bgp_attr_malformed(
2745 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2749 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2751 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2754 stream_forward_getp(peer
->curr
, length
);
2757 return BGP_ATTR_PARSE_PROCEED
;
2760 /* Prefix SID attribute
2761 * draft-ietf-idr-bgp-prefix-sid-05
2763 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2765 struct peer
*const peer
= args
->peer
;
2766 struct attr
*const attr
= args
->attr
;
2767 bgp_attr_parse_ret_t ret
;
2769 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2773 size_t headersz
= sizeof(type
) + sizeof(length
);
2774 size_t psid_parsed_length
= 0;
2776 while (STREAM_READABLE(peer
->curr
) > 0
2777 && psid_parsed_length
< args
->length
) {
2779 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2782 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2783 headersz
, STREAM_READABLE(peer
->curr
));
2784 return bgp_attr_malformed(
2785 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2789 type
= stream_getc(peer
->curr
);
2790 length
= stream_getw(peer
->curr
);
2792 if (STREAM_READABLE(peer
->curr
) < length
) {
2795 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2796 length
, STREAM_READABLE(peer
->curr
));
2797 return bgp_attr_malformed(args
,
2798 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2802 ret
= bgp_attr_psid_sub(type
, length
, args
);
2804 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2807 psid_parsed_length
+= length
+ headersz
;
2809 if (psid_parsed_length
> args
->length
) {
2812 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2813 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2814 return bgp_attr_malformed(
2815 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2820 return BGP_ATTR_PARSE_PROCEED
;
2823 /* PMSI tunnel attribute (RFC 6514)
2824 * Basic validation checks done here.
2826 static bgp_attr_parse_ret_t
2827 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2829 struct peer
*const peer
= args
->peer
;
2830 struct attr
*const attr
= args
->attr
;
2831 const bgp_size_t length
= args
->length
;
2833 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2835 /* Verify that the receiver is expecting "ingress replication" as we
2836 * can only support that.
2838 if (length
< attr_parse_len
) {
2839 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2841 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2844 stream_getc(peer
->curr
); /* Flags */
2845 tnl_type
= stream_getc(peer
->curr
);
2846 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2847 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2848 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2849 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2852 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2854 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2855 "Bad PMSI tunnel attribute length %d for IR",
2857 return bgp_attr_malformed(
2858 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2863 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2864 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
2865 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2867 /* Forward read pointer of input stream. */
2868 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2870 return BGP_ATTR_PARSE_PROCEED
;
2873 /* BGP unknown attribute treatment. */
2874 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2876 bgp_size_t total
= args
->total
;
2877 struct transit
*transit
;
2878 struct peer
*const peer
= args
->peer
;
2879 struct attr
*const attr
= args
->attr
;
2880 uint8_t *const startp
= args
->startp
;
2881 const uint8_t type
= args
->type
;
2882 const uint8_t flag
= args
->flags
;
2883 const bgp_size_t length
= args
->length
;
2885 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2887 "%s Unknown attribute is received (type %d, length %d)",
2888 peer
->host
, type
, length
);
2890 /* Forward read pointer of input stream. */
2891 stream_forward_getp(peer
->curr
, length
);
2893 /* If any of the mandatory well-known attributes are not recognized,
2894 then the Error Subcode is set to Unrecognized Well-known
2895 Attribute. The Data field contains the unrecognized attribute
2896 (type, length and value). */
2897 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2898 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2902 /* Unrecognized non-transitive optional attributes must be quietly
2903 ignored and not passed along to other BGP peers. */
2904 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2905 return BGP_ATTR_PARSE_PROCEED
;
2907 /* If a path with recognized transitive optional attribute is
2908 accepted and passed along to other BGP peers and the Partial bit
2909 in the Attribute Flags octet is set to 1 by some previous AS, it
2910 is not set back to 0 by the current AS. */
2911 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2913 /* Store transitive attribute to the end of attr->transit. */
2914 transit
= bgp_attr_get_transit(attr
);
2916 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2919 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2920 transit
->length
+ total
);
2922 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2924 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2925 transit
->length
+= total
;
2926 bgp_attr_set_transit(attr
, transit
);
2928 return BGP_ATTR_PARSE_PROCEED
;
2931 /* Well-known attribute check. */
2932 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2936 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2938 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2939 return BGP_ATTR_PARSE_PROCEED
;
2941 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2942 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2943 are present, it should. Check for any other attribute being present
2946 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2947 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2948 return BGP_ATTR_PARSE_PROCEED
;
2950 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2951 type
= BGP_ATTR_ORIGIN
;
2953 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2954 type
= BGP_ATTR_AS_PATH
;
2956 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2958 * NLRI is empty. We can't easily check NLRI empty here though.
2960 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2961 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2962 type
= BGP_ATTR_NEXT_HOP
;
2964 if (peer
->sort
== BGP_PEER_IBGP
2965 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2966 type
= BGP_ATTR_LOCAL_PREF
;
2968 /* If any of the well-known mandatory attributes are not present
2969 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
2972 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2973 "%s Missing well-known attribute %s.", peer
->host
,
2974 lookup_msg(attr_str
, type
, NULL
));
2975 return BGP_ATTR_PARSE_WITHDRAW
;
2977 return BGP_ATTR_PARSE_PROCEED
;
2980 /* Read attribute of update packet. This function is called from
2981 bgp_update_receive() in bgp_packet.c. */
2982 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2983 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2984 struct bgp_nlri
*mp_withdraw
)
2986 bgp_attr_parse_ret_t ret
;
2990 uint8_t *startp
, *endp
;
2992 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2993 /* we need the as4_path only until we have synthesized the as_path with
2995 /* same goes for as4_aggregator */
2996 struct aspath
*as4_path
= NULL
;
2997 as_t as4_aggregator
= 0;
2998 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2999 struct transit
*transit
;
3001 /* Initialize bitmap. */
3002 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3004 /* End pointer of BGP attribute. */
3005 endp
= BGP_INPUT_PNT(peer
) + size
;
3007 /* Get attributes to the end of attribute length. */
3008 while (BGP_INPUT_PNT(peer
) < endp
) {
3009 /* Check remaining length check.*/
3010 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3011 /* XXX warning: long int format, int arg (arg 5) */
3013 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3014 "%s: error BGP attribute length %lu is smaller than min len",
3016 (unsigned long)(endp
3017 - stream_pnt(BGP_INPUT(peer
))));
3019 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3020 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3021 ret
= BGP_ATTR_PARSE_ERROR
;
3025 /* Fetch attribute flag and type. */
3026 startp
= BGP_INPUT_PNT(peer
);
3027 /* "The lower-order four bits of the Attribute Flags octet are
3028 unused. They MUST be zero when sent and MUST be ignored when
3030 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3031 type
= stream_getc(BGP_INPUT(peer
));
3033 /* Check whether Extended-Length applies and is in bounds */
3034 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3035 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3037 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3038 "%s: Extended length set, but just %lu bytes of attr header",
3040 (unsigned long)(endp
3041 - stream_pnt(BGP_INPUT(peer
))));
3043 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3044 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3045 ret
= BGP_ATTR_PARSE_ERROR
;
3049 /* Check extended attribue length bit. */
3050 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3051 length
= stream_getw(BGP_INPUT(peer
));
3053 length
= stream_getc(BGP_INPUT(peer
));
3055 /* If any attribute appears more than once in the UPDATE
3056 message, then the Error Subcode is set to Malformed Attribute
3059 if (CHECK_BITMAP(seen
, type
)) {
3061 EC_BGP_ATTRIBUTE_REPEATED
,
3062 "%s: error BGP attribute type %d appears twice in a message",
3065 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3066 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3067 ret
= BGP_ATTR_PARSE_ERROR
;
3071 /* Set type to bitmap to check duplicate attribute. `type' is
3072 unsigned char so it never overflow bitmap range. */
3074 SET_BITMAP(seen
, type
);
3076 /* Overflow check. */
3077 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3079 if (attr_endp
> endp
) {
3081 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3082 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3083 peer
->host
, type
, length
, size
, attr_endp
,
3087 * If any recognized attribute has an Attribute
3088 * Length that conflicts with the expected length
3089 * (based on the attribute type code), then the
3090 * Error Subcode MUST be set to Attribute Length
3091 * Error. The Data field MUST contain the erroneous
3092 * attribute (type, length, and value).
3094 * We do not currently have a good way to determine the
3095 * length of the attribute independent of the length
3096 * received in the message. Instead we send the
3097 * minimum between the amount of data we have and the
3098 * amount specified by the attribute length field.
3100 * Instead of directly passing in the packet buffer and
3101 * offset we use the stream_get* functions to read into
3102 * a stack buffer, since they perform bounds checking
3103 * and we are working with untrusted data.
3105 unsigned char ndata
[peer
->max_packet_size
];
3106 memset(ndata
, 0x00, sizeof(ndata
));
3108 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3109 /* Rewind to end of flag field */
3110 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3112 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3114 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3116 size_t atl
= attr_endp
- startp
;
3117 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3118 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3120 bgp_notify_send_with_data(
3121 peer
, BGP_NOTIFY_UPDATE_ERR
,
3122 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3125 ret
= BGP_ATTR_PARSE_ERROR
;
3129 struct bgp_attr_parser_args attr_args
= {
3136 .total
= attr_endp
- startp
,
3140 /* If any recognized attribute has Attribute Flags that conflict
3141 with the Attribute Type Code, then the Error Subcode is set
3143 Attribute Flags Error. The Data field contains the erroneous
3144 attribute (type, length and value). */
3145 if (bgp_attr_flag_invalid(&attr_args
)) {
3146 ret
= bgp_attr_malformed(
3147 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3149 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3154 /* OK check attribute and store it's value. */
3156 case BGP_ATTR_ORIGIN
:
3157 ret
= bgp_attr_origin(&attr_args
);
3159 case BGP_ATTR_AS_PATH
:
3160 ret
= bgp_attr_aspath(&attr_args
);
3162 case BGP_ATTR_AS4_PATH
:
3163 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3165 case BGP_ATTR_NEXT_HOP
:
3166 ret
= bgp_attr_nexthop(&attr_args
);
3168 case BGP_ATTR_MULTI_EXIT_DISC
:
3169 ret
= bgp_attr_med(&attr_args
);
3171 case BGP_ATTR_LOCAL_PREF
:
3172 ret
= bgp_attr_local_pref(&attr_args
);
3174 case BGP_ATTR_ATOMIC_AGGREGATE
:
3175 ret
= bgp_attr_atomic(&attr_args
);
3177 case BGP_ATTR_AGGREGATOR
:
3178 ret
= bgp_attr_aggregator(&attr_args
);
3180 case BGP_ATTR_AS4_AGGREGATOR
:
3181 ret
= bgp_attr_as4_aggregator(&attr_args
,
3183 &as4_aggregator_addr
);
3185 case BGP_ATTR_COMMUNITIES
:
3186 ret
= bgp_attr_community(&attr_args
);
3188 case BGP_ATTR_LARGE_COMMUNITIES
:
3189 ret
= bgp_attr_large_community(&attr_args
);
3191 case BGP_ATTR_ORIGINATOR_ID
:
3192 ret
= bgp_attr_originator_id(&attr_args
);
3194 case BGP_ATTR_CLUSTER_LIST
:
3195 ret
= bgp_attr_cluster_list(&attr_args
);
3197 case BGP_ATTR_MP_REACH_NLRI
:
3198 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3200 case BGP_ATTR_MP_UNREACH_NLRI
:
3201 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3203 case BGP_ATTR_EXT_COMMUNITIES
:
3204 ret
= bgp_attr_ext_communities(&attr_args
);
3206 #ifdef ENABLE_BGP_VNC_ATTR
3209 case BGP_ATTR_ENCAP
:
3210 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3213 case BGP_ATTR_PREFIX_SID
:
3214 ret
= bgp_attr_prefix_sid(&attr_args
);
3216 case BGP_ATTR_PMSI_TUNNEL
:
3217 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3219 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3220 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3223 ret
= bgp_attr_unknown(&attr_args
);
3227 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3228 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3229 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3230 ret
= BGP_ATTR_PARSE_ERROR
;
3234 if (ret
== BGP_ATTR_PARSE_EOR
) {
3238 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3239 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3240 "%s: Attribute %s, parse error", peer
->host
,
3241 lookup_msg(attr_str
, type
, NULL
));
3244 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3246 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3247 "%s: Attribute %s, parse error - treating as withdrawal",
3248 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3252 /* Check the fetched length. */
3253 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3254 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3255 "%s: BGP attribute %s, fetch error",
3256 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3257 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3258 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3259 ret
= BGP_ATTR_PARSE_ERROR
;
3265 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3266 * About Prefix-SID path attribute,
3267 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3268 * may only appear in a BGP Prefix-SID attribute attached to
3269 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3270 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3272 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3273 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3275 /* Check final read pointer is same as end pointer. */
3276 if (BGP_INPUT_PNT(peer
) != endp
) {
3277 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3278 "%s: BGP attribute %s, length mismatch", peer
->host
,
3279 lookup_msg(attr_str
, type
, NULL
));
3280 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3281 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3283 ret
= BGP_ATTR_PARSE_ERROR
;
3288 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3289 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3290 * This is implemented below and will result in a NOTIFICATION. If the
3291 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3292 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3293 * message SHOULD NOT be sent. This is implemented elsewhere.
3295 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3296 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3297 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3298 * speaker that receives the message SHOULD ignore this attribute.
3300 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3301 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3302 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3303 ret
= BGP_ATTR_PARSE_ERROR
;
3308 /* Check all mandatory well-known attributes are present */
3309 ret
= bgp_attr_check(peer
, attr
);
3314 * At this place we can see whether we got AS4_PATH and/or
3315 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3316 * We can not do this before we've read all attributes because
3317 * the as4 handling does not say whether AS4_PATH has to be sent
3318 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3319 * in relationship to AGGREGATOR.
3320 * So, to be defensive, we are not relying on any order and read
3321 * all attributes first, including these 32bit ones, and now,
3322 * afterwards, we look what and if something is to be done for as4.
3324 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3327 /* actually... this doesn't ever return failure currently, but
3328 * better safe than sorry */
3329 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3330 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3331 &as4_aggregator_addr
)) {
3332 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3333 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3334 ret
= BGP_ATTR_PARSE_ERROR
;
3339 * Finally do the checks on the aspath we did not do yet
3340 * because we waited for a potentially synthesized aspath.
3342 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3343 ret
= bgp_attr_aspath_check(peer
, attr
);
3344 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3348 ret
= BGP_ATTR_PARSE_PROCEED
;
3352 * At this stage, we have done all fiddling with as4, and the
3353 * resulting info is in attr->aggregator resp. attr->aspath so
3354 * we can chuck as4_aggregator and as4_path alltogether in order
3359 * unintern - it is in the hash
3360 * The flag that we got this is still there, but that
3361 * does not do any trouble
3363 aspath_unintern(&as4_path
);
3366 transit
= bgp_attr_get_transit(attr
);
3367 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3368 /* Finally intern unknown attribute. */
3370 bgp_attr_set_transit(attr
, transit_intern(transit
));
3371 if (attr
->encap_subtlvs
)
3372 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3374 #ifdef ENABLE_BGP_VNC
3375 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3376 bgp_attr_get_vnc_subtlvs(attr
);
3379 bgp_attr_set_vnc_subtlvs(
3381 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3385 transit_free(transit
);
3386 bgp_attr_set_transit(attr
, NULL
);
3389 bgp_attr_flush_encap(attr
);
3393 transit
= bgp_attr_get_transit(attr
);
3395 assert(transit
->refcnt
> 0);
3396 if (attr
->encap_subtlvs
)
3397 assert(attr
->encap_subtlvs
->refcnt
> 0);
3398 #ifdef ENABLE_BGP_VNC
3399 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3400 bgp_attr_get_vnc_subtlvs(attr
);
3403 assert(vnc_subtlvs
->refcnt
> 0);
3410 * Extract the tunnel type from extended community
3412 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3413 bgp_encap_types
*tunnel_type
)
3415 struct ecommunity
*ecom
;
3421 ecom
= attr
->ecommunity
;
3422 if (!ecom
|| !ecom
->size
)
3425 for (i
= 0; i
< ecom
->size
; i
++) {
3427 uint8_t type
, sub_type
;
3429 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3432 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3433 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3435 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3442 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3443 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3448 iana_safi_t pkt_safi
;
3451 /* Set extended bit always to encode the attribute length as 2 bytes */
3452 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3453 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3454 sizep
= stream_get_endp(s
);
3455 stream_putw(s
, 0); /* Marker: Attribute length. */
3458 /* Convert AFI, SAFI to values for packet. */
3459 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3461 stream_putw(s
, pkt_afi
); /* AFI */
3462 stream_putc(s
, pkt_safi
); /* SAFI */
3466 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3467 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3468 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3469 else if (safi
== SAFI_FLOWSPEC
)
3472 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3475 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3480 case SAFI_MULTICAST
:
3481 case SAFI_LABELED_UNICAST
:
3483 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3487 stream_putl(s
, 0); /* RD = 0, per RFC */
3489 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3494 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3497 if (attr
->mp_nexthop_len
== 0)
3498 stream_putc(s
, 0); /* no nexthop for flowspec */
3500 stream_putc(s
, attr
->mp_nexthop_len
);
3501 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3510 case SAFI_MULTICAST
:
3511 case SAFI_LABELED_UNICAST
:
3513 if (attr
->mp_nexthop_len
3514 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3516 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3517 stream_put(s
, &attr
->mp_nexthop_global
,
3519 stream_put(s
, &attr
->mp_nexthop_local
,
3522 stream_putc(s
, IPV6_MAX_BYTELEN
);
3523 stream_put(s
, &attr
->mp_nexthop_global
,
3527 case SAFI_MPLS_VPN
: {
3528 if (attr
->mp_nexthop_len
3529 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3531 stream_putl(s
, 0); /* RD = 0, per RFC */
3533 stream_put(s
, &attr
->mp_nexthop_global
,
3535 } else if (attr
->mp_nexthop_len
3536 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3538 stream_putl(s
, 0); /* RD = 0, per RFC */
3540 stream_put(s
, &attr
->mp_nexthop_global
,
3542 stream_putl(s
, 0); /* RD = 0, per RFC */
3544 stream_put(s
, &attr
->mp_nexthop_local
,
3549 stream_putc(s
, IPV6_MAX_BYTELEN
);
3550 stream_put(s
, &attr
->mp_nexthop_global
,
3554 stream_putc(s
, 0); /* no nexthop for flowspec */
3560 if (safi
!= SAFI_FLOWSPEC
)
3562 EC_BGP_ATTR_NH_SEND_LEN
,
3563 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3564 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3573 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3574 const struct prefix
*p
,
3575 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3576 uint32_t num_labels
, int addpath_encode
,
3577 uint32_t addpath_tx_id
, struct attr
*attr
)
3579 if (safi
== SAFI_MPLS_VPN
) {
3581 stream_putl(s
, addpath_tx_id
);
3582 /* Label, RD, Prefix write. */
3583 stream_putc(s
, p
->prefixlen
+ 88);
3584 stream_put(s
, label
, BGP_LABEL_BYTES
);
3585 stream_put(s
, prd
->val
, 8);
3586 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3587 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3588 /* EVPN prefix - contents depend on type */
3589 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3590 addpath_encode
, addpath_tx_id
);
3591 } else if (safi
== SAFI_LABELED_UNICAST
) {
3592 /* Prefix write with label. */
3593 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3595 } else if (safi
== SAFI_FLOWSPEC
) {
3596 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3597 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3598 p
->u
.prefix_flowspec
.prefixlen
);
3600 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3603 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3604 const struct prefix
*p
)
3606 int size
= PSIZE(p
->prefixlen
);
3607 if (safi
== SAFI_MPLS_VPN
)
3609 else if (safi
== SAFI_LABELED_UNICAST
)
3610 size
+= BGP_LABEL_BYTES
;
3611 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3612 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3618 * Encodes the tunnel encapsulation attribute,
3619 * and with ENABLE_BGP_VNC the VNC attribute which uses
3620 * almost the same TLV format
3622 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3623 struct stream
*s
, struct attr
*attr
,
3626 unsigned int attrlenfield
= 0;
3627 unsigned int attrhdrlen
= 0;
3628 struct bgp_attr_encap_subtlv
*subtlvs
;
3629 struct bgp_attr_encap_subtlv
*st
;
3630 const char *attrname
;
3632 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3633 && (!attr
->encap_tunneltype
3634 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3638 case BGP_ATTR_ENCAP
:
3639 attrname
= "Tunnel Encap";
3640 subtlvs
= attr
->encap_subtlvs
;
3641 if (subtlvs
== NULL
) /* nothing to do */
3644 * The tunnel encap attr has an "outer" tlv.
3646 * L = total length of subtlvs,
3647 * V = concatenated subtlvs.
3649 attrlenfield
= 2 + 2; /* T + L */
3650 attrhdrlen
= 1 + 1; /* subTLV T + L */
3653 #ifdef ENABLE_BGP_VNC_ATTR
3656 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3657 if (subtlvs
== NULL
) /* nothing to do */
3659 attrlenfield
= 0; /* no outer T + L */
3660 attrhdrlen
= 2 + 2; /* subTLV T + L */
3668 /* compute attr length */
3669 for (st
= subtlvs
; st
; st
= st
->next
) {
3670 attrlenfield
+= (attrhdrlen
+ st
->length
);
3673 if (attrlenfield
> 0xffff) {
3674 zlog_info("%s attribute is too long (length=%d), can't send it",
3675 attrname
, attrlenfield
);
3679 if (attrlenfield
> 0xff) {
3680 /* 2-octet length field */
3682 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3683 | BGP_ATTR_FLAG_EXTLEN
);
3684 stream_putc(s
, attrtype
);
3685 stream_putw(s
, attrlenfield
& 0xffff);
3687 /* 1-octet length field */
3688 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3689 stream_putc(s
, attrtype
);
3690 stream_putc(s
, attrlenfield
& 0xff);
3693 if (attrtype
== BGP_ATTR_ENCAP
) {
3694 /* write outer T+L */
3695 stream_putw(s
, attr
->encap_tunneltype
);
3696 stream_putw(s
, attrlenfield
- 4);
3699 /* write each sub-tlv */
3700 for (st
= subtlvs
; st
; st
= st
->next
) {
3701 if (attrtype
== BGP_ATTR_ENCAP
) {
3702 stream_putc(s
, st
->type
);
3703 stream_putc(s
, st
->length
);
3704 #ifdef ENABLE_BGP_VNC
3706 stream_putw(s
, st
->type
);
3707 stream_putw(s
, st
->length
);
3710 stream_put(s
, st
->value
, st
->length
);
3714 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3716 /* Set MP attribute length. Don't count the (2) bytes used to encode
3718 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3721 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3723 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3724 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3725 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3726 PEER_FLAG_REMOVE_PRIVATE_AS
)
3727 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3728 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3729 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3730 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3731 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3732 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3737 /* Make attribute packet. */
3738 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3739 struct stream
*s
, struct attr
*attr
,
3740 struct bpacket_attr_vec_arr
*vecarr
,
3741 struct prefix
*p
, afi_t afi
, safi_t safi
,
3742 struct peer
*from
, struct prefix_rd
*prd
,
3743 mpls_label_t
*label
, uint32_t num_labels
,
3744 int addpath_encode
, uint32_t addpath_tx_id
)
3747 size_t aspath_sizep
;
3748 struct aspath
*aspath
;
3749 int send_as4_path
= 0;
3750 int send_as4_aggregator
= 0;
3751 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
);
3756 /* Remember current pointer. */
3757 cp
= stream_get_endp(s
);
3760 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3761 && !peer_cap_enhe(peer
, afi
, safi
))) {
3762 size_t mpattrlen_pos
= 0;
3764 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3766 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3767 num_labels
, addpath_encode
,
3768 addpath_tx_id
, attr
);
3769 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3772 /* Origin attribute. */
3773 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3774 stream_putc(s
, BGP_ATTR_ORIGIN
);
3776 stream_putc(s
, attr
->origin
);
3778 /* AS path attribute. */
3780 /* If remote-peer is EBGP */
3781 if (peer
->sort
== BGP_PEER_EBGP
3782 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3783 PEER_FLAG_AS_PATH_UNCHANGED
)
3784 || attr
->aspath
->segments
== NULL
)
3785 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3786 PEER_FLAG_RSERVER_CLIENT
))) {
3787 aspath
= aspath_dup(attr
->aspath
);
3789 /* Even though we may not be configured for confederations we
3791 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3792 aspath
= aspath_delete_confed_seq(aspath
);
3794 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3795 /* Stuff our path CONFED_ID on the front */
3796 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3798 if (peer
->change_local_as
) {
3799 /* If replace-as is specified, we only use the
3800 change_local_as when
3801 advertising routes. */
3802 if (!CHECK_FLAG(peer
->flags
,
3803 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3804 if (bgp_append_local_as(peer
, afi
,
3806 aspath
= aspath_add_seq(
3807 aspath
, peer
->local_as
);
3808 aspath
= aspath_add_seq(aspath
,
3809 peer
->change_local_as
);
3811 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3814 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3815 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3817 aspath
= aspath_dup(attr
->aspath
);
3818 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3820 aspath
= attr
->aspath
;
3822 /* If peer is not AS4 capable, then:
3823 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3824 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3826 * types are in it (i.e. exclude them if they are there)
3827 * AND do this only if there is at least one asnum > 65535 in the
3829 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3831 * all ASnums > 65535 to BGP_AS_TRANS
3834 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3835 stream_putc(s
, BGP_ATTR_AS_PATH
);
3836 aspath_sizep
= stream_get_endp(s
);
3838 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3840 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3843 if (!use32bit
&& aspath_has_as4(aspath
))
3845 1; /* we'll do this later, at the correct place */
3847 /* Nexthop attribute. */
3848 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3849 && !peer_cap_enhe(peer
, afi
, safi
)) {
3850 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3852 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3853 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3854 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3855 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3858 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3859 } else if (peer_cap_enhe(from
, afi
, safi
)
3860 || (nh_afi
== AFI_IP6
)) {
3862 * Likely this is the case when an IPv4 prefix was
3863 * received with Extended Next-hop capability in this
3864 * or another vrf and is now being advertised to
3865 * non-ENHE peers. Since peer_cap_enhe only checks
3866 * peers in this vrf, also check the nh_afi to catch
3867 * the case where the originator was in another vrf.
3868 * Setting the mandatory (ipv4) next-hop attribute here
3869 * to enable implicit next-hop self with correct A-F
3870 * (ipv4 address family).
3872 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3873 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3874 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3877 stream_put_ipv4(s
, 0);
3881 /* MED attribute. */
3882 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3883 || bgp
->maxmed_active
) {
3884 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3885 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3887 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3891 /* Local preference. */
3892 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3893 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3894 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3896 stream_putl(s
, attr
->local_pref
);
3899 /* Atomic aggregate. */
3900 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3901 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3902 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3907 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3908 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3909 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3910 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3913 /* AS4 capable peer */
3915 stream_putl(s
, attr
->aggregator_as
);
3917 /* 2-byte AS peer */
3920 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3922 if (attr
->aggregator_as
> UINT16_MAX
) {
3923 stream_putw(s
, BGP_AS_TRANS
);
3925 /* we have to send AS4_AGGREGATOR, too.
3926 * we'll do that later in order to send
3927 * attributes in ascending
3930 send_as4_aggregator
= 1;
3932 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3934 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3937 /* Community attribute. */
3938 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3939 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3940 if (attr
->community
->size
* 4 > 255) {
3942 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3943 | BGP_ATTR_FLAG_EXTLEN
);
3944 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3945 stream_putw(s
, attr
->community
->size
* 4);
3948 BGP_ATTR_FLAG_OPTIONAL
3949 | BGP_ATTR_FLAG_TRANS
);
3950 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3951 stream_putc(s
, attr
->community
->size
* 4);
3953 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3957 * Large Community attribute.
3959 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3960 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3961 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3962 if (lcom_length(attr
->lcommunity
) > 255) {
3964 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3965 | BGP_ATTR_FLAG_EXTLEN
);
3966 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3967 stream_putw(s
, lcom_length(attr
->lcommunity
));
3970 BGP_ATTR_FLAG_OPTIONAL
3971 | BGP_ATTR_FLAG_TRANS
);
3972 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3973 stream_putc(s
, lcom_length(attr
->lcommunity
));
3975 stream_put(s
, attr
->lcommunity
->val
,
3976 lcom_length(attr
->lcommunity
));
3979 /* Route Reflector. */
3980 if (peer
->sort
== BGP_PEER_IBGP
&& from
3981 && from
->sort
== BGP_PEER_IBGP
) {
3982 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
3984 /* Originator ID. */
3985 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3986 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3989 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3990 stream_put_in_addr(s
, &attr
->originator_id
);
3992 stream_put_in_addr(s
, &from
->remote_id
);
3995 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3996 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3999 stream_putc(s
, cluster
->length
+ 4);
4000 /* If this peer configuration's parent BGP has
4002 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4003 stream_put_in_addr(s
, &bgp
->cluster_id
);
4005 stream_put_in_addr(s
, &bgp
->router_id
);
4006 stream_put(s
, cluster
->list
, cluster
->length
);
4009 /* If this peer configuration's parent BGP has
4011 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4012 stream_put_in_addr(s
, &bgp
->cluster_id
);
4014 stream_put_in_addr(s
, &bgp
->router_id
);
4018 /* Extended Communities attribute. */
4019 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4020 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4021 if (peer
->sort
== BGP_PEER_IBGP
4022 || peer
->sort
== BGP_PEER_CONFED
) {
4023 if (attr
->ecommunity
->size
* 8 > 255) {
4025 BGP_ATTR_FLAG_OPTIONAL
4026 | BGP_ATTR_FLAG_TRANS
4027 | BGP_ATTR_FLAG_EXTLEN
);
4028 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4029 stream_putw(s
, attr
->ecommunity
->size
* 8);
4032 BGP_ATTR_FLAG_OPTIONAL
4033 | BGP_ATTR_FLAG_TRANS
);
4034 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4035 stream_putc(s
, attr
->ecommunity
->size
* 8);
4037 stream_put(s
, attr
->ecommunity
->val
,
4038 attr
->ecommunity
->size
* 8);
4042 int ecom_tr_size
= 0;
4045 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
4046 pnt
= attr
->ecommunity
->val
+ (i
* 8);
4049 if (CHECK_FLAG(tbit
,
4050 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4057 if (ecom_tr_size
* 8 > 255) {
4060 BGP_ATTR_FLAG_OPTIONAL
4061 | BGP_ATTR_FLAG_TRANS
4062 | BGP_ATTR_FLAG_EXTLEN
);
4064 BGP_ATTR_EXT_COMMUNITIES
);
4065 stream_putw(s
, ecom_tr_size
* 8);
4069 BGP_ATTR_FLAG_OPTIONAL
4070 | BGP_ATTR_FLAG_TRANS
);
4072 BGP_ATTR_EXT_COMMUNITIES
);
4073 stream_putc(s
, ecom_tr_size
* 8);
4076 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
4077 pnt
= attr
->ecommunity
->val
+ (i
* 8);
4082 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4085 stream_put(s
, pnt
, 8);
4091 /* Label index attribute. */
4092 if (safi
== SAFI_LABELED_UNICAST
) {
4093 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4094 uint32_t label_index
;
4096 label_index
= attr
->label_index
;
4098 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4100 BGP_ATTR_FLAG_OPTIONAL
4101 | BGP_ATTR_FLAG_TRANS
);
4102 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4104 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4106 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4107 stream_putc(s
, 0); // reserved
4108 stream_putw(s
, 0); // flags
4109 stream_putl(s
, label_index
);
4114 /* SRv6 Service Information Attribute. */
4115 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4116 if (attr
->srv6_l3vpn
) {
4117 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4118 | BGP_ATTR_FLAG_TRANS
);
4119 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4120 stream_putc(s
, 24); /* tlv len */
4121 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4122 stream_putw(s
, 21); /* sub-tlv len */
4123 stream_putc(s
, 0); /* reserved */
4124 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4125 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4126 stream_putc(s
, 0); /* sid_flags */
4127 stream_putw(s
, 0xffff); /* endpoint */
4128 stream_putc(s
, 0); /* reserved */
4129 } else if (attr
->srv6_vpn
) {
4130 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4131 | BGP_ATTR_FLAG_TRANS
);
4132 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4133 stream_putc(s
, 22); /* tlv len */
4134 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4135 stream_putw(s
, 0x13); /* tlv len */
4136 stream_putc(s
, 0x00); /* reserved */
4137 stream_putc(s
, 0x01); /* sid_type */
4138 stream_putc(s
, 0x00); /* sif_flags */
4139 stream_put(s
, &attr
->srv6_vpn
->sid
,
4140 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4144 if (send_as4_path
) {
4145 /* If the peer is NOT As4 capable, AND */
4146 /* there are ASnums > 65535 in path THEN
4147 * give out AS4_PATH */
4149 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4151 * Hm, I wonder... confederation things *should* only be at
4152 * the beginning of an aspath, right? Then we should use
4153 * aspath_delete_confed_seq for this, because it is already
4155 * Folks, talk to me: what is reasonable here!?
4157 aspath
= aspath_delete_confed_seq(aspath
);
4160 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4161 | BGP_ATTR_FLAG_EXTLEN
);
4162 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4163 aspath_sizep
= stream_get_endp(s
);
4165 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4168 if (aspath
!= attr
->aspath
)
4169 aspath_free(aspath
);
4171 if (send_as4_aggregator
) {
4172 /* send AS4_AGGREGATOR, at this place */
4173 /* this section of code moved here in order to ensure the
4175 * *ascending* order of attributes
4177 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4178 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4180 stream_putl(s
, attr
->aggregator_as
);
4181 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4184 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4185 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4186 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4187 /* Tunnel Encap attribute */
4188 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4190 #ifdef ENABLE_BGP_VNC_ATTR
4192 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4197 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4198 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4199 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4200 stream_putc(s
, 9); // Length
4201 stream_putc(s
, 0); // Flags
4202 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4203 stream_put(s
, &(attr
->label
),
4204 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4205 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4206 // Unicast tunnel endpoint IP address
4209 /* Unknown transit attribute. */
4210 struct transit
*transit
= bgp_attr_get_transit(attr
);
4213 stream_put(s
, transit
->val
, transit
->length
);
4215 /* Return total size of attribute. */
4216 return stream_get_endp(s
) - cp
;
4219 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4221 unsigned long attrlen_pnt
;
4223 iana_safi_t pkt_safi
;
4225 /* Set extended bit always to encode the attribute length as 2 bytes */
4226 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4227 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4229 attrlen_pnt
= stream_get_endp(s
);
4230 stream_putw(s
, 0); /* Length of this attribute. */
4232 /* Convert AFI, SAFI to values for packet. */
4233 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4235 stream_putw(s
, pkt_afi
);
4236 stream_putc(s
, pkt_safi
);
4241 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4242 afi_t afi
, safi_t safi
,
4243 const struct prefix_rd
*prd
,
4244 mpls_label_t
*label
, uint32_t num_labels
,
4245 int addpath_encode
, uint32_t addpath_tx_id
,
4248 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4250 if (safi
== SAFI_LABELED_UNICAST
) {
4251 label
= (mpls_label_t
*)wlabel
;
4255 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4256 addpath_encode
, addpath_tx_id
, attr
);
4259 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4261 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4264 /* Initialization of attribute. */
4265 void bgp_attr_init(void)
4278 void bgp_attr_finish(void)
4283 ecommunity_finish();
4284 lcommunity_finish();
4291 /* Make attribute packet. */
4292 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4293 const struct prefix
*prefix
)
4298 struct aspath
*aspath
;
4299 int addpath_encode
= 0;
4300 uint32_t addpath_tx_id
= 0;
4302 /* Remember current pointer. */
4303 cp
= stream_get_endp(s
);
4305 /* Place holder of length. */
4308 /* Origin attribute. */
4309 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4310 stream_putc(s
, BGP_ATTR_ORIGIN
);
4312 stream_putc(s
, attr
->origin
);
4314 aspath
= attr
->aspath
;
4316 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4317 stream_putc(s
, BGP_ATTR_AS_PATH
);
4318 aspath_lenp
= stream_get_endp(s
);
4321 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4323 /* Nexthop attribute. */
4324 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4325 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4326 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4327 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4329 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4332 /* MED attribute. */
4333 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4334 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4335 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4337 stream_putl(s
, attr
->med
);
4340 /* Local preference. */
4341 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4342 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4343 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4345 stream_putl(s
, attr
->local_pref
);
4348 /* Atomic aggregate. */
4349 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4350 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4351 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4356 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4357 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4358 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4360 stream_putl(s
, attr
->aggregator_as
);
4361 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4364 /* Community attribute. */
4365 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4366 if (attr
->community
->size
* 4 > 255) {
4368 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4369 | BGP_ATTR_FLAG_EXTLEN
);
4370 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4371 stream_putw(s
, attr
->community
->size
* 4);
4374 BGP_ATTR_FLAG_OPTIONAL
4375 | BGP_ATTR_FLAG_TRANS
);
4376 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4377 stream_putc(s
, attr
->community
->size
* 4);
4379 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4382 /* Large Community attribute. */
4383 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4384 if (lcom_length(attr
->lcommunity
) > 255) {
4386 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4387 | BGP_ATTR_FLAG_EXTLEN
);
4388 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4389 stream_putw(s
, lcom_length(attr
->lcommunity
));
4392 BGP_ATTR_FLAG_OPTIONAL
4393 | BGP_ATTR_FLAG_TRANS
);
4394 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4395 stream_putc(s
, lcom_length(attr
->lcommunity
));
4398 stream_put(s
, attr
->lcommunity
->val
,
4399 lcom_length(attr
->lcommunity
));
4402 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4403 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4404 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4405 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4408 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4409 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4410 sizep
= stream_get_endp(s
);
4413 stream_putc(s
, 0); /* Marker: Attribute length. */
4414 stream_putw(s
, AFI_IP6
); /* AFI */
4415 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4418 stream_putc(s
, attr
->mp_nexthop_len
);
4419 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4420 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4421 stream_put(s
, &attr
->mp_nexthop_local
,
4428 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
4431 /* Set MP attribute length. */
4432 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4436 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4437 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4439 BGP_ATTR_FLAG_OPTIONAL
4440 | BGP_ATTR_FLAG_TRANS
);
4441 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4443 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4444 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4445 stream_putc(s
, 0); // reserved
4446 stream_putw(s
, 0); // flags
4447 stream_putl(s
, attr
->label_index
);
4451 /* Return total size of attribute. */
4452 len
= stream_get_endp(s
) - cp
- 2;
4453 stream_putw_at(s
, cp
, len
);