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
);
700 bool attrhash_cmp(const void *p1
, const void *p2
)
702 const struct attr
*attr1
= p1
;
703 const struct attr
*attr2
= p2
;
705 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
706 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
707 && attr1
->aspath
== attr2
->aspath
708 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
709 && attr1
->local_pref
== attr2
->local_pref
710 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
711 if (attr1
->aggregator_as
== attr2
->aggregator_as
712 && attr1
->aggregator_addr
.s_addr
713 == attr2
->aggregator_addr
.s_addr
714 && attr1
->weight
== attr2
->weight
715 && attr1
->tag
== attr2
->tag
716 && attr1
->label_index
== attr2
->label_index
717 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
718 && attr1
->ecommunity
== attr2
->ecommunity
719 && bgp_attr_get_ipv6_ecommunity(attr1
)
720 == bgp_attr_get_ipv6_ecommunity(attr2
)
721 && attr1
->lcommunity
== attr2
->lcommunity
722 && bgp_attr_get_cluster(attr1
)
723 == bgp_attr_get_cluster(attr2
)
724 && bgp_attr_get_transit(attr1
)
725 == bgp_attr_get_transit(attr2
)
726 && attr1
->rmap_table_id
== attr2
->rmap_table_id
727 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
728 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
729 #ifdef ENABLE_BGP_VNC
730 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
731 bgp_attr_get_vnc_subtlvs(attr2
))
733 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
734 &attr2
->mp_nexthop_global
)
735 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
736 &attr2
->mp_nexthop_local
)
737 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
738 &attr2
->mp_nexthop_global_in
)
739 && IPV4_ADDR_SAME(&attr1
->originator_id
,
740 &attr2
->originator_id
)
741 && overlay_index_same(attr1
, attr2
)
742 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
743 && attr1
->es_flags
== attr2
->es_flags
744 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
745 && attr1
->df_pref
== attr2
->df_pref
746 && attr1
->df_alg
== attr2
->df_alg
747 && attr1
->nh_ifindex
== attr2
->nh_ifindex
748 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
749 && attr1
->distance
== attr2
->distance
750 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
751 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
752 && attr1
->srte_color
== attr2
->srte_color
753 && attr1
->nh_type
== attr2
->nh_type
754 && attr1
->bh_type
== attr2
->bh_type
)
761 static void attrhash_init(void)
764 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
768 * special for hash_clean below
770 static void attr_vfree(void *attr
)
772 XFREE(MTYPE_ATTR
, attr
);
775 static void attrhash_finish(void)
777 hash_clean(attrhash
, attr_vfree
);
782 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
784 struct attr
*attr
= bucket
->data
;
785 char sid_str
[BUFSIZ
];
787 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
790 if (attr
->srv6_l3vpn
)
791 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
792 else if (attr
->srv6_vpn
)
793 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
796 "\tflags: %" PRIu64
" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
797 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
798 attr
->origin
, attr
->weight
, attr
->label
, sid_str
);
801 void attr_show_all(struct vty
*vty
)
803 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
804 void *))attr_show_all_iterator
,
808 static void *bgp_attr_hash_alloc(void *p
)
810 struct attr
*val
= (struct attr
*)p
;
813 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
815 if (val
->encap_subtlvs
) {
816 val
->encap_subtlvs
= NULL
;
818 #ifdef ENABLE_BGP_VNC
819 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
820 bgp_attr_get_vnc_subtlvs(val
);
823 bgp_attr_set_vnc_subtlvs(val
, NULL
);
826 val
->srv6_l3vpn
= NULL
;
828 val
->srv6_vpn
= NULL
;
834 /* Internet argument attribute. */
835 struct attr
*bgp_attr_intern(struct attr
*attr
)
838 struct ecommunity
*ecomm
;
840 /* Intern referenced strucutre. */
842 if (!attr
->aspath
->refcnt
)
843 attr
->aspath
= aspath_intern(attr
->aspath
);
845 attr
->aspath
->refcnt
++;
847 if (attr
->community
) {
848 if (!attr
->community
->refcnt
)
849 attr
->community
= community_intern(attr
->community
);
851 attr
->community
->refcnt
++;
854 if (attr
->ecommunity
) {
855 if (!attr
->ecommunity
->refcnt
)
856 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
858 attr
->ecommunity
->refcnt
++;
861 ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
864 bgp_attr_set_ipv6_ecommunity(attr
,
865 ecommunity_intern(ecomm
));
870 if (attr
->lcommunity
) {
871 if (!attr
->lcommunity
->refcnt
)
872 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
874 attr
->lcommunity
->refcnt
++;
877 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
880 if (!cluster
->refcnt
)
881 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
886 struct transit
*transit
= bgp_attr_get_transit(attr
);
889 if (!transit
->refcnt
)
890 bgp_attr_set_transit(attr
, transit_intern(transit
));
894 if (attr
->encap_subtlvs
) {
895 if (!attr
->encap_subtlvs
->refcnt
)
896 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
899 attr
->encap_subtlvs
->refcnt
++;
901 if (attr
->srv6_l3vpn
) {
902 if (!attr
->srv6_l3vpn
->refcnt
)
903 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
905 attr
->srv6_l3vpn
->refcnt
++;
907 if (attr
->srv6_vpn
) {
908 if (!attr
->srv6_vpn
->refcnt
)
909 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
911 attr
->srv6_vpn
->refcnt
++;
913 #ifdef ENABLE_BGP_VNC
914 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
915 bgp_attr_get_vnc_subtlvs(attr
);
918 if (!vnc_subtlvs
->refcnt
)
919 bgp_attr_set_vnc_subtlvs(
921 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
923 vnc_subtlvs
->refcnt
++;
927 /* At this point, attr only contains intern'd pointers. that means
928 * if we find it in attrhash, it has all the same pointers and we
929 * correctly updated the refcounts on these.
930 * If we don't find it, we need to allocate a one because in all
931 * cases this returns a new reference to a hashed attr, but the input
933 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
939 /* Make network statement's attribute. */
940 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
942 memset(attr
, 0, sizeof(struct attr
));
944 attr
->origin
= origin
;
945 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
946 attr
->aspath
= aspath_empty();
947 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
948 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
950 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
951 attr
->label
= MPLS_INVALID_LABEL
;
952 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
953 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
958 /* Create the attributes for an aggregate */
959 struct attr
*bgp_attr_aggregate_intern(
960 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
961 struct community
*community
, struct ecommunity
*ecommunity
,
962 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
963 uint8_t atomic_aggregate
, const struct prefix
*p
)
969 memset(&attr
, 0, sizeof(struct attr
));
971 /* Origin attribute. */
972 attr
.origin
= origin
;
973 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
975 /* AS path attribute. */
977 attr
.aspath
= aspath_intern(aspath
);
979 attr
.aspath
= aspath_empty();
980 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
982 /* Next hop attribute. */
983 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
986 uint32_t gshut
= COMMUNITY_GSHUT
;
988 /* If we are not shutting down ourselves and we are
989 * aggregating a route that contains the GSHUT community we
990 * need to remove that community when creating the aggregate */
991 if (!bgp_in_graceful_shutdown(bgp
)
992 && community_include(community
, gshut
)) {
993 community_del_val(community
, &gshut
);
996 attr
.community
= community
;
997 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1001 attr
.ecommunity
= ecommunity
;
1002 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1006 attr
.lcommunity
= lcommunity
;
1007 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1010 if (bgp_in_graceful_shutdown(bgp
))
1011 bgp_attr_add_gshut_community(&attr
);
1013 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1014 attr
.label
= MPLS_INVALID_LABEL
;
1015 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1016 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1017 if (!aggregate
->as_set
|| atomic_aggregate
)
1018 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1019 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1020 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1021 attr
.aggregator_as
= bgp
->confed_id
;
1023 attr
.aggregator_as
= bgp
->as
;
1024 attr
.aggregator_addr
= bgp
->router_id
;
1025 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1026 attr
.label
= MPLS_INVALID_LABEL
;
1028 /* Apply route-map */
1029 if (aggregate
->rmap
.name
) {
1030 struct attr attr_tmp
= attr
;
1031 struct bgp_path_info rmap_path
;
1033 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1034 rmap_path
.peer
= bgp
->peer_self
;
1035 rmap_path
.attr
= &attr_tmp
;
1037 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1039 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1041 bgp
->peer_self
->rmap_type
= 0;
1043 if (ret
== RMAP_DENYMATCH
) {
1044 /* Free uninterned attribute. */
1045 bgp_attr_flush(&attr_tmp
);
1047 /* Unintern original. */
1048 aspath_unintern(&attr
.aspath
);
1052 if (bgp_in_graceful_shutdown(bgp
))
1053 bgp_attr_add_gshut_community(&attr_tmp
);
1055 new = bgp_attr_intern(&attr_tmp
);
1058 if (bgp_in_graceful_shutdown(bgp
))
1059 bgp_attr_add_gshut_community(&attr
);
1061 new = bgp_attr_intern(&attr
);
1064 aspath_unintern(&new->aspath
);
1068 /* Unintern just the sub-components of the attr, but not the attr */
1069 void bgp_attr_unintern_sub(struct attr
*attr
)
1071 struct ecommunity
*ecomm
;
1072 struct cluster_list
*cluster
;
1074 /* aspath refcount shoud be decrement. */
1076 aspath_unintern(&attr
->aspath
);
1077 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1079 if (attr
->community
)
1080 community_unintern(&attr
->community
);
1081 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1083 ecommunity_unintern(&attr
->ecommunity
);
1084 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
1086 ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1087 ecommunity_unintern(&ecomm
);
1088 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
));
1089 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1091 if (attr
->lcommunity
)
1092 lcommunity_unintern(&attr
->lcommunity
);
1093 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1095 cluster
= bgp_attr_get_cluster(attr
);
1097 cluster_unintern(&cluster
);
1098 bgp_attr_set_cluster(attr
, cluster
);
1100 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1102 struct transit
*transit
= bgp_attr_get_transit(attr
);
1105 transit_unintern(&transit
);
1106 bgp_attr_set_transit(attr
, transit
);
1109 if (attr
->encap_subtlvs
)
1110 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1112 #ifdef ENABLE_BGP_VNC
1113 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1114 bgp_attr_get_vnc_subtlvs(attr
);
1117 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1118 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1122 if (attr
->srv6_l3vpn
)
1123 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1126 srv6_vpn_unintern(&attr
->srv6_vpn
);
1130 * We have some show commands that let you experimentally
1131 * apply a route-map. When we apply the route-map
1132 * we are reseting values but not saving them for
1133 * posterity via intern'ing( because route-maps don't
1134 * do that) but at this point in time we need
1135 * to compare the new attr to the old and if the
1136 * routemap has changed it we need to, as Snoop Dog says,
1137 * Drop it like it's hot
1139 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
1141 if (new->aspath
!= old
->aspath
)
1142 aspath_free(new->aspath
);
1144 if (new->community
!= old
->community
)
1145 community_free(&new->community
);
1147 if (new->ecommunity
!= old
->ecommunity
)
1148 ecommunity_free(&new->ecommunity
);
1150 if (new->lcommunity
!= old
->lcommunity
)
1151 lcommunity_free(&new->lcommunity
);
1153 if (new->srv6_l3vpn
!= old
->srv6_l3vpn
) {
1154 srv6_l3vpn_free(new->srv6_l3vpn
);
1155 new->srv6_l3vpn
= NULL
;
1158 if (new->srv6_vpn
!= old
->srv6_vpn
) {
1159 srv6_vpn_free(new->srv6_vpn
);
1160 new->srv6_vpn
= NULL
;
1164 /* Free bgp attribute and aspath. */
1165 void bgp_attr_unintern(struct attr
**pattr
)
1167 struct attr
*attr
= *pattr
;
1171 /* Decrement attribute reference. */
1176 /* If reference becomes zero then free attribute object. */
1177 if (attr
->refcnt
== 0) {
1178 ret
= hash_release(attrhash
, attr
);
1179 assert(ret
!= NULL
);
1180 XFREE(MTYPE_ATTR
, attr
);
1184 bgp_attr_unintern_sub(&tmp
);
1187 void bgp_attr_flush(struct attr
*attr
)
1189 struct ecommunity
*ecomm
;
1190 struct cluster_list
*cluster
;
1192 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1193 aspath_free(attr
->aspath
);
1194 attr
->aspath
= NULL
;
1196 if (attr
->community
&& !attr
->community
->refcnt
)
1197 community_free(&attr
->community
);
1198 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
1199 ecommunity_free(&attr
->ecommunity
);
1200 ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1201 if (ecomm
&& !ecomm
->refcnt
)
1202 ecommunity_free(&ecomm
);
1203 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1204 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
1205 lcommunity_free(&attr
->lcommunity
);
1207 cluster
= bgp_attr_get_cluster(attr
);
1208 if (cluster
&& !cluster
->refcnt
) {
1209 cluster_free(cluster
);
1210 bgp_attr_set_cluster(attr
, NULL
);
1213 struct transit
*transit
= bgp_attr_get_transit(attr
);
1215 if (transit
&& !transit
->refcnt
) {
1216 transit_free(transit
);
1217 bgp_attr_set_transit(attr
, NULL
);
1219 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1220 encap_free(attr
->encap_subtlvs
);
1221 attr
->encap_subtlvs
= NULL
;
1223 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1224 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1225 attr
->srv6_l3vpn
= NULL
;
1227 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1228 srv6_vpn_free(attr
->srv6_vpn
);
1229 attr
->srv6_vpn
= NULL
;
1231 #ifdef ENABLE_BGP_VNC
1232 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1233 bgp_attr_get_vnc_subtlvs(attr
);
1235 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1236 encap_free(vnc_subtlvs
);
1237 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1242 /* Implement draft-scudder-idr-optional-transitive behaviour and
1243 * avoid resetting sessions for malformed attributes which are
1244 * are partial/optional and hence where the error likely was not
1245 * introduced by the sending neighbour.
1247 static bgp_attr_parse_ret_t
1248 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1251 struct peer
*const peer
= args
->peer
;
1252 struct attr
*const attr
= args
->attr
;
1253 const uint8_t flags
= args
->flags
;
1254 /* startp and length must be special-cased, as whether or not to
1255 * send the attribute data with the NOTIFY depends on the error,
1256 * the caller therefore signals this with the seperate length argument
1258 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1260 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1261 char attr_str
[BUFSIZ
] = {0};
1263 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1265 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1268 /* Only relax error handling for eBGP peers */
1269 if (peer
->sort
!= BGP_PEER_EBGP
) {
1270 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1271 notify_datap
, length
);
1272 return BGP_ATTR_PARSE_ERROR
;
1275 /* Adjust the stream getp to the end of the attribute, in case we can
1276 * still proceed but the caller hasn't read all the attribute.
1278 stream_set_getp(BGP_INPUT(peer
),
1279 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1282 switch (args
->type
) {
1283 /* where an attribute is relatively inconsequential, e.g. it does not
1284 * affect route selection, and can be safely ignored, then any such
1285 * attributes which are malformed should just be ignored and the route
1286 * processed as normal.
1288 case BGP_ATTR_AS4_AGGREGATOR
:
1289 case BGP_ATTR_AGGREGATOR
:
1290 case BGP_ATTR_ATOMIC_AGGREGATE
:
1291 return BGP_ATTR_PARSE_PROCEED
;
1293 /* Core attributes, particularly ones which may influence route
1294 * selection, should be treat-as-withdraw.
1296 case BGP_ATTR_ORIGIN
:
1297 case BGP_ATTR_AS_PATH
:
1298 case BGP_ATTR_NEXT_HOP
:
1299 case BGP_ATTR_MULTI_EXIT_DISC
:
1300 case BGP_ATTR_LOCAL_PREF
:
1301 case BGP_ATTR_COMMUNITIES
:
1302 case BGP_ATTR_EXT_COMMUNITIES
:
1303 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1304 case BGP_ATTR_LARGE_COMMUNITIES
:
1305 case BGP_ATTR_ORIGINATOR_ID
:
1306 case BGP_ATTR_CLUSTER_LIST
:
1307 return BGP_ATTR_PARSE_WITHDRAW
;
1308 case BGP_ATTR_MP_REACH_NLRI
:
1309 case BGP_ATTR_MP_UNREACH_NLRI
:
1310 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1311 notify_datap
, length
);
1312 return BGP_ATTR_PARSE_ERROR
;
1315 /* Partial optional attributes that are malformed should not cause
1316 * the whole session to be reset. Instead treat it as a withdrawal
1317 * of the routes, if possible.
1319 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1320 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1321 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1322 return BGP_ATTR_PARSE_WITHDRAW
;
1324 /* default to reset */
1325 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1328 /* Find out what is wrong with the path attribute flag bits and log the error.
1329 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1330 Extended Length. Checking O/T/P bits at once implies, that the attribute
1331 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1332 non-transitive" attribute. */
1334 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1335 uint8_t desired_flags
/* how RFC says it must be */
1338 uint8_t seen
= 0, i
;
1339 uint8_t real_flags
= args
->flags
;
1340 const uint8_t attr_code
= args
->type
;
1342 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1343 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1344 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1345 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1346 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1347 flog_err(EC_BGP_ATTR_FLAG
,
1348 "%s attribute must%s be flagged as \"%s\"",
1349 lookup_msg(attr_str
, attr_code
, NULL
),
1350 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1353 attr_flag_str
[i
].str
);
1358 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1359 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1360 real_flags
, desired_flags
);
1364 /* Required flags for attributes. EXTLEN will be masked off when testing,
1365 * as will PARTIAL for optional+transitive attributes.
1367 const uint8_t attr_flags_values
[] = {
1368 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1369 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1370 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1371 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1372 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1373 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1374 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1375 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1376 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1377 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1378 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1379 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1380 [BGP_ATTR_EXT_COMMUNITIES
] =
1381 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1382 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1383 [BGP_ATTR_AS4_AGGREGATOR
] =
1384 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1385 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1386 [BGP_ATTR_LARGE_COMMUNITIES
] =
1387 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1388 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1389 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1390 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1392 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1394 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1396 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1397 const uint8_t flags
= args
->flags
;
1398 const uint8_t attr_code
= args
->type
;
1400 /* there may be attributes we don't know about */
1401 if (attr_code
> attr_flags_values_max
)
1403 if (attr_flags_values
[attr_code
] == 0)
1406 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1410 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1411 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1414 "%s well-known attributes must have transitive flag set (%x)",
1415 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1419 /* "For well-known attributes and for optional non-transitive
1421 * the Partial bit MUST be set to 0."
1423 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1424 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1425 flog_err(EC_BGP_ATTR_FLAG
,
1426 "%s well-known attribute must NOT have the partial flag set (%x)",
1427 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1430 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1431 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1432 flog_err(EC_BGP_ATTR_FLAG
,
1433 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1434 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1439 /* Optional transitive attributes may go through speakers that don't
1440 * reocgnise them and set the Partial bit.
1442 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1443 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1444 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1446 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1449 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1453 /* Get origin attribute of the update message. */
1454 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1456 struct peer
*const peer
= args
->peer
;
1457 struct attr
*const attr
= args
->attr
;
1458 const bgp_size_t length
= args
->length
;
1460 /* If any recognized attribute has Attribute Length that conflicts
1461 with the expected length (based on the attribute type code), then
1462 the Error Subcode is set to Attribute Length Error. The Data
1463 field contains the erroneous attribute (type, length and
1466 flog_err(EC_BGP_ATTR_LEN
,
1467 "Origin attribute length is not one %d", length
);
1468 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1472 /* Fetch origin attribute. */
1473 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1475 /* If the ORIGIN attribute has an undefined value, then the Error
1476 Subcode is set to Invalid Origin Attribute. The Data field
1477 contains the unrecognized attribute (type, length and value). */
1478 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1479 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1480 flog_err(EC_BGP_ATTR_ORIGIN
,
1481 "Origin attribute value is invalid %d", attr
->origin
);
1482 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1486 /* Set oring attribute flag. */
1487 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1492 /* Parse AS path information. This function is wrapper of
1494 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1496 struct attr
*const attr
= args
->attr
;
1497 struct peer
*const peer
= args
->peer
;
1498 const bgp_size_t length
= args
->length
;
1501 * peer with AS4 => will get 4Byte ASnums
1502 * otherwise, will get 16 Bit
1504 attr
->aspath
= aspath_parse(
1506 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1507 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1509 /* In case of IBGP, length will be zero. */
1510 if (!attr
->aspath
) {
1511 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1512 "Malformed AS path from %s, length is %d", peer
->host
,
1514 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1518 /* Set aspath attribute flag. */
1519 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1521 return BGP_ATTR_PARSE_PROCEED
;
1524 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1525 struct attr
*const attr
)
1527 /* These checks were part of bgp_attr_aspath, but with
1528 * as4 we should to check aspath things when
1529 * aspath synthesizing with as4_path has already taken place.
1530 * Otherwise we check ASPATH and use the synthesized thing, and that is
1532 * So do the checks later, i.e. here
1534 struct aspath
*aspath
;
1536 /* Confederation sanity check. */
1537 if ((peer
->sort
== BGP_PEER_CONFED
1538 && !aspath_left_confed_check(attr
->aspath
))
1539 || (peer
->sort
== BGP_PEER_EBGP
1540 && aspath_confed_check(attr
->aspath
))) {
1541 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1543 return BGP_ATTR_PARSE_WITHDRAW
;
1546 /* First AS check for EBGP. */
1547 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1548 if (peer
->sort
== BGP_PEER_EBGP
1549 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1550 flog_err(EC_BGP_ATTR_FIRST_AS
,
1551 "%s incorrect first AS (must be %u)",
1552 peer
->host
, peer
->as
);
1553 return BGP_ATTR_PARSE_WITHDRAW
;
1557 /* Codification of AS 0 Processing */
1558 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1560 EC_BGP_ATTR_MAL_AS_PATH
,
1561 "Malformed AS path, AS number is 0 in the path from %s",
1563 return BGP_ATTR_PARSE_WITHDRAW
;
1566 /* local-as prepend */
1567 if (peer
->change_local_as
1568 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1569 aspath
= aspath_dup(attr
->aspath
);
1570 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1571 aspath_unintern(&attr
->aspath
);
1572 attr
->aspath
= aspath_intern(aspath
);
1575 return BGP_ATTR_PARSE_PROCEED
;
1578 /* Parse AS4 path information. This function is another wrapper of
1580 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1581 struct aspath
**as4_path
)
1583 struct peer
*const peer
= args
->peer
;
1584 struct attr
*const attr
= args
->attr
;
1585 const bgp_size_t length
= args
->length
;
1587 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1589 /* In case of IBGP, length will be zero. */
1591 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1592 "Malformed AS4 path from %s, length is %d", peer
->host
,
1594 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1598 /* Set aspath attribute flag. */
1599 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1601 return BGP_ATTR_PARSE_PROCEED
;
1605 * Check that the nexthop attribute is valid.
1607 bgp_attr_parse_ret_t
1608 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1610 in_addr_t nexthop_h
;
1612 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1613 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1614 || IPV4_CLASS_DE(nexthop_h
))
1615 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1616 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1617 char buf
[INET_ADDRSTRLEN
];
1619 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1621 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1623 data
[0] = BGP_ATTR_FLAG_TRANS
;
1624 data
[1] = BGP_ATTR_NEXT_HOP
;
1625 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1626 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1627 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1628 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1630 return BGP_ATTR_PARSE_ERROR
;
1633 return BGP_ATTR_PARSE_PROCEED
;
1636 /* Nexthop attribute. */
1637 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1639 struct peer
*const peer
= args
->peer
;
1640 struct attr
*const attr
= args
->attr
;
1641 const bgp_size_t length
= args
->length
;
1643 /* Check nexthop attribute length. */
1645 flog_err(EC_BGP_ATTR_LEN
,
1646 "Nexthop attribute length isn't four [%d]", length
);
1648 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1652 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1653 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1655 return BGP_ATTR_PARSE_PROCEED
;
1658 /* MED atrribute. */
1659 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1661 struct peer
*const peer
= args
->peer
;
1662 struct attr
*const attr
= args
->attr
;
1663 const bgp_size_t length
= args
->length
;
1667 flog_err(EC_BGP_ATTR_LEN
,
1668 "MED attribute length isn't four [%d]", length
);
1670 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1674 attr
->med
= stream_getl(peer
->curr
);
1676 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1678 return BGP_ATTR_PARSE_PROCEED
;
1681 /* Local preference attribute. */
1682 static bgp_attr_parse_ret_t
1683 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1685 struct peer
*const peer
= args
->peer
;
1686 struct attr
*const attr
= args
->attr
;
1687 const bgp_size_t length
= args
->length
;
1689 /* if received from an internal neighbor, it SHALL be considered
1690 * malformed if its length is not equal to 4. If malformed, the
1691 * UPDATE message SHALL be handled using the approach of "treat-as-
1694 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1695 flog_err(EC_BGP_ATTR_LEN
,
1696 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1697 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1701 /* If it is contained in an UPDATE message that is received from an
1702 external peer, then this attribute MUST be ignored by the
1703 receiving speaker. */
1704 if (peer
->sort
== BGP_PEER_EBGP
) {
1705 STREAM_FORWARD_GETP(peer
->curr
, length
);
1706 return BGP_ATTR_PARSE_PROCEED
;
1709 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1711 /* Set the local-pref flag. */
1712 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1714 return BGP_ATTR_PARSE_PROCEED
;
1717 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1721 /* Atomic aggregate. */
1722 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1724 struct attr
*const attr
= args
->attr
;
1725 const bgp_size_t length
= args
->length
;
1729 flog_err(EC_BGP_ATTR_LEN
,
1730 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1732 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1736 /* Set atomic aggregate flag. */
1737 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1739 return BGP_ATTR_PARSE_PROCEED
;
1742 /* Aggregator attribute */
1743 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1745 struct peer
*const peer
= args
->peer
;
1746 struct attr
*const attr
= args
->attr
;
1747 const bgp_size_t length
= args
->length
;
1752 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1753 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1754 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1757 if (length
!= wantedlen
) {
1758 flog_err(EC_BGP_ATTR_LEN
,
1759 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1761 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1765 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1766 aggregator_as
= stream_getl(peer
->curr
);
1768 aggregator_as
= stream_getw(peer
->curr
);
1770 attr
->aggregator_as
= aggregator_as
;
1771 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1773 /* Codification of AS 0 Processing */
1774 if (aggregator_as
== BGP_AS_ZERO
) {
1775 flog_err(EC_BGP_ATTR_LEN
,
1776 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1777 peer
->host
, aspath_print(attr
->aspath
));
1779 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1780 char attr_str
[BUFSIZ
] = {0};
1782 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1784 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1787 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1790 return BGP_ATTR_PARSE_PROCEED
;
1793 /* New Aggregator attribute */
1794 static bgp_attr_parse_ret_t
1795 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1796 as_t
*as4_aggregator_as
,
1797 struct in_addr
*as4_aggregator_addr
)
1799 struct peer
*const peer
= args
->peer
;
1800 struct attr
*const attr
= args
->attr
;
1801 const bgp_size_t length
= args
->length
;
1805 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1807 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1811 aggregator_as
= stream_getl(peer
->curr
);
1813 *as4_aggregator_as
= aggregator_as
;
1814 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1816 /* Codification of AS 0 Processing */
1817 if (aggregator_as
== BGP_AS_ZERO
) {
1818 flog_err(EC_BGP_ATTR_LEN
,
1819 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1820 peer
->host
, aspath_print(attr
->aspath
));
1822 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1823 char attr_str
[BUFSIZ
] = {0};
1825 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1827 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1830 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1833 return BGP_ATTR_PARSE_PROCEED
;
1836 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1838 static bgp_attr_parse_ret_t
1839 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1840 struct aspath
*as4_path
, as_t as4_aggregator
,
1841 struct in_addr
*as4_aggregator_addr
)
1843 int ignore_as4_path
= 0;
1844 struct aspath
*newpath
;
1846 if (!attr
->aspath
) {
1847 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1849 * checked that all well-known, mandatory attributes were
1852 * Can only be a problem with peer itself - hard error
1854 return BGP_ATTR_PARSE_ERROR
;
1857 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1858 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1860 * It is worth a warning though, because the peer really
1861 * should not send them
1863 if (BGP_DEBUG(as4
, AS4
)) {
1864 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1865 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1866 "AS4 capable peer, yet it sent");
1869 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1870 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1872 "AS4 capable peer, yet it sent");
1875 return BGP_ATTR_PARSE_PROCEED
;
1878 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1879 * because that may override AS4_PATH
1881 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1882 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1884 * if the as_number in aggregator is not AS_TRANS,
1885 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1886 * and the Aggregator shall be taken as
1887 * info on the aggregating node, and the AS_PATH
1888 * shall be taken as the AS_PATH
1890 * the Aggregator shall be ignored and the
1891 * AS4_AGGREGATOR shall be taken as the
1892 * Aggregating node and the AS_PATH is to be
1893 * constructed "as in all other cases"
1895 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1897 if (BGP_DEBUG(as4
, AS4
))
1899 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1901 ignore_as4_path
= 1;
1903 /* "New_aggregator shall be taken as aggregator"
1905 attr
->aggregator_as
= as4_aggregator
;
1906 attr
->aggregator_addr
.s_addr
=
1907 as4_aggregator_addr
->s_addr
;
1910 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1911 * That is bogus - but reading the conditions
1912 * we have to handle AS4_AGGREGATOR as if it were
1913 * AGGREGATOR in that case
1915 if (BGP_DEBUG(as4
, AS4
))
1917 "[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",
1919 attr
->aggregator_as
= as4_aggregator
;
1920 /* sweep it under the carpet and simulate a "good"
1922 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1926 /* need to reconcile NEW_AS_PATH and AS_PATH */
1927 if (!ignore_as4_path
1928 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1929 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1931 return BGP_ATTR_PARSE_ERROR
;
1933 aspath_unintern(&attr
->aspath
);
1934 attr
->aspath
= aspath_intern(newpath
);
1936 return BGP_ATTR_PARSE_PROCEED
;
1939 /* Community attribute. */
1940 static bgp_attr_parse_ret_t
1941 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1943 struct peer
*const peer
= args
->peer
;
1944 struct attr
*const attr
= args
->attr
;
1945 const bgp_size_t length
= args
->length
;
1948 attr
->community
= NULL
;
1949 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1954 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1956 /* XXX: fix community_parse to use stream API and remove this */
1957 stream_forward_getp(peer
->curr
, length
);
1959 /* The Community attribute SHALL be considered malformed if its
1960 * length is not a non-zero multiple of 4.
1962 if (!attr
->community
)
1963 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1966 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1968 return BGP_ATTR_PARSE_PROCEED
;
1971 /* Originator ID attribute. */
1972 static bgp_attr_parse_ret_t
1973 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1975 struct peer
*const peer
= args
->peer
;
1976 struct attr
*const attr
= args
->attr
;
1977 const bgp_size_t length
= args
->length
;
1979 /* if received from an internal neighbor, it SHALL be considered
1980 * malformed if its length is not equal to 4. If malformed, the
1981 * UPDATE message SHALL be handled using the approach of "treat-as-
1985 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1988 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1992 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1994 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1996 return BGP_ATTR_PARSE_PROCEED
;
1999 /* Cluster list attribute. */
2000 static bgp_attr_parse_ret_t
2001 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2003 struct peer
*const peer
= args
->peer
;
2004 struct attr
*const attr
= args
->attr
;
2005 const bgp_size_t length
= args
->length
;
2007 /* if received from an internal neighbor, it SHALL be considered
2008 * malformed if its length is not a non-zero multiple of 4. If
2009 * malformed, the UPDATE message SHALL be handled using the approach
2010 * of "treat-as-withdraw".
2012 if (length
== 0 || length
% 4) {
2013 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2015 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2019 bgp_attr_set_cluster(
2020 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2023 /* XXX: Fix cluster_parse to use stream API and then remove this */
2024 stream_forward_getp(peer
->curr
, length
);
2026 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2028 return BGP_ATTR_PARSE_PROCEED
;
2031 /* Multiprotocol reachability information parse. */
2032 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2033 struct bgp_nlri
*mp_update
)
2037 iana_safi_t pkt_safi
;
2039 bgp_size_t nlri_len
;
2042 struct peer
*const peer
= args
->peer
;
2043 struct attr
*const attr
= args
->attr
;
2044 const bgp_size_t length
= args
->length
;
2046 /* Set end of packet. */
2047 s
= BGP_INPUT(peer
);
2048 start
= stream_get_getp(s
);
2050 /* safe to read statically sized header? */
2051 #define BGP_MP_REACH_MIN_SIZE 5
2052 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2053 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2054 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2055 __func__
, peer
->host
, (unsigned long)length
);
2056 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2059 /* Load AFI, SAFI. */
2060 pkt_afi
= stream_getw(s
);
2061 pkt_safi
= stream_getc(s
);
2063 /* Convert AFI, SAFI to internal values, check. */
2064 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2065 /* Log if AFI or SAFI is unrecognized. This is not an error
2067 * the attribute is otherwise malformed.
2069 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2071 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2072 peer
->host
, iana_afi2str(pkt_afi
),
2073 iana_safi2str(pkt_safi
));
2074 return BGP_ATTR_PARSE_ERROR
;
2077 /* Get nexthop length. */
2078 attr
->mp_nexthop_len
= stream_getc(s
);
2080 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2082 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2083 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2084 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2087 /* Nexthop length check. */
2088 switch (attr
->mp_nexthop_len
) {
2090 if (safi
!= SAFI_FLOWSPEC
) {
2091 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2092 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2093 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2096 case BGP_ATTR_NHLEN_VPNV4
:
2097 stream_getl(s
); /* RD high */
2098 stream_getl(s
); /* RD low */
2100 * NOTE: intentional fall through
2101 * - for consistency in rx processing
2103 * The following comment is to signal GCC this intention
2104 * and suppress the warning
2107 case BGP_ATTR_NHLEN_IPV4
:
2108 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2109 /* Probably needed for RFC 2283 */
2110 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2111 memcpy(&attr
->nexthop
.s_addr
,
2112 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2114 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2115 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2116 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2117 stream_getl(s
); /* RD high */
2118 stream_getl(s
); /* RD low */
2120 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2121 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2122 if (!peer
->nexthop
.ifp
) {
2123 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2125 return BGP_ATTR_PARSE_WITHDRAW
;
2127 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2130 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2131 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2132 if (attr
->mp_nexthop_len
2133 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2134 stream_getl(s
); /* RD high */
2135 stream_getl(s
); /* RD low */
2137 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2138 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2139 if (!peer
->nexthop
.ifp
) {
2140 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",
2142 return BGP_ATTR_PARSE_WITHDRAW
;
2144 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2146 if (attr
->mp_nexthop_len
2147 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2148 stream_getl(s
); /* RD high */
2149 stream_getl(s
); /* RD low */
2151 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2152 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2153 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2155 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2156 peer
->host
, &attr
->mp_nexthop_global
,
2157 &attr
->mp_nexthop_local
);
2159 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2161 if (!peer
->nexthop
.ifp
) {
2162 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2164 return BGP_ATTR_PARSE_WITHDRAW
;
2166 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2169 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2170 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2171 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2175 zlog_info("%s: %s sent SNPA which couldn't be read",
2176 __func__
, peer
->host
);
2177 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2182 if ((val
= stream_getc(s
)))
2184 EC_BGP_DEFUNCT_SNPA_LEN
,
2185 "%s sent non-zero value, %u, for defunct SNPA-length field",
2189 /* must have nrli_len, what is left of the attribute */
2190 nlri_len
= LEN_LEFT
;
2191 if (nlri_len
> STREAM_READABLE(s
)) {
2192 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2193 __func__
, peer
->host
);
2194 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2198 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2199 __func__
, peer
->host
);
2201 mp_update
->afi
= afi
;
2202 mp_update
->safi
= safi
;
2203 return BGP_ATTR_PARSE_EOR
;
2206 mp_update
->afi
= afi
;
2207 mp_update
->safi
= safi
;
2208 mp_update
->nlri
= stream_pnt(s
);
2209 mp_update
->length
= nlri_len
;
2211 stream_forward_getp(s
, nlri_len
);
2213 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2215 return BGP_ATTR_PARSE_PROCEED
;
2219 /* Multiprotocol unreachable parse */
2220 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2221 struct bgp_nlri
*mp_withdraw
)
2226 iana_safi_t pkt_safi
;
2228 uint16_t withdraw_len
;
2229 struct peer
*const peer
= args
->peer
;
2230 struct attr
*const attr
= args
->attr
;
2231 const bgp_size_t length
= args
->length
;
2235 #define BGP_MP_UNREACH_MIN_SIZE 3
2236 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2237 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2239 pkt_afi
= stream_getw(s
);
2240 pkt_safi
= stream_getc(s
);
2242 /* Convert AFI, SAFI to internal values, check. */
2243 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2244 /* Log if AFI or SAFI is unrecognized. This is not an error
2246 * the attribute is otherwise malformed.
2248 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2250 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2251 peer
->host
, iana_afi2str(pkt_afi
),
2252 iana_safi2str(pkt_safi
));
2253 return BGP_ATTR_PARSE_ERROR
;
2256 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2258 mp_withdraw
->afi
= afi
;
2259 mp_withdraw
->safi
= safi
;
2260 mp_withdraw
->nlri
= stream_pnt(s
);
2261 mp_withdraw
->length
= withdraw_len
;
2263 stream_forward_getp(s
, withdraw_len
);
2265 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2267 return BGP_ATTR_PARSE_PROCEED
;
2270 /* Large Community attribute. */
2271 static bgp_attr_parse_ret_t
2272 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2274 struct peer
*const peer
= args
->peer
;
2275 struct attr
*const attr
= args
->attr
;
2276 const bgp_size_t length
= args
->length
;
2279 * Large community follows new attribute format.
2282 attr
->lcommunity
= NULL
;
2283 /* Empty extcomm doesn't seem to be invalid per se */
2284 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2288 attr
->lcommunity
= lcommunity_parse(stream_pnt(peer
->curr
), length
);
2289 /* XXX: fix ecommunity_parse to use stream API */
2290 stream_forward_getp(peer
->curr
, length
);
2292 if (!attr
->lcommunity
)
2293 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2296 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2298 return BGP_ATTR_PARSE_PROCEED
;
2301 /* Extended Community attribute. */
2302 static bgp_attr_parse_ret_t
2303 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2305 struct peer
*const peer
= args
->peer
;
2306 struct attr
*const attr
= args
->attr
;
2307 const bgp_size_t length
= args
->length
;
2312 attr
->ecommunity
= NULL
;
2313 /* Empty extcomm doesn't seem to be invalid per se */
2314 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2318 attr
->ecommunity
= ecommunity_parse(
2319 stream_pnt(peer
->curr
), length
,
2320 CHECK_FLAG(peer
->flags
,
2321 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2322 /* XXX: fix ecommunity_parse to use stream API */
2323 stream_forward_getp(peer
->curr
, length
);
2325 /* The Extended Community attribute SHALL be considered malformed if
2326 * its length is not a non-zero multiple of 8.
2328 if (!attr
->ecommunity
)
2329 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2332 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2334 /* Extract DF election preference and mobility sequence number */
2335 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2337 /* Extract MAC mobility sequence number, if any. */
2338 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2339 attr
->sticky
= sticky
;
2341 /* Check if this is a Gateway MAC-IP advertisement */
2342 attr
->default_gw
= bgp_attr_default_gw(attr
);
2344 /* Handle scenario where router flag ecommunity is not
2345 * set but default gw ext community is present.
2346 * Use default gateway, set and propogate R-bit.
2348 if (attr
->default_gw
)
2349 attr
->router_flag
= 1;
2351 /* Check EVPN Neighbor advertisement flags, R-bit */
2352 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2354 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2356 /* Extract the Rmac, if any */
2357 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2358 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2359 && bgp_mac_exist(&attr
->rmac
))
2360 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2364 /* Get the tunnel type from encap extended community */
2365 bgp_attr_extcom_tunnel_type(attr
,
2366 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2368 /* Extract link bandwidth, if any. */
2369 (void)ecommunity_linkbw_present(attr
->ecommunity
, &attr
->link_bw
);
2371 return BGP_ATTR_PARSE_PROCEED
;
2374 /* IPv6 Extended Community attribute. */
2375 static bgp_attr_parse_ret_t
2376 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2378 struct peer
*const peer
= args
->peer
;
2379 struct attr
*const attr
= args
->attr
;
2380 const bgp_size_t length
= args
->length
;
2381 struct ecommunity
*ipv6_ecomm
= NULL
;
2384 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2385 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2389 ipv6_ecomm
= ecommunity_parse_ipv6(
2390 stream_pnt(peer
->curr
), length
,
2391 CHECK_FLAG(peer
->flags
,
2392 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2393 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2395 /* XXX: fix ecommunity_parse to use stream API */
2396 stream_forward_getp(peer
->curr
, length
);
2399 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2402 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
);
2404 return BGP_ATTR_PARSE_PROCEED
;
2407 /* Parse Tunnel Encap attribute in an UPDATE */
2408 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2409 bgp_size_t length
, /* IN: attr's length field */
2410 struct attr
*attr
, /* IN: caller already allocated */
2411 uint8_t flag
, /* IN: attr's flags field */
2415 uint16_t tunneltype
= 0;
2417 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2419 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2420 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2422 "Tunnel Encap attribute flag isn't optional and transitive %d",
2424 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2425 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2430 if (BGP_ATTR_ENCAP
== type
) {
2431 /* read outer TLV type and length */
2432 uint16_t tlv_length
;
2436 "Tunnel Encap attribute not long enough to contain outer T,L");
2437 bgp_notify_send_with_data(
2438 peer
, BGP_NOTIFY_UPDATE_ERR
,
2439 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2442 tunneltype
= stream_getw(BGP_INPUT(peer
));
2443 tlv_length
= stream_getw(BGP_INPUT(peer
));
2446 if (tlv_length
!= length
) {
2447 zlog_info("%s: tlv_length(%d) != length(%d)",
2448 __func__
, tlv_length
, length
);
2452 while (length
>= 4) {
2453 uint16_t subtype
= 0;
2454 uint16_t sublength
= 0;
2455 struct bgp_attr_encap_subtlv
*tlv
;
2457 if (BGP_ATTR_ENCAP
== type
) {
2458 subtype
= stream_getc(BGP_INPUT(peer
));
2459 sublength
= stream_getc(BGP_INPUT(peer
));
2461 #ifdef ENABLE_BGP_VNC
2463 subtype
= stream_getw(BGP_INPUT(peer
));
2464 sublength
= stream_getw(BGP_INPUT(peer
));
2469 if (sublength
> length
) {
2471 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2473 bgp_notify_send_with_data(
2474 peer
, BGP_NOTIFY_UPDATE_ERR
,
2475 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2479 /* alloc and copy sub-tlv */
2480 /* TBD make sure these are freed when attributes are released */
2481 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2482 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2483 tlv
->type
= subtype
;
2484 tlv
->length
= sublength
;
2485 stream_get(tlv
->value
, peer
->curr
, sublength
);
2486 length
-= sublength
;
2488 /* attach tlv to encap chain */
2489 if (BGP_ATTR_ENCAP
== type
) {
2490 struct bgp_attr_encap_subtlv
*stlv_last
;
2491 for (stlv_last
= attr
->encap_subtlvs
;
2492 stlv_last
&& stlv_last
->next
;
2493 stlv_last
= stlv_last
->next
)
2496 stlv_last
->next
= tlv
;
2498 attr
->encap_subtlvs
= tlv
;
2500 #ifdef ENABLE_BGP_VNC
2502 struct bgp_attr_encap_subtlv
*stlv_last
;
2503 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2504 bgp_attr_get_vnc_subtlvs(attr
);
2506 for (stlv_last
= vnc_subtlvs
;
2507 stlv_last
&& stlv_last
->next
;
2508 stlv_last
= stlv_last
->next
)
2511 stlv_last
->next
= tlv
;
2513 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2518 if (BGP_ATTR_ENCAP
== type
) {
2519 attr
->encap_tunneltype
= tunneltype
;
2523 /* spurious leftover data */
2525 "Tunnel Encap attribute length is bad: %d leftover octets",
2527 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2528 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2537 * Read an individual SID value returning how much data we have read
2538 * Returns 0 if there was an error that needs to be passed up the stack
2540 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2541 struct bgp_attr_parser_args
*args
)
2543 struct peer
*const peer
= args
->peer
;
2544 struct attr
*const attr
= args
->attr
;
2545 uint32_t label_index
;
2546 struct in6_addr ipv6_sid
;
2548 uint32_t srgb_range
;
2550 uint8_t sid_type
, sid_flags
;
2551 uint16_t endpoint_behavior
;
2554 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2555 if (STREAM_READABLE(peer
->curr
) < length
2556 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2557 flog_err(EC_BGP_ATTR_LEN
,
2558 "Prefix SID label index length is %hu instead of %u",
2559 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2560 return bgp_attr_malformed(args
,
2561 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2565 /* Ignore flags and reserved */
2566 stream_getc(peer
->curr
);
2567 stream_getw(peer
->curr
);
2569 /* Fetch the label index and see if it is valid. */
2570 label_index
= stream_getl(peer
->curr
);
2571 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2572 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2575 /* Store label index; subsequently, we'll check on
2577 attr
->label_index
= label_index
;
2580 /* Placeholder code for the IPv6 SID type */
2581 else if (type
== BGP_PREFIX_SID_IPV6
) {
2582 if (STREAM_READABLE(peer
->curr
) < length
2583 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2584 flog_err(EC_BGP_ATTR_LEN
,
2585 "Prefix SID IPv6 length is %hu instead of %u",
2586 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2587 return bgp_attr_malformed(args
,
2588 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2592 /* Ignore reserved */
2593 stream_getc(peer
->curr
);
2594 stream_getw(peer
->curr
);
2596 stream_get(&ipv6_sid
, peer
->curr
, 16);
2599 /* Placeholder code for the Originator SRGB type */
2600 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2602 * ietf-idr-bgp-prefix-sid-05:
2603 * Length is the total length of the value portion of the
2604 * TLV: 2 + multiple of 6.
2606 * peer->curr stream readp should be at the beginning of the 16
2607 * bit flag field at this point in the code.
2611 * Check that the TLV length field is sane: at least 2 bytes of
2612 * flag, and at least 1 SRGB (these are 6 bytes each)
2614 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2617 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2619 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2620 return bgp_attr_malformed(
2621 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2626 * Check that we actually have at least as much data as
2627 * specified by the length field
2629 if (STREAM_READABLE(peer
->curr
) < length
) {
2630 flog_err(EC_BGP_ATTR_LEN
,
2631 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2632 length
, STREAM_READABLE(peer
->curr
));
2633 return bgp_attr_malformed(
2634 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2639 * Check that the portion of the TLV containing the sequence of
2640 * SRGBs corresponds to a multiple of the SRGB size; to get
2641 * that length, we skip the 16 bit flags field
2643 stream_getw(peer
->curr
);
2645 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2648 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2649 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2650 return bgp_attr_malformed(
2651 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2655 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2657 for (int i
= 0; i
< srgb_count
; i
++) {
2658 stream_get(&srgb_base
, peer
->curr
, 3);
2659 stream_get(&srgb_range
, peer
->curr
, 3);
2663 /* Placeholder code for the VPN-SID Service type */
2664 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2665 if (STREAM_READABLE(peer
->curr
) < length
2666 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2667 flog_err(EC_BGP_ATTR_LEN
,
2668 "Prefix SID VPN SID length is %hu instead of %u",
2669 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2670 return bgp_attr_malformed(args
,
2671 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2675 /* Parse VPN-SID Sub-TLV */
2676 stream_getc(peer
->curr
); /* reserved */
2677 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2678 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2679 stream_get(&ipv6_sid
, peer
->curr
,
2680 sizeof(ipv6_sid
)); /* sid_value */
2682 /* Log VPN-SID Sub-TLV */
2683 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2684 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2686 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2687 __func__
, buf
, sid_type
, sid_flags
);
2690 /* Configure from Info */
2691 if (attr
->srv6_vpn
) {
2692 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2693 "Prefix SID SRv6 VPN field repeated");
2694 return bgp_attr_malformed(
2695 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2697 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2698 sizeof(struct bgp_attr_srv6_vpn
));
2699 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2700 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2701 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2704 /* Placeholder code for the SRv6 L3 Service type */
2705 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2706 if (STREAM_READABLE(peer
->curr
) < length
2707 || length
!= BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
) {
2708 flog_err(EC_BGP_ATTR_LEN
,
2709 "Prefix SID SRv6 L3-Service length is %hu instead of %u",
2710 length
, BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH
);
2711 return bgp_attr_malformed(args
,
2712 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2716 /* Parse L3-SERVICE Sub-TLV */
2717 stream_getc(peer
->curr
); /* reserved */
2718 stream_get(&ipv6_sid
, peer
->curr
,
2719 sizeof(ipv6_sid
)); /* sid_value */
2720 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2721 endpoint_behavior
= stream_getw(peer
->curr
); /* endpoint */
2722 stream_getc(peer
->curr
); /* reserved */
2724 /* Log L3-SERVICE Sub-TLV */
2725 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2726 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2728 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2729 __func__
, buf
, sid_flags
, endpoint_behavior
);
2732 /* Configure from Info */
2733 if (attr
->srv6_l3vpn
) {
2734 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2735 "Prefix SID SRv6 L3VPN field repeated");
2736 return bgp_attr_malformed(
2737 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2739 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2740 sizeof(struct bgp_attr_srv6_l3vpn
));
2741 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2742 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2743 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2744 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2747 /* Placeholder code for Unsupported TLV */
2750 if (STREAM_READABLE(peer
->curr
) < length
) {
2753 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2754 length
, STREAM_READABLE(peer
->curr
));
2755 return bgp_attr_malformed(
2756 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2760 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2762 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2765 stream_forward_getp(peer
->curr
, length
);
2768 return BGP_ATTR_PARSE_PROCEED
;
2771 /* Prefix SID attribute
2772 * draft-ietf-idr-bgp-prefix-sid-05
2774 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2776 struct peer
*const peer
= args
->peer
;
2777 struct attr
*const attr
= args
->attr
;
2778 bgp_attr_parse_ret_t ret
;
2780 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2784 size_t headersz
= sizeof(type
) + sizeof(length
);
2785 size_t psid_parsed_length
= 0;
2787 while (STREAM_READABLE(peer
->curr
) > 0
2788 && psid_parsed_length
< args
->length
) {
2790 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2793 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2794 headersz
, STREAM_READABLE(peer
->curr
));
2795 return bgp_attr_malformed(
2796 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2800 type
= stream_getc(peer
->curr
);
2801 length
= stream_getw(peer
->curr
);
2803 if (STREAM_READABLE(peer
->curr
) < length
) {
2806 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2807 length
, STREAM_READABLE(peer
->curr
));
2808 return bgp_attr_malformed(args
,
2809 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2813 ret
= bgp_attr_psid_sub(type
, length
, args
);
2815 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2818 psid_parsed_length
+= length
+ headersz
;
2820 if (psid_parsed_length
> args
->length
) {
2823 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2824 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2825 return bgp_attr_malformed(
2826 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2831 return BGP_ATTR_PARSE_PROCEED
;
2834 /* PMSI tunnel attribute (RFC 6514)
2835 * Basic validation checks done here.
2837 static bgp_attr_parse_ret_t
2838 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2840 struct peer
*const peer
= args
->peer
;
2841 struct attr
*const attr
= args
->attr
;
2842 const bgp_size_t length
= args
->length
;
2844 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2846 /* Verify that the receiver is expecting "ingress replication" as we
2847 * can only support that.
2849 if (length
< attr_parse_len
) {
2850 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2852 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2855 stream_getc(peer
->curr
); /* Flags */
2856 tnl_type
= stream_getc(peer
->curr
);
2857 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2858 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2859 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2860 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2863 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2865 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2866 "Bad PMSI tunnel attribute length %d for IR",
2868 return bgp_attr_malformed(
2869 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2874 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2875 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
2876 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2878 /* Forward read pointer of input stream. */
2879 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2881 return BGP_ATTR_PARSE_PROCEED
;
2884 /* BGP unknown attribute treatment. */
2885 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2887 bgp_size_t total
= args
->total
;
2888 struct transit
*transit
;
2889 struct peer
*const peer
= args
->peer
;
2890 struct attr
*const attr
= args
->attr
;
2891 uint8_t *const startp
= args
->startp
;
2892 const uint8_t type
= args
->type
;
2893 const uint8_t flag
= args
->flags
;
2894 const bgp_size_t length
= args
->length
;
2896 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2898 "%s Unknown attribute is received (type %d, length %d)",
2899 peer
->host
, type
, length
);
2901 /* Forward read pointer of input stream. */
2902 stream_forward_getp(peer
->curr
, length
);
2904 /* If any of the mandatory well-known attributes are not recognized,
2905 then the Error Subcode is set to Unrecognized Well-known
2906 Attribute. The Data field contains the unrecognized attribute
2907 (type, length and value). */
2908 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2909 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2913 /* Unrecognized non-transitive optional attributes must be quietly
2914 ignored and not passed along to other BGP peers. */
2915 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2916 return BGP_ATTR_PARSE_PROCEED
;
2918 /* If a path with recognized transitive optional attribute is
2919 accepted and passed along to other BGP peers and the Partial bit
2920 in the Attribute Flags octet is set to 1 by some previous AS, it
2921 is not set back to 0 by the current AS. */
2922 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2924 /* Store transitive attribute to the end of attr->transit. */
2925 transit
= bgp_attr_get_transit(attr
);
2927 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2929 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2930 transit
->length
+ total
);
2932 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2933 transit
->length
+= total
;
2934 bgp_attr_set_transit(attr
, transit
);
2936 return BGP_ATTR_PARSE_PROCEED
;
2939 /* Well-known attribute check. */
2940 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2944 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2946 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2947 return BGP_ATTR_PARSE_PROCEED
;
2949 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2950 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2951 are present, it should. Check for any other attribute being present
2954 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2955 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2956 return BGP_ATTR_PARSE_PROCEED
;
2958 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2959 type
= BGP_ATTR_ORIGIN
;
2961 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2962 type
= BGP_ATTR_AS_PATH
;
2964 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2966 * NLRI is empty. We can't easily check NLRI empty here though.
2968 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2969 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2970 type
= BGP_ATTR_NEXT_HOP
;
2972 if (peer
->sort
== BGP_PEER_IBGP
2973 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2974 type
= BGP_ATTR_LOCAL_PREF
;
2976 /* If any of the well-known mandatory attributes are not present
2977 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
2980 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2981 "%s Missing well-known attribute %s.", peer
->host
,
2982 lookup_msg(attr_str
, type
, NULL
));
2983 return BGP_ATTR_PARSE_WITHDRAW
;
2985 return BGP_ATTR_PARSE_PROCEED
;
2988 /* Read attribute of update packet. This function is called from
2989 bgp_update_receive() in bgp_packet.c. */
2990 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2991 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2992 struct bgp_nlri
*mp_withdraw
)
2994 bgp_attr_parse_ret_t ret
;
2998 uint8_t *startp
, *endp
;
3000 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3001 /* we need the as4_path only until we have synthesized the as_path with
3003 /* same goes for as4_aggregator */
3004 struct aspath
*as4_path
= NULL
;
3005 as_t as4_aggregator
= 0;
3006 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3007 struct transit
*transit
;
3009 /* Initialize bitmap. */
3010 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3012 /* End pointer of BGP attribute. */
3013 endp
= BGP_INPUT_PNT(peer
) + size
;
3015 /* Get attributes to the end of attribute length. */
3016 while (BGP_INPUT_PNT(peer
) < endp
) {
3017 /* Check remaining length check.*/
3018 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3019 /* XXX warning: long int format, int arg (arg 5) */
3021 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3022 "%s: error BGP attribute length %lu is smaller than min len",
3024 (unsigned long)(endp
3025 - stream_pnt(BGP_INPUT(peer
))));
3027 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3028 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3029 ret
= BGP_ATTR_PARSE_ERROR
;
3033 /* Fetch attribute flag and type. */
3034 startp
= BGP_INPUT_PNT(peer
);
3035 /* "The lower-order four bits of the Attribute Flags octet are
3036 unused. They MUST be zero when sent and MUST be ignored when
3038 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3039 type
= stream_getc(BGP_INPUT(peer
));
3041 /* Check whether Extended-Length applies and is in bounds */
3042 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3043 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3045 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3046 "%s: Extended length set, but just %lu bytes of attr header",
3048 (unsigned long)(endp
3049 - stream_pnt(BGP_INPUT(peer
))));
3051 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3052 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3053 ret
= BGP_ATTR_PARSE_ERROR
;
3057 /* Check extended attribue length bit. */
3058 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3059 length
= stream_getw(BGP_INPUT(peer
));
3061 length
= stream_getc(BGP_INPUT(peer
));
3063 /* If any attribute appears more than once in the UPDATE
3064 message, then the Error Subcode is set to Malformed Attribute
3067 if (CHECK_BITMAP(seen
, type
)) {
3069 EC_BGP_ATTRIBUTE_REPEATED
,
3070 "%s: error BGP attribute type %d appears twice in a message",
3073 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3074 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3075 ret
= BGP_ATTR_PARSE_ERROR
;
3079 /* Set type to bitmap to check duplicate attribute. `type' is
3080 unsigned char so it never overflow bitmap range. */
3082 SET_BITMAP(seen
, type
);
3084 /* Overflow check. */
3085 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3087 if (attr_endp
> endp
) {
3089 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3090 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3091 peer
->host
, type
, length
, size
, attr_endp
,
3095 * If any recognized attribute has an Attribute
3096 * Length that conflicts with the expected length
3097 * (based on the attribute type code), then the
3098 * Error Subcode MUST be set to Attribute Length
3099 * Error. The Data field MUST contain the erroneous
3100 * attribute (type, length, and value).
3102 * We do not currently have a good way to determine the
3103 * length of the attribute independent of the length
3104 * received in the message. Instead we send the
3105 * minimum between the amount of data we have and the
3106 * amount specified by the attribute length field.
3108 * Instead of directly passing in the packet buffer and
3109 * offset we use the stream_get* functions to read into
3110 * a stack buffer, since they perform bounds checking
3111 * and we are working with untrusted data.
3113 unsigned char ndata
[peer
->max_packet_size
];
3114 memset(ndata
, 0x00, sizeof(ndata
));
3116 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3117 /* Rewind to end of flag field */
3118 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3120 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3122 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3124 size_t atl
= attr_endp
- startp
;
3125 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3126 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3128 bgp_notify_send_with_data(
3129 peer
, BGP_NOTIFY_UPDATE_ERR
,
3130 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3133 ret
= BGP_ATTR_PARSE_ERROR
;
3137 struct bgp_attr_parser_args attr_args
= {
3144 .total
= attr_endp
- startp
,
3148 /* If any recognized attribute has Attribute Flags that conflict
3149 with the Attribute Type Code, then the Error Subcode is set
3151 Attribute Flags Error. The Data field contains the erroneous
3152 attribute (type, length and value). */
3153 if (bgp_attr_flag_invalid(&attr_args
)) {
3154 ret
= bgp_attr_malformed(
3155 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3157 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3162 /* OK check attribute and store it's value. */
3164 case BGP_ATTR_ORIGIN
:
3165 ret
= bgp_attr_origin(&attr_args
);
3167 case BGP_ATTR_AS_PATH
:
3168 ret
= bgp_attr_aspath(&attr_args
);
3170 case BGP_ATTR_AS4_PATH
:
3171 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3173 case BGP_ATTR_NEXT_HOP
:
3174 ret
= bgp_attr_nexthop(&attr_args
);
3176 case BGP_ATTR_MULTI_EXIT_DISC
:
3177 ret
= bgp_attr_med(&attr_args
);
3179 case BGP_ATTR_LOCAL_PREF
:
3180 ret
= bgp_attr_local_pref(&attr_args
);
3182 case BGP_ATTR_ATOMIC_AGGREGATE
:
3183 ret
= bgp_attr_atomic(&attr_args
);
3185 case BGP_ATTR_AGGREGATOR
:
3186 ret
= bgp_attr_aggregator(&attr_args
);
3188 case BGP_ATTR_AS4_AGGREGATOR
:
3189 ret
= bgp_attr_as4_aggregator(&attr_args
,
3191 &as4_aggregator_addr
);
3193 case BGP_ATTR_COMMUNITIES
:
3194 ret
= bgp_attr_community(&attr_args
);
3196 case BGP_ATTR_LARGE_COMMUNITIES
:
3197 ret
= bgp_attr_large_community(&attr_args
);
3199 case BGP_ATTR_ORIGINATOR_ID
:
3200 ret
= bgp_attr_originator_id(&attr_args
);
3202 case BGP_ATTR_CLUSTER_LIST
:
3203 ret
= bgp_attr_cluster_list(&attr_args
);
3205 case BGP_ATTR_MP_REACH_NLRI
:
3206 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3208 case BGP_ATTR_MP_UNREACH_NLRI
:
3209 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3211 case BGP_ATTR_EXT_COMMUNITIES
:
3212 ret
= bgp_attr_ext_communities(&attr_args
);
3214 #ifdef ENABLE_BGP_VNC_ATTR
3217 case BGP_ATTR_ENCAP
:
3218 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3221 case BGP_ATTR_PREFIX_SID
:
3222 ret
= bgp_attr_prefix_sid(&attr_args
);
3224 case BGP_ATTR_PMSI_TUNNEL
:
3225 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3227 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3228 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3231 ret
= bgp_attr_unknown(&attr_args
);
3235 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3236 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3237 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3238 ret
= BGP_ATTR_PARSE_ERROR
;
3242 if (ret
== BGP_ATTR_PARSE_EOR
) {
3246 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3247 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3248 "%s: Attribute %s, parse error", peer
->host
,
3249 lookup_msg(attr_str
, type
, NULL
));
3252 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3254 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3255 "%s: Attribute %s, parse error - treating as withdrawal",
3256 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3260 /* Check the fetched length. */
3261 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3262 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3263 "%s: BGP attribute %s, fetch error",
3264 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3265 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3266 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3267 ret
= BGP_ATTR_PARSE_ERROR
;
3273 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3274 * About Prefix-SID path attribute,
3275 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3276 * may only appear in a BGP Prefix-SID attribute attached to
3277 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3278 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3280 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3281 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3283 /* Check final read pointer is same as end pointer. */
3284 if (BGP_INPUT_PNT(peer
) != endp
) {
3285 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3286 "%s: BGP attribute %s, length mismatch", peer
->host
,
3287 lookup_msg(attr_str
, type
, NULL
));
3288 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3289 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3291 ret
= BGP_ATTR_PARSE_ERROR
;
3296 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3297 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3298 * This is implemented below and will result in a NOTIFICATION. If the
3299 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3300 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3301 * message SHOULD NOT be sent. This is implemented elsewhere.
3303 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3304 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3305 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3306 * speaker that receives the message SHOULD ignore this attribute.
3308 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3309 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3310 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3311 ret
= BGP_ATTR_PARSE_ERROR
;
3316 /* Check all mandatory well-known attributes are present */
3317 ret
= bgp_attr_check(peer
, attr
);
3322 * At this place we can see whether we got AS4_PATH and/or
3323 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3324 * We can not do this before we've read all attributes because
3325 * the as4 handling does not say whether AS4_PATH has to be sent
3326 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3327 * in relationship to AGGREGATOR.
3328 * So, to be defensive, we are not relying on any order and read
3329 * all attributes first, including these 32bit ones, and now,
3330 * afterwards, we look what and if something is to be done for as4.
3332 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3335 /* actually... this doesn't ever return failure currently, but
3336 * better safe than sorry */
3337 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3338 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3339 &as4_aggregator_addr
)) {
3340 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3341 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3342 ret
= BGP_ATTR_PARSE_ERROR
;
3347 * Finally do the checks on the aspath we did not do yet
3348 * because we waited for a potentially synthesized aspath.
3350 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3351 ret
= bgp_attr_aspath_check(peer
, attr
);
3352 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3356 ret
= BGP_ATTR_PARSE_PROCEED
;
3360 * At this stage, we have done all fiddling with as4, and the
3361 * resulting info is in attr->aggregator resp. attr->aspath so
3362 * we can chuck as4_aggregator and as4_path alltogether in order
3367 * unintern - it is in the hash
3368 * The flag that we got this is still there, but that
3369 * does not do any trouble
3371 aspath_unintern(&as4_path
);
3374 transit
= bgp_attr_get_transit(attr
);
3375 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3376 /* Finally intern unknown attribute. */
3378 bgp_attr_set_transit(attr
, transit_intern(transit
));
3379 if (attr
->encap_subtlvs
)
3380 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3382 #ifdef ENABLE_BGP_VNC
3383 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3384 bgp_attr_get_vnc_subtlvs(attr
);
3387 bgp_attr_set_vnc_subtlvs(
3389 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3393 transit_free(transit
);
3394 bgp_attr_set_transit(attr
, NULL
);
3397 bgp_attr_flush_encap(attr
);
3401 transit
= bgp_attr_get_transit(attr
);
3403 assert(transit
->refcnt
> 0);
3404 if (attr
->encap_subtlvs
)
3405 assert(attr
->encap_subtlvs
->refcnt
> 0);
3406 #ifdef ENABLE_BGP_VNC
3407 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3408 bgp_attr_get_vnc_subtlvs(attr
);
3411 assert(vnc_subtlvs
->refcnt
> 0);
3418 * Extract the tunnel type from extended community
3420 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3421 bgp_encap_types
*tunnel_type
)
3423 struct ecommunity
*ecom
;
3429 ecom
= attr
->ecommunity
;
3430 if (!ecom
|| !ecom
->size
)
3433 for (i
= 0; i
< ecom
->size
; i
++) {
3435 uint8_t type
, sub_type
;
3437 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3440 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3441 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3443 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3450 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3451 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3456 iana_safi_t pkt_safi
;
3459 /* Set extended bit always to encode the attribute length as 2 bytes */
3460 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3461 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3462 sizep
= stream_get_endp(s
);
3463 stream_putw(s
, 0); /* Marker: Attribute length. */
3466 /* Convert AFI, SAFI to values for packet. */
3467 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3469 stream_putw(s
, pkt_afi
); /* AFI */
3470 stream_putc(s
, pkt_safi
); /* SAFI */
3474 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3475 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3476 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3477 else if (safi
== SAFI_FLOWSPEC
)
3480 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3483 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3488 case SAFI_MULTICAST
:
3489 case SAFI_LABELED_UNICAST
:
3491 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3495 stream_putl(s
, 0); /* RD = 0, per RFC */
3497 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3502 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3505 if (attr
->mp_nexthop_len
== 0)
3506 stream_putc(s
, 0); /* no nexthop for flowspec */
3508 stream_putc(s
, attr
->mp_nexthop_len
);
3509 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3518 case SAFI_MULTICAST
:
3519 case SAFI_LABELED_UNICAST
:
3521 if (attr
->mp_nexthop_len
3522 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3524 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3525 stream_put(s
, &attr
->mp_nexthop_global
,
3527 stream_put(s
, &attr
->mp_nexthop_local
,
3530 stream_putc(s
, IPV6_MAX_BYTELEN
);
3531 stream_put(s
, &attr
->mp_nexthop_global
,
3535 case SAFI_MPLS_VPN
: {
3536 if (attr
->mp_nexthop_len
3537 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3539 stream_putl(s
, 0); /* RD = 0, per RFC */
3541 stream_put(s
, &attr
->mp_nexthop_global
,
3543 } else if (attr
->mp_nexthop_len
3544 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3546 stream_putl(s
, 0); /* RD = 0, per RFC */
3548 stream_put(s
, &attr
->mp_nexthop_global
,
3550 stream_putl(s
, 0); /* RD = 0, per RFC */
3552 stream_put(s
, &attr
->mp_nexthop_local
,
3557 stream_putc(s
, IPV6_MAX_BYTELEN
);
3558 stream_put(s
, &attr
->mp_nexthop_global
,
3562 stream_putc(s
, 0); /* no nexthop for flowspec */
3568 if (safi
!= SAFI_FLOWSPEC
)
3570 EC_BGP_ATTR_NH_SEND_LEN
,
3571 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3572 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3581 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3582 const struct prefix
*p
,
3583 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3584 uint32_t num_labels
, int addpath_encode
,
3585 uint32_t addpath_tx_id
, struct attr
*attr
)
3587 if (safi
== SAFI_MPLS_VPN
) {
3589 stream_putl(s
, addpath_tx_id
);
3590 /* Label, RD, Prefix write. */
3591 stream_putc(s
, p
->prefixlen
+ 88);
3592 stream_put(s
, label
, BGP_LABEL_BYTES
);
3593 stream_put(s
, prd
->val
, 8);
3594 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3595 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3596 /* EVPN prefix - contents depend on type */
3597 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3598 addpath_encode
, addpath_tx_id
);
3599 } else if (safi
== SAFI_LABELED_UNICAST
) {
3600 /* Prefix write with label. */
3601 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3603 } else if (safi
== SAFI_FLOWSPEC
) {
3604 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3605 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3606 p
->u
.prefix_flowspec
.prefixlen
);
3608 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3611 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3612 const struct prefix
*p
)
3614 int size
= PSIZE(p
->prefixlen
);
3615 if (safi
== SAFI_MPLS_VPN
)
3617 else if (safi
== SAFI_LABELED_UNICAST
)
3618 size
+= BGP_LABEL_BYTES
;
3619 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3620 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3626 * Encodes the tunnel encapsulation attribute,
3627 * and with ENABLE_BGP_VNC the VNC attribute which uses
3628 * almost the same TLV format
3630 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3631 struct stream
*s
, struct attr
*attr
,
3634 unsigned int attrlenfield
= 0;
3635 unsigned int attrhdrlen
= 0;
3636 struct bgp_attr_encap_subtlv
*subtlvs
;
3637 struct bgp_attr_encap_subtlv
*st
;
3638 const char *attrname
;
3640 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3641 && (!attr
->encap_tunneltype
3642 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3646 case BGP_ATTR_ENCAP
:
3647 attrname
= "Tunnel Encap";
3648 subtlvs
= attr
->encap_subtlvs
;
3649 if (subtlvs
== NULL
) /* nothing to do */
3652 * The tunnel encap attr has an "outer" tlv.
3654 * L = total length of subtlvs,
3655 * V = concatenated subtlvs.
3657 attrlenfield
= 2 + 2; /* T + L */
3658 attrhdrlen
= 1 + 1; /* subTLV T + L */
3661 #ifdef ENABLE_BGP_VNC_ATTR
3664 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3665 if (subtlvs
== NULL
) /* nothing to do */
3667 attrlenfield
= 0; /* no outer T + L */
3668 attrhdrlen
= 2 + 2; /* subTLV T + L */
3676 /* compute attr length */
3677 for (st
= subtlvs
; st
; st
= st
->next
) {
3678 attrlenfield
+= (attrhdrlen
+ st
->length
);
3681 if (attrlenfield
> 0xffff) {
3682 zlog_info("%s attribute is too long (length=%d), can't send it",
3683 attrname
, attrlenfield
);
3687 if (attrlenfield
> 0xff) {
3688 /* 2-octet length field */
3690 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3691 | BGP_ATTR_FLAG_EXTLEN
);
3692 stream_putc(s
, attrtype
);
3693 stream_putw(s
, attrlenfield
& 0xffff);
3695 /* 1-octet length field */
3696 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3697 stream_putc(s
, attrtype
);
3698 stream_putc(s
, attrlenfield
& 0xff);
3701 if (attrtype
== BGP_ATTR_ENCAP
) {
3702 /* write outer T+L */
3703 stream_putw(s
, attr
->encap_tunneltype
);
3704 stream_putw(s
, attrlenfield
- 4);
3707 /* write each sub-tlv */
3708 for (st
= subtlvs
; st
; st
= st
->next
) {
3709 if (attrtype
== BGP_ATTR_ENCAP
) {
3710 stream_putc(s
, st
->type
);
3711 stream_putc(s
, st
->length
);
3712 #ifdef ENABLE_BGP_VNC
3714 stream_putw(s
, st
->type
);
3715 stream_putw(s
, st
->length
);
3718 stream_put(s
, st
->value
, st
->length
);
3722 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3724 /* Set MP attribute length. Don't count the (2) bytes used to encode
3726 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3729 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3731 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3732 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3733 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3734 PEER_FLAG_REMOVE_PRIVATE_AS
)
3735 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3736 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3737 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3738 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3739 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3740 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3745 /* Make attribute packet. */
3746 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3747 struct stream
*s
, struct attr
*attr
,
3748 struct bpacket_attr_vec_arr
*vecarr
,
3749 struct prefix
*p
, afi_t afi
, safi_t safi
,
3750 struct peer
*from
, struct prefix_rd
*prd
,
3751 mpls_label_t
*label
, uint32_t num_labels
,
3752 int addpath_encode
, uint32_t addpath_tx_id
)
3755 size_t aspath_sizep
;
3756 struct aspath
*aspath
;
3757 int send_as4_path
= 0;
3758 int send_as4_aggregator
= 0;
3759 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
3760 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
3765 /* Remember current pointer. */
3766 cp
= stream_get_endp(s
);
3769 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3770 && !peer_cap_enhe(peer
, afi
, safi
))) {
3771 size_t mpattrlen_pos
= 0;
3773 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3775 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3776 num_labels
, addpath_encode
,
3777 addpath_tx_id
, attr
);
3778 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3781 /* Origin attribute. */
3782 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3783 stream_putc(s
, BGP_ATTR_ORIGIN
);
3785 stream_putc(s
, attr
->origin
);
3787 /* AS path attribute. */
3789 /* If remote-peer is EBGP */
3790 if (peer
->sort
== BGP_PEER_EBGP
3791 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3792 PEER_FLAG_AS_PATH_UNCHANGED
)
3793 || attr
->aspath
->segments
== NULL
)
3794 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3795 PEER_FLAG_RSERVER_CLIENT
))) {
3796 aspath
= aspath_dup(attr
->aspath
);
3798 /* Even though we may not be configured for confederations we
3800 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3801 aspath
= aspath_delete_confed_seq(aspath
);
3803 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3804 /* Stuff our path CONFED_ID on the front */
3805 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3807 if (peer
->change_local_as
) {
3808 /* If replace-as is specified, we only use the
3809 change_local_as when
3810 advertising routes. */
3811 if (!CHECK_FLAG(peer
->flags
,
3812 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3813 if (bgp_append_local_as(peer
, afi
,
3815 aspath
= aspath_add_seq(
3816 aspath
, peer
->local_as
);
3817 aspath
= aspath_add_seq(aspath
,
3818 peer
->change_local_as
);
3820 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3823 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3824 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3826 aspath
= aspath_dup(attr
->aspath
);
3827 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3829 aspath
= attr
->aspath
;
3831 /* If peer is not AS4 capable, then:
3832 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3833 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3835 * types are in it (i.e. exclude them if they are there)
3836 * AND do this only if there is at least one asnum > 65535 in the
3838 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3840 * all ASnums > 65535 to BGP_AS_TRANS
3843 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3844 stream_putc(s
, BGP_ATTR_AS_PATH
);
3845 aspath_sizep
= stream_get_endp(s
);
3847 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3849 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3852 if (!use32bit
&& aspath_has_as4(aspath
))
3854 1; /* we'll do this later, at the correct place */
3856 /* Nexthop attribute. */
3857 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3858 && !peer_cap_enhe(peer
, afi
, safi
)) {
3859 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3861 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3862 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3863 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3864 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3867 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3868 } else if (peer_cap_enhe(from
, afi
, safi
)
3869 || (nh_afi
== AFI_IP6
)) {
3871 * Likely this is the case when an IPv4 prefix was
3872 * received with Extended Next-hop capability in this
3873 * or another vrf and is now being advertised to
3874 * non-ENHE peers. Since peer_cap_enhe only checks
3875 * peers in this vrf, also check the nh_afi to catch
3876 * the case where the originator was in another vrf.
3877 * Setting the mandatory (ipv4) next-hop attribute here
3878 * to enable implicit next-hop self with correct A-F
3879 * (ipv4 address family).
3881 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3882 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3883 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3886 stream_put_ipv4(s
, 0);
3890 /* MED attribute. */
3891 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3892 || bgp
->maxmed_active
) {
3893 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3894 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3896 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3900 /* Local preference. */
3901 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3902 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3903 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3905 stream_putl(s
, attr
->local_pref
);
3908 /* Atomic aggregate. */
3909 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3910 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3911 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3916 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3917 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3918 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3919 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3922 /* AS4 capable peer */
3924 stream_putl(s
, attr
->aggregator_as
);
3926 /* 2-byte AS peer */
3929 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3931 if (attr
->aggregator_as
> UINT16_MAX
) {
3932 stream_putw(s
, BGP_AS_TRANS
);
3934 /* we have to send AS4_AGGREGATOR, too.
3935 * we'll do that later in order to send
3936 * attributes in ascending
3939 send_as4_aggregator
= 1;
3941 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3943 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3946 /* Community attribute. */
3947 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3948 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3949 if (attr
->community
->size
* 4 > 255) {
3951 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3952 | BGP_ATTR_FLAG_EXTLEN
);
3953 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3954 stream_putw(s
, attr
->community
->size
* 4);
3957 BGP_ATTR_FLAG_OPTIONAL
3958 | BGP_ATTR_FLAG_TRANS
);
3959 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3960 stream_putc(s
, attr
->community
->size
* 4);
3962 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3966 * Large Community attribute.
3968 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3969 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3970 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3971 if (lcom_length(attr
->lcommunity
) > 255) {
3973 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3974 | BGP_ATTR_FLAG_EXTLEN
);
3975 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3976 stream_putw(s
, lcom_length(attr
->lcommunity
));
3979 BGP_ATTR_FLAG_OPTIONAL
3980 | BGP_ATTR_FLAG_TRANS
);
3981 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3982 stream_putc(s
, lcom_length(attr
->lcommunity
));
3984 stream_put(s
, attr
->lcommunity
->val
,
3985 lcom_length(attr
->lcommunity
));
3988 /* Route Reflector. */
3989 if (peer
->sort
== BGP_PEER_IBGP
&& from
3990 && from
->sort
== BGP_PEER_IBGP
) {
3991 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
3993 /* Originator ID. */
3994 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3995 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3998 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3999 stream_put_in_addr(s
, &attr
->originator_id
);
4001 stream_put_in_addr(s
, &from
->remote_id
);
4004 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4005 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4008 stream_putc(s
, cluster
->length
+ 4);
4009 /* If this peer configuration's parent BGP has
4011 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4012 stream_put_in_addr(s
, &bgp
->cluster_id
);
4014 stream_put_in_addr(s
, &bgp
->router_id
);
4015 stream_put(s
, cluster
->list
, cluster
->length
);
4018 /* If this peer configuration's parent BGP has
4020 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4021 stream_put_in_addr(s
, &bgp
->cluster_id
);
4023 stream_put_in_addr(s
, &bgp
->router_id
);
4027 /* Extended Communities attribute. */
4028 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4029 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4030 if (peer
->sort
== BGP_PEER_IBGP
4031 || peer
->sort
== BGP_PEER_CONFED
) {
4032 if (attr
->ecommunity
->size
* 8 > 255) {
4034 BGP_ATTR_FLAG_OPTIONAL
4035 | BGP_ATTR_FLAG_TRANS
4036 | BGP_ATTR_FLAG_EXTLEN
);
4037 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4038 stream_putw(s
, attr
->ecommunity
->size
* 8);
4041 BGP_ATTR_FLAG_OPTIONAL
4042 | BGP_ATTR_FLAG_TRANS
);
4043 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4044 stream_putc(s
, attr
->ecommunity
->size
* 8);
4046 stream_put(s
, attr
->ecommunity
->val
,
4047 attr
->ecommunity
->size
* 8);
4051 int ecom_tr_size
= 0;
4054 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
4055 pnt
= attr
->ecommunity
->val
+ (i
* 8);
4058 if (CHECK_FLAG(tbit
,
4059 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4066 if (ecom_tr_size
* 8 > 255) {
4069 BGP_ATTR_FLAG_OPTIONAL
4070 | BGP_ATTR_FLAG_TRANS
4071 | BGP_ATTR_FLAG_EXTLEN
);
4073 BGP_ATTR_EXT_COMMUNITIES
);
4074 stream_putw(s
, ecom_tr_size
* 8);
4078 BGP_ATTR_FLAG_OPTIONAL
4079 | BGP_ATTR_FLAG_TRANS
);
4081 BGP_ATTR_EXT_COMMUNITIES
);
4082 stream_putc(s
, ecom_tr_size
* 8);
4085 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
4086 pnt
= attr
->ecommunity
->val
+ (i
* 8);
4091 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4094 stream_put(s
, pnt
, 8);
4100 /* Label index attribute. */
4101 if (safi
== SAFI_LABELED_UNICAST
) {
4102 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4103 uint32_t label_index
;
4105 label_index
= attr
->label_index
;
4107 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4109 BGP_ATTR_FLAG_OPTIONAL
4110 | BGP_ATTR_FLAG_TRANS
);
4111 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4113 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4115 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4116 stream_putc(s
, 0); // reserved
4117 stream_putw(s
, 0); // flags
4118 stream_putl(s
, label_index
);
4123 /* SRv6 Service Information Attribute. */
4124 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4125 if (attr
->srv6_l3vpn
) {
4126 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4127 | BGP_ATTR_FLAG_TRANS
);
4128 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4129 stream_putc(s
, 24); /* tlv len */
4130 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4131 stream_putw(s
, 21); /* sub-tlv len */
4132 stream_putc(s
, 0); /* reserved */
4133 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4134 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4135 stream_putc(s
, 0); /* sid_flags */
4136 stream_putw(s
, 0xffff); /* endpoint */
4137 stream_putc(s
, 0); /* reserved */
4138 } else if (attr
->srv6_vpn
) {
4139 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4140 | BGP_ATTR_FLAG_TRANS
);
4141 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4142 stream_putc(s
, 22); /* tlv len */
4143 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4144 stream_putw(s
, 0x13); /* tlv len */
4145 stream_putc(s
, 0x00); /* reserved */
4146 stream_putc(s
, 0x01); /* sid_type */
4147 stream_putc(s
, 0x00); /* sif_flags */
4148 stream_put(s
, &attr
->srv6_vpn
->sid
,
4149 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4153 if (send_as4_path
) {
4154 /* If the peer is NOT As4 capable, AND */
4155 /* there are ASnums > 65535 in path THEN
4156 * give out AS4_PATH */
4158 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4160 * Hm, I wonder... confederation things *should* only be at
4161 * the beginning of an aspath, right? Then we should use
4162 * aspath_delete_confed_seq for this, because it is already
4164 * Folks, talk to me: what is reasonable here!?
4166 aspath
= aspath_delete_confed_seq(aspath
);
4169 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4170 | BGP_ATTR_FLAG_EXTLEN
);
4171 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4172 aspath_sizep
= stream_get_endp(s
);
4174 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4177 if (aspath
!= attr
->aspath
)
4178 aspath_free(aspath
);
4180 if (send_as4_aggregator
) {
4181 /* send AS4_AGGREGATOR, at this place */
4182 /* this section of code moved here in order to ensure the
4184 * *ascending* order of attributes
4186 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4187 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4189 stream_putl(s
, attr
->aggregator_as
);
4190 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4193 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4194 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4195 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4196 /* Tunnel Encap attribute */
4197 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4199 #ifdef ENABLE_BGP_VNC_ATTR
4201 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4206 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4207 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4208 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4209 stream_putc(s
, 9); // Length
4210 stream_putc(s
, 0); // Flags
4211 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4212 stream_put(s
, &(attr
->label
),
4213 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4214 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4215 // Unicast tunnel endpoint IP address
4218 /* Unknown transit attribute. */
4219 struct transit
*transit
= bgp_attr_get_transit(attr
);
4222 stream_put(s
, transit
->val
, transit
->length
);
4224 /* Return total size of attribute. */
4225 return stream_get_endp(s
) - cp
;
4228 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4230 unsigned long attrlen_pnt
;
4232 iana_safi_t pkt_safi
;
4234 /* Set extended bit always to encode the attribute length as 2 bytes */
4235 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4236 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4238 attrlen_pnt
= stream_get_endp(s
);
4239 stream_putw(s
, 0); /* Length of this attribute. */
4241 /* Convert AFI, SAFI to values for packet. */
4242 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4244 stream_putw(s
, pkt_afi
);
4245 stream_putc(s
, pkt_safi
);
4250 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4251 afi_t afi
, safi_t safi
,
4252 const struct prefix_rd
*prd
,
4253 mpls_label_t
*label
, uint32_t num_labels
,
4254 int addpath_encode
, uint32_t addpath_tx_id
,
4257 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4259 if (safi
== SAFI_LABELED_UNICAST
) {
4260 label
= (mpls_label_t
*)wlabel
;
4264 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4265 addpath_encode
, addpath_tx_id
, attr
);
4268 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4270 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4273 /* Initialization of attribute. */
4274 void bgp_attr_init(void)
4287 void bgp_attr_finish(void)
4292 ecommunity_finish();
4293 lcommunity_finish();
4300 /* Make attribute packet. */
4301 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4302 const struct prefix
*prefix
)
4307 struct aspath
*aspath
;
4308 int addpath_encode
= 0;
4309 uint32_t addpath_tx_id
= 0;
4311 /* Remember current pointer. */
4312 cp
= stream_get_endp(s
);
4314 /* Place holder of length. */
4317 /* Origin attribute. */
4318 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4319 stream_putc(s
, BGP_ATTR_ORIGIN
);
4321 stream_putc(s
, attr
->origin
);
4323 aspath
= attr
->aspath
;
4325 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4326 stream_putc(s
, BGP_ATTR_AS_PATH
);
4327 aspath_lenp
= stream_get_endp(s
);
4330 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4332 /* Nexthop attribute. */
4333 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4334 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4335 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4336 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4338 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4341 /* MED attribute. */
4342 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4343 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4344 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4346 stream_putl(s
, attr
->med
);
4349 /* Local preference. */
4350 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4351 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4352 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4354 stream_putl(s
, attr
->local_pref
);
4357 /* Atomic aggregate. */
4358 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4359 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4360 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4365 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4366 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4367 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4369 stream_putl(s
, attr
->aggregator_as
);
4370 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4373 /* Community attribute. */
4374 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4375 if (attr
->community
->size
* 4 > 255) {
4377 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4378 | BGP_ATTR_FLAG_EXTLEN
);
4379 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4380 stream_putw(s
, attr
->community
->size
* 4);
4383 BGP_ATTR_FLAG_OPTIONAL
4384 | BGP_ATTR_FLAG_TRANS
);
4385 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4386 stream_putc(s
, attr
->community
->size
* 4);
4388 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4391 /* Large Community attribute. */
4392 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4393 if (lcom_length(attr
->lcommunity
) > 255) {
4395 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4396 | BGP_ATTR_FLAG_EXTLEN
);
4397 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4398 stream_putw(s
, lcom_length(attr
->lcommunity
));
4401 BGP_ATTR_FLAG_OPTIONAL
4402 | BGP_ATTR_FLAG_TRANS
);
4403 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4404 stream_putc(s
, lcom_length(attr
->lcommunity
));
4407 stream_put(s
, attr
->lcommunity
->val
,
4408 lcom_length(attr
->lcommunity
));
4411 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4412 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4413 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4414 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4417 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4418 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4419 sizep
= stream_get_endp(s
);
4422 stream_putc(s
, 0); /* Marker: Attribute length. */
4423 stream_putw(s
, AFI_IP6
); /* AFI */
4424 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4427 stream_putc(s
, attr
->mp_nexthop_len
);
4428 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4429 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4430 stream_put(s
, &attr
->mp_nexthop_local
,
4437 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
4440 /* Set MP attribute length. */
4441 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4445 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4446 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4448 BGP_ATTR_FLAG_OPTIONAL
4449 | BGP_ATTR_FLAG_TRANS
);
4450 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4452 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4453 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4454 stream_putc(s
, 0); // reserved
4455 stream_putw(s
, 0); // flags
4456 stream_putl(s
, attr
->label_index
);
4460 /* Return total size of attribute. */
4461 len
= stream_get_endp(s
) - cp
- 2;
4462 stream_putw_at(s
, cp
, len
);