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
));
672 if (bgp_attr_get_community(attr
))
673 MIX(community_hash_make(bgp_attr_get_community(attr
)));
674 if (bgp_attr_get_lcommunity(attr
))
675 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
676 if (bgp_attr_get_ecommunity(attr
))
677 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
678 if (bgp_attr_get_ipv6_ecommunity(attr
))
679 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
680 if (bgp_attr_get_cluster(attr
))
681 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
682 if (bgp_attr_get_transit(attr
))
683 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
684 if (attr
->encap_subtlvs
)
685 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
686 if (attr
->srv6_l3vpn
)
687 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
689 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
690 #ifdef ENABLE_BGP_VNC
691 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
692 bgp_attr_get_vnc_subtlvs(attr
);
694 MIX(encap_hash_key_make(vnc_subtlvs
));
696 MIX(attr
->mp_nexthop_len
);
697 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
698 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
699 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
700 MIX(attr
->rmap_table_id
);
707 bool attrhash_cmp(const void *p1
, const void *p2
)
709 const struct attr
*attr1
= p1
;
710 const struct attr
*attr2
= p2
;
712 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
713 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
714 && attr1
->aspath
== attr2
->aspath
715 && bgp_attr_get_community(attr1
)
716 == bgp_attr_get_community(attr2
)
717 && attr1
->med
== attr2
->med
718 && attr1
->local_pref
== attr2
->local_pref
719 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
720 if (attr1
->aggregator_as
== attr2
->aggregator_as
721 && attr1
->aggregator_addr
.s_addr
722 == attr2
->aggregator_addr
.s_addr
723 && attr1
->weight
== attr2
->weight
724 && attr1
->tag
== attr2
->tag
725 && attr1
->label_index
== attr2
->label_index
726 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
727 && bgp_attr_get_ecommunity(attr1
)
728 == bgp_attr_get_ecommunity(attr2
)
729 && bgp_attr_get_ipv6_ecommunity(attr1
)
730 == bgp_attr_get_ipv6_ecommunity(attr2
)
731 && bgp_attr_get_lcommunity(attr1
)
732 == bgp_attr_get_lcommunity(attr2
)
733 && bgp_attr_get_cluster(attr1
)
734 == bgp_attr_get_cluster(attr2
)
735 && bgp_attr_get_transit(attr1
)
736 == bgp_attr_get_transit(attr2
)
737 && attr1
->rmap_table_id
== attr2
->rmap_table_id
738 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
739 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
740 #ifdef ENABLE_BGP_VNC
741 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
742 bgp_attr_get_vnc_subtlvs(attr2
))
744 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
745 &attr2
->mp_nexthop_global
)
746 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
747 &attr2
->mp_nexthop_local
)
748 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
749 &attr2
->mp_nexthop_global_in
)
750 && IPV4_ADDR_SAME(&attr1
->originator_id
,
751 &attr2
->originator_id
)
752 && overlay_index_same(attr1
, attr2
)
753 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
754 && attr1
->es_flags
== attr2
->es_flags
755 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
756 && attr1
->df_pref
== attr2
->df_pref
757 && attr1
->df_alg
== attr2
->df_alg
758 && attr1
->nh_ifindex
== attr2
->nh_ifindex
759 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
760 && attr1
->distance
== attr2
->distance
761 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
762 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
763 && attr1
->srte_color
== attr2
->srte_color
764 && attr1
->nh_type
== attr2
->nh_type
765 && attr1
->bh_type
== attr2
->bh_type
)
772 static void attrhash_init(void)
775 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
779 * special for hash_clean below
781 static void attr_vfree(void *attr
)
783 XFREE(MTYPE_ATTR
, attr
);
786 static void attrhash_finish(void)
788 hash_clean(attrhash
, attr_vfree
);
793 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
795 struct attr
*attr
= bucket
->data
;
796 char sid_str
[BUFSIZ
];
798 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
801 if (attr
->srv6_l3vpn
)
802 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
803 else if (attr
->srv6_vpn
)
804 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
807 "\tflags: %" PRIu64
" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
808 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
809 attr
->origin
, attr
->weight
, attr
->label
, sid_str
);
812 void attr_show_all(struct vty
*vty
)
814 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
815 void *))attr_show_all_iterator
,
819 static void *bgp_attr_hash_alloc(void *p
)
821 struct attr
*val
= (struct attr
*)p
;
824 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
826 if (val
->encap_subtlvs
) {
827 val
->encap_subtlvs
= NULL
;
829 #ifdef ENABLE_BGP_VNC
830 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
831 bgp_attr_get_vnc_subtlvs(val
);
834 bgp_attr_set_vnc_subtlvs(val
, NULL
);
841 /* Internet argument attribute. */
842 struct attr
*bgp_attr_intern(struct attr
*attr
)
845 struct ecommunity
*ecomm
= NULL
;
846 struct ecommunity
*ipv6_ecomm
= NULL
;
847 struct lcommunity
*lcomm
= NULL
;
848 struct community
*comm
= NULL
;
850 /* Intern referenced strucutre. */
852 if (!attr
->aspath
->refcnt
)
853 attr
->aspath
= aspath_intern(attr
->aspath
);
855 attr
->aspath
->refcnt
++;
858 comm
= bgp_attr_get_community(attr
);
861 bgp_attr_set_community(attr
, community_intern(comm
));
866 ecomm
= bgp_attr_get_ecommunity(attr
);
869 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
874 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
876 if (!ipv6_ecomm
->refcnt
)
877 bgp_attr_set_ipv6_ecommunity(
878 attr
, ecommunity_intern(ipv6_ecomm
));
880 ipv6_ecomm
->refcnt
++;
883 lcomm
= bgp_attr_get_lcommunity(attr
);
886 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
891 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
894 if (!cluster
->refcnt
)
895 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
900 struct transit
*transit
= bgp_attr_get_transit(attr
);
903 if (!transit
->refcnt
)
904 bgp_attr_set_transit(attr
, transit_intern(transit
));
908 if (attr
->encap_subtlvs
) {
909 if (!attr
->encap_subtlvs
->refcnt
)
910 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
913 attr
->encap_subtlvs
->refcnt
++;
915 if (attr
->srv6_l3vpn
) {
916 if (!attr
->srv6_l3vpn
->refcnt
)
917 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
919 attr
->srv6_l3vpn
->refcnt
++;
921 if (attr
->srv6_vpn
) {
922 if (!attr
->srv6_vpn
->refcnt
)
923 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
925 attr
->srv6_vpn
->refcnt
++;
927 #ifdef ENABLE_BGP_VNC
928 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
929 bgp_attr_get_vnc_subtlvs(attr
);
932 if (!vnc_subtlvs
->refcnt
)
933 bgp_attr_set_vnc_subtlvs(
935 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
937 vnc_subtlvs
->refcnt
++;
941 /* At this point, attr only contains intern'd pointers. that means
942 * if we find it in attrhash, it has all the same pointers and we
943 * correctly updated the refcounts on these.
944 * If we don't find it, we need to allocate a one because in all
945 * cases this returns a new reference to a hashed attr, but the input
947 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
953 /* Make network statement's attribute. */
954 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
956 memset(attr
, 0, sizeof(struct attr
));
958 attr
->origin
= origin
;
959 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
960 attr
->aspath
= aspath_empty();
961 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
962 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
964 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
965 attr
->label
= MPLS_INVALID_LABEL
;
966 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
967 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
972 /* Create the attributes for an aggregate */
973 struct attr
*bgp_attr_aggregate_intern(
974 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
975 struct community
*community
, struct ecommunity
*ecommunity
,
976 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
977 uint8_t atomic_aggregate
, const struct prefix
*p
)
983 memset(&attr
, 0, sizeof(struct attr
));
985 /* Origin attribute. */
986 attr
.origin
= origin
;
987 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
989 /* AS path attribute. */
991 attr
.aspath
= aspath_intern(aspath
);
993 attr
.aspath
= aspath_empty();
994 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
996 /* Next hop attribute. */
997 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1000 uint32_t gshut
= COMMUNITY_GSHUT
;
1002 /* If we are not shutting down ourselves and we are
1003 * aggregating a route that contains the GSHUT community we
1004 * need to remove that community when creating the aggregate */
1005 if (!bgp_in_graceful_shutdown(bgp
)
1006 && community_include(community
, gshut
)) {
1007 community_del_val(community
, &gshut
);
1010 bgp_attr_set_community(&attr
, community
);
1011 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1015 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1016 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1020 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1021 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1024 if (bgp_in_graceful_shutdown(bgp
))
1025 bgp_attr_add_gshut_community(&attr
);
1027 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1028 attr
.label
= MPLS_INVALID_LABEL
;
1029 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1030 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1031 if (!aggregate
->as_set
|| atomic_aggregate
)
1032 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1033 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1034 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1035 attr
.aggregator_as
= bgp
->confed_id
;
1037 attr
.aggregator_as
= bgp
->as
;
1038 attr
.aggregator_addr
= bgp
->router_id
;
1039 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1040 attr
.label
= MPLS_INVALID_LABEL
;
1042 /* Apply route-map */
1043 if (aggregate
->rmap
.name
) {
1044 struct attr attr_tmp
= attr
;
1045 struct bgp_path_info rmap_path
;
1047 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1048 rmap_path
.peer
= bgp
->peer_self
;
1049 rmap_path
.attr
= &attr_tmp
;
1051 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1053 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1055 bgp
->peer_self
->rmap_type
= 0;
1057 if (ret
== RMAP_DENYMATCH
) {
1058 /* Free uninterned attribute. */
1059 bgp_attr_flush(&attr_tmp
);
1061 /* Unintern original. */
1062 aspath_unintern(&attr
.aspath
);
1066 if (bgp_in_graceful_shutdown(bgp
))
1067 bgp_attr_add_gshut_community(&attr_tmp
);
1069 new = bgp_attr_intern(&attr_tmp
);
1072 if (bgp_in_graceful_shutdown(bgp
))
1073 bgp_attr_add_gshut_community(&attr
);
1075 new = bgp_attr_intern(&attr
);
1078 /* Always release the 'intern()'ed AS Path. */
1079 aspath_unintern(&attr
.aspath
);
1084 /* Unintern just the sub-components of the attr, but not the attr */
1085 void bgp_attr_unintern_sub(struct attr
*attr
)
1087 struct ecommunity
*ecomm
= NULL
;
1088 struct ecommunity
*ipv6_ecomm
= NULL
;
1089 struct cluster_list
*cluster
;
1090 struct lcommunity
*lcomm
= NULL
;
1091 struct community
*comm
= NULL
;
1093 /* aspath refcount shoud be decrement. */
1094 aspath_unintern(&attr
->aspath
);
1095 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1097 comm
= bgp_attr_get_community(attr
);
1098 community_unintern(&comm
);
1099 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1100 bgp_attr_set_community(attr
, NULL
);
1102 ecomm
= bgp_attr_get_ecommunity(attr
);
1103 ecommunity_unintern(&ecomm
);
1104 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
1105 bgp_attr_set_ecommunity(attr
, NULL
);
1107 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1108 ecommunity_unintern(&ipv6_ecomm
);
1109 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
));
1110 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1112 lcomm
= bgp_attr_get_lcommunity(attr
);
1113 lcommunity_unintern(&lcomm
);
1114 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1115 bgp_attr_set_lcommunity(attr
, NULL
);
1117 cluster
= bgp_attr_get_cluster(attr
);
1119 cluster_unintern(&cluster
);
1120 bgp_attr_set_cluster(attr
, cluster
);
1122 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1124 struct transit
*transit
= bgp_attr_get_transit(attr
);
1127 transit_unintern(&transit
);
1128 bgp_attr_set_transit(attr
, transit
);
1131 if (attr
->encap_subtlvs
)
1132 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1134 #ifdef ENABLE_BGP_VNC
1135 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1136 bgp_attr_get_vnc_subtlvs(attr
);
1139 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1140 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1144 if (attr
->srv6_l3vpn
)
1145 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1148 srv6_vpn_unintern(&attr
->srv6_vpn
);
1151 /* Free bgp attribute and aspath. */
1152 void bgp_attr_unintern(struct attr
**pattr
)
1154 struct attr
*attr
= *pattr
;
1158 /* Decrement attribute reference. */
1163 /* If reference becomes zero then free attribute object. */
1164 if (attr
->refcnt
== 0) {
1165 ret
= hash_release(attrhash
, attr
);
1166 assert(ret
!= NULL
);
1167 XFREE(MTYPE_ATTR
, attr
);
1171 bgp_attr_unintern_sub(&tmp
);
1174 void bgp_attr_flush(struct attr
*attr
)
1176 struct ecommunity
*ecomm
;
1177 struct ecommunity
*ipv6_ecomm
;
1178 struct cluster_list
*cluster
;
1179 struct lcommunity
*lcomm
;
1180 struct community
*comm
;
1182 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1183 aspath_free(attr
->aspath
);
1184 attr
->aspath
= NULL
;
1186 comm
= bgp_attr_get_community(attr
);
1187 if (comm
&& !comm
->refcnt
)
1188 community_free(&comm
);
1189 bgp_attr_set_community(attr
, NULL
);
1191 ecomm
= bgp_attr_get_ecommunity(attr
);
1192 if (ecomm
&& !ecomm
->refcnt
)
1193 ecommunity_free(&ecomm
);
1194 bgp_attr_set_ecommunity(attr
, NULL
);
1196 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1197 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1198 ecommunity_free(&ipv6_ecomm
);
1199 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1201 lcomm
= bgp_attr_get_lcommunity(attr
);
1202 if (lcomm
&& !lcomm
->refcnt
)
1203 lcommunity_free(&lcomm
);
1204 bgp_attr_set_lcommunity(attr
, NULL
);
1206 cluster
= bgp_attr_get_cluster(attr
);
1207 if (cluster
&& !cluster
->refcnt
) {
1208 cluster_free(cluster
);
1209 bgp_attr_set_cluster(attr
, NULL
);
1212 struct transit
*transit
= bgp_attr_get_transit(attr
);
1214 if (transit
&& !transit
->refcnt
) {
1215 transit_free(transit
);
1216 bgp_attr_set_transit(attr
, NULL
);
1218 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1219 encap_free(attr
->encap_subtlvs
);
1220 attr
->encap_subtlvs
= NULL
;
1222 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1223 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1224 attr
->srv6_l3vpn
= NULL
;
1226 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1227 srv6_vpn_free(attr
->srv6_vpn
);
1228 attr
->srv6_vpn
= NULL
;
1230 #ifdef ENABLE_BGP_VNC
1231 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1232 bgp_attr_get_vnc_subtlvs(attr
);
1234 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1235 encap_free(vnc_subtlvs
);
1236 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1241 /* Implement draft-scudder-idr-optional-transitive behaviour and
1242 * avoid resetting sessions for malformed attributes which are
1243 * are partial/optional and hence where the error likely was not
1244 * introduced by the sending neighbour.
1246 static bgp_attr_parse_ret_t
1247 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1250 struct peer
*const peer
= args
->peer
;
1251 struct attr
*const attr
= args
->attr
;
1252 const uint8_t flags
= args
->flags
;
1253 /* startp and length must be special-cased, as whether or not to
1254 * send the attribute data with the NOTIFY depends on the error,
1255 * the caller therefore signals this with the seperate length argument
1257 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1259 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1260 char attr_str
[BUFSIZ
] = {0};
1262 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1264 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1267 /* Only relax error handling for eBGP peers */
1268 if (peer
->sort
!= BGP_PEER_EBGP
) {
1269 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1270 notify_datap
, length
);
1271 return BGP_ATTR_PARSE_ERROR
;
1274 /* Adjust the stream getp to the end of the attribute, in case we can
1275 * still proceed but the caller hasn't read all the attribute.
1277 stream_set_getp(BGP_INPUT(peer
),
1278 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1281 switch (args
->type
) {
1282 /* where an attribute is relatively inconsequential, e.g. it does not
1283 * affect route selection, and can be safely ignored, then any such
1284 * attributes which are malformed should just be ignored and the route
1285 * processed as normal.
1287 case BGP_ATTR_AS4_AGGREGATOR
:
1288 case BGP_ATTR_AGGREGATOR
:
1289 case BGP_ATTR_ATOMIC_AGGREGATE
:
1290 return BGP_ATTR_PARSE_PROCEED
;
1292 /* Core attributes, particularly ones which may influence route
1293 * selection, should be treat-as-withdraw.
1295 case BGP_ATTR_ORIGIN
:
1296 case BGP_ATTR_AS_PATH
:
1297 case BGP_ATTR_NEXT_HOP
:
1298 case BGP_ATTR_MULTI_EXIT_DISC
:
1299 case BGP_ATTR_LOCAL_PREF
:
1300 case BGP_ATTR_COMMUNITIES
:
1301 case BGP_ATTR_EXT_COMMUNITIES
:
1302 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1303 case BGP_ATTR_LARGE_COMMUNITIES
:
1304 case BGP_ATTR_ORIGINATOR_ID
:
1305 case BGP_ATTR_CLUSTER_LIST
:
1306 return BGP_ATTR_PARSE_WITHDRAW
;
1307 case BGP_ATTR_MP_REACH_NLRI
:
1308 case BGP_ATTR_MP_UNREACH_NLRI
:
1309 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1310 notify_datap
, length
);
1311 return BGP_ATTR_PARSE_ERROR
;
1314 /* Partial optional attributes that are malformed should not cause
1315 * the whole session to be reset. Instead treat it as a withdrawal
1316 * of the routes, if possible.
1318 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1319 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1320 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1321 return BGP_ATTR_PARSE_WITHDRAW
;
1323 /* default to reset */
1324 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1327 /* Find out what is wrong with the path attribute flag bits and log the error.
1328 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1329 Extended Length. Checking O/T/P bits at once implies, that the attribute
1330 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1331 non-transitive" attribute. */
1333 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1334 uint8_t desired_flags
/* how RFC says it must be */
1337 uint8_t seen
= 0, i
;
1338 uint8_t real_flags
= args
->flags
;
1339 const uint8_t attr_code
= args
->type
;
1341 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1342 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1343 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1344 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1345 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1346 flog_err(EC_BGP_ATTR_FLAG
,
1347 "%s attribute must%s be flagged as \"%s\"",
1348 lookup_msg(attr_str
, attr_code
, NULL
),
1349 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1352 attr_flag_str
[i
].str
);
1357 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1358 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1359 real_flags
, desired_flags
);
1363 /* Required flags for attributes. EXTLEN will be masked off when testing,
1364 * as will PARTIAL for optional+transitive attributes.
1366 const uint8_t attr_flags_values
[] = {
1367 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1368 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1369 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1370 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1371 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1372 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1373 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1374 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1375 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1376 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1377 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1378 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1379 [BGP_ATTR_EXT_COMMUNITIES
] =
1380 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1381 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1382 [BGP_ATTR_AS4_AGGREGATOR
] =
1383 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1384 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1385 [BGP_ATTR_LARGE_COMMUNITIES
] =
1386 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1387 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1388 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1389 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1391 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1393 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1395 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1396 const uint8_t flags
= args
->flags
;
1397 const uint8_t attr_code
= args
->type
;
1399 /* there may be attributes we don't know about */
1400 if (attr_code
> attr_flags_values_max
)
1402 if (attr_flags_values
[attr_code
] == 0)
1405 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1409 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1410 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1413 "%s well-known attributes must have transitive flag set (%x)",
1414 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1418 /* "For well-known attributes and for optional non-transitive
1420 * the Partial bit MUST be set to 0."
1422 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1423 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1424 flog_err(EC_BGP_ATTR_FLAG
,
1425 "%s well-known attribute must NOT have the partial flag set (%x)",
1426 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1429 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1430 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1431 flog_err(EC_BGP_ATTR_FLAG
,
1432 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1433 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1438 /* Optional transitive attributes may go through speakers that don't
1439 * reocgnise them and set the Partial bit.
1441 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1442 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1443 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1445 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1448 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1452 /* Get origin attribute of the update message. */
1453 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1455 struct peer
*const peer
= args
->peer
;
1456 struct attr
*const attr
= args
->attr
;
1457 const bgp_size_t length
= args
->length
;
1459 /* If any recognized attribute has Attribute Length that conflicts
1460 with the expected length (based on the attribute type code), then
1461 the Error Subcode is set to Attribute Length Error. The Data
1462 field contains the erroneous attribute (type, length and
1465 flog_err(EC_BGP_ATTR_LEN
,
1466 "Origin attribute length is not one %d", length
);
1467 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1471 /* Fetch origin attribute. */
1472 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1474 /* If the ORIGIN attribute has an undefined value, then the Error
1475 Subcode is set to Invalid Origin Attribute. The Data field
1476 contains the unrecognized attribute (type, length and value). */
1477 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1478 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1479 flog_err(EC_BGP_ATTR_ORIGIN
,
1480 "Origin attribute value is invalid %d", attr
->origin
);
1481 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1485 /* Set oring attribute flag. */
1486 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1491 /* Parse AS path information. This function is wrapper of
1493 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1495 struct attr
*const attr
= args
->attr
;
1496 struct peer
*const peer
= args
->peer
;
1497 const bgp_size_t length
= args
->length
;
1500 * peer with AS4 => will get 4Byte ASnums
1501 * otherwise, will get 16 Bit
1503 attr
->aspath
= aspath_parse(
1505 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1506 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1508 /* In case of IBGP, length will be zero. */
1509 if (!attr
->aspath
) {
1510 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1511 "Malformed AS path from %s, length is %d", peer
->host
,
1513 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1517 /* Set aspath attribute flag. */
1518 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1520 return BGP_ATTR_PARSE_PROCEED
;
1523 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1524 struct attr
*const attr
)
1526 /* These checks were part of bgp_attr_aspath, but with
1527 * as4 we should to check aspath things when
1528 * aspath synthesizing with as4_path has already taken place.
1529 * Otherwise we check ASPATH and use the synthesized thing, and that is
1531 * So do the checks later, i.e. here
1533 struct aspath
*aspath
;
1535 /* Confederation sanity check. */
1536 if ((peer
->sort
== BGP_PEER_CONFED
1537 && !aspath_left_confed_check(attr
->aspath
))
1538 || (peer
->sort
== BGP_PEER_EBGP
1539 && aspath_confed_check(attr
->aspath
))) {
1540 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1542 return BGP_ATTR_PARSE_WITHDRAW
;
1545 /* First AS check for EBGP. */
1546 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1547 if (peer
->sort
== BGP_PEER_EBGP
1548 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1549 flog_err(EC_BGP_ATTR_FIRST_AS
,
1550 "%s incorrect first AS (must be %u)",
1551 peer
->host
, peer
->as
);
1552 return BGP_ATTR_PARSE_WITHDRAW
;
1556 /* Codification of AS 0 Processing */
1557 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1559 EC_BGP_ATTR_MAL_AS_PATH
,
1560 "Malformed AS path, AS number is 0 in the path from %s",
1562 return BGP_ATTR_PARSE_WITHDRAW
;
1565 /* local-as prepend */
1566 if (peer
->change_local_as
1567 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1568 aspath
= aspath_dup(attr
->aspath
);
1569 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1570 aspath_unintern(&attr
->aspath
);
1571 attr
->aspath
= aspath_intern(aspath
);
1574 return BGP_ATTR_PARSE_PROCEED
;
1577 /* Parse AS4 path information. This function is another wrapper of
1579 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1580 struct aspath
**as4_path
)
1582 struct peer
*const peer
= args
->peer
;
1583 struct attr
*const attr
= args
->attr
;
1584 const bgp_size_t length
= args
->length
;
1586 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1588 /* In case of IBGP, length will be zero. */
1590 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1591 "Malformed AS4 path from %s, length is %d", peer
->host
,
1593 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1597 /* Set aspath attribute flag. */
1598 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1600 return BGP_ATTR_PARSE_PROCEED
;
1604 * Check that the nexthop attribute is valid.
1606 bgp_attr_parse_ret_t
1607 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1609 in_addr_t nexthop_h
;
1611 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1612 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1613 || IPV4_CLASS_DE(nexthop_h
))
1614 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1615 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1616 char buf
[INET_ADDRSTRLEN
];
1618 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1620 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1622 data
[0] = BGP_ATTR_FLAG_TRANS
;
1623 data
[1] = BGP_ATTR_NEXT_HOP
;
1624 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1625 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1626 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1627 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1629 return BGP_ATTR_PARSE_ERROR
;
1632 return BGP_ATTR_PARSE_PROCEED
;
1635 /* Nexthop attribute. */
1636 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1638 struct peer
*const peer
= args
->peer
;
1639 struct attr
*const attr
= args
->attr
;
1640 const bgp_size_t length
= args
->length
;
1642 /* Check nexthop attribute length. */
1644 flog_err(EC_BGP_ATTR_LEN
,
1645 "Nexthop attribute length isn't four [%d]", length
);
1647 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1651 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1652 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1654 return BGP_ATTR_PARSE_PROCEED
;
1657 /* MED atrribute. */
1658 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1660 struct peer
*const peer
= args
->peer
;
1661 struct attr
*const attr
= args
->attr
;
1662 const bgp_size_t length
= args
->length
;
1666 flog_err(EC_BGP_ATTR_LEN
,
1667 "MED attribute length isn't four [%d]", length
);
1669 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1673 attr
->med
= stream_getl(peer
->curr
);
1675 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1677 return BGP_ATTR_PARSE_PROCEED
;
1680 /* Local preference attribute. */
1681 static bgp_attr_parse_ret_t
1682 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1684 struct peer
*const peer
= args
->peer
;
1685 struct attr
*const attr
= args
->attr
;
1686 const bgp_size_t length
= args
->length
;
1688 /* if received from an internal neighbor, it SHALL be considered
1689 * malformed if its length is not equal to 4. If malformed, the
1690 * UPDATE message SHALL be handled using the approach of "treat-as-
1693 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1694 flog_err(EC_BGP_ATTR_LEN
,
1695 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1696 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1700 /* If it is contained in an UPDATE message that is received from an
1701 external peer, then this attribute MUST be ignored by the
1702 receiving speaker. */
1703 if (peer
->sort
== BGP_PEER_EBGP
) {
1704 STREAM_FORWARD_GETP(peer
->curr
, length
);
1705 return BGP_ATTR_PARSE_PROCEED
;
1708 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1710 /* Set the local-pref flag. */
1711 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1713 return BGP_ATTR_PARSE_PROCEED
;
1716 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1720 /* Atomic aggregate. */
1721 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1723 struct attr
*const attr
= args
->attr
;
1724 const bgp_size_t length
= args
->length
;
1728 flog_err(EC_BGP_ATTR_LEN
,
1729 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1731 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1735 /* Set atomic aggregate flag. */
1736 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1738 return BGP_ATTR_PARSE_PROCEED
;
1741 /* Aggregator attribute */
1742 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1744 struct peer
*const peer
= args
->peer
;
1745 struct attr
*const attr
= args
->attr
;
1746 const bgp_size_t length
= args
->length
;
1751 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1752 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1753 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1756 if (length
!= wantedlen
) {
1757 flog_err(EC_BGP_ATTR_LEN
,
1758 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1760 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1764 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1765 aggregator_as
= stream_getl(peer
->curr
);
1767 aggregator_as
= stream_getw(peer
->curr
);
1769 attr
->aggregator_as
= aggregator_as
;
1770 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1772 /* Codification of AS 0 Processing */
1773 if (aggregator_as
== BGP_AS_ZERO
) {
1774 flog_err(EC_BGP_ATTR_LEN
,
1775 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1776 peer
->host
, aspath_print(attr
->aspath
));
1778 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1779 char attr_str
[BUFSIZ
] = {0};
1781 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1783 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1786 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1789 return BGP_ATTR_PARSE_PROCEED
;
1792 /* New Aggregator attribute */
1793 static bgp_attr_parse_ret_t
1794 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1795 as_t
*as4_aggregator_as
,
1796 struct in_addr
*as4_aggregator_addr
)
1798 struct peer
*const peer
= args
->peer
;
1799 struct attr
*const attr
= args
->attr
;
1800 const bgp_size_t length
= args
->length
;
1804 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1806 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1810 aggregator_as
= stream_getl(peer
->curr
);
1812 *as4_aggregator_as
= aggregator_as
;
1813 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1815 /* Codification of AS 0 Processing */
1816 if (aggregator_as
== BGP_AS_ZERO
) {
1817 flog_err(EC_BGP_ATTR_LEN
,
1818 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1819 peer
->host
, aspath_print(attr
->aspath
));
1821 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1822 char attr_str
[BUFSIZ
] = {0};
1824 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1826 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1829 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1832 return BGP_ATTR_PARSE_PROCEED
;
1835 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1837 static bgp_attr_parse_ret_t
1838 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1839 struct aspath
*as4_path
, as_t as4_aggregator
,
1840 struct in_addr
*as4_aggregator_addr
)
1842 int ignore_as4_path
= 0;
1843 struct aspath
*newpath
;
1845 if (!attr
->aspath
) {
1846 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1848 * checked that all well-known, mandatory attributes were
1851 * Can only be a problem with peer itself - hard error
1853 return BGP_ATTR_PARSE_ERROR
;
1856 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1857 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1859 * It is worth a warning though, because the peer really
1860 * should not send them
1862 if (BGP_DEBUG(as4
, AS4
)) {
1863 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1864 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1865 "AS4 capable peer, yet it sent");
1868 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1869 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1871 "AS4 capable peer, yet it sent");
1874 return BGP_ATTR_PARSE_PROCEED
;
1877 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1878 * because that may override AS4_PATH
1880 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1881 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1883 * if the as_number in aggregator is not AS_TRANS,
1884 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1885 * and the Aggregator shall be taken as
1886 * info on the aggregating node, and the AS_PATH
1887 * shall be taken as the AS_PATH
1889 * the Aggregator shall be ignored and the
1890 * AS4_AGGREGATOR shall be taken as the
1891 * Aggregating node and the AS_PATH is to be
1892 * constructed "as in all other cases"
1894 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1896 if (BGP_DEBUG(as4
, AS4
))
1898 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1900 ignore_as4_path
= 1;
1902 /* "New_aggregator shall be taken as aggregator"
1904 attr
->aggregator_as
= as4_aggregator
;
1905 attr
->aggregator_addr
.s_addr
=
1906 as4_aggregator_addr
->s_addr
;
1909 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1910 * That is bogus - but reading the conditions
1911 * we have to handle AS4_AGGREGATOR as if it were
1912 * AGGREGATOR in that case
1914 if (BGP_DEBUG(as4
, AS4
))
1916 "[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",
1918 attr
->aggregator_as
= as4_aggregator
;
1919 /* sweep it under the carpet and simulate a "good"
1921 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1925 /* need to reconcile NEW_AS_PATH and AS_PATH */
1926 if (!ignore_as4_path
1927 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1928 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1930 return BGP_ATTR_PARSE_ERROR
;
1932 aspath_unintern(&attr
->aspath
);
1933 attr
->aspath
= aspath_intern(newpath
);
1935 return BGP_ATTR_PARSE_PROCEED
;
1938 /* Community attribute. */
1939 static bgp_attr_parse_ret_t
1940 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1942 struct peer
*const peer
= args
->peer
;
1943 struct attr
*const attr
= args
->attr
;
1944 const bgp_size_t length
= args
->length
;
1947 bgp_attr_set_community(attr
, NULL
);
1948 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1952 bgp_attr_set_community(
1954 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
1956 /* XXX: fix community_parse to use stream API and remove this */
1957 stream_forward_getp(peer
->curr
, length
);
1959 /* The Community attribute SHALL be considered malformed if its
1960 * length is not a non-zero multiple of 4.
1962 if (!bgp_attr_get_community(attr
))
1963 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1966 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1968 return BGP_ATTR_PARSE_PROCEED
;
1971 /* Originator ID attribute. */
1972 static bgp_attr_parse_ret_t
1973 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1975 struct peer
*const peer
= args
->peer
;
1976 struct attr
*const attr
= args
->attr
;
1977 const bgp_size_t length
= args
->length
;
1979 /* if received from an internal neighbor, it SHALL be considered
1980 * malformed if its length is not equal to 4. If malformed, the
1981 * UPDATE message SHALL be handled using the approach of "treat-as-
1985 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1988 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1992 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1994 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1996 return BGP_ATTR_PARSE_PROCEED
;
1999 /* Cluster list attribute. */
2000 static bgp_attr_parse_ret_t
2001 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2003 struct peer
*const peer
= args
->peer
;
2004 struct attr
*const attr
= args
->attr
;
2005 const bgp_size_t length
= args
->length
;
2007 /* if received from an internal neighbor, it SHALL be considered
2008 * malformed if its length is not a non-zero multiple of 4. If
2009 * malformed, the UPDATE message SHALL be handled using the approach
2010 * of "treat-as-withdraw".
2012 if (length
== 0 || length
% 4) {
2013 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2015 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2019 bgp_attr_set_cluster(
2020 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2023 /* XXX: Fix cluster_parse to use stream API and then remove this */
2024 stream_forward_getp(peer
->curr
, length
);
2026 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2028 return BGP_ATTR_PARSE_PROCEED
;
2031 /* Multiprotocol reachability information parse. */
2032 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2033 struct bgp_nlri
*mp_update
)
2037 iana_safi_t pkt_safi
;
2039 bgp_size_t nlri_len
;
2042 struct peer
*const peer
= args
->peer
;
2043 struct attr
*const attr
= args
->attr
;
2044 const bgp_size_t length
= args
->length
;
2046 /* Set end of packet. */
2047 s
= BGP_INPUT(peer
);
2048 start
= stream_get_getp(s
);
2050 /* safe to read statically sized header? */
2051 #define BGP_MP_REACH_MIN_SIZE 5
2052 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2053 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2054 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2055 __func__
, peer
->host
, (unsigned long)length
);
2056 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2059 /* Load AFI, SAFI. */
2060 pkt_afi
= stream_getw(s
);
2061 pkt_safi
= stream_getc(s
);
2063 /* Convert AFI, SAFI to internal values, check. */
2064 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2065 /* Log if AFI or SAFI is unrecognized. This is not an error
2067 * the attribute is otherwise malformed.
2069 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2071 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2072 peer
->host
, iana_afi2str(pkt_afi
),
2073 iana_safi2str(pkt_safi
));
2074 return BGP_ATTR_PARSE_ERROR
;
2077 /* Get nexthop length. */
2078 attr
->mp_nexthop_len
= stream_getc(s
);
2080 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2082 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2083 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2084 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2087 /* Nexthop length check. */
2088 switch (attr
->mp_nexthop_len
) {
2090 if (safi
!= SAFI_FLOWSPEC
) {
2091 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2092 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2093 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2096 case BGP_ATTR_NHLEN_VPNV4
:
2097 stream_getl(s
); /* RD high */
2098 stream_getl(s
); /* RD low */
2100 * NOTE: intentional fall through
2101 * - for consistency in rx processing
2103 * The following comment is to signal GCC this intention
2104 * and suppress the warning
2107 case BGP_ATTR_NHLEN_IPV4
:
2108 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2109 /* Probably needed for RFC 2283 */
2110 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2111 memcpy(&attr
->nexthop
.s_addr
,
2112 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2114 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2115 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2116 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2117 stream_getl(s
); /* RD high */
2118 stream_getl(s
); /* RD low */
2120 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2121 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2122 if (!peer
->nexthop
.ifp
) {
2123 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2125 return BGP_ATTR_PARSE_WITHDRAW
;
2127 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2130 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2131 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2132 if (attr
->mp_nexthop_len
2133 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2134 stream_getl(s
); /* RD high */
2135 stream_getl(s
); /* RD low */
2137 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2138 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2139 if (!peer
->nexthop
.ifp
) {
2140 zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2142 return BGP_ATTR_PARSE_WITHDRAW
;
2144 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2146 if (attr
->mp_nexthop_len
2147 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2148 stream_getl(s
); /* RD high */
2149 stream_getl(s
); /* RD low */
2151 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2152 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2153 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2155 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2156 peer
->host
, &attr
->mp_nexthop_global
,
2157 &attr
->mp_nexthop_local
);
2159 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2161 if (!peer
->nexthop
.ifp
) {
2162 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2164 return BGP_ATTR_PARSE_WITHDRAW
;
2166 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2169 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2170 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2171 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2175 zlog_info("%s: %s sent SNPA which couldn't be read",
2176 __func__
, peer
->host
);
2177 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2182 if ((val
= stream_getc(s
)))
2184 EC_BGP_DEFUNCT_SNPA_LEN
,
2185 "%s sent non-zero value, %u, for defunct SNPA-length field",
2189 /* must have nrli_len, what is left of the attribute */
2190 nlri_len
= LEN_LEFT
;
2191 if (nlri_len
> STREAM_READABLE(s
)) {
2192 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2193 __func__
, peer
->host
);
2194 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2198 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2199 __func__
, peer
->host
);
2201 mp_update
->afi
= afi
;
2202 mp_update
->safi
= safi
;
2203 return BGP_ATTR_PARSE_EOR
;
2206 mp_update
->afi
= afi
;
2207 mp_update
->safi
= safi
;
2208 mp_update
->nlri
= stream_pnt(s
);
2209 mp_update
->length
= nlri_len
;
2211 stream_forward_getp(s
, nlri_len
);
2213 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2215 return BGP_ATTR_PARSE_PROCEED
;
2219 /* Multiprotocol unreachable parse */
2220 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2221 struct bgp_nlri
*mp_withdraw
)
2226 iana_safi_t pkt_safi
;
2228 uint16_t withdraw_len
;
2229 struct peer
*const peer
= args
->peer
;
2230 struct attr
*const attr
= args
->attr
;
2231 const bgp_size_t length
= args
->length
;
2235 #define BGP_MP_UNREACH_MIN_SIZE 3
2236 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2237 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2239 pkt_afi
= stream_getw(s
);
2240 pkt_safi
= stream_getc(s
);
2242 /* Convert AFI, SAFI to internal values, check. */
2243 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2244 /* Log if AFI or SAFI is unrecognized. This is not an error
2246 * the attribute is otherwise malformed.
2248 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2250 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2251 peer
->host
, iana_afi2str(pkt_afi
),
2252 iana_safi2str(pkt_safi
));
2253 return BGP_ATTR_PARSE_ERROR
;
2256 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2258 mp_withdraw
->afi
= afi
;
2259 mp_withdraw
->safi
= safi
;
2260 mp_withdraw
->nlri
= stream_pnt(s
);
2261 mp_withdraw
->length
= withdraw_len
;
2263 stream_forward_getp(s
, withdraw_len
);
2265 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2267 return BGP_ATTR_PARSE_PROCEED
;
2270 /* Large Community attribute. */
2271 static bgp_attr_parse_ret_t
2272 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2274 struct peer
*const peer
= args
->peer
;
2275 struct attr
*const attr
= args
->attr
;
2276 const bgp_size_t length
= args
->length
;
2279 * Large community follows new attribute format.
2282 bgp_attr_set_lcommunity(attr
, NULL
);
2283 /* Empty extcomm doesn't seem to be invalid per se */
2284 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2288 bgp_attr_set_lcommunity(
2289 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2290 /* XXX: fix ecommunity_parse to use stream API */
2291 stream_forward_getp(peer
->curr
, length
);
2293 if (!bgp_attr_get_lcommunity(attr
))
2294 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2297 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2299 return BGP_ATTR_PARSE_PROCEED
;
2302 /* Extended Community attribute. */
2303 static bgp_attr_parse_ret_t
2304 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2306 struct peer
*const peer
= args
->peer
;
2307 struct attr
*const attr
= args
->attr
;
2308 const bgp_size_t length
= args
->length
;
2311 struct ecommunity
*ecomm
;
2314 bgp_attr_set_ecommunity(attr
, NULL
);
2315 /* Empty extcomm doesn't seem to be invalid per se */
2316 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2320 ecomm
= ecommunity_parse(
2321 stream_pnt(peer
->curr
), length
,
2322 CHECK_FLAG(peer
->flags
,
2323 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2324 bgp_attr_set_ecommunity(attr
, ecomm
);
2325 /* XXX: fix ecommunity_parse to use stream API */
2326 stream_forward_getp(peer
->curr
, length
);
2328 /* The Extended Community attribute SHALL be considered malformed if
2329 * its length is not a non-zero multiple of 8.
2331 if (!bgp_attr_get_ecommunity(attr
))
2332 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2335 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2337 /* Extract DF election preference and mobility sequence number */
2338 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2340 /* Extract MAC mobility sequence number, if any. */
2341 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2342 attr
->sticky
= sticky
;
2344 /* Check if this is a Gateway MAC-IP advertisement */
2345 attr
->default_gw
= bgp_attr_default_gw(attr
);
2347 /* Handle scenario where router flag ecommunity is not
2348 * set but default gw ext community is present.
2349 * Use default gateway, set and propogate R-bit.
2351 if (attr
->default_gw
)
2352 attr
->router_flag
= 1;
2354 /* Check EVPN Neighbor advertisement flags, R-bit */
2355 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2357 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2359 /* Extract the Rmac, if any */
2360 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2361 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2362 && bgp_mac_exist(&attr
->rmac
))
2363 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2367 /* Get the tunnel type from encap extended community */
2368 bgp_attr_extcom_tunnel_type(attr
,
2369 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2371 /* Extract link bandwidth, if any. */
2372 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2375 return BGP_ATTR_PARSE_PROCEED
;
2378 /* IPv6 Extended Community attribute. */
2379 static bgp_attr_parse_ret_t
2380 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2382 struct peer
*const peer
= args
->peer
;
2383 struct attr
*const attr
= args
->attr
;
2384 const bgp_size_t length
= args
->length
;
2385 struct ecommunity
*ipv6_ecomm
= NULL
;
2388 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2389 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2393 ipv6_ecomm
= ecommunity_parse_ipv6(
2394 stream_pnt(peer
->curr
), length
,
2395 CHECK_FLAG(peer
->flags
,
2396 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2397 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2399 /* XXX: fix ecommunity_parse to use stream API */
2400 stream_forward_getp(peer
->curr
, length
);
2403 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2406 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
);
2408 return BGP_ATTR_PARSE_PROCEED
;
2411 /* Parse Tunnel Encap attribute in an UPDATE */
2412 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2413 bgp_size_t length
, /* IN: attr's length field */
2414 struct attr
*attr
, /* IN: caller already allocated */
2415 uint8_t flag
, /* IN: attr's flags field */
2419 uint16_t tunneltype
= 0;
2421 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2423 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2424 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2426 "Tunnel Encap attribute flag isn't optional and transitive %d",
2428 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2429 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2434 if (BGP_ATTR_ENCAP
== type
) {
2435 /* read outer TLV type and length */
2436 uint16_t tlv_length
;
2440 "Tunnel Encap attribute not long enough to contain outer T,L");
2441 bgp_notify_send_with_data(
2442 peer
, BGP_NOTIFY_UPDATE_ERR
,
2443 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2446 tunneltype
= stream_getw(BGP_INPUT(peer
));
2447 tlv_length
= stream_getw(BGP_INPUT(peer
));
2450 if (tlv_length
!= length
) {
2451 zlog_info("%s: tlv_length(%d) != length(%d)",
2452 __func__
, tlv_length
, length
);
2456 while (length
>= 4) {
2457 uint16_t subtype
= 0;
2458 uint16_t sublength
= 0;
2459 struct bgp_attr_encap_subtlv
*tlv
;
2461 if (BGP_ATTR_ENCAP
== type
) {
2462 subtype
= stream_getc(BGP_INPUT(peer
));
2463 sublength
= stream_getc(BGP_INPUT(peer
));
2465 #ifdef ENABLE_BGP_VNC
2467 subtype
= stream_getw(BGP_INPUT(peer
));
2468 sublength
= stream_getw(BGP_INPUT(peer
));
2473 if (sublength
> length
) {
2475 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2477 bgp_notify_send_with_data(
2478 peer
, BGP_NOTIFY_UPDATE_ERR
,
2479 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2483 /* alloc and copy sub-tlv */
2484 /* TBD make sure these are freed when attributes are released */
2485 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2486 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2487 tlv
->type
= subtype
;
2488 tlv
->length
= sublength
;
2489 stream_get(tlv
->value
, peer
->curr
, sublength
);
2490 length
-= sublength
;
2492 /* attach tlv to encap chain */
2493 if (BGP_ATTR_ENCAP
== type
) {
2494 struct bgp_attr_encap_subtlv
*stlv_last
;
2495 for (stlv_last
= attr
->encap_subtlvs
;
2496 stlv_last
&& stlv_last
->next
;
2497 stlv_last
= stlv_last
->next
)
2500 stlv_last
->next
= tlv
;
2502 attr
->encap_subtlvs
= tlv
;
2504 #ifdef ENABLE_BGP_VNC
2506 struct bgp_attr_encap_subtlv
*stlv_last
;
2507 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2508 bgp_attr_get_vnc_subtlvs(attr
);
2510 for (stlv_last
= vnc_subtlvs
;
2511 stlv_last
&& stlv_last
->next
;
2512 stlv_last
= stlv_last
->next
)
2515 stlv_last
->next
= tlv
;
2517 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2522 if (BGP_ATTR_ENCAP
== type
) {
2523 attr
->encap_tunneltype
= tunneltype
;
2527 /* spurious leftover data */
2529 "Tunnel Encap attribute length is bad: %d leftover octets",
2531 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2532 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2541 /* SRv6 Service Data Sub-Sub-TLV attribute
2542 * draft-ietf-bess-srv6-services-07
2544 static bgp_attr_parse_ret_t
2545 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2547 struct peer
*const peer
= args
->peer
;
2548 struct attr
*const attr
= args
->attr
;
2549 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2550 transposition_len
, transposition_offset
;
2552 size_t headersz
= sizeof(type
) + sizeof(length
);
2554 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2557 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2558 headersz
, STREAM_READABLE(peer
->curr
));
2559 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2563 type
= stream_getc(peer
->curr
);
2564 length
= stream_getw(peer
->curr
);
2566 if (STREAM_READABLE(peer
->curr
) < length
) {
2569 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2570 length
, STREAM_READABLE(peer
->curr
));
2571 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2575 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2576 loc_block_len
= stream_getc(peer
->curr
);
2577 loc_node_len
= stream_getc(peer
->curr
);
2578 func_len
= stream_getc(peer
->curr
);
2579 arg_len
= stream_getc(peer
->curr
);
2580 transposition_len
= stream_getc(peer
->curr
);
2581 transposition_offset
= stream_getc(peer
->curr
);
2583 /* Log SRv6 Service Data Sub-Sub-TLV */
2584 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2586 "%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",
2587 __func__
, loc_block_len
, loc_node_len
, func_len
,
2588 arg_len
, transposition_len
,
2589 transposition_offset
);
2592 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2593 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2594 attr
->srv6_l3vpn
->func_len
= func_len
;
2595 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2596 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2597 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2601 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2603 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2606 stream_forward_getp(peer
->curr
, length
);
2609 return BGP_ATTR_PARSE_PROCEED
;
2612 /* SRv6 Service Sub-TLV attribute
2613 * draft-ietf-bess-srv6-services-07
2615 static bgp_attr_parse_ret_t
2616 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2618 struct peer
*const peer
= args
->peer
;
2619 struct attr
*const attr
= args
->attr
;
2620 struct in6_addr ipv6_sid
;
2621 uint8_t type
, sid_flags
;
2622 uint16_t length
, endpoint_behavior
;
2623 size_t headersz
= sizeof(type
) + sizeof(length
);
2624 bgp_attr_parse_ret_t err
;
2627 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2630 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2631 headersz
, STREAM_READABLE(peer
->curr
));
2632 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2636 type
= stream_getc(peer
->curr
);
2637 length
= stream_getw(peer
->curr
);
2639 if (STREAM_READABLE(peer
->curr
) < length
) {
2642 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2643 length
, STREAM_READABLE(peer
->curr
));
2644 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2648 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2649 stream_getc(peer
->curr
);
2650 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2651 sid_flags
= stream_getc(peer
->curr
);
2652 endpoint_behavior
= stream_getw(peer
->curr
);
2653 stream_getc(peer
->curr
);
2655 /* Log SRv6 Service Sub-TLV */
2656 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2657 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2659 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2660 __func__
, buf
, sid_flags
, endpoint_behavior
);
2663 /* Configure from Info */
2664 if (attr
->srv6_l3vpn
) {
2665 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2666 "Prefix SID SRv6 L3VPN field repeated");
2667 return bgp_attr_malformed(
2668 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2670 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2671 sizeof(struct bgp_attr_srv6_l3vpn
));
2672 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2673 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2674 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2675 attr
->srv6_l3vpn
->loc_block_len
= 0;
2676 attr
->srv6_l3vpn
->loc_node_len
= 0;
2677 attr
->srv6_l3vpn
->func_len
= 0;
2678 attr
->srv6_l3vpn
->arg_len
= 0;
2679 attr
->srv6_l3vpn
->transposition_len
= 0;
2680 attr
->srv6_l3vpn
->transposition_offset
= 0;
2682 // Sub-Sub-TLV found
2683 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2684 err
= bgp_attr_srv6_service_data(args
);
2686 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2690 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2693 /* Placeholder code for unsupported type */
2695 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2697 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2700 stream_forward_getp(peer
->curr
, length
);
2703 return BGP_ATTR_PARSE_PROCEED
;
2707 * Read an individual SID value returning how much data we have read
2708 * Returns 0 if there was an error that needs to be passed up the stack
2710 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2711 struct bgp_attr_parser_args
*args
)
2713 struct peer
*const peer
= args
->peer
;
2714 struct attr
*const attr
= args
->attr
;
2715 uint32_t label_index
;
2716 struct in6_addr ipv6_sid
;
2718 uint32_t srgb_range
;
2720 uint8_t sid_type
, sid_flags
;
2723 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2724 if (STREAM_READABLE(peer
->curr
) < length
2725 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2726 flog_err(EC_BGP_ATTR_LEN
,
2727 "Prefix SID label index length is %hu instead of %u",
2728 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2729 return bgp_attr_malformed(args
,
2730 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2734 /* Ignore flags and reserved */
2735 stream_getc(peer
->curr
);
2736 stream_getw(peer
->curr
);
2738 /* Fetch the label index and see if it is valid. */
2739 label_index
= stream_getl(peer
->curr
);
2740 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2741 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2744 /* Store label index; subsequently, we'll check on
2746 attr
->label_index
= label_index
;
2749 /* Placeholder code for the IPv6 SID type */
2750 else if (type
== BGP_PREFIX_SID_IPV6
) {
2751 if (STREAM_READABLE(peer
->curr
) < length
2752 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2753 flog_err(EC_BGP_ATTR_LEN
,
2754 "Prefix SID IPv6 length is %hu instead of %u",
2755 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2756 return bgp_attr_malformed(args
,
2757 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2761 /* Ignore reserved */
2762 stream_getc(peer
->curr
);
2763 stream_getw(peer
->curr
);
2765 stream_get(&ipv6_sid
, peer
->curr
, 16);
2768 /* Placeholder code for the Originator SRGB type */
2769 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2771 * ietf-idr-bgp-prefix-sid-05:
2772 * Length is the total length of the value portion of the
2773 * TLV: 2 + multiple of 6.
2775 * peer->curr stream readp should be at the beginning of the 16
2776 * bit flag field at this point in the code.
2780 * Check that the TLV length field is sane: at least 2 bytes of
2781 * flag, and at least 1 SRGB (these are 6 bytes each)
2783 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2786 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2788 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2789 return bgp_attr_malformed(
2790 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2795 * Check that we actually have at least as much data as
2796 * specified by the length field
2798 if (STREAM_READABLE(peer
->curr
) < length
) {
2799 flog_err(EC_BGP_ATTR_LEN
,
2800 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2801 length
, STREAM_READABLE(peer
->curr
));
2802 return bgp_attr_malformed(
2803 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2808 * Check that the portion of the TLV containing the sequence of
2809 * SRGBs corresponds to a multiple of the SRGB size; to get
2810 * that length, we skip the 16 bit flags field
2812 stream_getw(peer
->curr
);
2814 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2817 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2818 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2819 return bgp_attr_malformed(
2820 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2824 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2826 for (int i
= 0; i
< srgb_count
; i
++) {
2827 stream_get(&srgb_base
, peer
->curr
, 3);
2828 stream_get(&srgb_range
, peer
->curr
, 3);
2832 /* Placeholder code for the VPN-SID Service type */
2833 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2834 if (STREAM_READABLE(peer
->curr
) < length
2835 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2836 flog_err(EC_BGP_ATTR_LEN
,
2837 "Prefix SID VPN SID length is %hu instead of %u",
2838 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2839 return bgp_attr_malformed(args
,
2840 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2844 /* Parse VPN-SID Sub-TLV */
2845 stream_getc(peer
->curr
); /* reserved */
2846 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2847 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2848 stream_get(&ipv6_sid
, peer
->curr
,
2849 sizeof(ipv6_sid
)); /* sid_value */
2851 /* Log VPN-SID Sub-TLV */
2852 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2853 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2855 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2856 __func__
, buf
, sid_type
, sid_flags
);
2859 /* Configure from Info */
2860 if (attr
->srv6_vpn
) {
2861 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2862 "Prefix SID SRv6 VPN field repeated");
2863 return bgp_attr_malformed(
2864 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2866 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2867 sizeof(struct bgp_attr_srv6_vpn
));
2868 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2869 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2870 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2873 /* Placeholder code for the SRv6 L3 Service type */
2874 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2875 if (STREAM_READABLE(peer
->curr
) < length
) {
2878 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
2879 length
, STREAM_READABLE(peer
->curr
));
2880 return bgp_attr_malformed(args
,
2881 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2885 /* ignore reserved */
2886 stream_getc(peer
->curr
);
2888 return bgp_attr_srv6_service(args
);
2891 /* Placeholder code for Unsupported TLV */
2894 if (STREAM_READABLE(peer
->curr
) < length
) {
2897 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2898 length
, STREAM_READABLE(peer
->curr
));
2899 return bgp_attr_malformed(
2900 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2904 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2906 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2909 stream_forward_getp(peer
->curr
, length
);
2912 return BGP_ATTR_PARSE_PROCEED
;
2915 /* Prefix SID attribute
2916 * draft-ietf-idr-bgp-prefix-sid-05
2918 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2920 struct peer
*const peer
= args
->peer
;
2921 struct attr
*const attr
= args
->attr
;
2922 bgp_attr_parse_ret_t ret
;
2924 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2928 size_t headersz
= sizeof(type
) + sizeof(length
);
2929 size_t psid_parsed_length
= 0;
2931 while (STREAM_READABLE(peer
->curr
) > 0
2932 && psid_parsed_length
< args
->length
) {
2934 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2937 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2938 headersz
, STREAM_READABLE(peer
->curr
));
2939 return bgp_attr_malformed(
2940 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2944 type
= stream_getc(peer
->curr
);
2945 length
= stream_getw(peer
->curr
);
2947 if (STREAM_READABLE(peer
->curr
) < length
) {
2950 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2951 length
, STREAM_READABLE(peer
->curr
));
2952 return bgp_attr_malformed(args
,
2953 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2957 ret
= bgp_attr_psid_sub(type
, length
, args
);
2959 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2962 psid_parsed_length
+= length
+ headersz
;
2964 if (psid_parsed_length
> args
->length
) {
2967 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2968 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2969 return bgp_attr_malformed(
2970 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2975 return BGP_ATTR_PARSE_PROCEED
;
2978 /* PMSI tunnel attribute (RFC 6514)
2979 * Basic validation checks done here.
2981 static bgp_attr_parse_ret_t
2982 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2984 struct peer
*const peer
= args
->peer
;
2985 struct attr
*const attr
= args
->attr
;
2986 const bgp_size_t length
= args
->length
;
2988 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2990 /* Verify that the receiver is expecting "ingress replication" as we
2991 * can only support that.
2993 if (length
< attr_parse_len
) {
2994 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2996 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2999 stream_getc(peer
->curr
); /* Flags */
3000 tnl_type
= stream_getc(peer
->curr
);
3001 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3002 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3003 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3004 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3007 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3009 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3010 "Bad PMSI tunnel attribute length %d for IR",
3012 return bgp_attr_malformed(
3013 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3018 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3019 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3020 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3022 /* Forward read pointer of input stream. */
3023 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3025 return BGP_ATTR_PARSE_PROCEED
;
3028 /* BGP unknown attribute treatment. */
3029 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3031 bgp_size_t total
= args
->total
;
3032 struct transit
*transit
;
3033 struct peer
*const peer
= args
->peer
;
3034 struct attr
*const attr
= args
->attr
;
3035 uint8_t *const startp
= args
->startp
;
3036 const uint8_t type
= args
->type
;
3037 const uint8_t flag
= args
->flags
;
3038 const bgp_size_t length
= args
->length
;
3040 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3042 "%s Unknown attribute is received (type %d, length %d)",
3043 peer
->host
, type
, length
);
3045 /* Forward read pointer of input stream. */
3046 stream_forward_getp(peer
->curr
, length
);
3048 /* If any of the mandatory well-known attributes are not recognized,
3049 then the Error Subcode is set to Unrecognized Well-known
3050 Attribute. The Data field contains the unrecognized attribute
3051 (type, length and value). */
3052 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3053 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3057 /* Unrecognized non-transitive optional attributes must be quietly
3058 ignored and not passed along to other BGP peers. */
3059 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3060 return BGP_ATTR_PARSE_PROCEED
;
3062 /* If a path with recognized transitive optional attribute is
3063 accepted and passed along to other BGP peers and the Partial bit
3064 in the Attribute Flags octet is set to 1 by some previous AS, it
3065 is not set back to 0 by the current AS. */
3066 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3068 /* Store transitive attribute to the end of attr->transit. */
3069 transit
= bgp_attr_get_transit(attr
);
3071 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3073 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3074 transit
->length
+ total
);
3076 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3077 transit
->length
+= total
;
3078 bgp_attr_set_transit(attr
, transit
);
3080 return BGP_ATTR_PARSE_PROCEED
;
3083 /* Well-known attribute check. */
3084 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3088 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3090 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3091 return BGP_ATTR_PARSE_PROCEED
;
3093 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3094 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3095 are present, it should. Check for any other attribute being present
3098 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3099 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3100 return BGP_ATTR_PARSE_PROCEED
;
3102 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3103 type
= BGP_ATTR_ORIGIN
;
3105 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3106 type
= BGP_ATTR_AS_PATH
;
3108 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3110 * NLRI is empty. We can't easily check NLRI empty here though.
3112 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3113 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3114 type
= BGP_ATTR_NEXT_HOP
;
3116 if (peer
->sort
== BGP_PEER_IBGP
3117 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3118 type
= BGP_ATTR_LOCAL_PREF
;
3120 /* If any of the well-known mandatory attributes are not present
3121 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3124 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3125 "%s Missing well-known attribute %s.", peer
->host
,
3126 lookup_msg(attr_str
, type
, NULL
));
3127 return BGP_ATTR_PARSE_WITHDRAW
;
3129 return BGP_ATTR_PARSE_PROCEED
;
3132 /* Read attribute of update packet. This function is called from
3133 bgp_update_receive() in bgp_packet.c. */
3134 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3135 bgp_size_t size
, struct bgp_nlri
*mp_update
,
3136 struct bgp_nlri
*mp_withdraw
)
3138 bgp_attr_parse_ret_t ret
;
3142 uint8_t *startp
, *endp
;
3144 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3145 /* we need the as4_path only until we have synthesized the as_path with
3147 /* same goes for as4_aggregator */
3148 struct aspath
*as4_path
= NULL
;
3149 as_t as4_aggregator
= 0;
3150 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3151 struct transit
*transit
;
3153 /* Initialize bitmap. */
3154 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3156 /* End pointer of BGP attribute. */
3157 endp
= BGP_INPUT_PNT(peer
) + size
;
3159 /* Get attributes to the end of attribute length. */
3160 while (BGP_INPUT_PNT(peer
) < endp
) {
3161 /* Check remaining length check.*/
3162 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3163 /* XXX warning: long int format, int arg (arg 5) */
3165 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3166 "%s: error BGP attribute length %lu is smaller than min len",
3168 (unsigned long)(endp
3169 - stream_pnt(BGP_INPUT(peer
))));
3171 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3172 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3173 ret
= BGP_ATTR_PARSE_ERROR
;
3177 /* Fetch attribute flag and type. */
3178 startp
= BGP_INPUT_PNT(peer
);
3179 /* "The lower-order four bits of the Attribute Flags octet are
3180 unused. They MUST be zero when sent and MUST be ignored when
3182 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3183 type
= stream_getc(BGP_INPUT(peer
));
3185 /* Check whether Extended-Length applies and is in bounds */
3186 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3187 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3189 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3190 "%s: Extended length set, but just %lu bytes of attr header",
3192 (unsigned long)(endp
3193 - stream_pnt(BGP_INPUT(peer
))));
3195 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3196 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3197 ret
= BGP_ATTR_PARSE_ERROR
;
3201 /* Check extended attribue length bit. */
3202 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3203 length
= stream_getw(BGP_INPUT(peer
));
3205 length
= stream_getc(BGP_INPUT(peer
));
3207 /* If any attribute appears more than once in the UPDATE
3208 message, then the Error Subcode is set to Malformed Attribute
3211 if (CHECK_BITMAP(seen
, type
)) {
3213 EC_BGP_ATTRIBUTE_REPEATED
,
3214 "%s: error BGP attribute type %d appears twice in a message",
3217 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3218 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3219 ret
= BGP_ATTR_PARSE_ERROR
;
3223 /* Set type to bitmap to check duplicate attribute. `type' is
3224 unsigned char so it never overflow bitmap range. */
3226 SET_BITMAP(seen
, type
);
3228 /* Overflow check. */
3229 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3231 if (attr_endp
> endp
) {
3233 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3234 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3235 peer
->host
, type
, length
, size
, attr_endp
,
3239 * If any recognized attribute has an Attribute
3240 * Length that conflicts with the expected length
3241 * (based on the attribute type code), then the
3242 * Error Subcode MUST be set to Attribute Length
3243 * Error. The Data field MUST contain the erroneous
3244 * attribute (type, length, and value).
3246 * We do not currently have a good way to determine the
3247 * length of the attribute independent of the length
3248 * received in the message. Instead we send the
3249 * minimum between the amount of data we have and the
3250 * amount specified by the attribute length field.
3252 * Instead of directly passing in the packet buffer and
3253 * offset we use the stream_get* functions to read into
3254 * a stack buffer, since they perform bounds checking
3255 * and we are working with untrusted data.
3257 unsigned char ndata
[peer
->max_packet_size
];
3258 memset(ndata
, 0x00, sizeof(ndata
));
3260 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3261 /* Rewind to end of flag field */
3262 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3264 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3266 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3268 size_t atl
= attr_endp
- startp
;
3269 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3270 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3272 bgp_notify_send_with_data(
3273 peer
, BGP_NOTIFY_UPDATE_ERR
,
3274 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3277 ret
= BGP_ATTR_PARSE_ERROR
;
3281 struct bgp_attr_parser_args attr_args
= {
3288 .total
= attr_endp
- startp
,
3292 /* If any recognized attribute has Attribute Flags that conflict
3293 with the Attribute Type Code, then the Error Subcode is set
3295 Attribute Flags Error. The Data field contains the erroneous
3296 attribute (type, length and value). */
3297 if (bgp_attr_flag_invalid(&attr_args
)) {
3298 ret
= bgp_attr_malformed(
3299 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3301 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3306 /* OK check attribute and store it's value. */
3308 case BGP_ATTR_ORIGIN
:
3309 ret
= bgp_attr_origin(&attr_args
);
3311 case BGP_ATTR_AS_PATH
:
3312 ret
= bgp_attr_aspath(&attr_args
);
3314 case BGP_ATTR_AS4_PATH
:
3315 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3317 case BGP_ATTR_NEXT_HOP
:
3318 ret
= bgp_attr_nexthop(&attr_args
);
3320 case BGP_ATTR_MULTI_EXIT_DISC
:
3321 ret
= bgp_attr_med(&attr_args
);
3323 case BGP_ATTR_LOCAL_PREF
:
3324 ret
= bgp_attr_local_pref(&attr_args
);
3326 case BGP_ATTR_ATOMIC_AGGREGATE
:
3327 ret
= bgp_attr_atomic(&attr_args
);
3329 case BGP_ATTR_AGGREGATOR
:
3330 ret
= bgp_attr_aggregator(&attr_args
);
3332 case BGP_ATTR_AS4_AGGREGATOR
:
3333 ret
= bgp_attr_as4_aggregator(&attr_args
,
3335 &as4_aggregator_addr
);
3337 case BGP_ATTR_COMMUNITIES
:
3338 ret
= bgp_attr_community(&attr_args
);
3340 case BGP_ATTR_LARGE_COMMUNITIES
:
3341 ret
= bgp_attr_large_community(&attr_args
);
3343 case BGP_ATTR_ORIGINATOR_ID
:
3344 ret
= bgp_attr_originator_id(&attr_args
);
3346 case BGP_ATTR_CLUSTER_LIST
:
3347 ret
= bgp_attr_cluster_list(&attr_args
);
3349 case BGP_ATTR_MP_REACH_NLRI
:
3350 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3352 case BGP_ATTR_MP_UNREACH_NLRI
:
3353 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3355 case BGP_ATTR_EXT_COMMUNITIES
:
3356 ret
= bgp_attr_ext_communities(&attr_args
);
3358 #ifdef ENABLE_BGP_VNC_ATTR
3361 case BGP_ATTR_ENCAP
:
3362 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3365 case BGP_ATTR_PREFIX_SID
:
3366 ret
= bgp_attr_prefix_sid(&attr_args
);
3368 case BGP_ATTR_PMSI_TUNNEL
:
3369 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3371 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3372 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3375 ret
= bgp_attr_unknown(&attr_args
);
3379 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3380 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3381 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3382 ret
= BGP_ATTR_PARSE_ERROR
;
3386 if (ret
== BGP_ATTR_PARSE_EOR
) {
3390 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3391 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3392 "%s: Attribute %s, parse error", peer
->host
,
3393 lookup_msg(attr_str
, type
, NULL
));
3396 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3398 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3399 "%s: Attribute %s, parse error - treating as withdrawal",
3400 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3404 /* Check the fetched length. */
3405 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3406 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3407 "%s: BGP attribute %s, fetch error",
3408 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3409 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3410 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3411 ret
= BGP_ATTR_PARSE_ERROR
;
3417 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3418 * About Prefix-SID path attribute,
3419 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3420 * may only appear in a BGP Prefix-SID attribute attached to
3421 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3422 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3424 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3425 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3427 /* Check final read pointer is same as end pointer. */
3428 if (BGP_INPUT_PNT(peer
) != endp
) {
3429 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3430 "%s: BGP attribute %s, length mismatch", peer
->host
,
3431 lookup_msg(attr_str
, type
, NULL
));
3432 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3433 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3435 ret
= BGP_ATTR_PARSE_ERROR
;
3440 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3441 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3442 * This is implemented below and will result in a NOTIFICATION. If the
3443 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3444 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3445 * message SHOULD NOT be sent. This is implemented elsewhere.
3447 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3448 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3449 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3450 * speaker that receives the message SHOULD ignore this attribute.
3452 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3453 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3454 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3455 ret
= BGP_ATTR_PARSE_ERROR
;
3460 /* Check all mandatory well-known attributes are present */
3461 ret
= bgp_attr_check(peer
, attr
);
3466 * At this place we can see whether we got AS4_PATH and/or
3467 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3468 * We can not do this before we've read all attributes because
3469 * the as4 handling does not say whether AS4_PATH has to be sent
3470 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3471 * in relationship to AGGREGATOR.
3472 * So, to be defensive, we are not relying on any order and read
3473 * all attributes first, including these 32bit ones, and now,
3474 * afterwards, we look what and if something is to be done for as4.
3476 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3479 /* actually... this doesn't ever return failure currently, but
3480 * better safe than sorry */
3481 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3482 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3483 &as4_aggregator_addr
)) {
3484 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3485 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3486 ret
= BGP_ATTR_PARSE_ERROR
;
3491 * Finally do the checks on the aspath we did not do yet
3492 * because we waited for a potentially synthesized aspath.
3494 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3495 ret
= bgp_attr_aspath_check(peer
, attr
);
3496 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3500 ret
= BGP_ATTR_PARSE_PROCEED
;
3504 * At this stage, we have done all fiddling with as4, and the
3505 * resulting info is in attr->aggregator resp. attr->aspath so
3506 * we can chuck as4_aggregator and as4_path alltogether in order
3510 * unintern - it is in the hash
3511 * The flag that we got this is still there, but that
3512 * does not do any trouble
3514 aspath_unintern(&as4_path
);
3516 transit
= bgp_attr_get_transit(attr
);
3517 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3518 /* Finally intern unknown attribute. */
3520 bgp_attr_set_transit(attr
, transit_intern(transit
));
3521 if (attr
->encap_subtlvs
)
3522 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3524 #ifdef ENABLE_BGP_VNC
3525 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3526 bgp_attr_get_vnc_subtlvs(attr
);
3529 bgp_attr_set_vnc_subtlvs(
3531 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3535 transit_free(transit
);
3536 bgp_attr_set_transit(attr
, NULL
);
3539 bgp_attr_flush_encap(attr
);
3543 transit
= bgp_attr_get_transit(attr
);
3545 assert(transit
->refcnt
> 0);
3546 if (attr
->encap_subtlvs
)
3547 assert(attr
->encap_subtlvs
->refcnt
> 0);
3548 #ifdef ENABLE_BGP_VNC
3549 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3550 bgp_attr_get_vnc_subtlvs(attr
);
3553 assert(vnc_subtlvs
->refcnt
> 0);
3560 * Extract the tunnel type from extended community
3562 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3563 bgp_encap_types
*tunnel_type
)
3565 struct ecommunity
*ecom
;
3571 ecom
= bgp_attr_get_ecommunity(attr
);
3572 if (!ecom
|| !ecom
->size
)
3575 for (i
= 0; i
< ecom
->size
; i
++) {
3577 uint8_t type
, sub_type
;
3579 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3582 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3583 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3585 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3592 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3593 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3598 iana_safi_t pkt_safi
;
3601 /* Set extended bit always to encode the attribute length as 2 bytes */
3602 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3603 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3604 sizep
= stream_get_endp(s
);
3605 stream_putw(s
, 0); /* Marker: Attribute length. */
3608 /* Convert AFI, SAFI to values for packet. */
3609 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3611 stream_putw(s
, pkt_afi
); /* AFI */
3612 stream_putc(s
, pkt_safi
); /* SAFI */
3616 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3617 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3618 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3619 else if (safi
== SAFI_FLOWSPEC
)
3622 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3625 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3630 case SAFI_MULTICAST
:
3631 case SAFI_LABELED_UNICAST
:
3633 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3637 stream_putl(s
, 0); /* RD = 0, per RFC */
3639 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3644 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3647 if (attr
->mp_nexthop_len
== 0)
3648 stream_putc(s
, 0); /* no nexthop for flowspec */
3650 stream_putc(s
, attr
->mp_nexthop_len
);
3651 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3660 case SAFI_MULTICAST
:
3661 case SAFI_LABELED_UNICAST
:
3663 if (attr
->mp_nexthop_len
3664 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3666 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3667 stream_put(s
, &attr
->mp_nexthop_global
,
3669 stream_put(s
, &attr
->mp_nexthop_local
,
3672 stream_putc(s
, IPV6_MAX_BYTELEN
);
3673 stream_put(s
, &attr
->mp_nexthop_global
,
3677 case SAFI_MPLS_VPN
: {
3678 if (attr
->mp_nexthop_len
3679 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3681 stream_putl(s
, 0); /* RD = 0, per RFC */
3683 stream_put(s
, &attr
->mp_nexthop_global
,
3685 } else if (attr
->mp_nexthop_len
3686 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3688 stream_putl(s
, 0); /* RD = 0, per RFC */
3690 stream_put(s
, &attr
->mp_nexthop_global
,
3692 stream_putl(s
, 0); /* RD = 0, per RFC */
3694 stream_put(s
, &attr
->mp_nexthop_local
,
3699 stream_putc(s
, IPV6_MAX_BYTELEN
);
3700 stream_put(s
, &attr
->mp_nexthop_global
,
3704 stream_putc(s
, 0); /* no nexthop for flowspec */
3710 if (safi
!= SAFI_FLOWSPEC
)
3712 EC_BGP_ATTR_NH_SEND_LEN
,
3713 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3714 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3723 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3724 const struct prefix
*p
,
3725 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3726 uint32_t num_labels
, bool addpath_capable
,
3727 uint32_t addpath_tx_id
, struct attr
*attr
)
3729 if (safi
== SAFI_MPLS_VPN
) {
3730 if (addpath_capable
)
3731 stream_putl(s
, addpath_tx_id
);
3732 /* Label, RD, Prefix write. */
3733 stream_putc(s
, p
->prefixlen
+ 88);
3734 stream_put(s
, label
, BGP_LABEL_BYTES
);
3735 stream_put(s
, prd
->val
, 8);
3736 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3737 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3738 /* EVPN prefix - contents depend on type */
3739 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3740 addpath_capable
, addpath_tx_id
);
3741 } else if (safi
== SAFI_LABELED_UNICAST
) {
3742 /* Prefix write with label. */
3743 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3745 } else if (safi
== SAFI_FLOWSPEC
) {
3746 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3747 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3748 p
->u
.prefix_flowspec
.prefixlen
);
3750 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
3753 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3754 const struct prefix
*p
)
3756 int size
= PSIZE(p
->prefixlen
);
3757 if (safi
== SAFI_MPLS_VPN
)
3759 else if (safi
== SAFI_LABELED_UNICAST
)
3760 size
+= BGP_LABEL_BYTES
;
3761 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3762 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3768 * Encodes the tunnel encapsulation attribute,
3769 * and with ENABLE_BGP_VNC the VNC attribute which uses
3770 * almost the same TLV format
3772 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3773 struct stream
*s
, struct attr
*attr
,
3776 unsigned int attrlenfield
= 0;
3777 unsigned int attrhdrlen
= 0;
3778 struct bgp_attr_encap_subtlv
*subtlvs
;
3779 struct bgp_attr_encap_subtlv
*st
;
3780 const char *attrname
;
3782 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3783 && (!attr
->encap_tunneltype
3784 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3788 case BGP_ATTR_ENCAP
:
3789 attrname
= "Tunnel Encap";
3790 subtlvs
= attr
->encap_subtlvs
;
3791 if (subtlvs
== NULL
) /* nothing to do */
3794 * The tunnel encap attr has an "outer" tlv.
3796 * L = total length of subtlvs,
3797 * V = concatenated subtlvs.
3799 attrlenfield
= 2 + 2; /* T + L */
3800 attrhdrlen
= 1 + 1; /* subTLV T + L */
3803 #ifdef ENABLE_BGP_VNC_ATTR
3806 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3807 if (subtlvs
== NULL
) /* nothing to do */
3809 attrlenfield
= 0; /* no outer T + L */
3810 attrhdrlen
= 2 + 2; /* subTLV T + L */
3818 /* compute attr length */
3819 for (st
= subtlvs
; st
; st
= st
->next
) {
3820 attrlenfield
+= (attrhdrlen
+ st
->length
);
3823 if (attrlenfield
> 0xffff) {
3824 zlog_info("%s attribute is too long (length=%d), can't send it",
3825 attrname
, attrlenfield
);
3829 if (attrlenfield
> 0xff) {
3830 /* 2-octet length field */
3832 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3833 | BGP_ATTR_FLAG_EXTLEN
);
3834 stream_putc(s
, attrtype
);
3835 stream_putw(s
, attrlenfield
& 0xffff);
3837 /* 1-octet length field */
3838 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3839 stream_putc(s
, attrtype
);
3840 stream_putc(s
, attrlenfield
& 0xff);
3843 if (attrtype
== BGP_ATTR_ENCAP
) {
3844 /* write outer T+L */
3845 stream_putw(s
, attr
->encap_tunneltype
);
3846 stream_putw(s
, attrlenfield
- 4);
3849 /* write each sub-tlv */
3850 for (st
= subtlvs
; st
; st
= st
->next
) {
3851 if (attrtype
== BGP_ATTR_ENCAP
) {
3852 stream_putc(s
, st
->type
);
3853 stream_putc(s
, st
->length
);
3854 #ifdef ENABLE_BGP_VNC
3856 stream_putw(s
, st
->type
);
3857 stream_putw(s
, st
->length
);
3860 stream_put(s
, st
->value
, st
->length
);
3864 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3866 /* Set MP attribute length. Don't count the (2) bytes used to encode
3868 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3871 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3873 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3874 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3875 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3876 PEER_FLAG_REMOVE_PRIVATE_AS
)
3877 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3878 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3879 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3880 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3881 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3882 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3887 /* Make attribute packet. */
3888 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3889 struct stream
*s
, struct attr
*attr
,
3890 struct bpacket_attr_vec_arr
*vecarr
,
3891 struct prefix
*p
, afi_t afi
, safi_t safi
,
3892 struct peer
*from
, struct prefix_rd
*prd
,
3893 mpls_label_t
*label
, uint32_t num_labels
,
3894 bool addpath_capable
, uint32_t addpath_tx_id
)
3897 size_t aspath_sizep
;
3898 struct aspath
*aspath
;
3899 int send_as4_path
= 0;
3900 int send_as4_aggregator
= 0;
3901 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
3902 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
3907 /* Remember current pointer. */
3908 cp
= stream_get_endp(s
);
3911 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3912 && !peer_cap_enhe(peer
, afi
, safi
))) {
3913 size_t mpattrlen_pos
= 0;
3915 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3917 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3918 num_labels
, addpath_capable
,
3919 addpath_tx_id
, attr
);
3920 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3923 /* Origin attribute. */
3924 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3925 stream_putc(s
, BGP_ATTR_ORIGIN
);
3927 stream_putc(s
, attr
->origin
);
3929 /* AS path attribute. */
3931 /* If remote-peer is EBGP */
3932 if (peer
->sort
== BGP_PEER_EBGP
3933 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3934 PEER_FLAG_AS_PATH_UNCHANGED
)
3935 || attr
->aspath
->segments
== NULL
)
3936 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3937 PEER_FLAG_RSERVER_CLIENT
))) {
3938 aspath
= aspath_dup(attr
->aspath
);
3940 /* Even though we may not be configured for confederations we
3942 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3943 aspath
= aspath_delete_confed_seq(aspath
);
3945 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3946 /* Stuff our path CONFED_ID on the front */
3947 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3949 if (peer
->change_local_as
) {
3950 /* If replace-as is specified, we only use the
3951 change_local_as when
3952 advertising routes. */
3953 if (!CHECK_FLAG(peer
->flags
,
3954 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3955 if (bgp_append_local_as(peer
, afi
,
3957 aspath
= aspath_add_seq(
3958 aspath
, peer
->local_as
);
3959 aspath
= aspath_add_seq(aspath
,
3960 peer
->change_local_as
);
3962 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3965 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3966 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3968 aspath
= aspath_dup(attr
->aspath
);
3969 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3971 aspath
= attr
->aspath
;
3973 /* If peer is not AS4 capable, then:
3974 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3975 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3977 * types are in it (i.e. exclude them if they are there)
3978 * AND do this only if there is at least one asnum > 65535 in the
3980 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3982 * all ASnums > 65535 to BGP_AS_TRANS
3985 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3986 stream_putc(s
, BGP_ATTR_AS_PATH
);
3987 aspath_sizep
= stream_get_endp(s
);
3989 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3991 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3994 if (!use32bit
&& aspath_has_as4(aspath
))
3996 1; /* we'll do this later, at the correct place */
3998 /* Nexthop attribute. */
3999 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4000 && !peer_cap_enhe(peer
, afi
, safi
)) {
4001 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4003 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4004 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4005 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4006 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4009 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4010 } else if (peer_cap_enhe(from
, afi
, safi
)
4011 || (nh_afi
== AFI_IP6
)) {
4013 * Likely this is the case when an IPv4 prefix was
4014 * received with Extended Next-hop capability in this
4015 * or another vrf and is now being advertised to
4016 * non-ENHE peers. Since peer_cap_enhe only checks
4017 * peers in this vrf, also check the nh_afi to catch
4018 * the case where the originator was in another vrf.
4019 * Setting the mandatory (ipv4) next-hop attribute here
4020 * to enable implicit next-hop self with correct A-F
4021 * (ipv4 address family).
4023 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4024 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4025 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4028 stream_put_ipv4(s
, 0);
4032 /* MED attribute. */
4033 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4034 || bgp
->maxmed_active
) {
4035 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4036 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4038 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4042 /* Local preference. */
4043 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4044 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4045 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4047 stream_putl(s
, attr
->local_pref
);
4050 /* Atomic aggregate. */
4051 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4052 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4053 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4058 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4059 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4060 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4061 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4064 /* AS4 capable peer */
4066 stream_putl(s
, attr
->aggregator_as
);
4068 /* 2-byte AS peer */
4071 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4073 if (attr
->aggregator_as
> UINT16_MAX
) {
4074 stream_putw(s
, BGP_AS_TRANS
);
4076 /* we have to send AS4_AGGREGATOR, too.
4077 * we'll do that later in order to send
4078 * attributes in ascending
4081 send_as4_aggregator
= 1;
4083 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4085 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4088 /* Community attribute. */
4089 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4090 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4091 struct community
*comm
= NULL
;
4093 comm
= bgp_attr_get_community(attr
);
4094 if (comm
->size
* 4 > 255) {
4096 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4097 | BGP_ATTR_FLAG_EXTLEN
);
4098 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4099 stream_putw(s
, comm
->size
* 4);
4102 BGP_ATTR_FLAG_OPTIONAL
4103 | BGP_ATTR_FLAG_TRANS
);
4104 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4105 stream_putc(s
, comm
->size
* 4);
4107 stream_put(s
, comm
->val
, comm
->size
* 4);
4111 * Large Community attribute.
4113 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4114 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4115 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4116 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4118 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4119 | BGP_ATTR_FLAG_EXTLEN
);
4120 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4122 lcom_length(bgp_attr_get_lcommunity(attr
)));
4125 BGP_ATTR_FLAG_OPTIONAL
4126 | BGP_ATTR_FLAG_TRANS
);
4127 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4129 lcom_length(bgp_attr_get_lcommunity(attr
)));
4131 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4132 lcom_length(bgp_attr_get_lcommunity(attr
)));
4135 /* Route Reflector. */
4136 if (peer
->sort
== BGP_PEER_IBGP
&& from
4137 && from
->sort
== BGP_PEER_IBGP
) {
4138 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4140 /* Originator ID. */
4141 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4142 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4145 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4146 stream_put_in_addr(s
, &attr
->originator_id
);
4148 stream_put_in_addr(s
, &from
->remote_id
);
4151 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4152 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4155 stream_putc(s
, cluster
->length
+ 4);
4156 /* If this peer configuration's parent BGP has
4158 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4159 stream_put_in_addr(s
, &bgp
->cluster_id
);
4161 stream_put_in_addr(s
, &bgp
->router_id
);
4162 stream_put(s
, cluster
->list
, cluster
->length
);
4165 /* If this peer configuration's parent BGP has
4167 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4168 stream_put_in_addr(s
, &bgp
->cluster_id
);
4170 stream_put_in_addr(s
, &bgp
->router_id
);
4174 /* Extended Communities attribute. */
4175 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4176 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4177 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4179 if (peer
->sort
== BGP_PEER_IBGP
4180 || peer
->sort
== BGP_PEER_CONFED
) {
4181 if (ecomm
->size
* 8 > 255) {
4183 BGP_ATTR_FLAG_OPTIONAL
4184 | BGP_ATTR_FLAG_TRANS
4185 | BGP_ATTR_FLAG_EXTLEN
);
4186 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4187 stream_putw(s
, ecomm
->size
* 8);
4190 BGP_ATTR_FLAG_OPTIONAL
4191 | BGP_ATTR_FLAG_TRANS
);
4192 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4193 stream_putc(s
, ecomm
->size
* 8);
4195 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4199 int ecom_tr_size
= 0;
4202 for (i
= 0; i
< ecomm
->size
; i
++) {
4203 pnt
= ecomm
->val
+ (i
* 8);
4206 if (CHECK_FLAG(tbit
,
4207 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4214 if (ecom_tr_size
* 8 > 255) {
4217 BGP_ATTR_FLAG_OPTIONAL
4218 | BGP_ATTR_FLAG_TRANS
4219 | BGP_ATTR_FLAG_EXTLEN
);
4221 BGP_ATTR_EXT_COMMUNITIES
);
4222 stream_putw(s
, ecom_tr_size
* 8);
4226 BGP_ATTR_FLAG_OPTIONAL
4227 | BGP_ATTR_FLAG_TRANS
);
4229 BGP_ATTR_EXT_COMMUNITIES
);
4230 stream_putc(s
, ecom_tr_size
* 8);
4233 for (i
= 0; i
< ecomm
->size
; i
++) {
4234 pnt
= ecomm
->val
+ (i
* 8);
4239 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4242 stream_put(s
, pnt
, 8);
4248 /* Label index attribute. */
4249 if (safi
== SAFI_LABELED_UNICAST
) {
4250 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4251 uint32_t label_index
;
4253 label_index
= attr
->label_index
;
4255 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4257 BGP_ATTR_FLAG_OPTIONAL
4258 | BGP_ATTR_FLAG_TRANS
);
4259 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4261 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4263 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4264 stream_putc(s
, 0); // reserved
4265 stream_putw(s
, 0); // flags
4266 stream_putl(s
, label_index
);
4271 /* SRv6 Service Information Attribute. */
4272 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4273 if (attr
->srv6_l3vpn
) {
4274 uint8_t subtlv_len
=
4275 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4277 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4278 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4279 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4280 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4281 | BGP_ATTR_FLAG_TRANS
);
4282 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4283 stream_putc(s
, attr_len
);
4284 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4285 stream_putw(s
, tlv_len
);
4286 stream_putc(s
, 0); /* reserved */
4287 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4288 stream_putw(s
, subtlv_len
);
4289 stream_putc(s
, 0); /* reserved */
4290 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4291 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4292 stream_putc(s
, 0); /* sid_flags */
4293 stream_putw(s
, 0xffff); /* endpoint */
4294 stream_putc(s
, 0); /* reserved */
4297 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4300 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4301 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4302 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4303 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4304 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4305 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4306 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4307 } else if (attr
->srv6_vpn
) {
4308 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4309 | BGP_ATTR_FLAG_TRANS
);
4310 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4311 stream_putc(s
, 22); /* tlv len */
4312 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4313 stream_putw(s
, 0x13); /* tlv len */
4314 stream_putc(s
, 0x00); /* reserved */
4315 stream_putc(s
, 0x01); /* sid_type */
4316 stream_putc(s
, 0x00); /* sif_flags */
4317 stream_put(s
, &attr
->srv6_vpn
->sid
,
4318 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4322 if (send_as4_path
) {
4323 /* If the peer is NOT As4 capable, AND */
4324 /* there are ASnums > 65535 in path THEN
4325 * give out AS4_PATH */
4327 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4329 * Hm, I wonder... confederation things *should* only be at
4330 * the beginning of an aspath, right? Then we should use
4331 * aspath_delete_confed_seq for this, because it is already
4333 * Folks, talk to me: what is reasonable here!?
4335 aspath
= aspath_delete_confed_seq(aspath
);
4338 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4339 | BGP_ATTR_FLAG_EXTLEN
);
4340 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4341 aspath_sizep
= stream_get_endp(s
);
4343 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4346 if (aspath
!= attr
->aspath
)
4347 aspath_free(aspath
);
4349 if (send_as4_aggregator
) {
4350 /* send AS4_AGGREGATOR, at this place */
4351 /* this section of code moved here in order to ensure the
4353 * *ascending* order of attributes
4355 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4356 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4358 stream_putl(s
, attr
->aggregator_as
);
4359 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4362 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4363 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4364 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4365 /* Tunnel Encap attribute */
4366 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4368 #ifdef ENABLE_BGP_VNC_ATTR
4370 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4375 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4376 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4377 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4378 stream_putc(s
, 9); // Length
4379 stream_putc(s
, 0); // Flags
4380 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4381 stream_put(s
, &(attr
->label
),
4382 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4383 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4384 // Unicast tunnel endpoint IP address
4387 /* Unknown transit attribute. */
4388 struct transit
*transit
= bgp_attr_get_transit(attr
);
4391 stream_put(s
, transit
->val
, transit
->length
);
4393 /* Return total size of attribute. */
4394 return stream_get_endp(s
) - cp
;
4397 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4399 unsigned long attrlen_pnt
;
4401 iana_safi_t pkt_safi
;
4403 /* Set extended bit always to encode the attribute length as 2 bytes */
4404 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4405 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4407 attrlen_pnt
= stream_get_endp(s
);
4408 stream_putw(s
, 0); /* Length of this attribute. */
4410 /* Convert AFI, SAFI to values for packet. */
4411 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4413 stream_putw(s
, pkt_afi
);
4414 stream_putc(s
, pkt_safi
);
4419 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4420 afi_t afi
, safi_t safi
,
4421 const struct prefix_rd
*prd
,
4422 mpls_label_t
*label
, uint32_t num_labels
,
4423 bool addpath_capable
, uint32_t addpath_tx_id
,
4426 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4428 if (safi
== SAFI_LABELED_UNICAST
) {
4429 label
= (mpls_label_t
*)wlabel
;
4433 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4434 addpath_capable
, addpath_tx_id
, attr
);
4437 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4439 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4442 /* Initialization of attribute. */
4443 void bgp_attr_init(void)
4456 void bgp_attr_finish(void)
4461 ecommunity_finish();
4462 lcommunity_finish();
4469 /* Make attribute packet. */
4470 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4471 const struct prefix
*prefix
)
4476 struct aspath
*aspath
;
4477 bool addpath_capable
= false;
4478 uint32_t addpath_tx_id
= 0;
4480 /* Remember current pointer. */
4481 cp
= stream_get_endp(s
);
4483 /* Place holder of length. */
4486 /* Origin attribute. */
4487 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4488 stream_putc(s
, BGP_ATTR_ORIGIN
);
4490 stream_putc(s
, attr
->origin
);
4492 aspath
= attr
->aspath
;
4494 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4495 stream_putc(s
, BGP_ATTR_AS_PATH
);
4496 aspath_lenp
= stream_get_endp(s
);
4499 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4501 /* Nexthop attribute. */
4502 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4503 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4504 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4505 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4507 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4510 /* MED attribute. */
4511 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4512 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4513 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4515 stream_putl(s
, attr
->med
);
4518 /* Local preference. */
4519 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4520 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4521 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4523 stream_putl(s
, attr
->local_pref
);
4526 /* Atomic aggregate. */
4527 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4528 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4529 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4534 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4535 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4536 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4538 stream_putl(s
, attr
->aggregator_as
);
4539 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4542 /* Community attribute. */
4543 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4544 struct community
*comm
= NULL
;
4546 comm
= bgp_attr_get_community(attr
);
4547 if (comm
->size
* 4 > 255) {
4549 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4550 | BGP_ATTR_FLAG_EXTLEN
);
4551 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4552 stream_putw(s
, comm
->size
* 4);
4555 BGP_ATTR_FLAG_OPTIONAL
4556 | BGP_ATTR_FLAG_TRANS
);
4557 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4558 stream_putc(s
, comm
->size
* 4);
4560 stream_put(s
, comm
->val
, comm
->size
* 4);
4563 /* Large Community attribute. */
4564 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4565 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4567 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4568 | BGP_ATTR_FLAG_EXTLEN
);
4569 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4571 lcom_length(bgp_attr_get_lcommunity(attr
)));
4574 BGP_ATTR_FLAG_OPTIONAL
4575 | BGP_ATTR_FLAG_TRANS
);
4576 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4578 lcom_length(bgp_attr_get_lcommunity(attr
)));
4581 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4582 lcom_length(bgp_attr_get_lcommunity(attr
)));
4585 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4586 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4587 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4588 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4591 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4592 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4593 sizep
= stream_get_endp(s
);
4596 stream_putc(s
, 0); /* Marker: Attribute length. */
4597 stream_putw(s
, AFI_IP6
); /* AFI */
4598 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4601 stream_putc(s
, attr
->mp_nexthop_len
);
4602 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4603 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4604 stream_put(s
, &attr
->mp_nexthop_local
,
4611 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4614 /* Set MP attribute length. */
4615 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4619 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4620 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4622 BGP_ATTR_FLAG_OPTIONAL
4623 | BGP_ATTR_FLAG_TRANS
);
4624 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4626 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4627 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4628 stream_putc(s
, 0); // reserved
4629 stream_putw(s
, 0); // flags
4630 stream_putl(s
, attr
->label_index
);
4634 /* Return total size of attribute. */
4635 len
= stream_get_endp(s
) - cp
- 2;
4636 stream_putw_at(s
, cp
, len
);