1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_aspath.h"
41 #include "bgpd/bgp_community.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_errors.h"
44 #include "bgpd/bgp_label.h"
45 #include "bgpd/bgp_packet.h"
46 #include "bgpd/bgp_ecommunity.h"
47 #include "bgpd/bgp_lcommunity.h"
48 #include "bgpd/bgp_updgrp.h"
49 #include "bgpd/bgp_encap_types.h"
51 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
52 #include "bgp_encap_types.h"
53 #include "bgp_vnc_types.h"
56 #include "bgp_flowspec_private.h"
59 /* Attribute strings for logging. */
60 static const struct message attr_str
[] = {
61 {BGP_ATTR_ORIGIN
, "ORIGIN"},
62 {BGP_ATTR_AS_PATH
, "AS_PATH"},
63 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
64 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
65 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
66 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
67 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
68 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
69 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
70 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
71 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
72 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
73 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
74 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
75 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
76 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
77 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
78 {BGP_ATTR_ENCAP
, "ENCAP"},
79 #ifdef ENABLE_BGP_VNC_ATTR
80 {BGP_ATTR_VNC
, "VNC"},
82 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
83 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
84 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
87 static const struct message attr_flag_str
[] = {
88 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
89 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
90 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
91 /* bgp_attr_flags_diagnose() relies on this bit being last in
93 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
96 static struct hash
*cluster_hash
;
98 static void *cluster_hash_alloc(void *p
)
100 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
101 struct cluster_list
*cluster
;
103 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
104 cluster
->length
= val
->length
;
106 if (cluster
->length
) {
107 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
108 memcpy(cluster
->list
, val
->list
, val
->length
);
110 cluster
->list
= NULL
;
117 /* Cluster list related functions. */
118 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
120 struct cluster_list tmp
= {};
121 struct cluster_list
*cluster
;
124 tmp
.list
= length
== 0 ? NULL
: pnt
;
126 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
131 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
135 for (i
= 0; i
< cluster
->length
/ 4; i
++)
136 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
141 static unsigned int cluster_hash_key_make(const void *p
)
143 const struct cluster_list
*cluster
= p
;
145 return jhash(cluster
->list
, cluster
->length
, 0);
148 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
150 const struct cluster_list
*cluster1
= p1
;
151 const struct cluster_list
*cluster2
= p2
;
153 if (cluster1
->list
== cluster2
->list
)
156 if (!cluster1
->list
|| !cluster2
->list
)
159 if (cluster1
->length
!= cluster2
->length
)
162 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
165 static void cluster_free(struct cluster_list
*cluster
)
167 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
168 XFREE(MTYPE_CLUSTER
, cluster
);
171 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
173 struct cluster_list
*find
;
175 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
181 static void cluster_unintern(struct cluster_list
**cluster
)
183 if ((*cluster
)->refcnt
)
184 (*cluster
)->refcnt
--;
186 if ((*cluster
)->refcnt
== 0) {
187 void *p
= hash_release(cluster_hash
, *cluster
);
188 assert(p
== *cluster
);
189 cluster_free(*cluster
);
194 static void cluster_init(void)
196 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
200 static void cluster_finish(void)
202 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
203 hash_free(cluster_hash
);
207 static struct hash
*encap_hash
= NULL
;
208 #ifdef ENABLE_BGP_VNC
209 static struct hash
*vnc_hash
= NULL
;
211 static struct hash
*srv6_l3vpn_hash
;
212 static struct hash
*srv6_vpn_hash
;
214 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
216 struct bgp_attr_encap_subtlv
*new;
217 struct bgp_attr_encap_subtlv
*tail
;
218 struct bgp_attr_encap_subtlv
*p
;
220 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
221 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
223 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
226 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
229 memcpy(tail
, p
, size
);
236 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
238 struct bgp_attr_encap_subtlv
*next
;
242 XFREE(MTYPE_ENCAP_TLV
, p
);
247 void bgp_attr_flush_encap(struct attr
*attr
)
252 if (attr
->encap_subtlvs
) {
253 encap_free(attr
->encap_subtlvs
);
254 attr
->encap_subtlvs
= NULL
;
256 #ifdef ENABLE_BGP_VNC
257 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
258 bgp_attr_get_vnc_subtlvs(attr
);
261 encap_free(vnc_subtlvs
);
262 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
268 * Compare encap sub-tlv chains
273 * This algorithm could be made faster if needed
275 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
276 const struct bgp_attr_encap_subtlv
*h2
)
278 const struct bgp_attr_encap_subtlv
*p
;
279 const struct bgp_attr_encap_subtlv
*q
;
283 if (h1
== NULL
|| h2
== NULL
)
286 for (p
= h1
; p
; p
= p
->next
) {
287 for (q
= h2
; q
; q
= q
->next
) {
288 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
289 && !memcmp(p
->value
, q
->value
, p
->length
)) {
298 for (p
= h2
; p
; p
= p
->next
) {
299 for (q
= h1
; q
; q
= q
->next
) {
300 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
301 && !memcmp(p
->value
, q
->value
, p
->length
)) {
313 static void *encap_hash_alloc(void *p
)
315 /* Encap structure is already allocated. */
321 #ifdef ENABLE_BGP_VNC
326 static struct bgp_attr_encap_subtlv
*
327 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
329 struct bgp_attr_encap_subtlv
*find
;
330 struct hash
*hash
= encap_hash
;
331 #ifdef ENABLE_BGP_VNC
332 if (type
== VNC_SUBTLV_TYPE
)
336 find
= hash_get(hash
, encap
, encap_hash_alloc
);
344 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
345 encap_subtlv_type type
)
347 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
351 if (encap
->refcnt
== 0) {
352 struct hash
*hash
= encap_hash
;
353 #ifdef ENABLE_BGP_VNC
354 if (type
== VNC_SUBTLV_TYPE
)
357 hash_release(hash
, encap
);
363 static unsigned int encap_hash_key_make(const void *p
)
365 const struct bgp_attr_encap_subtlv
*encap
= p
;
367 return jhash(encap
->value
, encap
->length
, 0);
370 static bool encap_hash_cmp(const void *p1
, const void *p2
)
372 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
373 (const struct bgp_attr_encap_subtlv
*)p2
);
376 static void encap_init(void)
378 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
380 #ifdef ENABLE_BGP_VNC
381 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
386 static void encap_finish(void)
388 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
389 hash_free(encap_hash
);
391 #ifdef ENABLE_BGP_VNC
392 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
398 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
407 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
408 bgp_attr_get_evpn_overlay(a2
));
411 /* Unknown transit attribute. */
412 static struct hash
*transit_hash
;
414 static void transit_free(struct transit
*transit
)
416 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
417 XFREE(MTYPE_TRANSIT
, transit
);
420 static void *transit_hash_alloc(void *p
)
422 /* Transit structure is already allocated. */
426 static struct transit
*transit_intern(struct transit
*transit
)
428 struct transit
*find
;
430 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
432 transit_free(transit
);
438 static void transit_unintern(struct transit
**transit
)
440 if ((*transit
)->refcnt
)
441 (*transit
)->refcnt
--;
443 if ((*transit
)->refcnt
== 0) {
444 hash_release(transit_hash
, *transit
);
445 transit_free(*transit
);
450 static void *srv6_l3vpn_hash_alloc(void *p
)
455 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
457 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
460 static struct bgp_attr_srv6_l3vpn
*
461 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
463 struct bgp_attr_srv6_l3vpn
*find
;
465 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
467 srv6_l3vpn_free(l3vpn
);
472 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
474 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
479 if (l3vpn
->refcnt
== 0) {
480 hash_release(srv6_l3vpn_hash
, l3vpn
);
481 srv6_l3vpn_free(l3vpn
);
486 static void *srv6_vpn_hash_alloc(void *p
)
491 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
493 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
496 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
498 struct bgp_attr_srv6_vpn
*find
;
500 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
507 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
509 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
514 if (vpn
->refcnt
== 0) {
515 hash_release(srv6_vpn_hash
, vpn
);
521 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
523 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
526 key
= jhash(&l3vpn
->sid
, 16, key
);
527 key
= jhash_1word(l3vpn
->sid_flags
, key
);
528 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
529 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
530 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
531 key
= jhash_1word(l3vpn
->func_len
, key
);
532 key
= jhash_1word(l3vpn
->arg_len
, key
);
533 key
= jhash_1word(l3vpn
->transposition_len
, key
);
534 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
538 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
540 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
541 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
543 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
544 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
545 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
546 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
547 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
548 && l3vpn1
->func_len
== l3vpn2
->func_len
549 && l3vpn1
->arg_len
== l3vpn2
->arg_len
550 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
551 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
554 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
555 const struct bgp_attr_srv6_l3vpn
*h2
)
559 else if (h1
== NULL
|| h2
== NULL
)
562 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
565 static unsigned int srv6_vpn_hash_key_make(const void *p
)
567 const struct bgp_attr_srv6_vpn
*vpn
= p
;
570 key
= jhash(&vpn
->sid
, 16, key
);
571 key
= jhash_1word(vpn
->sid_flags
, key
);
575 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
577 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
578 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
580 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
581 && vpn1
->sid_flags
== vpn2
->sid_flags
;
584 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
585 const struct bgp_attr_srv6_vpn
*h2
)
589 else if (h1
== NULL
|| h2
== NULL
)
592 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
595 static void srv6_init(void)
598 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
599 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
600 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
601 "BGP Prefix-SID SRv6-VPN-Service-TLV");
604 static void srv6_finish(void)
606 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
607 hash_free(srv6_l3vpn_hash
);
608 srv6_l3vpn_hash
= NULL
;
609 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
610 hash_free(srv6_vpn_hash
);
611 srv6_vpn_hash
= NULL
;
614 static unsigned int transit_hash_key_make(const void *p
)
616 const struct transit
*transit
= p
;
618 return jhash(transit
->val
, transit
->length
, 0);
621 static bool transit_hash_cmp(const void *p1
, const void *p2
)
623 const struct transit
*transit1
= p1
;
624 const struct transit
*transit2
= p2
;
626 return (transit1
->length
== transit2
->length
627 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
630 static void transit_init(void)
632 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
636 static void transit_finish(void)
638 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
639 hash_free(transit_hash
);
643 /* Attribute hash routines. */
644 static struct hash
*attrhash
;
646 unsigned long int attr_count(void)
648 return attrhash
->count
;
651 unsigned long int attr_unknown_count(void)
653 return transit_hash
->count
;
656 unsigned int attrhash_key_make(const void *p
)
658 const struct attr
*attr
= (struct attr
*)p
;
660 #define MIX(val) key = jhash_1word(val, key)
661 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
663 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
664 MIX3(attr
->local_pref
, attr
->aggregator_as
,
665 attr
->aggregator_addr
.s_addr
);
666 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
667 attr
->originator_id
.s_addr
);
668 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
671 MIX(aspath_key_make(attr
->aspath
));
673 MIX(community_hash_make(attr
->community
));
675 if (bgp_attr_get_lcommunity(attr
))
676 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
677 if (bgp_attr_get_ecommunity(attr
))
678 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
679 if (bgp_attr_get_ipv6_ecommunity(attr
))
680 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
681 if (bgp_attr_get_cluster(attr
))
682 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
683 if (bgp_attr_get_transit(attr
))
684 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
685 if (attr
->encap_subtlvs
)
686 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
687 if (attr
->srv6_l3vpn
)
688 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
690 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
691 #ifdef ENABLE_BGP_VNC
692 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
693 bgp_attr_get_vnc_subtlvs(attr
);
695 MIX(encap_hash_key_make(vnc_subtlvs
));
697 MIX(attr
->mp_nexthop_len
);
698 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
699 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
700 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
701 MIX(attr
->rmap_table_id
);
708 bool attrhash_cmp(const void *p1
, const void *p2
)
710 const struct attr
*attr1
= p1
;
711 const struct attr
*attr2
= p2
;
713 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
714 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
715 && attr1
->aspath
== attr2
->aspath
716 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
717 && attr1
->local_pref
== attr2
->local_pref
718 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
719 if (attr1
->aggregator_as
== attr2
->aggregator_as
720 && attr1
->aggregator_addr
.s_addr
721 == attr2
->aggregator_addr
.s_addr
722 && attr1
->weight
== attr2
->weight
723 && attr1
->tag
== attr2
->tag
724 && attr1
->label_index
== attr2
->label_index
725 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
726 && bgp_attr_get_ecommunity(attr1
)
727 == bgp_attr_get_ecommunity(attr2
)
728 && bgp_attr_get_ipv6_ecommunity(attr1
)
729 == bgp_attr_get_ipv6_ecommunity(attr2
)
730 && bgp_attr_get_lcommunity(attr1
)
731 == bgp_attr_get_lcommunity(attr2
)
732 && bgp_attr_get_cluster(attr1
)
733 == bgp_attr_get_cluster(attr2
)
734 && bgp_attr_get_transit(attr1
)
735 == bgp_attr_get_transit(attr2
)
736 && attr1
->rmap_table_id
== attr2
->rmap_table_id
737 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
738 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
739 #ifdef ENABLE_BGP_VNC
740 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
741 bgp_attr_get_vnc_subtlvs(attr2
))
743 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
744 &attr2
->mp_nexthop_global
)
745 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
746 &attr2
->mp_nexthop_local
)
747 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
748 &attr2
->mp_nexthop_global_in
)
749 && IPV4_ADDR_SAME(&attr1
->originator_id
,
750 &attr2
->originator_id
)
751 && overlay_index_same(attr1
, attr2
)
752 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
753 && attr1
->es_flags
== attr2
->es_flags
754 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
755 && attr1
->df_pref
== attr2
->df_pref
756 && attr1
->df_alg
== attr2
->df_alg
757 && attr1
->nh_ifindex
== attr2
->nh_ifindex
758 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
759 && attr1
->distance
== attr2
->distance
760 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
761 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
762 && attr1
->srte_color
== attr2
->srte_color
763 && attr1
->nh_type
== attr2
->nh_type
764 && attr1
->bh_type
== attr2
->bh_type
)
771 static void attrhash_init(void)
774 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
778 * special for hash_clean below
780 static void attr_vfree(void *attr
)
782 XFREE(MTYPE_ATTR
, attr
);
785 static void attrhash_finish(void)
787 hash_clean(attrhash
, attr_vfree
);
792 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
794 struct attr
*attr
= bucket
->data
;
795 char sid_str
[BUFSIZ
];
797 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
800 if (attr
->srv6_l3vpn
)
801 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
802 else if (attr
->srv6_vpn
)
803 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
806 "\tflags: %" PRIu64
" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
807 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
808 attr
->origin
, attr
->weight
, attr
->label
, sid_str
);
811 void attr_show_all(struct vty
*vty
)
813 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
814 void *))attr_show_all_iterator
,
818 static void *bgp_attr_hash_alloc(void *p
)
820 struct attr
*val
= (struct attr
*)p
;
823 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
825 if (val
->encap_subtlvs
) {
826 val
->encap_subtlvs
= NULL
;
828 #ifdef ENABLE_BGP_VNC
829 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
830 bgp_attr_get_vnc_subtlvs(val
);
833 bgp_attr_set_vnc_subtlvs(val
, NULL
);
840 /* Internet argument attribute. */
841 struct attr
*bgp_attr_intern(struct attr
*attr
)
844 struct ecommunity
*ecomm
= NULL
;
845 struct ecommunity
*ipv6_ecomm
= NULL
;
846 struct lcommunity
*lcomm
= NULL
;
848 /* Intern referenced strucutre. */
850 if (!attr
->aspath
->refcnt
)
851 attr
->aspath
= aspath_intern(attr
->aspath
);
853 attr
->aspath
->refcnt
++;
855 if (attr
->community
) {
856 if (!attr
->community
->refcnt
)
857 attr
->community
= community_intern(attr
->community
);
859 attr
->community
->refcnt
++;
862 ecomm
= bgp_attr_get_ecommunity(attr
);
865 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
870 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
872 if (!ipv6_ecomm
->refcnt
)
873 bgp_attr_set_ipv6_ecommunity(
874 attr
, ecommunity_intern(ipv6_ecomm
));
876 ipv6_ecomm
->refcnt
++;
879 lcomm
= bgp_attr_get_lcommunity(attr
);
882 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
887 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
890 if (!cluster
->refcnt
)
891 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
896 struct transit
*transit
= bgp_attr_get_transit(attr
);
899 if (!transit
->refcnt
)
900 bgp_attr_set_transit(attr
, transit_intern(transit
));
904 if (attr
->encap_subtlvs
) {
905 if (!attr
->encap_subtlvs
->refcnt
)
906 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
909 attr
->encap_subtlvs
->refcnt
++;
911 if (attr
->srv6_l3vpn
) {
912 if (!attr
->srv6_l3vpn
->refcnt
)
913 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
915 attr
->srv6_l3vpn
->refcnt
++;
917 if (attr
->srv6_vpn
) {
918 if (!attr
->srv6_vpn
->refcnt
)
919 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
921 attr
->srv6_vpn
->refcnt
++;
923 #ifdef ENABLE_BGP_VNC
924 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
925 bgp_attr_get_vnc_subtlvs(attr
);
928 if (!vnc_subtlvs
->refcnt
)
929 bgp_attr_set_vnc_subtlvs(
931 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
933 vnc_subtlvs
->refcnt
++;
937 /* At this point, attr only contains intern'd pointers. that means
938 * if we find it in attrhash, it has all the same pointers and we
939 * correctly updated the refcounts on these.
940 * If we don't find it, we need to allocate a one because in all
941 * cases this returns a new reference to a hashed attr, but the input
943 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
949 /* Make network statement's attribute. */
950 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
952 memset(attr
, 0, sizeof(struct attr
));
954 attr
->origin
= origin
;
955 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
956 attr
->aspath
= aspath_empty();
957 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
958 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
960 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
961 attr
->label
= MPLS_INVALID_LABEL
;
962 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
963 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
968 /* Create the attributes for an aggregate */
969 struct attr
*bgp_attr_aggregate_intern(
970 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
971 struct community
*community
, struct ecommunity
*ecommunity
,
972 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
973 uint8_t atomic_aggregate
, const struct prefix
*p
)
979 memset(&attr
, 0, sizeof(struct attr
));
981 /* Origin attribute. */
982 attr
.origin
= origin
;
983 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
985 /* AS path attribute. */
987 attr
.aspath
= aspath_intern(aspath
);
989 attr
.aspath
= aspath_empty();
990 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
992 /* Next hop attribute. */
993 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
996 uint32_t gshut
= COMMUNITY_GSHUT
;
998 /* If we are not shutting down ourselves and we are
999 * aggregating a route that contains the GSHUT community we
1000 * need to remove that community when creating the aggregate */
1001 if (!bgp_in_graceful_shutdown(bgp
)
1002 && community_include(community
, gshut
)) {
1003 community_del_val(community
, &gshut
);
1006 attr
.community
= community
;
1007 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1011 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1012 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1016 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1017 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1020 if (bgp_in_graceful_shutdown(bgp
))
1021 bgp_attr_add_gshut_community(&attr
);
1023 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1024 attr
.label
= MPLS_INVALID_LABEL
;
1025 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1026 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1027 if (!aggregate
->as_set
|| atomic_aggregate
)
1028 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1029 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1030 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1031 attr
.aggregator_as
= bgp
->confed_id
;
1033 attr
.aggregator_as
= bgp
->as
;
1034 attr
.aggregator_addr
= bgp
->router_id
;
1035 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1036 attr
.label
= MPLS_INVALID_LABEL
;
1038 /* Apply route-map */
1039 if (aggregate
->rmap
.name
) {
1040 struct attr attr_tmp
= attr
;
1041 struct bgp_path_info rmap_path
;
1043 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1044 rmap_path
.peer
= bgp
->peer_self
;
1045 rmap_path
.attr
= &attr_tmp
;
1047 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1049 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1051 bgp
->peer_self
->rmap_type
= 0;
1053 if (ret
== RMAP_DENYMATCH
) {
1054 /* Free uninterned attribute. */
1055 bgp_attr_flush(&attr_tmp
);
1057 /* Unintern original. */
1058 aspath_unintern(&attr
.aspath
);
1062 if (bgp_in_graceful_shutdown(bgp
))
1063 bgp_attr_add_gshut_community(&attr_tmp
);
1065 new = bgp_attr_intern(&attr_tmp
);
1068 if (bgp_in_graceful_shutdown(bgp
))
1069 bgp_attr_add_gshut_community(&attr
);
1071 new = bgp_attr_intern(&attr
);
1074 /* Always release the 'intern()'ed AS Path. */
1075 aspath_unintern(&attr
.aspath
);
1080 /* Unintern just the sub-components of the attr, but not the attr */
1081 void bgp_attr_unintern_sub(struct attr
*attr
)
1083 struct ecommunity
*ecomm
= NULL
;
1084 struct ecommunity
*ipv6_ecomm
= NULL
;
1085 struct cluster_list
*cluster
;
1086 struct lcommunity
*lcomm
= NULL
;
1088 /* aspath refcount shoud be decrement. */
1089 aspath_unintern(&attr
->aspath
);
1090 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1092 if (attr
->community
)
1093 community_unintern(&attr
->community
);
1094 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1096 ecomm
= bgp_attr_get_ecommunity(attr
);
1097 ecommunity_unintern(&ecomm
);
1098 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
1099 bgp_attr_set_ecommunity(attr
, NULL
);
1101 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1102 ecommunity_unintern(&ipv6_ecomm
);
1103 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
));
1104 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1106 lcomm
= bgp_attr_get_lcommunity(attr
);
1107 lcommunity_unintern(&lcomm
);
1108 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1109 bgp_attr_set_lcommunity(attr
, NULL
);
1111 cluster
= bgp_attr_get_cluster(attr
);
1113 cluster_unintern(&cluster
);
1114 bgp_attr_set_cluster(attr
, cluster
);
1116 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1118 struct transit
*transit
= bgp_attr_get_transit(attr
);
1121 transit_unintern(&transit
);
1122 bgp_attr_set_transit(attr
, transit
);
1125 if (attr
->encap_subtlvs
)
1126 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1128 #ifdef ENABLE_BGP_VNC
1129 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1130 bgp_attr_get_vnc_subtlvs(attr
);
1133 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1134 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1138 if (attr
->srv6_l3vpn
)
1139 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1142 srv6_vpn_unintern(&attr
->srv6_vpn
);
1145 /* Free bgp attribute and aspath. */
1146 void bgp_attr_unintern(struct attr
**pattr
)
1148 struct attr
*attr
= *pattr
;
1152 /* Decrement attribute reference. */
1157 /* If reference becomes zero then free attribute object. */
1158 if (attr
->refcnt
== 0) {
1159 ret
= hash_release(attrhash
, attr
);
1160 assert(ret
!= NULL
);
1161 XFREE(MTYPE_ATTR
, attr
);
1165 bgp_attr_unintern_sub(&tmp
);
1168 void bgp_attr_flush(struct attr
*attr
)
1170 struct ecommunity
*ecomm
;
1171 struct ecommunity
*ipv6_ecomm
;
1172 struct cluster_list
*cluster
;
1173 struct lcommunity
*lcomm
;
1175 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1176 aspath_free(attr
->aspath
);
1177 attr
->aspath
= NULL
;
1179 if (attr
->community
&& !attr
->community
->refcnt
)
1180 community_free(&attr
->community
);
1181 ecomm
= bgp_attr_get_ecommunity(attr
);
1182 if (ecomm
&& !ecomm
->refcnt
)
1183 ecommunity_free(&ecomm
);
1184 bgp_attr_set_ecommunity(attr
, NULL
);
1185 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1186 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1187 ecommunity_free(&ipv6_ecomm
);
1188 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1189 lcomm
= bgp_attr_get_lcommunity(attr
);
1190 if (lcomm
&& !lcomm
->refcnt
)
1191 lcommunity_free(&lcomm
);
1192 bgp_attr_set_lcommunity(attr
, NULL
);
1194 cluster
= bgp_attr_get_cluster(attr
);
1195 if (cluster
&& !cluster
->refcnt
) {
1196 cluster_free(cluster
);
1197 bgp_attr_set_cluster(attr
, NULL
);
1200 struct transit
*transit
= bgp_attr_get_transit(attr
);
1202 if (transit
&& !transit
->refcnt
) {
1203 transit_free(transit
);
1204 bgp_attr_set_transit(attr
, NULL
);
1206 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1207 encap_free(attr
->encap_subtlvs
);
1208 attr
->encap_subtlvs
= NULL
;
1210 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1211 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1212 attr
->srv6_l3vpn
= NULL
;
1214 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1215 srv6_vpn_free(attr
->srv6_vpn
);
1216 attr
->srv6_vpn
= NULL
;
1218 #ifdef ENABLE_BGP_VNC
1219 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1220 bgp_attr_get_vnc_subtlvs(attr
);
1222 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1223 encap_free(vnc_subtlvs
);
1224 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1229 /* Implement draft-scudder-idr-optional-transitive behaviour and
1230 * avoid resetting sessions for malformed attributes which are
1231 * are partial/optional and hence where the error likely was not
1232 * introduced by the sending neighbour.
1234 static bgp_attr_parse_ret_t
1235 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1238 struct peer
*const peer
= args
->peer
;
1239 struct attr
*const attr
= args
->attr
;
1240 const uint8_t flags
= args
->flags
;
1241 /* startp and length must be special-cased, as whether or not to
1242 * send the attribute data with the NOTIFY depends on the error,
1243 * the caller therefore signals this with the seperate length argument
1245 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1247 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1248 char attr_str
[BUFSIZ
] = {0};
1250 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1252 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1255 /* Only relax error handling for eBGP peers */
1256 if (peer
->sort
!= BGP_PEER_EBGP
) {
1257 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1258 notify_datap
, length
);
1259 return BGP_ATTR_PARSE_ERROR
;
1262 /* Adjust the stream getp to the end of the attribute, in case we can
1263 * still proceed but the caller hasn't read all the attribute.
1265 stream_set_getp(BGP_INPUT(peer
),
1266 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1269 switch (args
->type
) {
1270 /* where an attribute is relatively inconsequential, e.g. it does not
1271 * affect route selection, and can be safely ignored, then any such
1272 * attributes which are malformed should just be ignored and the route
1273 * processed as normal.
1275 case BGP_ATTR_AS4_AGGREGATOR
:
1276 case BGP_ATTR_AGGREGATOR
:
1277 case BGP_ATTR_ATOMIC_AGGREGATE
:
1278 return BGP_ATTR_PARSE_PROCEED
;
1280 /* Core attributes, particularly ones which may influence route
1281 * selection, should be treat-as-withdraw.
1283 case BGP_ATTR_ORIGIN
:
1284 case BGP_ATTR_AS_PATH
:
1285 case BGP_ATTR_NEXT_HOP
:
1286 case BGP_ATTR_MULTI_EXIT_DISC
:
1287 case BGP_ATTR_LOCAL_PREF
:
1288 case BGP_ATTR_COMMUNITIES
:
1289 case BGP_ATTR_EXT_COMMUNITIES
:
1290 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1291 case BGP_ATTR_LARGE_COMMUNITIES
:
1292 case BGP_ATTR_ORIGINATOR_ID
:
1293 case BGP_ATTR_CLUSTER_LIST
:
1294 return BGP_ATTR_PARSE_WITHDRAW
;
1295 case BGP_ATTR_MP_REACH_NLRI
:
1296 case BGP_ATTR_MP_UNREACH_NLRI
:
1297 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1298 notify_datap
, length
);
1299 return BGP_ATTR_PARSE_ERROR
;
1302 /* Partial optional attributes that are malformed should not cause
1303 * the whole session to be reset. Instead treat it as a withdrawal
1304 * of the routes, if possible.
1306 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1307 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1308 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1309 return BGP_ATTR_PARSE_WITHDRAW
;
1311 /* default to reset */
1312 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1315 /* Find out what is wrong with the path attribute flag bits and log the error.
1316 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1317 Extended Length. Checking O/T/P bits at once implies, that the attribute
1318 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1319 non-transitive" attribute. */
1321 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1322 uint8_t desired_flags
/* how RFC says it must be */
1325 uint8_t seen
= 0, i
;
1326 uint8_t real_flags
= args
->flags
;
1327 const uint8_t attr_code
= args
->type
;
1329 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1330 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1331 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1332 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1333 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1334 flog_err(EC_BGP_ATTR_FLAG
,
1335 "%s attribute must%s be flagged as \"%s\"",
1336 lookup_msg(attr_str
, attr_code
, NULL
),
1337 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1340 attr_flag_str
[i
].str
);
1345 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1346 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1347 real_flags
, desired_flags
);
1351 /* Required flags for attributes. EXTLEN will be masked off when testing,
1352 * as will PARTIAL for optional+transitive attributes.
1354 const uint8_t attr_flags_values
[] = {
1355 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1356 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1357 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1358 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1359 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1360 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1361 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1362 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1363 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1364 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1365 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1366 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1367 [BGP_ATTR_EXT_COMMUNITIES
] =
1368 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1369 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1370 [BGP_ATTR_AS4_AGGREGATOR
] =
1371 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1372 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1373 [BGP_ATTR_LARGE_COMMUNITIES
] =
1374 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1375 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1376 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1377 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1379 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1381 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1383 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1384 const uint8_t flags
= args
->flags
;
1385 const uint8_t attr_code
= args
->type
;
1387 /* there may be attributes we don't know about */
1388 if (attr_code
> attr_flags_values_max
)
1390 if (attr_flags_values
[attr_code
] == 0)
1393 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1397 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1398 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1401 "%s well-known attributes must have transitive flag set (%x)",
1402 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1406 /* "For well-known attributes and for optional non-transitive
1408 * the Partial bit MUST be set to 0."
1410 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1411 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1412 flog_err(EC_BGP_ATTR_FLAG
,
1413 "%s well-known attribute must NOT have the partial flag set (%x)",
1414 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1417 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1418 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1419 flog_err(EC_BGP_ATTR_FLAG
,
1420 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1421 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1426 /* Optional transitive attributes may go through speakers that don't
1427 * reocgnise them and set the Partial bit.
1429 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1430 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1431 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1433 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1436 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1440 /* Get origin attribute of the update message. */
1441 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1443 struct peer
*const peer
= args
->peer
;
1444 struct attr
*const attr
= args
->attr
;
1445 const bgp_size_t length
= args
->length
;
1447 /* If any recognized attribute has Attribute Length that conflicts
1448 with the expected length (based on the attribute type code), then
1449 the Error Subcode is set to Attribute Length Error. The Data
1450 field contains the erroneous attribute (type, length and
1453 flog_err(EC_BGP_ATTR_LEN
,
1454 "Origin attribute length is not one %d", length
);
1455 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1459 /* Fetch origin attribute. */
1460 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1462 /* If the ORIGIN attribute has an undefined value, then the Error
1463 Subcode is set to Invalid Origin Attribute. The Data field
1464 contains the unrecognized attribute (type, length and value). */
1465 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1466 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1467 flog_err(EC_BGP_ATTR_ORIGIN
,
1468 "Origin attribute value is invalid %d", attr
->origin
);
1469 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1473 /* Set oring attribute flag. */
1474 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1479 /* Parse AS path information. This function is wrapper of
1481 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1483 struct attr
*const attr
= args
->attr
;
1484 struct peer
*const peer
= args
->peer
;
1485 const bgp_size_t length
= args
->length
;
1488 * peer with AS4 => will get 4Byte ASnums
1489 * otherwise, will get 16 Bit
1491 attr
->aspath
= aspath_parse(
1493 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1494 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1496 /* In case of IBGP, length will be zero. */
1497 if (!attr
->aspath
) {
1498 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1499 "Malformed AS path from %s, length is %d", peer
->host
,
1501 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1505 /* Set aspath attribute flag. */
1506 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1508 return BGP_ATTR_PARSE_PROCEED
;
1511 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1512 struct attr
*const attr
)
1514 /* These checks were part of bgp_attr_aspath, but with
1515 * as4 we should to check aspath things when
1516 * aspath synthesizing with as4_path has already taken place.
1517 * Otherwise we check ASPATH and use the synthesized thing, and that is
1519 * So do the checks later, i.e. here
1521 struct aspath
*aspath
;
1523 /* Confederation sanity check. */
1524 if ((peer
->sort
== BGP_PEER_CONFED
1525 && !aspath_left_confed_check(attr
->aspath
))
1526 || (peer
->sort
== BGP_PEER_EBGP
1527 && aspath_confed_check(attr
->aspath
))) {
1528 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1530 return BGP_ATTR_PARSE_WITHDRAW
;
1533 /* First AS check for EBGP. */
1534 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1535 if (peer
->sort
== BGP_PEER_EBGP
1536 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1537 flog_err(EC_BGP_ATTR_FIRST_AS
,
1538 "%s incorrect first AS (must be %u)",
1539 peer
->host
, peer
->as
);
1540 return BGP_ATTR_PARSE_WITHDRAW
;
1544 /* Codification of AS 0 Processing */
1545 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1547 EC_BGP_ATTR_MAL_AS_PATH
,
1548 "Malformed AS path, AS number is 0 in the path from %s",
1550 return BGP_ATTR_PARSE_WITHDRAW
;
1553 /* local-as prepend */
1554 if (peer
->change_local_as
1555 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1556 aspath
= aspath_dup(attr
->aspath
);
1557 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1558 aspath_unintern(&attr
->aspath
);
1559 attr
->aspath
= aspath_intern(aspath
);
1562 return BGP_ATTR_PARSE_PROCEED
;
1565 /* Parse AS4 path information. This function is another wrapper of
1567 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1568 struct aspath
**as4_path
)
1570 struct peer
*const peer
= args
->peer
;
1571 struct attr
*const attr
= args
->attr
;
1572 const bgp_size_t length
= args
->length
;
1574 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1576 /* In case of IBGP, length will be zero. */
1578 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1579 "Malformed AS4 path from %s, length is %d", peer
->host
,
1581 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1585 /* Set aspath attribute flag. */
1586 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1588 return BGP_ATTR_PARSE_PROCEED
;
1592 * Check that the nexthop attribute is valid.
1594 bgp_attr_parse_ret_t
1595 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1597 in_addr_t nexthop_h
;
1599 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1600 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1601 || IPV4_CLASS_DE(nexthop_h
))
1602 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1603 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1604 char buf
[INET_ADDRSTRLEN
];
1606 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1608 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1610 data
[0] = BGP_ATTR_FLAG_TRANS
;
1611 data
[1] = BGP_ATTR_NEXT_HOP
;
1612 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1613 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1614 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1615 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1617 return BGP_ATTR_PARSE_ERROR
;
1620 return BGP_ATTR_PARSE_PROCEED
;
1623 /* Nexthop attribute. */
1624 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1626 struct peer
*const peer
= args
->peer
;
1627 struct attr
*const attr
= args
->attr
;
1628 const bgp_size_t length
= args
->length
;
1630 /* Check nexthop attribute length. */
1632 flog_err(EC_BGP_ATTR_LEN
,
1633 "Nexthop attribute length isn't four [%d]", length
);
1635 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1639 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1640 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1642 return BGP_ATTR_PARSE_PROCEED
;
1645 /* MED atrribute. */
1646 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1648 struct peer
*const peer
= args
->peer
;
1649 struct attr
*const attr
= args
->attr
;
1650 const bgp_size_t length
= args
->length
;
1654 flog_err(EC_BGP_ATTR_LEN
,
1655 "MED attribute length isn't four [%d]", length
);
1657 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1661 attr
->med
= stream_getl(peer
->curr
);
1663 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1665 return BGP_ATTR_PARSE_PROCEED
;
1668 /* Local preference attribute. */
1669 static bgp_attr_parse_ret_t
1670 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1672 struct peer
*const peer
= args
->peer
;
1673 struct attr
*const attr
= args
->attr
;
1674 const bgp_size_t length
= args
->length
;
1676 /* if received from an internal neighbor, it SHALL be considered
1677 * malformed if its length is not equal to 4. If malformed, the
1678 * UPDATE message SHALL be handled using the approach of "treat-as-
1681 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1682 flog_err(EC_BGP_ATTR_LEN
,
1683 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1684 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1688 /* If it is contained in an UPDATE message that is received from an
1689 external peer, then this attribute MUST be ignored by the
1690 receiving speaker. */
1691 if (peer
->sort
== BGP_PEER_EBGP
) {
1692 STREAM_FORWARD_GETP(peer
->curr
, length
);
1693 return BGP_ATTR_PARSE_PROCEED
;
1696 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1698 /* Set the local-pref flag. */
1699 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1701 return BGP_ATTR_PARSE_PROCEED
;
1704 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1708 /* Atomic aggregate. */
1709 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1711 struct attr
*const attr
= args
->attr
;
1712 const bgp_size_t length
= args
->length
;
1716 flog_err(EC_BGP_ATTR_LEN
,
1717 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1719 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1723 /* Set atomic aggregate flag. */
1724 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1726 return BGP_ATTR_PARSE_PROCEED
;
1729 /* Aggregator attribute */
1730 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1732 struct peer
*const peer
= args
->peer
;
1733 struct attr
*const attr
= args
->attr
;
1734 const bgp_size_t length
= args
->length
;
1739 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1740 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1741 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1744 if (length
!= wantedlen
) {
1745 flog_err(EC_BGP_ATTR_LEN
,
1746 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1748 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1752 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1753 aggregator_as
= stream_getl(peer
->curr
);
1755 aggregator_as
= stream_getw(peer
->curr
);
1757 attr
->aggregator_as
= aggregator_as
;
1758 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1760 /* Codification of AS 0 Processing */
1761 if (aggregator_as
== BGP_AS_ZERO
) {
1762 flog_err(EC_BGP_ATTR_LEN
,
1763 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1764 peer
->host
, aspath_print(attr
->aspath
));
1766 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1767 char attr_str
[BUFSIZ
] = {0};
1769 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1771 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1774 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1777 return BGP_ATTR_PARSE_PROCEED
;
1780 /* New Aggregator attribute */
1781 static bgp_attr_parse_ret_t
1782 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1783 as_t
*as4_aggregator_as
,
1784 struct in_addr
*as4_aggregator_addr
)
1786 struct peer
*const peer
= args
->peer
;
1787 struct attr
*const attr
= args
->attr
;
1788 const bgp_size_t length
= args
->length
;
1792 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1794 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1798 aggregator_as
= stream_getl(peer
->curr
);
1800 *as4_aggregator_as
= aggregator_as
;
1801 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1803 /* Codification of AS 0 Processing */
1804 if (aggregator_as
== BGP_AS_ZERO
) {
1805 flog_err(EC_BGP_ATTR_LEN
,
1806 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1807 peer
->host
, aspath_print(attr
->aspath
));
1809 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1810 char attr_str
[BUFSIZ
] = {0};
1812 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1814 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1817 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1820 return BGP_ATTR_PARSE_PROCEED
;
1823 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1825 static bgp_attr_parse_ret_t
1826 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1827 struct aspath
*as4_path
, as_t as4_aggregator
,
1828 struct in_addr
*as4_aggregator_addr
)
1830 int ignore_as4_path
= 0;
1831 struct aspath
*newpath
;
1833 if (!attr
->aspath
) {
1834 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1836 * checked that all well-known, mandatory attributes were
1839 * Can only be a problem with peer itself - hard error
1841 return BGP_ATTR_PARSE_ERROR
;
1844 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1845 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1847 * It is worth a warning though, because the peer really
1848 * should not send them
1850 if (BGP_DEBUG(as4
, AS4
)) {
1851 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1852 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1853 "AS4 capable peer, yet it sent");
1856 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1857 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1859 "AS4 capable peer, yet it sent");
1862 return BGP_ATTR_PARSE_PROCEED
;
1865 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1866 * because that may override AS4_PATH
1868 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1869 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1871 * if the as_number in aggregator is not AS_TRANS,
1872 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1873 * and the Aggregator shall be taken as
1874 * info on the aggregating node, and the AS_PATH
1875 * shall be taken as the AS_PATH
1877 * the Aggregator shall be ignored and the
1878 * AS4_AGGREGATOR shall be taken as the
1879 * Aggregating node and the AS_PATH is to be
1880 * constructed "as in all other cases"
1882 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1884 if (BGP_DEBUG(as4
, AS4
))
1886 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1888 ignore_as4_path
= 1;
1890 /* "New_aggregator shall be taken as aggregator"
1892 attr
->aggregator_as
= as4_aggregator
;
1893 attr
->aggregator_addr
.s_addr
=
1894 as4_aggregator_addr
->s_addr
;
1897 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1898 * That is bogus - but reading the conditions
1899 * we have to handle AS4_AGGREGATOR as if it were
1900 * AGGREGATOR in that case
1902 if (BGP_DEBUG(as4
, AS4
))
1904 "[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",
1906 attr
->aggregator_as
= as4_aggregator
;
1907 /* sweep it under the carpet and simulate a "good"
1909 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1913 /* need to reconcile NEW_AS_PATH and AS_PATH */
1914 if (!ignore_as4_path
1915 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1916 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1918 return BGP_ATTR_PARSE_ERROR
;
1920 aspath_unintern(&attr
->aspath
);
1921 attr
->aspath
= aspath_intern(newpath
);
1923 return BGP_ATTR_PARSE_PROCEED
;
1926 /* Community attribute. */
1927 static bgp_attr_parse_ret_t
1928 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1930 struct peer
*const peer
= args
->peer
;
1931 struct attr
*const attr
= args
->attr
;
1932 const bgp_size_t length
= args
->length
;
1935 attr
->community
= NULL
;
1936 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1941 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1943 /* XXX: fix community_parse to use stream API and remove this */
1944 stream_forward_getp(peer
->curr
, length
);
1946 /* The Community attribute SHALL be considered malformed if its
1947 * length is not a non-zero multiple of 4.
1949 if (!attr
->community
)
1950 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1953 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1955 return BGP_ATTR_PARSE_PROCEED
;
1958 /* Originator ID attribute. */
1959 static bgp_attr_parse_ret_t
1960 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1962 struct peer
*const peer
= args
->peer
;
1963 struct attr
*const attr
= args
->attr
;
1964 const bgp_size_t length
= args
->length
;
1966 /* if received from an internal neighbor, it SHALL be considered
1967 * malformed if its length is not equal to 4. If malformed, the
1968 * UPDATE message SHALL be handled using the approach of "treat-as-
1972 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1975 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1979 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1981 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1983 return BGP_ATTR_PARSE_PROCEED
;
1986 /* Cluster list attribute. */
1987 static bgp_attr_parse_ret_t
1988 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1990 struct peer
*const peer
= args
->peer
;
1991 struct attr
*const attr
= args
->attr
;
1992 const bgp_size_t length
= args
->length
;
1994 /* if received from an internal neighbor, it SHALL be considered
1995 * malformed if its length is not a non-zero multiple of 4. If
1996 * malformed, the UPDATE message SHALL be handled using the approach
1997 * of "treat-as-withdraw".
1999 if (length
== 0 || length
% 4) {
2000 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2002 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2006 bgp_attr_set_cluster(
2007 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2010 /* XXX: Fix cluster_parse to use stream API and then remove this */
2011 stream_forward_getp(peer
->curr
, length
);
2013 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2015 return BGP_ATTR_PARSE_PROCEED
;
2018 /* Multiprotocol reachability information parse. */
2019 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2020 struct bgp_nlri
*mp_update
)
2024 iana_safi_t pkt_safi
;
2026 bgp_size_t nlri_len
;
2029 struct peer
*const peer
= args
->peer
;
2030 struct attr
*const attr
= args
->attr
;
2031 const bgp_size_t length
= args
->length
;
2033 /* Set end of packet. */
2034 s
= BGP_INPUT(peer
);
2035 start
= stream_get_getp(s
);
2037 /* safe to read statically sized header? */
2038 #define BGP_MP_REACH_MIN_SIZE 5
2039 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2040 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2041 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2042 __func__
, peer
->host
, (unsigned long)length
);
2043 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2046 /* Load AFI, SAFI. */
2047 pkt_afi
= stream_getw(s
);
2048 pkt_safi
= stream_getc(s
);
2050 /* Convert AFI, SAFI to internal values, check. */
2051 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2052 /* Log if AFI or SAFI is unrecognized. This is not an error
2054 * the attribute is otherwise malformed.
2056 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2058 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2059 peer
->host
, iana_afi2str(pkt_afi
),
2060 iana_safi2str(pkt_safi
));
2061 return BGP_ATTR_PARSE_ERROR
;
2064 /* Get nexthop length. */
2065 attr
->mp_nexthop_len
= stream_getc(s
);
2067 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2069 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2070 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2071 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2074 /* Nexthop length check. */
2075 switch (attr
->mp_nexthop_len
) {
2077 if (safi
!= SAFI_FLOWSPEC
) {
2078 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2079 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2080 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2083 case BGP_ATTR_NHLEN_VPNV4
:
2084 stream_getl(s
); /* RD high */
2085 stream_getl(s
); /* RD low */
2087 * NOTE: intentional fall through
2088 * - for consistency in rx processing
2090 * The following comment is to signal GCC this intention
2091 * and suppress the warning
2094 case BGP_ATTR_NHLEN_IPV4
:
2095 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2096 /* Probably needed for RFC 2283 */
2097 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2098 memcpy(&attr
->nexthop
.s_addr
,
2099 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2101 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2102 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2103 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2104 stream_getl(s
); /* RD high */
2105 stream_getl(s
); /* RD low */
2107 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2108 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2109 if (!peer
->nexthop
.ifp
) {
2110 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2112 return BGP_ATTR_PARSE_WITHDRAW
;
2114 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2117 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2118 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2119 if (attr
->mp_nexthop_len
2120 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2121 stream_getl(s
); /* RD high */
2122 stream_getl(s
); /* RD low */
2124 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2125 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2126 if (!peer
->nexthop
.ifp
) {
2127 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",
2129 return BGP_ATTR_PARSE_WITHDRAW
;
2131 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2133 if (attr
->mp_nexthop_len
2134 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2135 stream_getl(s
); /* RD high */
2136 stream_getl(s
); /* RD low */
2138 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2139 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2140 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2142 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2143 peer
->host
, &attr
->mp_nexthop_global
,
2144 &attr
->mp_nexthop_local
);
2146 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2148 if (!peer
->nexthop
.ifp
) {
2149 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2151 return BGP_ATTR_PARSE_WITHDRAW
;
2153 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2156 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2157 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2158 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2162 zlog_info("%s: %s sent SNPA which couldn't be read",
2163 __func__
, peer
->host
);
2164 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2169 if ((val
= stream_getc(s
)))
2171 EC_BGP_DEFUNCT_SNPA_LEN
,
2172 "%s sent non-zero value, %u, for defunct SNPA-length field",
2176 /* must have nrli_len, what is left of the attribute */
2177 nlri_len
= LEN_LEFT
;
2178 if (nlri_len
> STREAM_READABLE(s
)) {
2179 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2180 __func__
, peer
->host
);
2181 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2185 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2186 __func__
, peer
->host
);
2188 mp_update
->afi
= afi
;
2189 mp_update
->safi
= safi
;
2190 return BGP_ATTR_PARSE_EOR
;
2193 mp_update
->afi
= afi
;
2194 mp_update
->safi
= safi
;
2195 mp_update
->nlri
= stream_pnt(s
);
2196 mp_update
->length
= nlri_len
;
2198 stream_forward_getp(s
, nlri_len
);
2200 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2202 return BGP_ATTR_PARSE_PROCEED
;
2206 /* Multiprotocol unreachable parse */
2207 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2208 struct bgp_nlri
*mp_withdraw
)
2213 iana_safi_t pkt_safi
;
2215 uint16_t withdraw_len
;
2216 struct peer
*const peer
= args
->peer
;
2217 struct attr
*const attr
= args
->attr
;
2218 const bgp_size_t length
= args
->length
;
2222 #define BGP_MP_UNREACH_MIN_SIZE 3
2223 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2224 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2226 pkt_afi
= stream_getw(s
);
2227 pkt_safi
= stream_getc(s
);
2229 /* Convert AFI, SAFI to internal values, check. */
2230 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2231 /* Log if AFI or SAFI is unrecognized. This is not an error
2233 * the attribute is otherwise malformed.
2235 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2237 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2238 peer
->host
, iana_afi2str(pkt_afi
),
2239 iana_safi2str(pkt_safi
));
2240 return BGP_ATTR_PARSE_ERROR
;
2243 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2245 mp_withdraw
->afi
= afi
;
2246 mp_withdraw
->safi
= safi
;
2247 mp_withdraw
->nlri
= stream_pnt(s
);
2248 mp_withdraw
->length
= withdraw_len
;
2250 stream_forward_getp(s
, withdraw_len
);
2252 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2254 return BGP_ATTR_PARSE_PROCEED
;
2257 /* Large Community attribute. */
2258 static bgp_attr_parse_ret_t
2259 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2261 struct peer
*const peer
= args
->peer
;
2262 struct attr
*const attr
= args
->attr
;
2263 const bgp_size_t length
= args
->length
;
2266 * Large community follows new attribute format.
2269 bgp_attr_set_lcommunity(attr
, NULL
);
2270 /* Empty extcomm doesn't seem to be invalid per se */
2271 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2275 bgp_attr_set_lcommunity(
2276 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2277 /* XXX: fix ecommunity_parse to use stream API */
2278 stream_forward_getp(peer
->curr
, length
);
2280 if (!bgp_attr_get_lcommunity(attr
))
2281 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2284 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2286 return BGP_ATTR_PARSE_PROCEED
;
2289 /* Extended Community attribute. */
2290 static bgp_attr_parse_ret_t
2291 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2293 struct peer
*const peer
= args
->peer
;
2294 struct attr
*const attr
= args
->attr
;
2295 const bgp_size_t length
= args
->length
;
2298 struct ecommunity
*ecomm
;
2301 bgp_attr_set_ecommunity(attr
, NULL
);
2302 /* Empty extcomm doesn't seem to be invalid per se */
2303 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2307 ecomm
= ecommunity_parse(
2308 stream_pnt(peer
->curr
), length
,
2309 CHECK_FLAG(peer
->flags
,
2310 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2311 bgp_attr_set_ecommunity(attr
, ecomm
);
2312 /* XXX: fix ecommunity_parse to use stream API */
2313 stream_forward_getp(peer
->curr
, length
);
2315 /* The Extended Community attribute SHALL be considered malformed if
2316 * its length is not a non-zero multiple of 8.
2318 if (!bgp_attr_get_ecommunity(attr
))
2319 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2322 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2324 /* Extract DF election preference and mobility sequence number */
2325 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2327 /* Extract MAC mobility sequence number, if any. */
2328 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2329 attr
->sticky
= sticky
;
2331 /* Check if this is a Gateway MAC-IP advertisement */
2332 attr
->default_gw
= bgp_attr_default_gw(attr
);
2334 /* Handle scenario where router flag ecommunity is not
2335 * set but default gw ext community is present.
2336 * Use default gateway, set and propogate R-bit.
2338 if (attr
->default_gw
)
2339 attr
->router_flag
= 1;
2341 /* Check EVPN Neighbor advertisement flags, R-bit */
2342 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2344 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2346 /* Extract the Rmac, if any */
2347 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2348 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2349 && bgp_mac_exist(&attr
->rmac
))
2350 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2354 /* Get the tunnel type from encap extended community */
2355 bgp_attr_extcom_tunnel_type(attr
,
2356 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2358 /* Extract link bandwidth, if any. */
2359 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2362 return BGP_ATTR_PARSE_PROCEED
;
2365 /* IPv6 Extended Community attribute. */
2366 static bgp_attr_parse_ret_t
2367 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2369 struct peer
*const peer
= args
->peer
;
2370 struct attr
*const attr
= args
->attr
;
2371 const bgp_size_t length
= args
->length
;
2372 struct ecommunity
*ipv6_ecomm
= NULL
;
2375 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2376 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2380 ipv6_ecomm
= ecommunity_parse_ipv6(
2381 stream_pnt(peer
->curr
), length
,
2382 CHECK_FLAG(peer
->flags
,
2383 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2384 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2386 /* XXX: fix ecommunity_parse to use stream API */
2387 stream_forward_getp(peer
->curr
, length
);
2390 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2393 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
);
2395 return BGP_ATTR_PARSE_PROCEED
;
2398 /* Parse Tunnel Encap attribute in an UPDATE */
2399 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2400 bgp_size_t length
, /* IN: attr's length field */
2401 struct attr
*attr
, /* IN: caller already allocated */
2402 uint8_t flag
, /* IN: attr's flags field */
2406 uint16_t tunneltype
= 0;
2408 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2410 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2411 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2413 "Tunnel Encap attribute flag isn't optional and transitive %d",
2415 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2416 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2421 if (BGP_ATTR_ENCAP
== type
) {
2422 /* read outer TLV type and length */
2423 uint16_t tlv_length
;
2427 "Tunnel Encap attribute not long enough to contain outer T,L");
2428 bgp_notify_send_with_data(
2429 peer
, BGP_NOTIFY_UPDATE_ERR
,
2430 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2433 tunneltype
= stream_getw(BGP_INPUT(peer
));
2434 tlv_length
= stream_getw(BGP_INPUT(peer
));
2437 if (tlv_length
!= length
) {
2438 zlog_info("%s: tlv_length(%d) != length(%d)",
2439 __func__
, tlv_length
, length
);
2443 while (length
>= 4) {
2444 uint16_t subtype
= 0;
2445 uint16_t sublength
= 0;
2446 struct bgp_attr_encap_subtlv
*tlv
;
2448 if (BGP_ATTR_ENCAP
== type
) {
2449 subtype
= stream_getc(BGP_INPUT(peer
));
2450 sublength
= stream_getc(BGP_INPUT(peer
));
2452 #ifdef ENABLE_BGP_VNC
2454 subtype
= stream_getw(BGP_INPUT(peer
));
2455 sublength
= stream_getw(BGP_INPUT(peer
));
2460 if (sublength
> length
) {
2462 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2464 bgp_notify_send_with_data(
2465 peer
, BGP_NOTIFY_UPDATE_ERR
,
2466 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2470 /* alloc and copy sub-tlv */
2471 /* TBD make sure these are freed when attributes are released */
2472 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2473 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2474 tlv
->type
= subtype
;
2475 tlv
->length
= sublength
;
2476 stream_get(tlv
->value
, peer
->curr
, sublength
);
2477 length
-= sublength
;
2479 /* attach tlv to encap chain */
2480 if (BGP_ATTR_ENCAP
== type
) {
2481 struct bgp_attr_encap_subtlv
*stlv_last
;
2482 for (stlv_last
= attr
->encap_subtlvs
;
2483 stlv_last
&& stlv_last
->next
;
2484 stlv_last
= stlv_last
->next
)
2487 stlv_last
->next
= tlv
;
2489 attr
->encap_subtlvs
= tlv
;
2491 #ifdef ENABLE_BGP_VNC
2493 struct bgp_attr_encap_subtlv
*stlv_last
;
2494 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2495 bgp_attr_get_vnc_subtlvs(attr
);
2497 for (stlv_last
= vnc_subtlvs
;
2498 stlv_last
&& stlv_last
->next
;
2499 stlv_last
= stlv_last
->next
)
2502 stlv_last
->next
= tlv
;
2504 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2509 if (BGP_ATTR_ENCAP
== type
) {
2510 attr
->encap_tunneltype
= tunneltype
;
2514 /* spurious leftover data */
2516 "Tunnel Encap attribute length is bad: %d leftover octets",
2518 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2519 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2528 /* SRv6 Service Data Sub-Sub-TLV attribute
2529 * draft-ietf-bess-srv6-services-07
2531 static bgp_attr_parse_ret_t
2532 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2534 struct peer
*const peer
= args
->peer
;
2535 struct attr
*const attr
= args
->attr
;
2536 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2537 transposition_len
, transposition_offset
;
2539 size_t headersz
= sizeof(type
) + sizeof(length
);
2541 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2544 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2545 headersz
, STREAM_READABLE(peer
->curr
));
2546 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2550 type
= stream_getc(peer
->curr
);
2551 length
= stream_getw(peer
->curr
);
2553 if (STREAM_READABLE(peer
->curr
) < length
) {
2556 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2557 length
, STREAM_READABLE(peer
->curr
));
2558 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2562 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2563 loc_block_len
= stream_getc(peer
->curr
);
2564 loc_node_len
= stream_getc(peer
->curr
);
2565 func_len
= stream_getc(peer
->curr
);
2566 arg_len
= stream_getc(peer
->curr
);
2567 transposition_len
= stream_getc(peer
->curr
);
2568 transposition_offset
= stream_getc(peer
->curr
);
2570 /* Log SRv6 Service Data Sub-Sub-TLV */
2571 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2573 "%s: srv6-l3-srv-data loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u, transposition-len=%u, transposition-offset=%u",
2574 __func__
, loc_block_len
, loc_node_len
, func_len
,
2575 arg_len
, transposition_len
,
2576 transposition_offset
);
2579 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2580 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2581 attr
->srv6_l3vpn
->func_len
= func_len
;
2582 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2583 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2584 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2588 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2590 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2593 stream_forward_getp(peer
->curr
, length
);
2596 return BGP_ATTR_PARSE_PROCEED
;
2599 /* SRv6 Service Sub-TLV attribute
2600 * draft-ietf-bess-srv6-services-07
2602 static bgp_attr_parse_ret_t
2603 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2605 struct peer
*const peer
= args
->peer
;
2606 struct attr
*const attr
= args
->attr
;
2607 struct in6_addr ipv6_sid
;
2608 uint8_t type
, sid_flags
;
2609 uint16_t length
, endpoint_behavior
;
2610 size_t headersz
= sizeof(type
) + sizeof(length
);
2611 bgp_attr_parse_ret_t err
;
2614 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2617 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2618 headersz
, STREAM_READABLE(peer
->curr
));
2619 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2623 type
= stream_getc(peer
->curr
);
2624 length
= stream_getw(peer
->curr
);
2626 if (STREAM_READABLE(peer
->curr
) < length
) {
2629 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2630 length
, STREAM_READABLE(peer
->curr
));
2631 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2635 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2636 stream_getc(peer
->curr
);
2637 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2638 sid_flags
= stream_getc(peer
->curr
);
2639 endpoint_behavior
= stream_getw(peer
->curr
);
2640 stream_getc(peer
->curr
);
2642 /* Log SRv6 Service Sub-TLV */
2643 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2644 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2646 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2647 __func__
, buf
, sid_flags
, endpoint_behavior
);
2650 /* Configure from Info */
2651 if (attr
->srv6_l3vpn
) {
2652 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2653 "Prefix SID SRv6 L3VPN field repeated");
2654 return bgp_attr_malformed(
2655 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2657 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2658 sizeof(struct bgp_attr_srv6_l3vpn
));
2659 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2660 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2661 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2662 attr
->srv6_l3vpn
->loc_block_len
= 0;
2663 attr
->srv6_l3vpn
->loc_node_len
= 0;
2664 attr
->srv6_l3vpn
->func_len
= 0;
2665 attr
->srv6_l3vpn
->arg_len
= 0;
2666 attr
->srv6_l3vpn
->transposition_len
= 0;
2667 attr
->srv6_l3vpn
->transposition_offset
= 0;
2669 // Sub-Sub-TLV found
2670 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2671 err
= bgp_attr_srv6_service_data(args
);
2673 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2677 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2680 /* Placeholder code for unsupported type */
2682 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2684 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2687 stream_forward_getp(peer
->curr
, length
);
2690 return BGP_ATTR_PARSE_PROCEED
;
2694 * Read an individual SID value returning how much data we have read
2695 * Returns 0 if there was an error that needs to be passed up the stack
2697 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2698 struct bgp_attr_parser_args
*args
)
2700 struct peer
*const peer
= args
->peer
;
2701 struct attr
*const attr
= args
->attr
;
2702 uint32_t label_index
;
2703 struct in6_addr ipv6_sid
;
2705 uint32_t srgb_range
;
2707 uint8_t sid_type
, sid_flags
;
2710 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2711 if (STREAM_READABLE(peer
->curr
) < length
2712 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2713 flog_err(EC_BGP_ATTR_LEN
,
2714 "Prefix SID label index length is %hu instead of %u",
2715 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2716 return bgp_attr_malformed(args
,
2717 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2721 /* Ignore flags and reserved */
2722 stream_getc(peer
->curr
);
2723 stream_getw(peer
->curr
);
2725 /* Fetch the label index and see if it is valid. */
2726 label_index
= stream_getl(peer
->curr
);
2727 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2728 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2731 /* Store label index; subsequently, we'll check on
2733 attr
->label_index
= label_index
;
2736 /* Placeholder code for the IPv6 SID type */
2737 else if (type
== BGP_PREFIX_SID_IPV6
) {
2738 if (STREAM_READABLE(peer
->curr
) < length
2739 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2740 flog_err(EC_BGP_ATTR_LEN
,
2741 "Prefix SID IPv6 length is %hu instead of %u",
2742 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2743 return bgp_attr_malformed(args
,
2744 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2748 /* Ignore reserved */
2749 stream_getc(peer
->curr
);
2750 stream_getw(peer
->curr
);
2752 stream_get(&ipv6_sid
, peer
->curr
, 16);
2755 /* Placeholder code for the Originator SRGB type */
2756 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2758 * ietf-idr-bgp-prefix-sid-05:
2759 * Length is the total length of the value portion of the
2760 * TLV: 2 + multiple of 6.
2762 * peer->curr stream readp should be at the beginning of the 16
2763 * bit flag field at this point in the code.
2767 * Check that the TLV length field is sane: at least 2 bytes of
2768 * flag, and at least 1 SRGB (these are 6 bytes each)
2770 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2773 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2775 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2776 return bgp_attr_malformed(
2777 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2782 * Check that we actually have at least as much data as
2783 * specified by the length field
2785 if (STREAM_READABLE(peer
->curr
) < length
) {
2786 flog_err(EC_BGP_ATTR_LEN
,
2787 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2788 length
, STREAM_READABLE(peer
->curr
));
2789 return bgp_attr_malformed(
2790 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2795 * Check that the portion of the TLV containing the sequence of
2796 * SRGBs corresponds to a multiple of the SRGB size; to get
2797 * that length, we skip the 16 bit flags field
2799 stream_getw(peer
->curr
);
2801 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2804 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2805 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2806 return bgp_attr_malformed(
2807 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2811 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2813 for (int i
= 0; i
< srgb_count
; i
++) {
2814 stream_get(&srgb_base
, peer
->curr
, 3);
2815 stream_get(&srgb_range
, peer
->curr
, 3);
2819 /* Placeholder code for the VPN-SID Service type */
2820 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2821 if (STREAM_READABLE(peer
->curr
) < length
2822 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2823 flog_err(EC_BGP_ATTR_LEN
,
2824 "Prefix SID VPN SID length is %hu instead of %u",
2825 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2826 return bgp_attr_malformed(args
,
2827 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2831 /* Parse VPN-SID Sub-TLV */
2832 stream_getc(peer
->curr
); /* reserved */
2833 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2834 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2835 stream_get(&ipv6_sid
, peer
->curr
,
2836 sizeof(ipv6_sid
)); /* sid_value */
2838 /* Log VPN-SID Sub-TLV */
2839 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2840 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2842 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2843 __func__
, buf
, sid_type
, sid_flags
);
2846 /* Configure from Info */
2847 if (attr
->srv6_vpn
) {
2848 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2849 "Prefix SID SRv6 VPN field repeated");
2850 return bgp_attr_malformed(
2851 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2853 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2854 sizeof(struct bgp_attr_srv6_vpn
));
2855 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2856 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2857 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2860 /* Placeholder code for the SRv6 L3 Service type */
2861 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2862 if (STREAM_READABLE(peer
->curr
) < length
) {
2865 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
2866 length
, STREAM_READABLE(peer
->curr
));
2867 return bgp_attr_malformed(args
,
2868 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2872 /* ignore reserved */
2873 stream_getc(peer
->curr
);
2875 return bgp_attr_srv6_service(args
);
2878 /* Placeholder code for Unsupported TLV */
2881 if (STREAM_READABLE(peer
->curr
) < length
) {
2884 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2885 length
, STREAM_READABLE(peer
->curr
));
2886 return bgp_attr_malformed(
2887 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2891 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2893 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2896 stream_forward_getp(peer
->curr
, length
);
2899 return BGP_ATTR_PARSE_PROCEED
;
2902 /* Prefix SID attribute
2903 * draft-ietf-idr-bgp-prefix-sid-05
2905 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2907 struct peer
*const peer
= args
->peer
;
2908 struct attr
*const attr
= args
->attr
;
2909 bgp_attr_parse_ret_t ret
;
2911 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2915 size_t headersz
= sizeof(type
) + sizeof(length
);
2916 size_t psid_parsed_length
= 0;
2918 while (STREAM_READABLE(peer
->curr
) > 0
2919 && psid_parsed_length
< args
->length
) {
2921 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2924 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2925 headersz
, STREAM_READABLE(peer
->curr
));
2926 return bgp_attr_malformed(
2927 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2931 type
= stream_getc(peer
->curr
);
2932 length
= stream_getw(peer
->curr
);
2934 if (STREAM_READABLE(peer
->curr
) < length
) {
2937 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2938 length
, STREAM_READABLE(peer
->curr
));
2939 return bgp_attr_malformed(args
,
2940 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2944 ret
= bgp_attr_psid_sub(type
, length
, args
);
2946 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2949 psid_parsed_length
+= length
+ headersz
;
2951 if (psid_parsed_length
> args
->length
) {
2954 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2955 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2956 return bgp_attr_malformed(
2957 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2962 return BGP_ATTR_PARSE_PROCEED
;
2965 /* PMSI tunnel attribute (RFC 6514)
2966 * Basic validation checks done here.
2968 static bgp_attr_parse_ret_t
2969 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2971 struct peer
*const peer
= args
->peer
;
2972 struct attr
*const attr
= args
->attr
;
2973 const bgp_size_t length
= args
->length
;
2975 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2977 /* Verify that the receiver is expecting "ingress replication" as we
2978 * can only support that.
2980 if (length
< attr_parse_len
) {
2981 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2983 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2986 stream_getc(peer
->curr
); /* Flags */
2987 tnl_type
= stream_getc(peer
->curr
);
2988 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2989 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2990 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2991 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2994 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2996 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2997 "Bad PMSI tunnel attribute length %d for IR",
2999 return bgp_attr_malformed(
3000 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3005 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3006 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3007 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3009 /* Forward read pointer of input stream. */
3010 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3012 return BGP_ATTR_PARSE_PROCEED
;
3015 /* BGP unknown attribute treatment. */
3016 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3018 bgp_size_t total
= args
->total
;
3019 struct transit
*transit
;
3020 struct peer
*const peer
= args
->peer
;
3021 struct attr
*const attr
= args
->attr
;
3022 uint8_t *const startp
= args
->startp
;
3023 const uint8_t type
= args
->type
;
3024 const uint8_t flag
= args
->flags
;
3025 const bgp_size_t length
= args
->length
;
3027 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3029 "%s Unknown attribute is received (type %d, length %d)",
3030 peer
->host
, type
, length
);
3032 /* Forward read pointer of input stream. */
3033 stream_forward_getp(peer
->curr
, length
);
3035 /* If any of the mandatory well-known attributes are not recognized,
3036 then the Error Subcode is set to Unrecognized Well-known
3037 Attribute. The Data field contains the unrecognized attribute
3038 (type, length and value). */
3039 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3040 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3044 /* Unrecognized non-transitive optional attributes must be quietly
3045 ignored and not passed along to other BGP peers. */
3046 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3047 return BGP_ATTR_PARSE_PROCEED
;
3049 /* If a path with recognized transitive optional attribute is
3050 accepted and passed along to other BGP peers and the Partial bit
3051 in the Attribute Flags octet is set to 1 by some previous AS, it
3052 is not set back to 0 by the current AS. */
3053 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3055 /* Store transitive attribute to the end of attr->transit. */
3056 transit
= bgp_attr_get_transit(attr
);
3058 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3060 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3061 transit
->length
+ total
);
3063 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3064 transit
->length
+= total
;
3065 bgp_attr_set_transit(attr
, transit
);
3067 return BGP_ATTR_PARSE_PROCEED
;
3070 /* Well-known attribute check. */
3071 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3075 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3077 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3078 return BGP_ATTR_PARSE_PROCEED
;
3080 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3081 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3082 are present, it should. Check for any other attribute being present
3085 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3086 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3087 return BGP_ATTR_PARSE_PROCEED
;
3089 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3090 type
= BGP_ATTR_ORIGIN
;
3092 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3093 type
= BGP_ATTR_AS_PATH
;
3095 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3097 * NLRI is empty. We can't easily check NLRI empty here though.
3099 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3100 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3101 type
= BGP_ATTR_NEXT_HOP
;
3103 if (peer
->sort
== BGP_PEER_IBGP
3104 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3105 type
= BGP_ATTR_LOCAL_PREF
;
3107 /* If any of the well-known mandatory attributes are not present
3108 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3111 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3112 "%s Missing well-known attribute %s.", peer
->host
,
3113 lookup_msg(attr_str
, type
, NULL
));
3114 return BGP_ATTR_PARSE_WITHDRAW
;
3116 return BGP_ATTR_PARSE_PROCEED
;
3119 /* Read attribute of update packet. This function is called from
3120 bgp_update_receive() in bgp_packet.c. */
3121 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3122 bgp_size_t size
, struct bgp_nlri
*mp_update
,
3123 struct bgp_nlri
*mp_withdraw
)
3125 bgp_attr_parse_ret_t ret
;
3129 uint8_t *startp
, *endp
;
3131 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3132 /* we need the as4_path only until we have synthesized the as_path with
3134 /* same goes for as4_aggregator */
3135 struct aspath
*as4_path
= NULL
;
3136 as_t as4_aggregator
= 0;
3137 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3138 struct transit
*transit
;
3140 /* Initialize bitmap. */
3141 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3143 /* End pointer of BGP attribute. */
3144 endp
= BGP_INPUT_PNT(peer
) + size
;
3146 /* Get attributes to the end of attribute length. */
3147 while (BGP_INPUT_PNT(peer
) < endp
) {
3148 /* Check remaining length check.*/
3149 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3150 /* XXX warning: long int format, int arg (arg 5) */
3152 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3153 "%s: error BGP attribute length %lu is smaller than min len",
3155 (unsigned long)(endp
3156 - stream_pnt(BGP_INPUT(peer
))));
3158 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3159 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3160 ret
= BGP_ATTR_PARSE_ERROR
;
3164 /* Fetch attribute flag and type. */
3165 startp
= BGP_INPUT_PNT(peer
);
3166 /* "The lower-order four bits of the Attribute Flags octet are
3167 unused. They MUST be zero when sent and MUST be ignored when
3169 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3170 type
= stream_getc(BGP_INPUT(peer
));
3172 /* Check whether Extended-Length applies and is in bounds */
3173 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3174 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3176 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3177 "%s: Extended length set, but just %lu bytes of attr header",
3179 (unsigned long)(endp
3180 - stream_pnt(BGP_INPUT(peer
))));
3182 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3183 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3184 ret
= BGP_ATTR_PARSE_ERROR
;
3188 /* Check extended attribue length bit. */
3189 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3190 length
= stream_getw(BGP_INPUT(peer
));
3192 length
= stream_getc(BGP_INPUT(peer
));
3194 /* If any attribute appears more than once in the UPDATE
3195 message, then the Error Subcode is set to Malformed Attribute
3198 if (CHECK_BITMAP(seen
, type
)) {
3200 EC_BGP_ATTRIBUTE_REPEATED
,
3201 "%s: error BGP attribute type %d appears twice in a message",
3204 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3205 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3206 ret
= BGP_ATTR_PARSE_ERROR
;
3210 /* Set type to bitmap to check duplicate attribute. `type' is
3211 unsigned char so it never overflow bitmap range. */
3213 SET_BITMAP(seen
, type
);
3215 /* Overflow check. */
3216 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3218 if (attr_endp
> endp
) {
3220 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3221 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3222 peer
->host
, type
, length
, size
, attr_endp
,
3226 * If any recognized attribute has an Attribute
3227 * Length that conflicts with the expected length
3228 * (based on the attribute type code), then the
3229 * Error Subcode MUST be set to Attribute Length
3230 * Error. The Data field MUST contain the erroneous
3231 * attribute (type, length, and value).
3233 * We do not currently have a good way to determine the
3234 * length of the attribute independent of the length
3235 * received in the message. Instead we send the
3236 * minimum between the amount of data we have and the
3237 * amount specified by the attribute length field.
3239 * Instead of directly passing in the packet buffer and
3240 * offset we use the stream_get* functions to read into
3241 * a stack buffer, since they perform bounds checking
3242 * and we are working with untrusted data.
3244 unsigned char ndata
[peer
->max_packet_size
];
3245 memset(ndata
, 0x00, sizeof(ndata
));
3247 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3248 /* Rewind to end of flag field */
3249 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3251 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3253 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3255 size_t atl
= attr_endp
- startp
;
3256 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3257 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3259 bgp_notify_send_with_data(
3260 peer
, BGP_NOTIFY_UPDATE_ERR
,
3261 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3264 ret
= BGP_ATTR_PARSE_ERROR
;
3268 struct bgp_attr_parser_args attr_args
= {
3275 .total
= attr_endp
- startp
,
3279 /* If any recognized attribute has Attribute Flags that conflict
3280 with the Attribute Type Code, then the Error Subcode is set
3282 Attribute Flags Error. The Data field contains the erroneous
3283 attribute (type, length and value). */
3284 if (bgp_attr_flag_invalid(&attr_args
)) {
3285 ret
= bgp_attr_malformed(
3286 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3288 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3293 /* OK check attribute and store it's value. */
3295 case BGP_ATTR_ORIGIN
:
3296 ret
= bgp_attr_origin(&attr_args
);
3298 case BGP_ATTR_AS_PATH
:
3299 ret
= bgp_attr_aspath(&attr_args
);
3301 case BGP_ATTR_AS4_PATH
:
3302 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3304 case BGP_ATTR_NEXT_HOP
:
3305 ret
= bgp_attr_nexthop(&attr_args
);
3307 case BGP_ATTR_MULTI_EXIT_DISC
:
3308 ret
= bgp_attr_med(&attr_args
);
3310 case BGP_ATTR_LOCAL_PREF
:
3311 ret
= bgp_attr_local_pref(&attr_args
);
3313 case BGP_ATTR_ATOMIC_AGGREGATE
:
3314 ret
= bgp_attr_atomic(&attr_args
);
3316 case BGP_ATTR_AGGREGATOR
:
3317 ret
= bgp_attr_aggregator(&attr_args
);
3319 case BGP_ATTR_AS4_AGGREGATOR
:
3320 ret
= bgp_attr_as4_aggregator(&attr_args
,
3322 &as4_aggregator_addr
);
3324 case BGP_ATTR_COMMUNITIES
:
3325 ret
= bgp_attr_community(&attr_args
);
3327 case BGP_ATTR_LARGE_COMMUNITIES
:
3328 ret
= bgp_attr_large_community(&attr_args
);
3330 case BGP_ATTR_ORIGINATOR_ID
:
3331 ret
= bgp_attr_originator_id(&attr_args
);
3333 case BGP_ATTR_CLUSTER_LIST
:
3334 ret
= bgp_attr_cluster_list(&attr_args
);
3336 case BGP_ATTR_MP_REACH_NLRI
:
3337 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3339 case BGP_ATTR_MP_UNREACH_NLRI
:
3340 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3342 case BGP_ATTR_EXT_COMMUNITIES
:
3343 ret
= bgp_attr_ext_communities(&attr_args
);
3345 #ifdef ENABLE_BGP_VNC_ATTR
3348 case BGP_ATTR_ENCAP
:
3349 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3352 case BGP_ATTR_PREFIX_SID
:
3353 ret
= bgp_attr_prefix_sid(&attr_args
);
3355 case BGP_ATTR_PMSI_TUNNEL
:
3356 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3358 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3359 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3362 ret
= bgp_attr_unknown(&attr_args
);
3366 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3367 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3368 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3369 ret
= BGP_ATTR_PARSE_ERROR
;
3373 if (ret
== BGP_ATTR_PARSE_EOR
) {
3377 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3378 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3379 "%s: Attribute %s, parse error", peer
->host
,
3380 lookup_msg(attr_str
, type
, NULL
));
3383 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3385 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3386 "%s: Attribute %s, parse error - treating as withdrawal",
3387 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3391 /* Check the fetched length. */
3392 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3393 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3394 "%s: BGP attribute %s, fetch error",
3395 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3396 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3397 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3398 ret
= BGP_ATTR_PARSE_ERROR
;
3404 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3405 * About Prefix-SID path attribute,
3406 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3407 * may only appear in a BGP Prefix-SID attribute attached to
3408 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3409 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3411 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3412 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3414 /* Check final read pointer is same as end pointer. */
3415 if (BGP_INPUT_PNT(peer
) != endp
) {
3416 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3417 "%s: BGP attribute %s, length mismatch", peer
->host
,
3418 lookup_msg(attr_str
, type
, NULL
));
3419 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3420 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3422 ret
= BGP_ATTR_PARSE_ERROR
;
3427 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3428 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3429 * This is implemented below and will result in a NOTIFICATION. If the
3430 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3431 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3432 * message SHOULD NOT be sent. This is implemented elsewhere.
3434 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3435 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3436 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3437 * speaker that receives the message SHOULD ignore this attribute.
3439 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3440 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3441 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3442 ret
= BGP_ATTR_PARSE_ERROR
;
3447 /* Check all mandatory well-known attributes are present */
3448 ret
= bgp_attr_check(peer
, attr
);
3453 * At this place we can see whether we got AS4_PATH and/or
3454 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3455 * We can not do this before we've read all attributes because
3456 * the as4 handling does not say whether AS4_PATH has to be sent
3457 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3458 * in relationship to AGGREGATOR.
3459 * So, to be defensive, we are not relying on any order and read
3460 * all attributes first, including these 32bit ones, and now,
3461 * afterwards, we look what and if something is to be done for as4.
3463 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3466 /* actually... this doesn't ever return failure currently, but
3467 * better safe than sorry */
3468 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3469 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3470 &as4_aggregator_addr
)) {
3471 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3472 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3473 ret
= BGP_ATTR_PARSE_ERROR
;
3478 * Finally do the checks on the aspath we did not do yet
3479 * because we waited for a potentially synthesized aspath.
3481 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3482 ret
= bgp_attr_aspath_check(peer
, attr
);
3483 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3487 ret
= BGP_ATTR_PARSE_PROCEED
;
3491 * At this stage, we have done all fiddling with as4, and the
3492 * resulting info is in attr->aggregator resp. attr->aspath so
3493 * we can chuck as4_aggregator and as4_path alltogether in order
3497 * unintern - it is in the hash
3498 * The flag that we got this is still there, but that
3499 * does not do any trouble
3501 aspath_unintern(&as4_path
);
3503 transit
= bgp_attr_get_transit(attr
);
3504 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3505 /* Finally intern unknown attribute. */
3507 bgp_attr_set_transit(attr
, transit_intern(transit
));
3508 if (attr
->encap_subtlvs
)
3509 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3511 #ifdef ENABLE_BGP_VNC
3512 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3513 bgp_attr_get_vnc_subtlvs(attr
);
3516 bgp_attr_set_vnc_subtlvs(
3518 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3522 transit_free(transit
);
3523 bgp_attr_set_transit(attr
, NULL
);
3526 bgp_attr_flush_encap(attr
);
3530 transit
= bgp_attr_get_transit(attr
);
3532 assert(transit
->refcnt
> 0);
3533 if (attr
->encap_subtlvs
)
3534 assert(attr
->encap_subtlvs
->refcnt
> 0);
3535 #ifdef ENABLE_BGP_VNC
3536 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3537 bgp_attr_get_vnc_subtlvs(attr
);
3540 assert(vnc_subtlvs
->refcnt
> 0);
3547 * Extract the tunnel type from extended community
3549 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3550 bgp_encap_types
*tunnel_type
)
3552 struct ecommunity
*ecom
;
3558 ecom
= bgp_attr_get_ecommunity(attr
);
3559 if (!ecom
|| !ecom
->size
)
3562 for (i
= 0; i
< ecom
->size
; i
++) {
3564 uint8_t type
, sub_type
;
3566 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3569 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3570 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3572 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3579 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3580 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3585 iana_safi_t pkt_safi
;
3588 /* Set extended bit always to encode the attribute length as 2 bytes */
3589 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3590 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3591 sizep
= stream_get_endp(s
);
3592 stream_putw(s
, 0); /* Marker: Attribute length. */
3595 /* Convert AFI, SAFI to values for packet. */
3596 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3598 stream_putw(s
, pkt_afi
); /* AFI */
3599 stream_putc(s
, pkt_safi
); /* SAFI */
3603 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3604 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3605 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3606 else if (safi
== SAFI_FLOWSPEC
)
3609 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3612 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3617 case SAFI_MULTICAST
:
3618 case SAFI_LABELED_UNICAST
:
3620 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3624 stream_putl(s
, 0); /* RD = 0, per RFC */
3626 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3631 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3634 if (attr
->mp_nexthop_len
== 0)
3635 stream_putc(s
, 0); /* no nexthop for flowspec */
3637 stream_putc(s
, attr
->mp_nexthop_len
);
3638 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3647 case SAFI_MULTICAST
:
3648 case SAFI_LABELED_UNICAST
:
3650 if (attr
->mp_nexthop_len
3651 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3653 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3654 stream_put(s
, &attr
->mp_nexthop_global
,
3656 stream_put(s
, &attr
->mp_nexthop_local
,
3659 stream_putc(s
, IPV6_MAX_BYTELEN
);
3660 stream_put(s
, &attr
->mp_nexthop_global
,
3664 case SAFI_MPLS_VPN
: {
3665 if (attr
->mp_nexthop_len
3666 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3668 stream_putl(s
, 0); /* RD = 0, per RFC */
3670 stream_put(s
, &attr
->mp_nexthop_global
,
3672 } else if (attr
->mp_nexthop_len
3673 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3675 stream_putl(s
, 0); /* RD = 0, per RFC */
3677 stream_put(s
, &attr
->mp_nexthop_global
,
3679 stream_putl(s
, 0); /* RD = 0, per RFC */
3681 stream_put(s
, &attr
->mp_nexthop_local
,
3686 stream_putc(s
, IPV6_MAX_BYTELEN
);
3687 stream_put(s
, &attr
->mp_nexthop_global
,
3691 stream_putc(s
, 0); /* no nexthop for flowspec */
3697 if (safi
!= SAFI_FLOWSPEC
)
3699 EC_BGP_ATTR_NH_SEND_LEN
,
3700 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3701 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3710 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3711 const struct prefix
*p
,
3712 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3713 uint32_t num_labels
, bool addpath_capable
,
3714 uint32_t addpath_tx_id
, struct attr
*attr
)
3716 if (safi
== SAFI_MPLS_VPN
) {
3717 if (addpath_capable
)
3718 stream_putl(s
, addpath_tx_id
);
3719 /* Label, RD, Prefix write. */
3720 stream_putc(s
, p
->prefixlen
+ 88);
3721 stream_put(s
, label
, BGP_LABEL_BYTES
);
3722 stream_put(s
, prd
->val
, 8);
3723 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3724 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3725 /* EVPN prefix - contents depend on type */
3726 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3727 addpath_capable
, addpath_tx_id
);
3728 } else if (safi
== SAFI_LABELED_UNICAST
) {
3729 /* Prefix write with label. */
3730 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3732 } else if (safi
== SAFI_FLOWSPEC
) {
3733 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3734 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3735 p
->u
.prefix_flowspec
.prefixlen
);
3737 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
3740 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3741 const struct prefix
*p
)
3743 int size
= PSIZE(p
->prefixlen
);
3744 if (safi
== SAFI_MPLS_VPN
)
3746 else if (safi
== SAFI_LABELED_UNICAST
)
3747 size
+= BGP_LABEL_BYTES
;
3748 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3749 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3755 * Encodes the tunnel encapsulation attribute,
3756 * and with ENABLE_BGP_VNC the VNC attribute which uses
3757 * almost the same TLV format
3759 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3760 struct stream
*s
, struct attr
*attr
,
3763 unsigned int attrlenfield
= 0;
3764 unsigned int attrhdrlen
= 0;
3765 struct bgp_attr_encap_subtlv
*subtlvs
;
3766 struct bgp_attr_encap_subtlv
*st
;
3767 const char *attrname
;
3769 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3770 && (!attr
->encap_tunneltype
3771 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3775 case BGP_ATTR_ENCAP
:
3776 attrname
= "Tunnel Encap";
3777 subtlvs
= attr
->encap_subtlvs
;
3778 if (subtlvs
== NULL
) /* nothing to do */
3781 * The tunnel encap attr has an "outer" tlv.
3783 * L = total length of subtlvs,
3784 * V = concatenated subtlvs.
3786 attrlenfield
= 2 + 2; /* T + L */
3787 attrhdrlen
= 1 + 1; /* subTLV T + L */
3790 #ifdef ENABLE_BGP_VNC_ATTR
3793 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3794 if (subtlvs
== NULL
) /* nothing to do */
3796 attrlenfield
= 0; /* no outer T + L */
3797 attrhdrlen
= 2 + 2; /* subTLV T + L */
3805 /* compute attr length */
3806 for (st
= subtlvs
; st
; st
= st
->next
) {
3807 attrlenfield
+= (attrhdrlen
+ st
->length
);
3810 if (attrlenfield
> 0xffff) {
3811 zlog_info("%s attribute is too long (length=%d), can't send it",
3812 attrname
, attrlenfield
);
3816 if (attrlenfield
> 0xff) {
3817 /* 2-octet length field */
3819 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3820 | BGP_ATTR_FLAG_EXTLEN
);
3821 stream_putc(s
, attrtype
);
3822 stream_putw(s
, attrlenfield
& 0xffff);
3824 /* 1-octet length field */
3825 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3826 stream_putc(s
, attrtype
);
3827 stream_putc(s
, attrlenfield
& 0xff);
3830 if (attrtype
== BGP_ATTR_ENCAP
) {
3831 /* write outer T+L */
3832 stream_putw(s
, attr
->encap_tunneltype
);
3833 stream_putw(s
, attrlenfield
- 4);
3836 /* write each sub-tlv */
3837 for (st
= subtlvs
; st
; st
= st
->next
) {
3838 if (attrtype
== BGP_ATTR_ENCAP
) {
3839 stream_putc(s
, st
->type
);
3840 stream_putc(s
, st
->length
);
3841 #ifdef ENABLE_BGP_VNC
3843 stream_putw(s
, st
->type
);
3844 stream_putw(s
, st
->length
);
3847 stream_put(s
, st
->value
, st
->length
);
3851 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3853 /* Set MP attribute length. Don't count the (2) bytes used to encode
3855 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3858 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3860 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3861 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3862 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3863 PEER_FLAG_REMOVE_PRIVATE_AS
)
3864 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3865 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3866 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3867 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3868 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3869 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3874 /* Make attribute packet. */
3875 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3876 struct stream
*s
, struct attr
*attr
,
3877 struct bpacket_attr_vec_arr
*vecarr
,
3878 struct prefix
*p
, afi_t afi
, safi_t safi
,
3879 struct peer
*from
, struct prefix_rd
*prd
,
3880 mpls_label_t
*label
, uint32_t num_labels
,
3881 bool addpath_capable
, uint32_t addpath_tx_id
)
3884 size_t aspath_sizep
;
3885 struct aspath
*aspath
;
3886 int send_as4_path
= 0;
3887 int send_as4_aggregator
= 0;
3888 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
3889 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
3894 /* Remember current pointer. */
3895 cp
= stream_get_endp(s
);
3898 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3899 && !peer_cap_enhe(peer
, afi
, safi
))) {
3900 size_t mpattrlen_pos
= 0;
3902 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3904 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3905 num_labels
, addpath_capable
,
3906 addpath_tx_id
, attr
);
3907 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3910 /* Origin attribute. */
3911 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3912 stream_putc(s
, BGP_ATTR_ORIGIN
);
3914 stream_putc(s
, attr
->origin
);
3916 /* AS path attribute. */
3918 /* If remote-peer is EBGP */
3919 if (peer
->sort
== BGP_PEER_EBGP
3920 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3921 PEER_FLAG_AS_PATH_UNCHANGED
)
3922 || attr
->aspath
->segments
== NULL
)
3923 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3924 PEER_FLAG_RSERVER_CLIENT
))) {
3925 aspath
= aspath_dup(attr
->aspath
);
3927 /* Even though we may not be configured for confederations we
3929 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3930 aspath
= aspath_delete_confed_seq(aspath
);
3932 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3933 /* Stuff our path CONFED_ID on the front */
3934 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3936 if (peer
->change_local_as
) {
3937 /* If replace-as is specified, we only use the
3938 change_local_as when
3939 advertising routes. */
3940 if (!CHECK_FLAG(peer
->flags
,
3941 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3942 if (bgp_append_local_as(peer
, afi
,
3944 aspath
= aspath_add_seq(
3945 aspath
, peer
->local_as
);
3946 aspath
= aspath_add_seq(aspath
,
3947 peer
->change_local_as
);
3949 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3952 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3953 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3955 aspath
= aspath_dup(attr
->aspath
);
3956 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3958 aspath
= attr
->aspath
;
3960 /* If peer is not AS4 capable, then:
3961 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3962 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3964 * types are in it (i.e. exclude them if they are there)
3965 * AND do this only if there is at least one asnum > 65535 in the
3967 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3969 * all ASnums > 65535 to BGP_AS_TRANS
3972 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3973 stream_putc(s
, BGP_ATTR_AS_PATH
);
3974 aspath_sizep
= stream_get_endp(s
);
3976 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3978 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3981 if (!use32bit
&& aspath_has_as4(aspath
))
3983 1; /* we'll do this later, at the correct place */
3985 /* Nexthop attribute. */
3986 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3987 && !peer_cap_enhe(peer
, afi
, safi
)) {
3988 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3990 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3991 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3992 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3993 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3996 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3997 } else if (peer_cap_enhe(from
, afi
, safi
)
3998 || (nh_afi
== AFI_IP6
)) {
4000 * Likely this is the case when an IPv4 prefix was
4001 * received with Extended Next-hop capability in this
4002 * or another vrf and is now being advertised to
4003 * non-ENHE peers. Since peer_cap_enhe only checks
4004 * peers in this vrf, also check the nh_afi to catch
4005 * the case where the originator was in another vrf.
4006 * Setting the mandatory (ipv4) next-hop attribute here
4007 * to enable implicit next-hop self with correct A-F
4008 * (ipv4 address family).
4010 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4011 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4012 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4015 stream_put_ipv4(s
, 0);
4019 /* MED attribute. */
4020 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4021 || bgp
->maxmed_active
) {
4022 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4023 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4025 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4029 /* Local preference. */
4030 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4031 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4032 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4034 stream_putl(s
, attr
->local_pref
);
4037 /* Atomic aggregate. */
4038 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4039 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4040 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4045 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4046 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4047 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4048 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4051 /* AS4 capable peer */
4053 stream_putl(s
, attr
->aggregator_as
);
4055 /* 2-byte AS peer */
4058 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4060 if (attr
->aggregator_as
> UINT16_MAX
) {
4061 stream_putw(s
, BGP_AS_TRANS
);
4063 /* we have to send AS4_AGGREGATOR, too.
4064 * we'll do that later in order to send
4065 * attributes in ascending
4068 send_as4_aggregator
= 1;
4070 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4072 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4075 /* Community attribute. */
4076 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4077 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4078 if (attr
->community
->size
* 4 > 255) {
4080 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4081 | BGP_ATTR_FLAG_EXTLEN
);
4082 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4083 stream_putw(s
, attr
->community
->size
* 4);
4086 BGP_ATTR_FLAG_OPTIONAL
4087 | BGP_ATTR_FLAG_TRANS
);
4088 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4089 stream_putc(s
, attr
->community
->size
* 4);
4091 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4095 * Large Community attribute.
4097 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4098 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4099 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4100 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4102 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4103 | BGP_ATTR_FLAG_EXTLEN
);
4104 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4106 lcom_length(bgp_attr_get_lcommunity(attr
)));
4109 BGP_ATTR_FLAG_OPTIONAL
4110 | BGP_ATTR_FLAG_TRANS
);
4111 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4113 lcom_length(bgp_attr_get_lcommunity(attr
)));
4115 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4116 lcom_length(bgp_attr_get_lcommunity(attr
)));
4119 /* Route Reflector. */
4120 if (peer
->sort
== BGP_PEER_IBGP
&& from
4121 && from
->sort
== BGP_PEER_IBGP
) {
4122 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4124 /* Originator ID. */
4125 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4126 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4129 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4130 stream_put_in_addr(s
, &attr
->originator_id
);
4132 stream_put_in_addr(s
, &from
->remote_id
);
4135 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4136 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4139 stream_putc(s
, cluster
->length
+ 4);
4140 /* If this peer configuration's parent BGP has
4142 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4143 stream_put_in_addr(s
, &bgp
->cluster_id
);
4145 stream_put_in_addr(s
, &bgp
->router_id
);
4146 stream_put(s
, cluster
->list
, cluster
->length
);
4149 /* If this peer configuration's parent BGP has
4151 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4152 stream_put_in_addr(s
, &bgp
->cluster_id
);
4154 stream_put_in_addr(s
, &bgp
->router_id
);
4158 /* Extended Communities attribute. */
4159 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4160 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4161 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4163 if (peer
->sort
== BGP_PEER_IBGP
4164 || peer
->sort
== BGP_PEER_CONFED
) {
4165 if (ecomm
->size
* 8 > 255) {
4167 BGP_ATTR_FLAG_OPTIONAL
4168 | BGP_ATTR_FLAG_TRANS
4169 | BGP_ATTR_FLAG_EXTLEN
);
4170 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4171 stream_putw(s
, ecomm
->size
* 8);
4174 BGP_ATTR_FLAG_OPTIONAL
4175 | BGP_ATTR_FLAG_TRANS
);
4176 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4177 stream_putc(s
, ecomm
->size
* 8);
4179 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4183 int ecom_tr_size
= 0;
4186 for (i
= 0; i
< ecomm
->size
; i
++) {
4187 pnt
= ecomm
->val
+ (i
* 8);
4190 if (CHECK_FLAG(tbit
,
4191 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4198 if (ecom_tr_size
* 8 > 255) {
4201 BGP_ATTR_FLAG_OPTIONAL
4202 | BGP_ATTR_FLAG_TRANS
4203 | BGP_ATTR_FLAG_EXTLEN
);
4205 BGP_ATTR_EXT_COMMUNITIES
);
4206 stream_putw(s
, ecom_tr_size
* 8);
4210 BGP_ATTR_FLAG_OPTIONAL
4211 | BGP_ATTR_FLAG_TRANS
);
4213 BGP_ATTR_EXT_COMMUNITIES
);
4214 stream_putc(s
, ecom_tr_size
* 8);
4217 for (i
= 0; i
< ecomm
->size
; i
++) {
4218 pnt
= ecomm
->val
+ (i
* 8);
4223 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4226 stream_put(s
, pnt
, 8);
4232 /* Label index attribute. */
4233 if (safi
== SAFI_LABELED_UNICAST
) {
4234 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4235 uint32_t label_index
;
4237 label_index
= attr
->label_index
;
4239 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4241 BGP_ATTR_FLAG_OPTIONAL
4242 | BGP_ATTR_FLAG_TRANS
);
4243 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4245 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4247 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4248 stream_putc(s
, 0); // reserved
4249 stream_putw(s
, 0); // flags
4250 stream_putl(s
, label_index
);
4255 /* SRv6 Service Information Attribute. */
4256 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4257 if (attr
->srv6_l3vpn
) {
4258 uint8_t subtlv_len
=
4259 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4261 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4262 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4263 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4264 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4265 | BGP_ATTR_FLAG_TRANS
);
4266 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4267 stream_putc(s
, attr_len
);
4268 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4269 stream_putw(s
, tlv_len
);
4270 stream_putc(s
, 0); /* reserved */
4271 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4272 stream_putw(s
, subtlv_len
);
4273 stream_putc(s
, 0); /* reserved */
4274 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4275 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4276 stream_putc(s
, 0); /* sid_flags */
4277 stream_putw(s
, 0xffff); /* endpoint */
4278 stream_putc(s
, 0); /* reserved */
4281 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4284 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4285 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4286 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4287 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4288 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4289 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4290 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4291 } else if (attr
->srv6_vpn
) {
4292 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4293 | BGP_ATTR_FLAG_TRANS
);
4294 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4295 stream_putc(s
, 22); /* tlv len */
4296 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4297 stream_putw(s
, 0x13); /* tlv len */
4298 stream_putc(s
, 0x00); /* reserved */
4299 stream_putc(s
, 0x01); /* sid_type */
4300 stream_putc(s
, 0x00); /* sif_flags */
4301 stream_put(s
, &attr
->srv6_vpn
->sid
,
4302 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4306 if (send_as4_path
) {
4307 /* If the peer is NOT As4 capable, AND */
4308 /* there are ASnums > 65535 in path THEN
4309 * give out AS4_PATH */
4311 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4313 * Hm, I wonder... confederation things *should* only be at
4314 * the beginning of an aspath, right? Then we should use
4315 * aspath_delete_confed_seq for this, because it is already
4317 * Folks, talk to me: what is reasonable here!?
4319 aspath
= aspath_delete_confed_seq(aspath
);
4322 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4323 | BGP_ATTR_FLAG_EXTLEN
);
4324 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4325 aspath_sizep
= stream_get_endp(s
);
4327 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4330 if (aspath
!= attr
->aspath
)
4331 aspath_free(aspath
);
4333 if (send_as4_aggregator
) {
4334 /* send AS4_AGGREGATOR, at this place */
4335 /* this section of code moved here in order to ensure the
4337 * *ascending* order of attributes
4339 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4340 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4342 stream_putl(s
, attr
->aggregator_as
);
4343 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4346 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4347 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4348 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4349 /* Tunnel Encap attribute */
4350 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4352 #ifdef ENABLE_BGP_VNC_ATTR
4354 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4359 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4360 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4361 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4362 stream_putc(s
, 9); // Length
4363 stream_putc(s
, 0); // Flags
4364 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4365 stream_put(s
, &(attr
->label
),
4366 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4367 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4368 // Unicast tunnel endpoint IP address
4371 /* Unknown transit attribute. */
4372 struct transit
*transit
= bgp_attr_get_transit(attr
);
4375 stream_put(s
, transit
->val
, transit
->length
);
4377 /* Return total size of attribute. */
4378 return stream_get_endp(s
) - cp
;
4381 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4383 unsigned long attrlen_pnt
;
4385 iana_safi_t pkt_safi
;
4387 /* Set extended bit always to encode the attribute length as 2 bytes */
4388 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4389 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4391 attrlen_pnt
= stream_get_endp(s
);
4392 stream_putw(s
, 0); /* Length of this attribute. */
4394 /* Convert AFI, SAFI to values for packet. */
4395 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4397 stream_putw(s
, pkt_afi
);
4398 stream_putc(s
, pkt_safi
);
4403 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4404 afi_t afi
, safi_t safi
,
4405 const struct prefix_rd
*prd
,
4406 mpls_label_t
*label
, uint32_t num_labels
,
4407 bool addpath_capable
, uint32_t addpath_tx_id
,
4410 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4412 if (safi
== SAFI_LABELED_UNICAST
) {
4413 label
= (mpls_label_t
*)wlabel
;
4417 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4418 addpath_capable
, addpath_tx_id
, attr
);
4421 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4423 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4426 /* Initialization of attribute. */
4427 void bgp_attr_init(void)
4440 void bgp_attr_finish(void)
4445 ecommunity_finish();
4446 lcommunity_finish();
4453 /* Make attribute packet. */
4454 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4455 const struct prefix
*prefix
)
4460 struct aspath
*aspath
;
4461 bool addpath_capable
= false;
4462 uint32_t addpath_tx_id
= 0;
4464 /* Remember current pointer. */
4465 cp
= stream_get_endp(s
);
4467 /* Place holder of length. */
4470 /* Origin attribute. */
4471 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4472 stream_putc(s
, BGP_ATTR_ORIGIN
);
4474 stream_putc(s
, attr
->origin
);
4476 aspath
= attr
->aspath
;
4478 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4479 stream_putc(s
, BGP_ATTR_AS_PATH
);
4480 aspath_lenp
= stream_get_endp(s
);
4483 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4485 /* Nexthop attribute. */
4486 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4487 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4488 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4489 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4491 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4494 /* MED attribute. */
4495 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4496 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4497 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4499 stream_putl(s
, attr
->med
);
4502 /* Local preference. */
4503 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4504 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4505 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4507 stream_putl(s
, attr
->local_pref
);
4510 /* Atomic aggregate. */
4511 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4512 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4513 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4518 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4519 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4520 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4522 stream_putl(s
, attr
->aggregator_as
);
4523 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4526 /* Community attribute. */
4527 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4528 if (attr
->community
->size
* 4 > 255) {
4530 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4531 | BGP_ATTR_FLAG_EXTLEN
);
4532 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4533 stream_putw(s
, attr
->community
->size
* 4);
4536 BGP_ATTR_FLAG_OPTIONAL
4537 | BGP_ATTR_FLAG_TRANS
);
4538 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4539 stream_putc(s
, attr
->community
->size
* 4);
4541 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4544 /* Large Community attribute. */
4545 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4546 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4548 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4549 | BGP_ATTR_FLAG_EXTLEN
);
4550 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4552 lcom_length(bgp_attr_get_lcommunity(attr
)));
4555 BGP_ATTR_FLAG_OPTIONAL
4556 | BGP_ATTR_FLAG_TRANS
);
4557 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4559 lcom_length(bgp_attr_get_lcommunity(attr
)));
4562 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4563 lcom_length(bgp_attr_get_lcommunity(attr
)));
4566 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4567 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4568 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4569 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4572 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4573 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4574 sizep
= stream_get_endp(s
);
4577 stream_putc(s
, 0); /* Marker: Attribute length. */
4578 stream_putw(s
, AFI_IP6
); /* AFI */
4579 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4582 stream_putc(s
, attr
->mp_nexthop_len
);
4583 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4584 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4585 stream_put(s
, &attr
->mp_nexthop_local
,
4592 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4595 /* Set MP attribute length. */
4596 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4600 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4601 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4603 BGP_ATTR_FLAG_OPTIONAL
4604 | BGP_ATTR_FLAG_TRANS
);
4605 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4607 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4608 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4609 stream_putc(s
, 0); // reserved
4610 stream_putw(s
, 0); // flags
4611 stream_putl(s
, attr
->label_index
);
4615 /* Return total size of attribute. */
4616 len
= stream_get_endp(s
) - cp
- 2;
4617 stream_putw_at(s
, cp
, len
);