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
" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
793 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
794 attr
->origin
, 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(
1502 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1503 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1505 /* In case of IBGP, length will be zero. */
1506 if (!attr
->aspath
) {
1507 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1508 "Malformed AS path from %s, length is %d", peer
->host
,
1510 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1514 /* Set aspath attribute flag. */
1515 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1517 return BGP_ATTR_PARSE_PROCEED
;
1520 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1521 struct attr
*const attr
)
1523 /* These checks were part of bgp_attr_aspath, but with
1524 * as4 we should to check aspath things when
1525 * aspath synthesizing with as4_path has already taken place.
1526 * Otherwise we check ASPATH and use the synthesized thing, and that is
1528 * So do the checks later, i.e. here
1530 struct aspath
*aspath
;
1532 /* Confederation sanity check. */
1533 if ((peer
->sort
== BGP_PEER_CONFED
1534 && !aspath_left_confed_check(attr
->aspath
))
1535 || (peer
->sort
== BGP_PEER_EBGP
1536 && aspath_confed_check(attr
->aspath
))) {
1537 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1539 return BGP_ATTR_PARSE_WITHDRAW
;
1542 /* First AS check for EBGP. */
1543 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1544 if (peer
->sort
== BGP_PEER_EBGP
1545 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1546 flog_err(EC_BGP_ATTR_FIRST_AS
,
1547 "%s incorrect first AS (must be %u)",
1548 peer
->host
, peer
->as
);
1549 return BGP_ATTR_PARSE_WITHDRAW
;
1553 /* Codification of AS 0 Processing */
1554 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1556 EC_BGP_ATTR_MAL_AS_PATH
,
1557 "Malformed AS path, AS number is 0 in the path from %s",
1559 return BGP_ATTR_PARSE_WITHDRAW
;
1562 /* local-as prepend */
1563 if (peer
->change_local_as
1564 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1565 aspath
= aspath_dup(attr
->aspath
);
1566 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1567 aspath_unintern(&attr
->aspath
);
1568 attr
->aspath
= aspath_intern(aspath
);
1571 return BGP_ATTR_PARSE_PROCEED
;
1574 /* Parse AS4 path information. This function is another wrapper of
1576 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1577 struct aspath
**as4_path
)
1579 struct peer
*const peer
= args
->peer
;
1580 struct attr
*const attr
= args
->attr
;
1581 const bgp_size_t length
= args
->length
;
1583 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1585 /* In case of IBGP, length will be zero. */
1587 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1588 "Malformed AS4 path from %s, length is %d", peer
->host
,
1590 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1594 /* Set aspath attribute flag. */
1595 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1597 return BGP_ATTR_PARSE_PROCEED
;
1601 * Check that the nexthop attribute is valid.
1603 bgp_attr_parse_ret_t
1604 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1606 in_addr_t nexthop_h
;
1608 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1609 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1610 || IPV4_CLASS_DE(nexthop_h
))
1611 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1612 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1613 char buf
[INET_ADDRSTRLEN
];
1615 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1617 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1619 data
[0] = BGP_ATTR_FLAG_TRANS
;
1620 data
[1] = BGP_ATTR_NEXT_HOP
;
1621 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1622 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1623 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1624 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1626 return BGP_ATTR_PARSE_ERROR
;
1629 return BGP_ATTR_PARSE_PROCEED
;
1632 /* Nexthop attribute. */
1633 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1635 struct peer
*const peer
= args
->peer
;
1636 struct attr
*const attr
= args
->attr
;
1637 const bgp_size_t length
= args
->length
;
1639 /* Check nexthop attribute length. */
1641 flog_err(EC_BGP_ATTR_LEN
,
1642 "Nexthop attribute length isn't four [%d]", length
);
1644 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1648 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1649 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1651 return BGP_ATTR_PARSE_PROCEED
;
1654 /* MED atrribute. */
1655 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1657 struct peer
*const peer
= args
->peer
;
1658 struct attr
*const attr
= args
->attr
;
1659 const bgp_size_t length
= args
->length
;
1663 flog_err(EC_BGP_ATTR_LEN
,
1664 "MED attribute length isn't four [%d]", length
);
1666 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1670 attr
->med
= stream_getl(peer
->curr
);
1672 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1674 return BGP_ATTR_PARSE_PROCEED
;
1677 /* Local preference attribute. */
1678 static bgp_attr_parse_ret_t
1679 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1681 struct peer
*const peer
= args
->peer
;
1682 struct attr
*const attr
= args
->attr
;
1683 const bgp_size_t length
= args
->length
;
1685 /* if received from an internal neighbor, it SHALL be considered
1686 * malformed if its length is not equal to 4. If malformed, the
1687 * UPDATE message SHALL be handled using the approach of "treat-as-
1690 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1691 flog_err(EC_BGP_ATTR_LEN
,
1692 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1693 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1697 /* If it is contained in an UPDATE message that is received from an
1698 external peer, then this attribute MUST be ignored by the
1699 receiving speaker. */
1700 if (peer
->sort
== BGP_PEER_EBGP
) {
1701 STREAM_FORWARD_GETP(peer
->curr
, length
);
1702 return BGP_ATTR_PARSE_PROCEED
;
1705 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1707 /* Set the local-pref flag. */
1708 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1710 return BGP_ATTR_PARSE_PROCEED
;
1713 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1717 /* Atomic aggregate. */
1718 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1720 struct attr
*const attr
= args
->attr
;
1721 const bgp_size_t length
= args
->length
;
1725 flog_err(EC_BGP_ATTR_LEN
,
1726 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1728 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1732 /* Set atomic aggregate flag. */
1733 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1735 return BGP_ATTR_PARSE_PROCEED
;
1738 /* Aggregator attribute */
1739 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1741 struct peer
*const peer
= args
->peer
;
1742 struct attr
*const attr
= args
->attr
;
1743 const bgp_size_t length
= args
->length
;
1748 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1749 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1750 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1753 if (length
!= wantedlen
) {
1754 flog_err(EC_BGP_ATTR_LEN
,
1755 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1757 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1761 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1762 aggregator_as
= stream_getl(peer
->curr
);
1764 aggregator_as
= stream_getw(peer
->curr
);
1766 attr
->aggregator_as
= aggregator_as
;
1767 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1769 /* Codification of AS 0 Processing */
1770 if (aggregator_as
== BGP_AS_ZERO
) {
1771 flog_err(EC_BGP_ATTR_LEN
,
1772 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1773 peer
->host
, aspath_print(attr
->aspath
));
1775 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1776 char attr_str
[BUFSIZ
] = {0};
1778 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1780 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1783 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1786 return BGP_ATTR_PARSE_PROCEED
;
1789 /* New Aggregator attribute */
1790 static bgp_attr_parse_ret_t
1791 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1792 as_t
*as4_aggregator_as
,
1793 struct in_addr
*as4_aggregator_addr
)
1795 struct peer
*const peer
= args
->peer
;
1796 struct attr
*const attr
= args
->attr
;
1797 const bgp_size_t length
= args
->length
;
1801 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1803 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1807 aggregator_as
= stream_getl(peer
->curr
);
1809 *as4_aggregator_as
= aggregator_as
;
1810 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1812 /* Codification of AS 0 Processing */
1813 if (aggregator_as
== BGP_AS_ZERO
) {
1814 flog_err(EC_BGP_ATTR_LEN
,
1815 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1816 peer
->host
, aspath_print(attr
->aspath
));
1818 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1819 char attr_str
[BUFSIZ
] = {0};
1821 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1823 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1826 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1829 return BGP_ATTR_PARSE_PROCEED
;
1832 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1834 static bgp_attr_parse_ret_t
1835 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1836 struct aspath
*as4_path
, as_t as4_aggregator
,
1837 struct in_addr
*as4_aggregator_addr
)
1839 int ignore_as4_path
= 0;
1840 struct aspath
*newpath
;
1842 if (!attr
->aspath
) {
1843 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1845 * checked that all well-known, mandatory attributes were
1848 * Can only be a problem with peer itself - hard error
1850 return BGP_ATTR_PARSE_ERROR
;
1853 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1854 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1856 * It is worth a warning though, because the peer really
1857 * should not send them
1859 if (BGP_DEBUG(as4
, AS4
)) {
1860 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1861 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1862 "AS4 capable peer, yet it sent");
1865 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1866 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1868 "AS4 capable peer, yet it sent");
1871 return BGP_ATTR_PARSE_PROCEED
;
1874 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1875 * because that may override AS4_PATH
1877 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1878 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1880 * if the as_number in aggregator is not AS_TRANS,
1881 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1882 * and the Aggregator shall be taken as
1883 * info on the aggregating node, and the AS_PATH
1884 * shall be taken as the AS_PATH
1886 * the Aggregator shall be ignored and the
1887 * AS4_AGGREGATOR shall be taken as the
1888 * Aggregating node and the AS_PATH is to be
1889 * constructed "as in all other cases"
1891 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1893 if (BGP_DEBUG(as4
, AS4
))
1895 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1897 ignore_as4_path
= 1;
1899 /* "New_aggregator shall be taken as aggregator"
1901 attr
->aggregator_as
= as4_aggregator
;
1902 attr
->aggregator_addr
.s_addr
=
1903 as4_aggregator_addr
->s_addr
;
1906 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1907 * That is bogus - but reading the conditions
1908 * we have to handle AS4_AGGREGATOR as if it were
1909 * AGGREGATOR in that case
1911 if (BGP_DEBUG(as4
, AS4
))
1913 "[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",
1915 attr
->aggregator_as
= as4_aggregator
;
1916 /* sweep it under the carpet and simulate a "good"
1918 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1922 /* need to reconcile NEW_AS_PATH and AS_PATH */
1923 if (!ignore_as4_path
1924 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1925 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1927 return BGP_ATTR_PARSE_ERROR
;
1929 aspath_unintern(&attr
->aspath
);
1930 attr
->aspath
= aspath_intern(newpath
);
1932 return BGP_ATTR_PARSE_PROCEED
;
1935 /* Community attribute. */
1936 static bgp_attr_parse_ret_t
1937 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1939 struct peer
*const peer
= args
->peer
;
1940 struct attr
*const attr
= args
->attr
;
1941 const bgp_size_t length
= args
->length
;
1944 attr
->community
= NULL
;
1945 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1950 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1952 /* XXX: fix community_parse to use stream API and remove this */
1953 stream_forward_getp(peer
->curr
, length
);
1955 /* The Community attribute SHALL be considered malformed if its
1956 * length is not a non-zero multiple of 4.
1958 if (!attr
->community
)
1959 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1962 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1964 return BGP_ATTR_PARSE_PROCEED
;
1967 /* Originator ID attribute. */
1968 static bgp_attr_parse_ret_t
1969 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1971 struct peer
*const peer
= args
->peer
;
1972 struct attr
*const attr
= args
->attr
;
1973 const bgp_size_t length
= args
->length
;
1975 /* if received from an internal neighbor, it SHALL be considered
1976 * malformed if its length is not equal to 4. If malformed, the
1977 * UPDATE message SHALL be handled using the approach of "treat-as-
1981 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1984 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1988 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1990 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1992 return BGP_ATTR_PARSE_PROCEED
;
1995 /* Cluster list attribute. */
1996 static bgp_attr_parse_ret_t
1997 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1999 struct peer
*const peer
= args
->peer
;
2000 struct attr
*const attr
= args
->attr
;
2001 const bgp_size_t length
= args
->length
;
2003 /* if received from an internal neighbor, it SHALL be considered
2004 * malformed if its length is not a non-zero multiple of 4. If
2005 * malformed, the UPDATE message SHALL be handled using the approach
2006 * of "treat-as-withdraw".
2008 if (length
== 0 || length
% 4) {
2009 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2011 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2015 bgp_attr_set_cluster(
2016 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2019 /* XXX: Fix cluster_parse to use stream API and then remove this */
2020 stream_forward_getp(peer
->curr
, length
);
2022 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2024 return BGP_ATTR_PARSE_PROCEED
;
2027 /* Multiprotocol reachability information parse. */
2028 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2029 struct bgp_nlri
*mp_update
)
2033 iana_safi_t pkt_safi
;
2035 bgp_size_t nlri_len
;
2038 struct peer
*const peer
= args
->peer
;
2039 struct attr
*const attr
= args
->attr
;
2040 const bgp_size_t length
= args
->length
;
2042 /* Set end of packet. */
2043 s
= BGP_INPUT(peer
);
2044 start
= stream_get_getp(s
);
2046 /* safe to read statically sized header? */
2047 #define BGP_MP_REACH_MIN_SIZE 5
2048 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2049 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2050 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2051 __func__
, peer
->host
, (unsigned long)length
);
2052 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2055 /* Load AFI, SAFI. */
2056 pkt_afi
= stream_getw(s
);
2057 pkt_safi
= stream_getc(s
);
2059 /* Convert AFI, SAFI to internal values, check. */
2060 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2061 /* Log if AFI or SAFI is unrecognized. This is not an error
2063 * the attribute is otherwise malformed.
2065 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2067 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2068 peer
->host
, iana_afi2str(pkt_afi
),
2069 iana_safi2str(pkt_safi
));
2070 return BGP_ATTR_PARSE_ERROR
;
2073 /* Get nexthop length. */
2074 attr
->mp_nexthop_len
= stream_getc(s
);
2076 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2078 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2079 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2080 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2083 /* Nexthop length check. */
2084 switch (attr
->mp_nexthop_len
) {
2086 if (safi
!= SAFI_FLOWSPEC
) {
2087 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2088 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2089 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2092 case BGP_ATTR_NHLEN_VPNV4
:
2093 stream_getl(s
); /* RD high */
2094 stream_getl(s
); /* RD low */
2096 * NOTE: intentional fall through
2097 * - for consistency in rx processing
2099 * The following comment is to signal GCC this intention
2100 * and suppress the warning
2103 case BGP_ATTR_NHLEN_IPV4
:
2104 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2105 /* Probably needed for RFC 2283 */
2106 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2107 memcpy(&attr
->nexthop
.s_addr
,
2108 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2110 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2111 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2112 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2113 stream_getl(s
); /* RD high */
2114 stream_getl(s
); /* RD low */
2116 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2117 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2118 if (!peer
->nexthop
.ifp
) {
2119 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2121 return BGP_ATTR_PARSE_WITHDRAW
;
2123 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2126 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2127 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2128 if (attr
->mp_nexthop_len
2129 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2130 stream_getl(s
); /* RD high */
2131 stream_getl(s
); /* RD low */
2133 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2134 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2135 if (!peer
->nexthop
.ifp
) {
2136 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",
2138 return BGP_ATTR_PARSE_WITHDRAW
;
2140 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2142 if (attr
->mp_nexthop_len
2143 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2144 stream_getl(s
); /* RD high */
2145 stream_getl(s
); /* RD low */
2147 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2148 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2149 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2151 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2152 peer
->host
, &attr
->mp_nexthop_global
,
2153 &attr
->mp_nexthop_local
);
2155 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2157 if (!peer
->nexthop
.ifp
) {
2158 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2160 return BGP_ATTR_PARSE_WITHDRAW
;
2162 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2165 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2166 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2167 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2171 zlog_info("%s: %s sent SNPA which couldn't be read",
2172 __func__
, peer
->host
);
2173 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2178 if ((val
= stream_getc(s
)))
2180 EC_BGP_DEFUNCT_SNPA_LEN
,
2181 "%s sent non-zero value, %u, for defunct SNPA-length field",
2185 /* must have nrli_len, what is left of the attribute */
2186 nlri_len
= LEN_LEFT
;
2187 if (nlri_len
> STREAM_READABLE(s
)) {
2188 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2189 __func__
, peer
->host
);
2190 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2194 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2195 __func__
, peer
->host
);
2197 mp_update
->afi
= afi
;
2198 mp_update
->safi
= safi
;
2199 return BGP_ATTR_PARSE_EOR
;
2202 mp_update
->afi
= afi
;
2203 mp_update
->safi
= safi
;
2204 mp_update
->nlri
= stream_pnt(s
);
2205 mp_update
->length
= nlri_len
;
2207 stream_forward_getp(s
, nlri_len
);
2209 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2211 return BGP_ATTR_PARSE_PROCEED
;
2215 /* Multiprotocol unreachable parse */
2216 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2217 struct bgp_nlri
*mp_withdraw
)
2222 iana_safi_t pkt_safi
;
2224 uint16_t withdraw_len
;
2225 struct peer
*const peer
= args
->peer
;
2226 struct attr
*const attr
= args
->attr
;
2227 const bgp_size_t length
= args
->length
;
2231 #define BGP_MP_UNREACH_MIN_SIZE 3
2232 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2233 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2235 pkt_afi
= stream_getw(s
);
2236 pkt_safi
= stream_getc(s
);
2238 /* Convert AFI, SAFI to internal values, check. */
2239 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2240 /* Log if AFI or SAFI is unrecognized. This is not an error
2242 * the attribute is otherwise malformed.
2244 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2246 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2247 peer
->host
, iana_afi2str(pkt_afi
),
2248 iana_safi2str(pkt_safi
));
2249 return BGP_ATTR_PARSE_ERROR
;
2252 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2254 mp_withdraw
->afi
= afi
;
2255 mp_withdraw
->safi
= safi
;
2256 mp_withdraw
->nlri
= stream_pnt(s
);
2257 mp_withdraw
->length
= withdraw_len
;
2259 stream_forward_getp(s
, withdraw_len
);
2261 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2263 return BGP_ATTR_PARSE_PROCEED
;
2266 /* Large Community attribute. */
2267 static bgp_attr_parse_ret_t
2268 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2270 struct peer
*const peer
= args
->peer
;
2271 struct attr
*const attr
= args
->attr
;
2272 const bgp_size_t length
= args
->length
;
2275 * Large community follows new attribute format.
2278 attr
->lcommunity
= NULL
;
2279 /* Empty extcomm doesn't seem to be invalid per se */
2280 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2284 attr
->lcommunity
= lcommunity_parse(stream_pnt(peer
->curr
), length
);
2285 /* XXX: fix ecommunity_parse to use stream API */
2286 stream_forward_getp(peer
->curr
, length
);
2288 if (!attr
->lcommunity
)
2289 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2292 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2294 return BGP_ATTR_PARSE_PROCEED
;
2297 /* Extended Community attribute. */
2298 static bgp_attr_parse_ret_t
2299 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2301 struct peer
*const peer
= args
->peer
;
2302 struct attr
*const attr
= args
->attr
;
2303 const bgp_size_t length
= args
->length
;
2308 attr
->ecommunity
= NULL
;
2309 /* Empty extcomm doesn't seem to be invalid per se */
2310 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2314 attr
->ecommunity
= ecommunity_parse(
2315 stream_pnt(peer
->curr
), length
,
2316 CHECK_FLAG(peer
->flags
,
2317 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2318 /* XXX: fix ecommunity_parse to use stream API */
2319 stream_forward_getp(peer
->curr
, length
);
2321 /* The Extended Community attribute SHALL be considered malformed if
2322 * its length is not a non-zero multiple of 8.
2324 if (!attr
->ecommunity
)
2325 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2328 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2330 /* Extract DF election preference and mobility sequence number */
2331 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2333 /* Extract MAC mobility sequence number, if any. */
2334 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2335 attr
->sticky
= sticky
;
2337 /* Check if this is a Gateway MAC-IP advertisement */
2338 attr
->default_gw
= bgp_attr_default_gw(attr
);
2340 /* Handle scenario where router flag ecommunity is not
2341 * set but default gw ext community is present.
2342 * Use default gateway, set and propogate R-bit.
2344 if (attr
->default_gw
)
2345 attr
->router_flag
= 1;
2347 /* Check EVPN Neighbor advertisement flags, R-bit */
2348 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2350 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2352 /* Extract the Rmac, if any */
2353 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2354 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2355 && bgp_mac_exist(&attr
->rmac
))
2356 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2360 /* Get the tunnel type from encap extended community */
2361 bgp_attr_extcom_tunnel_type(attr
,
2362 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2364 /* Extract link bandwidth, if any. */
2365 (void)ecommunity_linkbw_present(attr
->ecommunity
, &attr
->link_bw
);
2367 return BGP_ATTR_PARSE_PROCEED
;
2370 /* IPv6 Extended Community attribute. */
2371 static bgp_attr_parse_ret_t
2372 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2374 struct peer
*const peer
= args
->peer
;
2375 struct attr
*const attr
= args
->attr
;
2376 const bgp_size_t length
= args
->length
;
2377 struct ecommunity
*ipv6_ecomm
= NULL
;
2380 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2381 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2385 ipv6_ecomm
= ecommunity_parse_ipv6(
2386 stream_pnt(peer
->curr
), length
,
2387 CHECK_FLAG(peer
->flags
,
2388 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2389 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2391 /* XXX: fix ecommunity_parse to use stream API */
2392 stream_forward_getp(peer
->curr
, length
);
2395 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2398 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
);
2400 return BGP_ATTR_PARSE_PROCEED
;
2403 /* Parse Tunnel Encap attribute in an UPDATE */
2404 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2405 bgp_size_t length
, /* IN: attr's length field */
2406 struct attr
*attr
, /* IN: caller already allocated */
2407 uint8_t flag
, /* IN: attr's flags field */
2411 uint16_t tunneltype
= 0;
2413 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2415 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2416 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2418 "Tunnel Encap attribute flag isn't optional and transitive %d",
2420 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2421 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2426 if (BGP_ATTR_ENCAP
== type
) {
2427 /* read outer TLV type and length */
2428 uint16_t tlv_length
;
2432 "Tunnel Encap attribute not long enough to contain outer T,L");
2433 bgp_notify_send_with_data(
2434 peer
, BGP_NOTIFY_UPDATE_ERR
,
2435 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2438 tunneltype
= stream_getw(BGP_INPUT(peer
));
2439 tlv_length
= stream_getw(BGP_INPUT(peer
));
2442 if (tlv_length
!= length
) {
2443 zlog_info("%s: tlv_length(%d) != length(%d)",
2444 __func__
, tlv_length
, length
);
2448 while (length
>= 4) {
2449 uint16_t subtype
= 0;
2450 uint16_t sublength
= 0;
2451 struct bgp_attr_encap_subtlv
*tlv
;
2453 if (BGP_ATTR_ENCAP
== type
) {
2454 subtype
= stream_getc(BGP_INPUT(peer
));
2455 sublength
= stream_getc(BGP_INPUT(peer
));
2457 #ifdef ENABLE_BGP_VNC
2459 subtype
= stream_getw(BGP_INPUT(peer
));
2460 sublength
= stream_getw(BGP_INPUT(peer
));
2465 if (sublength
> length
) {
2467 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2469 bgp_notify_send_with_data(
2470 peer
, BGP_NOTIFY_UPDATE_ERR
,
2471 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2475 /* alloc and copy sub-tlv */
2476 /* TBD make sure these are freed when attributes are released */
2477 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2478 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2479 tlv
->type
= subtype
;
2480 tlv
->length
= sublength
;
2481 stream_get(tlv
->value
, peer
->curr
, sublength
);
2482 length
-= sublength
;
2484 /* attach tlv to encap chain */
2485 if (BGP_ATTR_ENCAP
== type
) {
2486 struct bgp_attr_encap_subtlv
*stlv_last
;
2487 for (stlv_last
= attr
->encap_subtlvs
;
2488 stlv_last
&& stlv_last
->next
;
2489 stlv_last
= stlv_last
->next
)
2492 stlv_last
->next
= tlv
;
2494 attr
->encap_subtlvs
= tlv
;
2496 #ifdef ENABLE_BGP_VNC
2498 struct bgp_attr_encap_subtlv
*stlv_last
;
2499 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2500 bgp_attr_get_vnc_subtlvs(attr
);
2502 for (stlv_last
= vnc_subtlvs
;
2503 stlv_last
&& stlv_last
->next
;
2504 stlv_last
= stlv_last
->next
)
2507 stlv_last
->next
= tlv
;
2509 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2514 if (BGP_ATTR_ENCAP
== type
) {
2515 attr
->encap_tunneltype
= tunneltype
;
2519 /* spurious leftover data */
2521 "Tunnel Encap attribute length is bad: %d leftover octets",
2523 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2524 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2533 * Read an individual SID value returning how much data we have read
2534 * Returns 0 if there was an error that needs to be passed up the stack
2536 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2537 struct bgp_attr_parser_args
*args
)
2539 struct peer
*const peer
= args
->peer
;
2540 struct attr
*const attr
= args
->attr
;
2541 uint32_t label_index
;
2542 struct in6_addr ipv6_sid
;
2544 uint32_t srgb_range
;
2546 uint8_t sid_type
, sid_flags
;
2547 uint16_t endpoint_behavior
;
2550 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2551 if (STREAM_READABLE(peer
->curr
) < length
2552 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2553 flog_err(EC_BGP_ATTR_LEN
,
2554 "Prefix SID label index length is %hu instead of %u",
2555 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2556 return bgp_attr_malformed(args
,
2557 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2561 /* Ignore flags and reserved */
2562 stream_getc(peer
->curr
);
2563 stream_getw(peer
->curr
);
2565 /* Fetch the label index and see if it is valid. */
2566 label_index
= stream_getl(peer
->curr
);
2567 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2568 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2571 /* Store label index; subsequently, we'll check on
2573 attr
->label_index
= label_index
;
2576 /* Placeholder code for the IPv6 SID type */
2577 else if (type
== BGP_PREFIX_SID_IPV6
) {
2578 if (STREAM_READABLE(peer
->curr
) < length
2579 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2580 flog_err(EC_BGP_ATTR_LEN
,
2581 "Prefix SID IPv6 length is %hu instead of %u",
2582 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2583 return bgp_attr_malformed(args
,
2584 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2588 /* Ignore reserved */
2589 stream_getc(peer
->curr
);
2590 stream_getw(peer
->curr
);
2592 stream_get(&ipv6_sid
, peer
->curr
, 16);
2595 /* Placeholder code for the Originator SRGB type */
2596 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2598 * ietf-idr-bgp-prefix-sid-05:
2599 * Length is the total length of the value portion of the
2600 * TLV: 2 + multiple of 6.
2602 * peer->curr stream readp should be at the beginning of the 16
2603 * bit flag field at this point in the code.
2607 * Check that the TLV length field is sane: at least 2 bytes of
2608 * flag, and at least 1 SRGB (these are 6 bytes each)
2610 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2613 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2615 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2616 return bgp_attr_malformed(
2617 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2622 * Check that we actually have at least as much data as
2623 * specified by the length field
2625 if (STREAM_READABLE(peer
->curr
) < length
) {
2626 flog_err(EC_BGP_ATTR_LEN
,
2627 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2628 length
, STREAM_READABLE(peer
->curr
));
2629 return bgp_attr_malformed(
2630 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2635 * Check that the portion of the TLV containing the sequence of
2636 * SRGBs corresponds to a multiple of the SRGB size; to get
2637 * that length, we skip the 16 bit flags field
2639 stream_getw(peer
->curr
);
2641 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2644 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2645 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2646 return bgp_attr_malformed(
2647 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2651 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2653 for (int i
= 0; i
< srgb_count
; i
++) {
2654 stream_get(&srgb_base
, peer
->curr
, 3);
2655 stream_get(&srgb_range
, peer
->curr
, 3);
2659 /* Placeholder code for the VPN-SID Service type */
2660 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2661 if (STREAM_READABLE(peer
->curr
) < length
2662 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2663 flog_err(EC_BGP_ATTR_LEN
,
2664 "Prefix SID VPN SID length is %hu instead of %u",
2665 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2666 return bgp_attr_malformed(args
,
2667 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2671 /* Parse VPN-SID Sub-TLV */
2672 stream_getc(peer
->curr
); /* reserved */
2673 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2674 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2675 stream_get(&ipv6_sid
, peer
->curr
,
2676 sizeof(ipv6_sid
)); /* sid_value */
2678 /* Log VPN-SID Sub-TLV */
2679 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2680 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2682 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2683 __func__
, buf
, sid_type
, sid_flags
);
2686 /* Configure from Info */
2687 if (attr
->srv6_vpn
) {
2688 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2689 "Prefix SID SRv6 VPN field repeated");
2690 return bgp_attr_malformed(
2691 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2693 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2694 sizeof(struct bgp_attr_srv6_vpn
));
2695 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2696 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2697 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2700 /* Placeholder code for the SRv6 L3 Service type */
2701 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2702 if (STREAM_READABLE(peer
->curr
) < length
2703 || length
!= BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
) {
2704 flog_err(EC_BGP_ATTR_LEN
,
2705 "Prefix SID SRv6 L3-Service length is %hu instead of %u",
2706 length
, BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
);
2707 return bgp_attr_malformed(args
,
2708 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2712 /* Parse L3-SERVICE Sub-TLV */
2713 stream_getc(peer
->curr
); /* reserved */
2714 stream_get(&ipv6_sid
, peer
->curr
,
2715 sizeof(ipv6_sid
)); /* sid_value */
2716 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2717 endpoint_behavior
= stream_getw(peer
->curr
); /* endpoint */
2718 stream_getc(peer
->curr
); /* reserved */
2720 /* Log L3-SERVICE Sub-TLV */
2721 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2722 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2724 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2725 __func__
, buf
, sid_flags
, endpoint_behavior
);
2728 /* Configure from Info */
2729 if (attr
->srv6_l3vpn
) {
2730 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2731 "Prefix SID SRv6 L3VPN field repeated");
2732 return bgp_attr_malformed(
2733 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2735 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2736 sizeof(struct bgp_attr_srv6_l3vpn
));
2737 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2738 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2739 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2740 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2743 /* Placeholder code for Unsupported TLV */
2746 if (STREAM_READABLE(peer
->curr
) < length
) {
2749 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2750 length
, STREAM_READABLE(peer
->curr
));
2751 return bgp_attr_malformed(
2752 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2756 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2758 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2761 stream_forward_getp(peer
->curr
, length
);
2764 return BGP_ATTR_PARSE_PROCEED
;
2767 /* Prefix SID attribute
2768 * draft-ietf-idr-bgp-prefix-sid-05
2770 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2772 struct peer
*const peer
= args
->peer
;
2773 struct attr
*const attr
= args
->attr
;
2774 bgp_attr_parse_ret_t ret
;
2776 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2780 size_t headersz
= sizeof(type
) + sizeof(length
);
2781 size_t psid_parsed_length
= 0;
2783 while (STREAM_READABLE(peer
->curr
) > 0
2784 && psid_parsed_length
< args
->length
) {
2786 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2789 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2790 headersz
, STREAM_READABLE(peer
->curr
));
2791 return bgp_attr_malformed(
2792 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2796 type
= stream_getc(peer
->curr
);
2797 length
= stream_getw(peer
->curr
);
2799 if (STREAM_READABLE(peer
->curr
) < length
) {
2802 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2803 length
, STREAM_READABLE(peer
->curr
));
2804 return bgp_attr_malformed(args
,
2805 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2809 ret
= bgp_attr_psid_sub(type
, length
, args
);
2811 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2814 psid_parsed_length
+= length
+ headersz
;
2816 if (psid_parsed_length
> args
->length
) {
2819 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2820 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2821 return bgp_attr_malformed(
2822 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2827 return BGP_ATTR_PARSE_PROCEED
;
2830 /* PMSI tunnel attribute (RFC 6514)
2831 * Basic validation checks done here.
2833 static bgp_attr_parse_ret_t
2834 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2836 struct peer
*const peer
= args
->peer
;
2837 struct attr
*const attr
= args
->attr
;
2838 const bgp_size_t length
= args
->length
;
2840 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2842 /* Verify that the receiver is expecting "ingress replication" as we
2843 * can only support that.
2845 if (length
< attr_parse_len
) {
2846 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2848 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2851 stream_getc(peer
->curr
); /* Flags */
2852 tnl_type
= stream_getc(peer
->curr
);
2853 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2854 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2855 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2856 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2859 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2861 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2862 "Bad PMSI tunnel attribute length %d for IR",
2864 return bgp_attr_malformed(
2865 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2870 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2871 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
2872 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2874 /* Forward read pointer of input stream. */
2875 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2877 return BGP_ATTR_PARSE_PROCEED
;
2880 /* BGP unknown attribute treatment. */
2881 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2883 bgp_size_t total
= args
->total
;
2884 struct transit
*transit
;
2885 struct peer
*const peer
= args
->peer
;
2886 struct attr
*const attr
= args
->attr
;
2887 uint8_t *const startp
= args
->startp
;
2888 const uint8_t type
= args
->type
;
2889 const uint8_t flag
= args
->flags
;
2890 const bgp_size_t length
= args
->length
;
2892 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2894 "%s Unknown attribute is received (type %d, length %d)",
2895 peer
->host
, type
, length
);
2897 /* Forward read pointer of input stream. */
2898 stream_forward_getp(peer
->curr
, length
);
2900 /* If any of the mandatory well-known attributes are not recognized,
2901 then the Error Subcode is set to Unrecognized Well-known
2902 Attribute. The Data field contains the unrecognized attribute
2903 (type, length and value). */
2904 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2905 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2909 /* Unrecognized non-transitive optional attributes must be quietly
2910 ignored and not passed along to other BGP peers. */
2911 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2912 return BGP_ATTR_PARSE_PROCEED
;
2914 /* If a path with recognized transitive optional attribute is
2915 accepted and passed along to other BGP peers and the Partial bit
2916 in the Attribute Flags octet is set to 1 by some previous AS, it
2917 is not set back to 0 by the current AS. */
2918 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2920 /* Store transitive attribute to the end of attr->transit. */
2921 transit
= bgp_attr_get_transit(attr
);
2923 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2925 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2926 transit
->length
+ total
);
2928 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2929 transit
->length
+= total
;
2930 bgp_attr_set_transit(attr
, transit
);
2932 return BGP_ATTR_PARSE_PROCEED
;
2935 /* Well-known attribute check. */
2936 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2940 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2942 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2943 return BGP_ATTR_PARSE_PROCEED
;
2945 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2946 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2947 are present, it should. Check for any other attribute being present
2950 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2951 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2952 return BGP_ATTR_PARSE_PROCEED
;
2954 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2955 type
= BGP_ATTR_ORIGIN
;
2957 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2958 type
= BGP_ATTR_AS_PATH
;
2960 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2962 * NLRI is empty. We can't easily check NLRI empty here though.
2964 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2965 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2966 type
= BGP_ATTR_NEXT_HOP
;
2968 if (peer
->sort
== BGP_PEER_IBGP
2969 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2970 type
= BGP_ATTR_LOCAL_PREF
;
2972 /* If any of the well-known mandatory attributes are not present
2973 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
2976 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2977 "%s Missing well-known attribute %s.", peer
->host
,
2978 lookup_msg(attr_str
, type
, NULL
));
2979 return BGP_ATTR_PARSE_WITHDRAW
;
2981 return BGP_ATTR_PARSE_PROCEED
;
2984 /* Read attribute of update packet. This function is called from
2985 bgp_update_receive() in bgp_packet.c. */
2986 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2987 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2988 struct bgp_nlri
*mp_withdraw
)
2990 bgp_attr_parse_ret_t ret
;
2994 uint8_t *startp
, *endp
;
2996 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2997 /* we need the as4_path only until we have synthesized the as_path with
2999 /* same goes for as4_aggregator */
3000 struct aspath
*as4_path
= NULL
;
3001 as_t as4_aggregator
= 0;
3002 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3003 struct transit
*transit
;
3005 /* Initialize bitmap. */
3006 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3008 /* End pointer of BGP attribute. */
3009 endp
= BGP_INPUT_PNT(peer
) + size
;
3011 /* Get attributes to the end of attribute length. */
3012 while (BGP_INPUT_PNT(peer
) < endp
) {
3013 /* Check remaining length check.*/
3014 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3015 /* XXX warning: long int format, int arg (arg 5) */
3017 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3018 "%s: error BGP attribute length %lu is smaller than min len",
3020 (unsigned long)(endp
3021 - stream_pnt(BGP_INPUT(peer
))));
3023 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3024 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3025 ret
= BGP_ATTR_PARSE_ERROR
;
3029 /* Fetch attribute flag and type. */
3030 startp
= BGP_INPUT_PNT(peer
);
3031 /* "The lower-order four bits of the Attribute Flags octet are
3032 unused. They MUST be zero when sent and MUST be ignored when
3034 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3035 type
= stream_getc(BGP_INPUT(peer
));
3037 /* Check whether Extended-Length applies and is in bounds */
3038 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3039 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3041 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3042 "%s: Extended length set, but just %lu bytes of attr header",
3044 (unsigned long)(endp
3045 - stream_pnt(BGP_INPUT(peer
))));
3047 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3048 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3049 ret
= BGP_ATTR_PARSE_ERROR
;
3053 /* Check extended attribue length bit. */
3054 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3055 length
= stream_getw(BGP_INPUT(peer
));
3057 length
= stream_getc(BGP_INPUT(peer
));
3059 /* If any attribute appears more than once in the UPDATE
3060 message, then the Error Subcode is set to Malformed Attribute
3063 if (CHECK_BITMAP(seen
, type
)) {
3065 EC_BGP_ATTRIBUTE_REPEATED
,
3066 "%s: error BGP attribute type %d appears twice in a message",
3069 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3070 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3071 ret
= BGP_ATTR_PARSE_ERROR
;
3075 /* Set type to bitmap to check duplicate attribute. `type' is
3076 unsigned char so it never overflow bitmap range. */
3078 SET_BITMAP(seen
, type
);
3080 /* Overflow check. */
3081 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3083 if (attr_endp
> endp
) {
3085 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3086 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3087 peer
->host
, type
, length
, size
, attr_endp
,
3091 * If any recognized attribute has an Attribute
3092 * Length that conflicts with the expected length
3093 * (based on the attribute type code), then the
3094 * Error Subcode MUST be set to Attribute Length
3095 * Error. The Data field MUST contain the erroneous
3096 * attribute (type, length, and value).
3098 * We do not currently have a good way to determine the
3099 * length of the attribute independent of the length
3100 * received in the message. Instead we send the
3101 * minimum between the amount of data we have and the
3102 * amount specified by the attribute length field.
3104 * Instead of directly passing in the packet buffer and
3105 * offset we use the stream_get* functions to read into
3106 * a stack buffer, since they perform bounds checking
3107 * and we are working with untrusted data.
3109 unsigned char ndata
[peer
->max_packet_size
];
3110 memset(ndata
, 0x00, sizeof(ndata
));
3112 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3113 /* Rewind to end of flag field */
3114 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3116 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3118 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3120 size_t atl
= attr_endp
- startp
;
3121 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3122 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3124 bgp_notify_send_with_data(
3125 peer
, BGP_NOTIFY_UPDATE_ERR
,
3126 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3129 ret
= BGP_ATTR_PARSE_ERROR
;
3133 struct bgp_attr_parser_args attr_args
= {
3140 .total
= attr_endp
- startp
,
3144 /* If any recognized attribute has Attribute Flags that conflict
3145 with the Attribute Type Code, then the Error Subcode is set
3147 Attribute Flags Error. The Data field contains the erroneous
3148 attribute (type, length and value). */
3149 if (bgp_attr_flag_invalid(&attr_args
)) {
3150 ret
= bgp_attr_malformed(
3151 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3153 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3158 /* OK check attribute and store it's value. */
3160 case BGP_ATTR_ORIGIN
:
3161 ret
= bgp_attr_origin(&attr_args
);
3163 case BGP_ATTR_AS_PATH
:
3164 ret
= bgp_attr_aspath(&attr_args
);
3166 case BGP_ATTR_AS4_PATH
:
3167 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3169 case BGP_ATTR_NEXT_HOP
:
3170 ret
= bgp_attr_nexthop(&attr_args
);
3172 case BGP_ATTR_MULTI_EXIT_DISC
:
3173 ret
= bgp_attr_med(&attr_args
);
3175 case BGP_ATTR_LOCAL_PREF
:
3176 ret
= bgp_attr_local_pref(&attr_args
);
3178 case BGP_ATTR_ATOMIC_AGGREGATE
:
3179 ret
= bgp_attr_atomic(&attr_args
);
3181 case BGP_ATTR_AGGREGATOR
:
3182 ret
= bgp_attr_aggregator(&attr_args
);
3184 case BGP_ATTR_AS4_AGGREGATOR
:
3185 ret
= bgp_attr_as4_aggregator(&attr_args
,
3187 &as4_aggregator_addr
);
3189 case BGP_ATTR_COMMUNITIES
:
3190 ret
= bgp_attr_community(&attr_args
);
3192 case BGP_ATTR_LARGE_COMMUNITIES
:
3193 ret
= bgp_attr_large_community(&attr_args
);
3195 case BGP_ATTR_ORIGINATOR_ID
:
3196 ret
= bgp_attr_originator_id(&attr_args
);
3198 case BGP_ATTR_CLUSTER_LIST
:
3199 ret
= bgp_attr_cluster_list(&attr_args
);
3201 case BGP_ATTR_MP_REACH_NLRI
:
3202 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3204 case BGP_ATTR_MP_UNREACH_NLRI
:
3205 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3207 case BGP_ATTR_EXT_COMMUNITIES
:
3208 ret
= bgp_attr_ext_communities(&attr_args
);
3210 #ifdef ENABLE_BGP_VNC_ATTR
3213 case BGP_ATTR_ENCAP
:
3214 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3217 case BGP_ATTR_PREFIX_SID
:
3218 ret
= bgp_attr_prefix_sid(&attr_args
);
3220 case BGP_ATTR_PMSI_TUNNEL
:
3221 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3223 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3224 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3227 ret
= bgp_attr_unknown(&attr_args
);
3231 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3232 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3233 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3234 ret
= BGP_ATTR_PARSE_ERROR
;
3238 if (ret
== BGP_ATTR_PARSE_EOR
) {
3242 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3243 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3244 "%s: Attribute %s, parse error", peer
->host
,
3245 lookup_msg(attr_str
, type
, NULL
));
3248 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3250 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3251 "%s: Attribute %s, parse error - treating as withdrawal",
3252 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3256 /* Check the fetched length. */
3257 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3258 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3259 "%s: BGP attribute %s, fetch error",
3260 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3261 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3262 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3263 ret
= BGP_ATTR_PARSE_ERROR
;
3269 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3270 * About Prefix-SID path attribute,
3271 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3272 * may only appear in a BGP Prefix-SID attribute attached to
3273 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3274 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3276 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3277 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3279 /* Check final read pointer is same as end pointer. */
3280 if (BGP_INPUT_PNT(peer
) != endp
) {
3281 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3282 "%s: BGP attribute %s, length mismatch", peer
->host
,
3283 lookup_msg(attr_str
, type
, NULL
));
3284 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3285 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3287 ret
= BGP_ATTR_PARSE_ERROR
;
3292 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3293 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3294 * This is implemented below and will result in a NOTIFICATION. If the
3295 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3296 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3297 * message SHOULD NOT be sent. This is implemented elsewhere.
3299 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3300 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3301 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3302 * speaker that receives the message SHOULD ignore this attribute.
3304 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3305 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3306 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3307 ret
= BGP_ATTR_PARSE_ERROR
;
3312 /* Check all mandatory well-known attributes are present */
3313 ret
= bgp_attr_check(peer
, attr
);
3318 * At this place we can see whether we got AS4_PATH and/or
3319 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3320 * We can not do this before we've read all attributes because
3321 * the as4 handling does not say whether AS4_PATH has to be sent
3322 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3323 * in relationship to AGGREGATOR.
3324 * So, to be defensive, we are not relying on any order and read
3325 * all attributes first, including these 32bit ones, and now,
3326 * afterwards, we look what and if something is to be done for as4.
3328 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3331 /* actually... this doesn't ever return failure currently, but
3332 * better safe than sorry */
3333 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3334 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3335 &as4_aggregator_addr
)) {
3336 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3337 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3338 ret
= BGP_ATTR_PARSE_ERROR
;
3343 * Finally do the checks on the aspath we did not do yet
3344 * because we waited for a potentially synthesized aspath.
3346 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3347 ret
= bgp_attr_aspath_check(peer
, attr
);
3348 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3352 ret
= BGP_ATTR_PARSE_PROCEED
;
3356 * At this stage, we have done all fiddling with as4, and the
3357 * resulting info is in attr->aggregator resp. attr->aspath so
3358 * we can chuck as4_aggregator and as4_path alltogether in order
3363 * unintern - it is in the hash
3364 * The flag that we got this is still there, but that
3365 * does not do any trouble
3367 aspath_unintern(&as4_path
);
3370 transit
= bgp_attr_get_transit(attr
);
3371 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3372 /* Finally intern unknown attribute. */
3374 bgp_attr_set_transit(attr
, transit_intern(transit
));
3375 if (attr
->encap_subtlvs
)
3376 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3378 #ifdef ENABLE_BGP_VNC
3379 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3380 bgp_attr_get_vnc_subtlvs(attr
);
3383 bgp_attr_set_vnc_subtlvs(
3385 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3389 transit_free(transit
);
3390 bgp_attr_set_transit(attr
, NULL
);
3393 bgp_attr_flush_encap(attr
);
3397 transit
= bgp_attr_get_transit(attr
);
3399 assert(transit
->refcnt
> 0);
3400 if (attr
->encap_subtlvs
)
3401 assert(attr
->encap_subtlvs
->refcnt
> 0);
3402 #ifdef ENABLE_BGP_VNC
3403 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3404 bgp_attr_get_vnc_subtlvs(attr
);
3407 assert(vnc_subtlvs
->refcnt
> 0);
3414 * Extract the tunnel type from extended community
3416 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3417 bgp_encap_types
*tunnel_type
)
3419 struct ecommunity
*ecom
;
3425 ecom
= attr
->ecommunity
;
3426 if (!ecom
|| !ecom
->size
)
3429 for (i
= 0; i
< ecom
->size
; i
++) {
3431 uint8_t type
, sub_type
;
3433 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3436 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3437 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3439 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3446 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3447 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3452 iana_safi_t pkt_safi
;
3455 /* Set extended bit always to encode the attribute length as 2 bytes */
3456 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3457 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3458 sizep
= stream_get_endp(s
);
3459 stream_putw(s
, 0); /* Marker: Attribute length. */
3462 /* Convert AFI, SAFI to values for packet. */
3463 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3465 stream_putw(s
, pkt_afi
); /* AFI */
3466 stream_putc(s
, pkt_safi
); /* SAFI */
3470 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3471 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3472 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3473 else if (safi
== SAFI_FLOWSPEC
)
3476 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3479 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3484 case SAFI_MULTICAST
:
3485 case SAFI_LABELED_UNICAST
:
3487 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3491 stream_putl(s
, 0); /* RD = 0, per RFC */
3493 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3498 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3501 if (attr
->mp_nexthop_len
== 0)
3502 stream_putc(s
, 0); /* no nexthop for flowspec */
3504 stream_putc(s
, attr
->mp_nexthop_len
);
3505 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3514 case SAFI_MULTICAST
:
3515 case SAFI_LABELED_UNICAST
:
3517 if (attr
->mp_nexthop_len
3518 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3520 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3521 stream_put(s
, &attr
->mp_nexthop_global
,
3523 stream_put(s
, &attr
->mp_nexthop_local
,
3526 stream_putc(s
, IPV6_MAX_BYTELEN
);
3527 stream_put(s
, &attr
->mp_nexthop_global
,
3531 case SAFI_MPLS_VPN
: {
3532 if (attr
->mp_nexthop_len
3533 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3535 stream_putl(s
, 0); /* RD = 0, per RFC */
3537 stream_put(s
, &attr
->mp_nexthop_global
,
3539 } else if (attr
->mp_nexthop_len
3540 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3542 stream_putl(s
, 0); /* RD = 0, per RFC */
3544 stream_put(s
, &attr
->mp_nexthop_global
,
3546 stream_putl(s
, 0); /* RD = 0, per RFC */
3548 stream_put(s
, &attr
->mp_nexthop_local
,
3553 stream_putc(s
, IPV6_MAX_BYTELEN
);
3554 stream_put(s
, &attr
->mp_nexthop_global
,
3558 stream_putc(s
, 0); /* no nexthop for flowspec */
3564 if (safi
!= SAFI_FLOWSPEC
)
3566 EC_BGP_ATTR_NH_SEND_LEN
,
3567 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3568 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3577 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3578 const struct prefix
*p
,
3579 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3580 uint32_t num_labels
, int addpath_encode
,
3581 uint32_t addpath_tx_id
, struct attr
*attr
)
3583 if (safi
== SAFI_MPLS_VPN
) {
3585 stream_putl(s
, addpath_tx_id
);
3586 /* Label, RD, Prefix write. */
3587 stream_putc(s
, p
->prefixlen
+ 88);
3588 stream_put(s
, label
, BGP_LABEL_BYTES
);
3589 stream_put(s
, prd
->val
, 8);
3590 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3591 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3592 /* EVPN prefix - contents depend on type */
3593 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3594 addpath_encode
, addpath_tx_id
);
3595 } else if (safi
== SAFI_LABELED_UNICAST
) {
3596 /* Prefix write with label. */
3597 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3599 } else if (safi
== SAFI_FLOWSPEC
) {
3600 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3601 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3602 p
->u
.prefix_flowspec
.prefixlen
);
3604 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3607 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3608 const struct prefix
*p
)
3610 int size
= PSIZE(p
->prefixlen
);
3611 if (safi
== SAFI_MPLS_VPN
)
3613 else if (safi
== SAFI_LABELED_UNICAST
)
3614 size
+= BGP_LABEL_BYTES
;
3615 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3616 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3622 * Encodes the tunnel encapsulation attribute,
3623 * and with ENABLE_BGP_VNC the VNC attribute which uses
3624 * almost the same TLV format
3626 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3627 struct stream
*s
, struct attr
*attr
,
3630 unsigned int attrlenfield
= 0;
3631 unsigned int attrhdrlen
= 0;
3632 struct bgp_attr_encap_subtlv
*subtlvs
;
3633 struct bgp_attr_encap_subtlv
*st
;
3634 const char *attrname
;
3636 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3637 && (!attr
->encap_tunneltype
3638 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3642 case BGP_ATTR_ENCAP
:
3643 attrname
= "Tunnel Encap";
3644 subtlvs
= attr
->encap_subtlvs
;
3645 if (subtlvs
== NULL
) /* nothing to do */
3648 * The tunnel encap attr has an "outer" tlv.
3650 * L = total length of subtlvs,
3651 * V = concatenated subtlvs.
3653 attrlenfield
= 2 + 2; /* T + L */
3654 attrhdrlen
= 1 + 1; /* subTLV T + L */
3657 #ifdef ENABLE_BGP_VNC_ATTR
3660 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3661 if (subtlvs
== NULL
) /* nothing to do */
3663 attrlenfield
= 0; /* no outer T + L */
3664 attrhdrlen
= 2 + 2; /* subTLV T + L */
3672 /* compute attr length */
3673 for (st
= subtlvs
; st
; st
= st
->next
) {
3674 attrlenfield
+= (attrhdrlen
+ st
->length
);
3677 if (attrlenfield
> 0xffff) {
3678 zlog_info("%s attribute is too long (length=%d), can't send it",
3679 attrname
, attrlenfield
);
3683 if (attrlenfield
> 0xff) {
3684 /* 2-octet length field */
3686 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3687 | BGP_ATTR_FLAG_EXTLEN
);
3688 stream_putc(s
, attrtype
);
3689 stream_putw(s
, attrlenfield
& 0xffff);
3691 /* 1-octet length field */
3692 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3693 stream_putc(s
, attrtype
);
3694 stream_putc(s
, attrlenfield
& 0xff);
3697 if (attrtype
== BGP_ATTR_ENCAP
) {
3698 /* write outer T+L */
3699 stream_putw(s
, attr
->encap_tunneltype
);
3700 stream_putw(s
, attrlenfield
- 4);
3703 /* write each sub-tlv */
3704 for (st
= subtlvs
; st
; st
= st
->next
) {
3705 if (attrtype
== BGP_ATTR_ENCAP
) {
3706 stream_putc(s
, st
->type
);
3707 stream_putc(s
, st
->length
);
3708 #ifdef ENABLE_BGP_VNC
3710 stream_putw(s
, st
->type
);
3711 stream_putw(s
, st
->length
);
3714 stream_put(s
, st
->value
, st
->length
);
3718 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3720 /* Set MP attribute length. Don't count the (2) bytes used to encode
3722 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3725 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3727 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3728 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3729 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3730 PEER_FLAG_REMOVE_PRIVATE_AS
)
3731 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3732 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3733 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3734 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3735 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3736 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3741 /* Make attribute packet. */
3742 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3743 struct stream
*s
, struct attr
*attr
,
3744 struct bpacket_attr_vec_arr
*vecarr
,
3745 struct prefix
*p
, afi_t afi
, safi_t safi
,
3746 struct peer
*from
, struct prefix_rd
*prd
,
3747 mpls_label_t
*label
, uint32_t num_labels
,
3748 int addpath_encode
, uint32_t addpath_tx_id
)
3751 size_t aspath_sizep
;
3752 struct aspath
*aspath
;
3753 int send_as4_path
= 0;
3754 int send_as4_aggregator
= 0;
3755 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
3756 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
3761 /* Remember current pointer. */
3762 cp
= stream_get_endp(s
);
3765 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3766 && !peer_cap_enhe(peer
, afi
, safi
))) {
3767 size_t mpattrlen_pos
= 0;
3769 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3771 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3772 num_labels
, addpath_encode
,
3773 addpath_tx_id
, attr
);
3774 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3777 /* Origin attribute. */
3778 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3779 stream_putc(s
, BGP_ATTR_ORIGIN
);
3781 stream_putc(s
, attr
->origin
);
3783 /* AS path attribute. */
3785 /* If remote-peer is EBGP */
3786 if (peer
->sort
== BGP_PEER_EBGP
3787 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3788 PEER_FLAG_AS_PATH_UNCHANGED
)
3789 || attr
->aspath
->segments
== NULL
)
3790 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3791 PEER_FLAG_RSERVER_CLIENT
))) {
3792 aspath
= aspath_dup(attr
->aspath
);
3794 /* Even though we may not be configured for confederations we
3796 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3797 aspath
= aspath_delete_confed_seq(aspath
);
3799 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3800 /* Stuff our path CONFED_ID on the front */
3801 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3803 if (peer
->change_local_as
) {
3804 /* If replace-as is specified, we only use the
3805 change_local_as when
3806 advertising routes. */
3807 if (!CHECK_FLAG(peer
->flags
,
3808 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3809 if (bgp_append_local_as(peer
, afi
,
3811 aspath
= aspath_add_seq(
3812 aspath
, peer
->local_as
);
3813 aspath
= aspath_add_seq(aspath
,
3814 peer
->change_local_as
);
3816 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3819 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3820 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3822 aspath
= aspath_dup(attr
->aspath
);
3823 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3825 aspath
= attr
->aspath
;
3827 /* If peer is not AS4 capable, then:
3828 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3829 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3831 * types are in it (i.e. exclude them if they are there)
3832 * AND do this only if there is at least one asnum > 65535 in the
3834 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3836 * all ASnums > 65535 to BGP_AS_TRANS
3839 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3840 stream_putc(s
, BGP_ATTR_AS_PATH
);
3841 aspath_sizep
= stream_get_endp(s
);
3843 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3845 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3848 if (!use32bit
&& aspath_has_as4(aspath
))
3850 1; /* we'll do this later, at the correct place */
3852 /* Nexthop attribute. */
3853 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3854 && !peer_cap_enhe(peer
, afi
, safi
)) {
3855 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3857 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3858 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3859 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3860 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3863 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3864 } else if (peer_cap_enhe(from
, afi
, safi
)
3865 || (nh_afi
== AFI_IP6
)) {
3867 * Likely this is the case when an IPv4 prefix was
3868 * received with Extended Next-hop capability in this
3869 * or another vrf and is now being advertised to
3870 * non-ENHE peers. Since peer_cap_enhe only checks
3871 * peers in this vrf, also check the nh_afi to catch
3872 * the case where the originator was in another vrf.
3873 * Setting the mandatory (ipv4) next-hop attribute here
3874 * to enable implicit next-hop self with correct A-F
3875 * (ipv4 address family).
3877 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3878 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3879 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3882 stream_put_ipv4(s
, 0);
3886 /* MED attribute. */
3887 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3888 || bgp
->maxmed_active
) {
3889 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3890 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3892 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3896 /* Local preference. */
3897 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3898 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3899 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3901 stream_putl(s
, attr
->local_pref
);
3904 /* Atomic aggregate. */
3905 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3906 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3907 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3912 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3913 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3914 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3915 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3918 /* AS4 capable peer */
3920 stream_putl(s
, attr
->aggregator_as
);
3922 /* 2-byte AS peer */
3925 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3927 if (attr
->aggregator_as
> UINT16_MAX
) {
3928 stream_putw(s
, BGP_AS_TRANS
);
3930 /* we have to send AS4_AGGREGATOR, too.
3931 * we'll do that later in order to send
3932 * attributes in ascending
3935 send_as4_aggregator
= 1;
3937 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3939 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3942 /* Community attribute. */
3943 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3944 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3945 if (attr
->community
->size
* 4 > 255) {
3947 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3948 | BGP_ATTR_FLAG_EXTLEN
);
3949 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3950 stream_putw(s
, attr
->community
->size
* 4);
3953 BGP_ATTR_FLAG_OPTIONAL
3954 | BGP_ATTR_FLAG_TRANS
);
3955 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3956 stream_putc(s
, attr
->community
->size
* 4);
3958 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3962 * Large Community attribute.
3964 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3965 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3966 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3967 if (lcom_length(attr
->lcommunity
) > 255) {
3969 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3970 | BGP_ATTR_FLAG_EXTLEN
);
3971 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3972 stream_putw(s
, lcom_length(attr
->lcommunity
));
3975 BGP_ATTR_FLAG_OPTIONAL
3976 | BGP_ATTR_FLAG_TRANS
);
3977 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3978 stream_putc(s
, lcom_length(attr
->lcommunity
));
3980 stream_put(s
, attr
->lcommunity
->val
,
3981 lcom_length(attr
->lcommunity
));
3984 /* Route Reflector. */
3985 if (peer
->sort
== BGP_PEER_IBGP
&& from
3986 && from
->sort
== BGP_PEER_IBGP
) {
3987 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
3989 /* Originator ID. */
3990 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3991 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3994 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3995 stream_put_in_addr(s
, &attr
->originator_id
);
3997 stream_put_in_addr(s
, &from
->remote_id
);
4000 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4001 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4004 stream_putc(s
, cluster
->length
+ 4);
4005 /* If this peer configuration's parent BGP has
4007 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4008 stream_put_in_addr(s
, &bgp
->cluster_id
);
4010 stream_put_in_addr(s
, &bgp
->router_id
);
4011 stream_put(s
, cluster
->list
, cluster
->length
);
4014 /* If this peer configuration's parent BGP has
4016 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4017 stream_put_in_addr(s
, &bgp
->cluster_id
);
4019 stream_put_in_addr(s
, &bgp
->router_id
);
4023 /* Extended Communities attribute. */
4024 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4025 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4026 if (peer
->sort
== BGP_PEER_IBGP
4027 || peer
->sort
== BGP_PEER_CONFED
) {
4028 if (attr
->ecommunity
->size
* 8 > 255) {
4030 BGP_ATTR_FLAG_OPTIONAL
4031 | BGP_ATTR_FLAG_TRANS
4032 | BGP_ATTR_FLAG_EXTLEN
);
4033 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4034 stream_putw(s
, attr
->ecommunity
->size
* 8);
4037 BGP_ATTR_FLAG_OPTIONAL
4038 | BGP_ATTR_FLAG_TRANS
);
4039 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4040 stream_putc(s
, attr
->ecommunity
->size
* 8);
4042 stream_put(s
, attr
->ecommunity
->val
,
4043 attr
->ecommunity
->size
* 8);
4047 int ecom_tr_size
= 0;
4050 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
4051 pnt
= attr
->ecommunity
->val
+ (i
* 8);
4054 if (CHECK_FLAG(tbit
,
4055 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4062 if (ecom_tr_size
* 8 > 255) {
4065 BGP_ATTR_FLAG_OPTIONAL
4066 | BGP_ATTR_FLAG_TRANS
4067 | BGP_ATTR_FLAG_EXTLEN
);
4069 BGP_ATTR_EXT_COMMUNITIES
);
4070 stream_putw(s
, ecom_tr_size
* 8);
4074 BGP_ATTR_FLAG_OPTIONAL
4075 | BGP_ATTR_FLAG_TRANS
);
4077 BGP_ATTR_EXT_COMMUNITIES
);
4078 stream_putc(s
, ecom_tr_size
* 8);
4081 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
4082 pnt
= attr
->ecommunity
->val
+ (i
* 8);
4087 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4090 stream_put(s
, pnt
, 8);
4096 /* Label index attribute. */
4097 if (safi
== SAFI_LABELED_UNICAST
) {
4098 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4099 uint32_t label_index
;
4101 label_index
= attr
->label_index
;
4103 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4105 BGP_ATTR_FLAG_OPTIONAL
4106 | BGP_ATTR_FLAG_TRANS
);
4107 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4109 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4111 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4112 stream_putc(s
, 0); // reserved
4113 stream_putw(s
, 0); // flags
4114 stream_putl(s
, label_index
);
4119 /* SRv6 Service Information Attribute. */
4120 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4121 if (attr
->srv6_l3vpn
) {
4122 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4123 | BGP_ATTR_FLAG_TRANS
);
4124 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4125 stream_putc(s
, 24); /* tlv len */
4126 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4127 stream_putw(s
, 21); /* sub-tlv len */
4128 stream_putc(s
, 0); /* reserved */
4129 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4130 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4131 stream_putc(s
, 0); /* sid_flags */
4132 stream_putw(s
, 0xffff); /* endpoint */
4133 stream_putc(s
, 0); /* reserved */
4134 } else if (attr
->srv6_vpn
) {
4135 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4136 | BGP_ATTR_FLAG_TRANS
);
4137 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4138 stream_putc(s
, 22); /* tlv len */
4139 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4140 stream_putw(s
, 0x13); /* tlv len */
4141 stream_putc(s
, 0x00); /* reserved */
4142 stream_putc(s
, 0x01); /* sid_type */
4143 stream_putc(s
, 0x00); /* sif_flags */
4144 stream_put(s
, &attr
->srv6_vpn
->sid
,
4145 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4149 if (send_as4_path
) {
4150 /* If the peer is NOT As4 capable, AND */
4151 /* there are ASnums > 65535 in path THEN
4152 * give out AS4_PATH */
4154 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4156 * Hm, I wonder... confederation things *should* only be at
4157 * the beginning of an aspath, right? Then we should use
4158 * aspath_delete_confed_seq for this, because it is already
4160 * Folks, talk to me: what is reasonable here!?
4162 aspath
= aspath_delete_confed_seq(aspath
);
4165 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4166 | BGP_ATTR_FLAG_EXTLEN
);
4167 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4168 aspath_sizep
= stream_get_endp(s
);
4170 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4173 if (aspath
!= attr
->aspath
)
4174 aspath_free(aspath
);
4176 if (send_as4_aggregator
) {
4177 /* send AS4_AGGREGATOR, at this place */
4178 /* this section of code moved here in order to ensure the
4180 * *ascending* order of attributes
4182 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4183 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4185 stream_putl(s
, attr
->aggregator_as
);
4186 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4189 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4190 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4191 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4192 /* Tunnel Encap attribute */
4193 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4195 #ifdef ENABLE_BGP_VNC_ATTR
4197 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4202 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4203 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4204 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4205 stream_putc(s
, 9); // Length
4206 stream_putc(s
, 0); // Flags
4207 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4208 stream_put(s
, &(attr
->label
),
4209 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4210 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4211 // Unicast tunnel endpoint IP address
4214 /* Unknown transit attribute. */
4215 struct transit
*transit
= bgp_attr_get_transit(attr
);
4218 stream_put(s
, transit
->val
, transit
->length
);
4220 /* Return total size of attribute. */
4221 return stream_get_endp(s
) - cp
;
4224 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4226 unsigned long attrlen_pnt
;
4228 iana_safi_t pkt_safi
;
4230 /* Set extended bit always to encode the attribute length as 2 bytes */
4231 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4232 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4234 attrlen_pnt
= stream_get_endp(s
);
4235 stream_putw(s
, 0); /* Length of this attribute. */
4237 /* Convert AFI, SAFI to values for packet. */
4238 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4240 stream_putw(s
, pkt_afi
);
4241 stream_putc(s
, pkt_safi
);
4246 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4247 afi_t afi
, safi_t safi
,
4248 const struct prefix_rd
*prd
,
4249 mpls_label_t
*label
, uint32_t num_labels
,
4250 int addpath_encode
, uint32_t addpath_tx_id
,
4253 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4255 if (safi
== SAFI_LABELED_UNICAST
) {
4256 label
= (mpls_label_t
*)wlabel
;
4260 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4261 addpath_encode
, addpath_tx_id
, attr
);
4264 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4266 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4269 /* Initialization of attribute. */
4270 void bgp_attr_init(void)
4283 void bgp_attr_finish(void)
4288 ecommunity_finish();
4289 lcommunity_finish();
4296 /* Make attribute packet. */
4297 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4298 const struct prefix
*prefix
)
4303 struct aspath
*aspath
;
4304 int addpath_encode
= 0;
4305 uint32_t addpath_tx_id
= 0;
4307 /* Remember current pointer. */
4308 cp
= stream_get_endp(s
);
4310 /* Place holder of length. */
4313 /* Origin attribute. */
4314 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4315 stream_putc(s
, BGP_ATTR_ORIGIN
);
4317 stream_putc(s
, attr
->origin
);
4319 aspath
= attr
->aspath
;
4321 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4322 stream_putc(s
, BGP_ATTR_AS_PATH
);
4323 aspath_lenp
= stream_get_endp(s
);
4326 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4328 /* Nexthop attribute. */
4329 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4330 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4331 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4332 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4334 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4337 /* MED attribute. */
4338 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4339 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4340 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4342 stream_putl(s
, attr
->med
);
4345 /* Local preference. */
4346 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4347 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4348 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4350 stream_putl(s
, attr
->local_pref
);
4353 /* Atomic aggregate. */
4354 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4355 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4356 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4361 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4362 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4363 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4365 stream_putl(s
, attr
->aggregator_as
);
4366 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4369 /* Community attribute. */
4370 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4371 if (attr
->community
->size
* 4 > 255) {
4373 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4374 | BGP_ATTR_FLAG_EXTLEN
);
4375 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4376 stream_putw(s
, attr
->community
->size
* 4);
4379 BGP_ATTR_FLAG_OPTIONAL
4380 | BGP_ATTR_FLAG_TRANS
);
4381 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4382 stream_putc(s
, attr
->community
->size
* 4);
4384 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4387 /* Large Community attribute. */
4388 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4389 if (lcom_length(attr
->lcommunity
) > 255) {
4391 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4392 | BGP_ATTR_FLAG_EXTLEN
);
4393 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4394 stream_putw(s
, lcom_length(attr
->lcommunity
));
4397 BGP_ATTR_FLAG_OPTIONAL
4398 | BGP_ATTR_FLAG_TRANS
);
4399 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4400 stream_putc(s
, lcom_length(attr
->lcommunity
));
4403 stream_put(s
, attr
->lcommunity
->val
,
4404 lcom_length(attr
->lcommunity
));
4407 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4408 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4409 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4410 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4413 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4414 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4415 sizep
= stream_get_endp(s
);
4418 stream_putc(s
, 0); /* Marker: Attribute length. */
4419 stream_putw(s
, AFI_IP6
); /* AFI */
4420 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4423 stream_putc(s
, attr
->mp_nexthop_len
);
4424 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4425 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4426 stream_put(s
, &attr
->mp_nexthop_local
,
4433 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
4436 /* Set MP attribute length. */
4437 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4441 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4442 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4444 BGP_ATTR_FLAG_OPTIONAL
4445 | BGP_ATTR_FLAG_TRANS
);
4446 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4448 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4449 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4450 stream_putc(s
, 0); // reserved
4451 stream_putw(s
, 0); // flags
4452 stream_putl(s
, attr
->label_index
);
4456 /* Return total size of attribute. */
4457 len
= stream_get_endp(s
) - cp
- 2;
4458 stream_putw_at(s
, cp
, len
);