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 {BGP_ATTR_OTC
, "OTC"},
80 #ifdef ENABLE_BGP_VNC_ATTR
81 {BGP_ATTR_VNC
, "VNC"},
83 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
84 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
85 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
88 static const struct message attr_flag_str
[] = {
89 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
90 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
91 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
92 /* bgp_attr_flags_diagnose() relies on this bit being last in
94 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
97 static struct hash
*cluster_hash
;
99 static void *cluster_hash_alloc(void *p
)
101 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
102 struct cluster_list
*cluster
;
104 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
105 cluster
->length
= val
->length
;
107 if (cluster
->length
) {
108 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
109 memcpy(cluster
->list
, val
->list
, val
->length
);
111 cluster
->list
= NULL
;
118 /* Cluster list related functions. */
119 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
121 struct cluster_list tmp
= {};
122 struct cluster_list
*cluster
;
125 tmp
.list
= length
== 0 ? NULL
: pnt
;
127 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
132 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
136 for (i
= 0; i
< cluster
->length
/ 4; i
++)
137 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
142 static unsigned int cluster_hash_key_make(const void *p
)
144 const struct cluster_list
*cluster
= p
;
146 return jhash(cluster
->list
, cluster
->length
, 0);
149 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
151 const struct cluster_list
*cluster1
= p1
;
152 const struct cluster_list
*cluster2
= p2
;
154 if (cluster1
->list
== cluster2
->list
)
157 if (!cluster1
->list
|| !cluster2
->list
)
160 if (cluster1
->length
!= cluster2
->length
)
163 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
166 static void cluster_free(struct cluster_list
*cluster
)
168 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
169 XFREE(MTYPE_CLUSTER
, cluster
);
172 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
174 struct cluster_list
*find
;
176 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
182 static void cluster_unintern(struct cluster_list
**cluster
)
184 if ((*cluster
)->refcnt
)
185 (*cluster
)->refcnt
--;
187 if ((*cluster
)->refcnt
== 0) {
188 void *p
= hash_release(cluster_hash
, *cluster
);
189 assert(p
== *cluster
);
190 cluster_free(*cluster
);
195 static void cluster_init(void)
197 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
201 static void cluster_finish(void)
203 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
204 hash_free(cluster_hash
);
208 static struct hash
*encap_hash
= NULL
;
209 #ifdef ENABLE_BGP_VNC
210 static struct hash
*vnc_hash
= NULL
;
212 static struct hash
*srv6_l3vpn_hash
;
213 static struct hash
*srv6_vpn_hash
;
215 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
217 struct bgp_attr_encap_subtlv
*new;
218 struct bgp_attr_encap_subtlv
*tail
;
219 struct bgp_attr_encap_subtlv
*p
;
221 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
222 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
224 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
227 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
230 memcpy(tail
, p
, size
);
237 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
239 struct bgp_attr_encap_subtlv
*next
;
243 XFREE(MTYPE_ENCAP_TLV
, p
);
248 void bgp_attr_flush_encap(struct attr
*attr
)
253 if (attr
->encap_subtlvs
) {
254 encap_free(attr
->encap_subtlvs
);
255 attr
->encap_subtlvs
= NULL
;
257 #ifdef ENABLE_BGP_VNC
258 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
259 bgp_attr_get_vnc_subtlvs(attr
);
262 encap_free(vnc_subtlvs
);
263 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
269 * Compare encap sub-tlv chains
274 * This algorithm could be made faster if needed
276 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
277 const struct bgp_attr_encap_subtlv
*h2
)
279 const struct bgp_attr_encap_subtlv
*p
;
280 const struct bgp_attr_encap_subtlv
*q
;
284 if (h1
== NULL
|| h2
== NULL
)
287 for (p
= h1
; p
; p
= p
->next
) {
288 for (q
= h2
; q
; q
= q
->next
) {
289 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
290 && !memcmp(p
->value
, q
->value
, p
->length
)) {
299 for (p
= h2
; p
; p
= p
->next
) {
300 for (q
= h1
; q
; q
= q
->next
) {
301 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
302 && !memcmp(p
->value
, q
->value
, p
->length
)) {
314 static void *encap_hash_alloc(void *p
)
316 /* Encap structure is already allocated. */
322 #ifdef ENABLE_BGP_VNC
327 static struct bgp_attr_encap_subtlv
*
328 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
330 struct bgp_attr_encap_subtlv
*find
;
331 struct hash
*hash
= encap_hash
;
332 #ifdef ENABLE_BGP_VNC
333 if (type
== VNC_SUBTLV_TYPE
)
337 find
= hash_get(hash
, encap
, encap_hash_alloc
);
345 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
346 encap_subtlv_type type
)
348 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
352 if (encap
->refcnt
== 0) {
353 struct hash
*hash
= encap_hash
;
354 #ifdef ENABLE_BGP_VNC
355 if (type
== VNC_SUBTLV_TYPE
)
358 hash_release(hash
, encap
);
364 static unsigned int encap_hash_key_make(const void *p
)
366 const struct bgp_attr_encap_subtlv
*encap
= p
;
368 return jhash(encap
->value
, encap
->length
, 0);
371 static bool encap_hash_cmp(const void *p1
, const void *p2
)
373 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
374 (const struct bgp_attr_encap_subtlv
*)p2
);
377 static void encap_init(void)
379 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
381 #ifdef ENABLE_BGP_VNC
382 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
387 static void encap_finish(void)
389 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
390 hash_free(encap_hash
);
392 #ifdef ENABLE_BGP_VNC
393 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
399 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
408 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
409 bgp_attr_get_evpn_overlay(a2
));
412 /* Unknown transit attribute. */
413 static struct hash
*transit_hash
;
415 static void transit_free(struct transit
*transit
)
417 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
418 XFREE(MTYPE_TRANSIT
, transit
);
421 static void *transit_hash_alloc(void *p
)
423 /* Transit structure is already allocated. */
427 static struct transit
*transit_intern(struct transit
*transit
)
429 struct transit
*find
;
431 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
433 transit_free(transit
);
439 static void transit_unintern(struct transit
**transit
)
441 if ((*transit
)->refcnt
)
442 (*transit
)->refcnt
--;
444 if ((*transit
)->refcnt
== 0) {
445 hash_release(transit_hash
, *transit
);
446 transit_free(*transit
);
451 static void *srv6_l3vpn_hash_alloc(void *p
)
456 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
458 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
461 static struct bgp_attr_srv6_l3vpn
*
462 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
464 struct bgp_attr_srv6_l3vpn
*find
;
466 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
468 srv6_l3vpn_free(l3vpn
);
473 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
475 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
480 if (l3vpn
->refcnt
== 0) {
481 hash_release(srv6_l3vpn_hash
, l3vpn
);
482 srv6_l3vpn_free(l3vpn
);
487 static void *srv6_vpn_hash_alloc(void *p
)
492 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
494 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
497 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
499 struct bgp_attr_srv6_vpn
*find
;
501 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
508 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
510 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
515 if (vpn
->refcnt
== 0) {
516 hash_release(srv6_vpn_hash
, vpn
);
522 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
524 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
527 key
= jhash(&l3vpn
->sid
, 16, key
);
528 key
= jhash_1word(l3vpn
->sid_flags
, key
);
529 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
530 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
531 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
532 key
= jhash_1word(l3vpn
->func_len
, key
);
533 key
= jhash_1word(l3vpn
->arg_len
, key
);
534 key
= jhash_1word(l3vpn
->transposition_len
, key
);
535 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
539 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
541 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
542 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
544 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
545 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
546 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
547 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
548 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
549 && l3vpn1
->func_len
== l3vpn2
->func_len
550 && l3vpn1
->arg_len
== l3vpn2
->arg_len
551 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
552 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
555 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
556 const struct bgp_attr_srv6_l3vpn
*h2
)
560 else if (h1
== NULL
|| h2
== NULL
)
563 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
566 static unsigned int srv6_vpn_hash_key_make(const void *p
)
568 const struct bgp_attr_srv6_vpn
*vpn
= p
;
571 key
= jhash(&vpn
->sid
, 16, key
);
572 key
= jhash_1word(vpn
->sid_flags
, key
);
576 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
578 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
579 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
581 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
582 && vpn1
->sid_flags
== vpn2
->sid_flags
;
585 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
586 const struct bgp_attr_srv6_vpn
*h2
)
590 else if (h1
== NULL
|| h2
== NULL
)
593 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
596 static void srv6_init(void)
599 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
600 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
601 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
602 "BGP Prefix-SID SRv6-VPN-Service-TLV");
605 static void srv6_finish(void)
607 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
608 hash_free(srv6_l3vpn_hash
);
609 srv6_l3vpn_hash
= NULL
;
610 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
611 hash_free(srv6_vpn_hash
);
612 srv6_vpn_hash
= NULL
;
615 static unsigned int transit_hash_key_make(const void *p
)
617 const struct transit
*transit
= p
;
619 return jhash(transit
->val
, transit
->length
, 0);
622 static bool transit_hash_cmp(const void *p1
, const void *p2
)
624 const struct transit
*transit1
= p1
;
625 const struct transit
*transit2
= p2
;
627 return (transit1
->length
== transit2
->length
628 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
631 static void transit_init(void)
633 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
637 static void transit_finish(void)
639 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
640 hash_free(transit_hash
);
644 /* Attribute hash routines. */
645 static struct hash
*attrhash
;
647 unsigned long int attr_count(void)
649 return attrhash
->count
;
652 unsigned long int attr_unknown_count(void)
654 return transit_hash
->count
;
657 unsigned int attrhash_key_make(const void *p
)
659 const struct attr
*attr
= (struct attr
*)p
;
661 #define MIX(val) key = jhash_1word(val, key)
662 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
664 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
665 MIX3(attr
->local_pref
, attr
->aggregator_as
,
666 attr
->aggregator_addr
.s_addr
);
667 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
668 attr
->originator_id
.s_addr
);
669 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
672 MIX(aspath_key_make(attr
->aspath
));
673 if (bgp_attr_get_community(attr
))
674 MIX(community_hash_make(bgp_attr_get_community(attr
)));
675 if (bgp_attr_get_lcommunity(attr
))
676 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
677 if (bgp_attr_get_ecommunity(attr
))
678 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
679 if (bgp_attr_get_ipv6_ecommunity(attr
))
680 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
681 if (bgp_attr_get_cluster(attr
))
682 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
683 if (bgp_attr_get_transit(attr
))
684 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
685 if (attr
->encap_subtlvs
)
686 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
687 if (attr
->srv6_l3vpn
)
688 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
690 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
691 #ifdef ENABLE_BGP_VNC
692 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
693 bgp_attr_get_vnc_subtlvs(attr
);
695 MIX(encap_hash_key_make(vnc_subtlvs
));
697 MIX(attr
->mp_nexthop_len
);
698 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
699 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
700 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
701 MIX(attr
->rmap_table_id
);
709 bool attrhash_cmp(const void *p1
, const void *p2
)
711 const struct attr
*attr1
= p1
;
712 const struct attr
*attr2
= p2
;
714 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
715 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
716 && attr1
->aspath
== attr2
->aspath
717 && bgp_attr_get_community(attr1
)
718 == bgp_attr_get_community(attr2
)
719 && attr1
->med
== attr2
->med
720 && attr1
->local_pref
== attr2
->local_pref
721 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
722 if (attr1
->aggregator_as
== attr2
->aggregator_as
723 && attr1
->aggregator_addr
.s_addr
724 == attr2
->aggregator_addr
.s_addr
725 && attr1
->weight
== attr2
->weight
726 && attr1
->tag
== attr2
->tag
727 && attr1
->label_index
== attr2
->label_index
728 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
729 && bgp_attr_get_ecommunity(attr1
)
730 == bgp_attr_get_ecommunity(attr2
)
731 && bgp_attr_get_ipv6_ecommunity(attr1
)
732 == bgp_attr_get_ipv6_ecommunity(attr2
)
733 && bgp_attr_get_lcommunity(attr1
)
734 == bgp_attr_get_lcommunity(attr2
)
735 && bgp_attr_get_cluster(attr1
)
736 == bgp_attr_get_cluster(attr2
)
737 && bgp_attr_get_transit(attr1
)
738 == bgp_attr_get_transit(attr2
)
739 && attr1
->rmap_table_id
== attr2
->rmap_table_id
740 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
741 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
742 #ifdef ENABLE_BGP_VNC
743 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
744 bgp_attr_get_vnc_subtlvs(attr2
))
746 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
747 &attr2
->mp_nexthop_global
)
748 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
749 &attr2
->mp_nexthop_local
)
750 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
751 &attr2
->mp_nexthop_global_in
)
752 && IPV4_ADDR_SAME(&attr1
->originator_id
,
753 &attr2
->originator_id
)
754 && overlay_index_same(attr1
, attr2
)
755 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
756 && attr1
->es_flags
== attr2
->es_flags
757 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
758 && attr1
->df_pref
== attr2
->df_pref
759 && attr1
->df_alg
== attr2
->df_alg
760 && attr1
->nh_ifindex
== attr2
->nh_ifindex
761 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
762 && attr1
->distance
== attr2
->distance
763 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
764 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
765 && attr1
->srte_color
== attr2
->srte_color
766 && attr1
->nh_type
== attr2
->nh_type
767 && attr1
->bh_type
== attr2
->bh_type
768 && attr1
->otc
== attr2
->otc
)
775 static void attrhash_init(void)
778 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
782 * special for hash_clean below
784 static void attr_vfree(void *attr
)
786 XFREE(MTYPE_ATTR
, attr
);
789 static void attrhash_finish(void)
791 hash_clean(attrhash
, attr_vfree
);
796 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
798 struct attr
*attr
= bucket
->data
;
799 char sid_str
[BUFSIZ
];
801 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
804 if (attr
->srv6_l3vpn
)
805 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
806 else if (attr
->srv6_vpn
)
807 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
810 "\tflags: %" PRIu64
" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
811 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
812 attr
->origin
, attr
->weight
, attr
->label
, sid_str
);
815 void attr_show_all(struct vty
*vty
)
817 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
818 void *))attr_show_all_iterator
,
822 static void *bgp_attr_hash_alloc(void *p
)
824 struct attr
*val
= (struct attr
*)p
;
827 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
829 if (val
->encap_subtlvs
) {
830 val
->encap_subtlvs
= NULL
;
832 #ifdef ENABLE_BGP_VNC
833 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
834 bgp_attr_get_vnc_subtlvs(val
);
837 bgp_attr_set_vnc_subtlvs(val
, NULL
);
844 /* Internet argument attribute. */
845 struct attr
*bgp_attr_intern(struct attr
*attr
)
848 struct ecommunity
*ecomm
= NULL
;
849 struct ecommunity
*ipv6_ecomm
= NULL
;
850 struct lcommunity
*lcomm
= NULL
;
851 struct community
*comm
= NULL
;
853 /* Intern referenced structure. */
855 if (!attr
->aspath
->refcnt
)
856 attr
->aspath
= aspath_intern(attr
->aspath
);
858 attr
->aspath
->refcnt
++;
861 comm
= bgp_attr_get_community(attr
);
864 bgp_attr_set_community(attr
, community_intern(comm
));
869 ecomm
= bgp_attr_get_ecommunity(attr
);
872 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
877 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
879 if (!ipv6_ecomm
->refcnt
)
880 bgp_attr_set_ipv6_ecommunity(
881 attr
, ecommunity_intern(ipv6_ecomm
));
883 ipv6_ecomm
->refcnt
++;
886 lcomm
= bgp_attr_get_lcommunity(attr
);
889 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
894 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
897 if (!cluster
->refcnt
)
898 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
903 struct transit
*transit
= bgp_attr_get_transit(attr
);
906 if (!transit
->refcnt
)
907 bgp_attr_set_transit(attr
, transit_intern(transit
));
911 if (attr
->encap_subtlvs
) {
912 if (!attr
->encap_subtlvs
->refcnt
)
913 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
916 attr
->encap_subtlvs
->refcnt
++;
918 if (attr
->srv6_l3vpn
) {
919 if (!attr
->srv6_l3vpn
->refcnt
)
920 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
922 attr
->srv6_l3vpn
->refcnt
++;
924 if (attr
->srv6_vpn
) {
925 if (!attr
->srv6_vpn
->refcnt
)
926 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
928 attr
->srv6_vpn
->refcnt
++;
930 #ifdef ENABLE_BGP_VNC
931 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
932 bgp_attr_get_vnc_subtlvs(attr
);
935 if (!vnc_subtlvs
->refcnt
)
936 bgp_attr_set_vnc_subtlvs(
938 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
940 vnc_subtlvs
->refcnt
++;
944 /* At this point, attr only contains intern'd pointers. that means
945 * if we find it in attrhash, it has all the same pointers and we
946 * correctly updated the refcounts on these.
947 * If we don't find it, we need to allocate a one because in all
948 * cases this returns a new reference to a hashed attr, but the input
950 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
956 /* Make network statement's attribute. */
957 struct attr
*bgp_attr_default_set(struct attr
*attr
, struct bgp
*bgp
,
960 memset(attr
, 0, sizeof(struct attr
));
962 attr
->origin
= origin
;
963 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
964 attr
->aspath
= aspath_empty();
965 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
966 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
968 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
969 attr
->label
= MPLS_INVALID_LABEL
;
970 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
971 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
972 attr
->local_pref
= bgp
->default_local_pref
;
977 /* Create the attributes for an aggregate */
978 struct attr
*bgp_attr_aggregate_intern(
979 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
980 struct community
*community
, struct ecommunity
*ecommunity
,
981 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
982 uint8_t atomic_aggregate
, const struct prefix
*p
)
988 memset(&attr
, 0, sizeof(attr
));
990 /* Origin attribute. */
991 attr
.origin
= origin
;
992 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
996 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
998 /* AS path attribute. */
1000 attr
.aspath
= aspath_intern(aspath
);
1002 attr
.aspath
= aspath_empty();
1003 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1005 /* Next hop attribute. */
1006 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1009 uint32_t gshut
= COMMUNITY_GSHUT
;
1011 /* If we are not shutting down ourselves and we are
1012 * aggregating a route that contains the GSHUT community we
1013 * need to remove that community when creating the aggregate */
1014 if (!bgp_in_graceful_shutdown(bgp
)
1015 && community_include(community
, gshut
)) {
1016 community_del_val(community
, &gshut
);
1019 bgp_attr_set_community(&attr
, community
);
1023 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1026 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1028 if (bgp_in_graceful_shutdown(bgp
))
1029 bgp_attr_add_gshut_community(&attr
);
1031 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1032 attr
.label
= MPLS_INVALID_LABEL
;
1033 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1034 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1035 if (!aggregate
->as_set
|| atomic_aggregate
)
1036 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1037 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1038 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1039 attr
.aggregator_as
= bgp
->confed_id
;
1041 attr
.aggregator_as
= bgp
->as
;
1042 attr
.aggregator_addr
= bgp
->router_id
;
1044 /* Apply route-map */
1045 if (aggregate
->rmap
.name
) {
1046 struct attr attr_tmp
= attr
;
1047 struct bgp_path_info rmap_path
;
1049 memset(&rmap_path
, 0, sizeof(rmap_path
));
1050 rmap_path
.peer
= bgp
->peer_self
;
1051 rmap_path
.attr
= &attr_tmp
;
1053 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1055 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1057 bgp
->peer_self
->rmap_type
= 0;
1059 if (ret
== RMAP_DENYMATCH
) {
1060 /* Free uninterned attribute. */
1061 bgp_attr_flush(&attr_tmp
);
1063 /* Unintern original. */
1064 aspath_unintern(&attr
.aspath
);
1068 if (bgp_in_graceful_shutdown(bgp
))
1069 bgp_attr_add_gshut_community(&attr_tmp
);
1071 new = bgp_attr_intern(&attr_tmp
);
1074 if (bgp_in_graceful_shutdown(bgp
))
1075 bgp_attr_add_gshut_community(&attr
);
1077 new = bgp_attr_intern(&attr
);
1080 /* Always release the 'intern()'ed AS Path. */
1081 aspath_unintern(&attr
.aspath
);
1086 /* Unintern just the sub-components of the attr, but not the attr */
1087 void bgp_attr_unintern_sub(struct attr
*attr
)
1089 struct ecommunity
*ecomm
= NULL
;
1090 struct ecommunity
*ipv6_ecomm
= NULL
;
1091 struct cluster_list
*cluster
;
1092 struct lcommunity
*lcomm
= NULL
;
1093 struct community
*comm
= NULL
;
1095 /* aspath refcount shoud be decrement. */
1096 aspath_unintern(&attr
->aspath
);
1097 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1099 comm
= bgp_attr_get_community(attr
);
1100 community_unintern(&comm
);
1101 bgp_attr_set_community(attr
, NULL
);
1103 ecomm
= bgp_attr_get_ecommunity(attr
);
1104 ecommunity_unintern(&ecomm
);
1105 bgp_attr_set_ecommunity(attr
, NULL
);
1107 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1108 ecommunity_unintern(&ipv6_ecomm
);
1109 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1111 lcomm
= bgp_attr_get_lcommunity(attr
);
1112 lcommunity_unintern(&lcomm
);
1113 bgp_attr_set_lcommunity(attr
, NULL
);
1115 cluster
= bgp_attr_get_cluster(attr
);
1117 cluster_unintern(&cluster
);
1118 bgp_attr_set_cluster(attr
, cluster
);
1120 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1122 struct transit
*transit
= bgp_attr_get_transit(attr
);
1125 transit_unintern(&transit
);
1126 bgp_attr_set_transit(attr
, transit
);
1129 if (attr
->encap_subtlvs
)
1130 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1132 #ifdef ENABLE_BGP_VNC
1133 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1134 bgp_attr_get_vnc_subtlvs(attr
);
1137 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1138 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1142 if (attr
->srv6_l3vpn
)
1143 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1146 srv6_vpn_unintern(&attr
->srv6_vpn
);
1149 /* Free bgp attribute and aspath. */
1150 void bgp_attr_unintern(struct attr
**pattr
)
1152 struct attr
*attr
= *pattr
;
1156 /* Decrement attribute reference. */
1161 /* If reference becomes zero then free attribute object. */
1162 if (attr
->refcnt
== 0) {
1163 ret
= hash_release(attrhash
, attr
);
1164 assert(ret
!= NULL
);
1165 XFREE(MTYPE_ATTR
, attr
);
1169 bgp_attr_unintern_sub(&tmp
);
1172 void bgp_attr_flush(struct attr
*attr
)
1174 struct ecommunity
*ecomm
;
1175 struct ecommunity
*ipv6_ecomm
;
1176 struct cluster_list
*cluster
;
1177 struct lcommunity
*lcomm
;
1178 struct community
*comm
;
1180 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1181 aspath_free(attr
->aspath
);
1182 attr
->aspath
= NULL
;
1184 comm
= bgp_attr_get_community(attr
);
1185 if (comm
&& !comm
->refcnt
)
1186 community_free(&comm
);
1187 bgp_attr_set_community(attr
, NULL
);
1189 ecomm
= bgp_attr_get_ecommunity(attr
);
1190 if (ecomm
&& !ecomm
->refcnt
)
1191 ecommunity_free(&ecomm
);
1192 bgp_attr_set_ecommunity(attr
, NULL
);
1194 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1195 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1196 ecommunity_free(&ipv6_ecomm
);
1197 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1199 lcomm
= bgp_attr_get_lcommunity(attr
);
1200 if (lcomm
&& !lcomm
->refcnt
)
1201 lcommunity_free(&lcomm
);
1202 bgp_attr_set_lcommunity(attr
, NULL
);
1204 cluster
= bgp_attr_get_cluster(attr
);
1205 if (cluster
&& !cluster
->refcnt
) {
1206 cluster_free(cluster
);
1207 bgp_attr_set_cluster(attr
, NULL
);
1210 struct transit
*transit
= bgp_attr_get_transit(attr
);
1212 if (transit
&& !transit
->refcnt
) {
1213 transit_free(transit
);
1214 bgp_attr_set_transit(attr
, NULL
);
1216 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1217 encap_free(attr
->encap_subtlvs
);
1218 attr
->encap_subtlvs
= NULL
;
1220 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1221 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1222 attr
->srv6_l3vpn
= NULL
;
1224 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1225 srv6_vpn_free(attr
->srv6_vpn
);
1226 attr
->srv6_vpn
= NULL
;
1228 #ifdef ENABLE_BGP_VNC
1229 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1230 bgp_attr_get_vnc_subtlvs(attr
);
1232 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1233 encap_free(vnc_subtlvs
);
1234 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1239 /* Implement draft-scudder-idr-optional-transitive behaviour and
1240 * avoid resetting sessions for malformed attributes which are
1241 * are partial/optional and hence where the error likely was not
1242 * introduced by the sending neighbour.
1244 static enum bgp_attr_parse_ret
1245 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1248 struct peer
*const peer
= args
->peer
;
1249 struct attr
*const attr
= args
->attr
;
1250 const uint8_t flags
= args
->flags
;
1251 /* startp and length must be special-cased, as whether or not to
1252 * send the attribute data with the NOTIFY depends on the error,
1253 * the caller therefore signals this with the seperate length argument
1255 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1257 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1258 char attr_str
[BUFSIZ
] = {0};
1260 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1262 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1265 /* Only relax error handling for eBGP peers */
1266 if (peer
->sort
!= BGP_PEER_EBGP
) {
1267 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1268 notify_datap
, length
);
1269 return BGP_ATTR_PARSE_ERROR
;
1272 /* Adjust the stream getp to the end of the attribute, in case we can
1273 * still proceed but the caller hasn't read all the attribute.
1275 stream_set_getp(BGP_INPUT(peer
),
1276 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1279 switch (args
->type
) {
1280 /* where an attribute is relatively inconsequential, e.g. it does not
1281 * affect route selection, and can be safely ignored, then any such
1282 * attributes which are malformed should just be ignored and the route
1283 * processed as normal.
1285 case BGP_ATTR_AS4_AGGREGATOR
:
1286 case BGP_ATTR_AGGREGATOR
:
1287 case BGP_ATTR_ATOMIC_AGGREGATE
:
1288 return BGP_ATTR_PARSE_PROCEED
;
1290 /* Core attributes, particularly ones which may influence route
1291 * selection, should be treat-as-withdraw.
1293 case BGP_ATTR_ORIGIN
:
1294 case BGP_ATTR_AS_PATH
:
1295 case BGP_ATTR_NEXT_HOP
:
1296 case BGP_ATTR_MULTI_EXIT_DISC
:
1297 case BGP_ATTR_LOCAL_PREF
:
1298 case BGP_ATTR_COMMUNITIES
:
1299 case BGP_ATTR_EXT_COMMUNITIES
:
1300 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1301 case BGP_ATTR_LARGE_COMMUNITIES
:
1302 case BGP_ATTR_ORIGINATOR_ID
:
1303 case BGP_ATTR_CLUSTER_LIST
:
1304 return BGP_ATTR_PARSE_WITHDRAW
;
1305 case BGP_ATTR_MP_REACH_NLRI
:
1306 case BGP_ATTR_MP_UNREACH_NLRI
:
1307 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1308 notify_datap
, length
);
1309 return BGP_ATTR_PARSE_ERROR
;
1312 /* Partial optional attributes that are malformed should not cause
1313 * the whole session to be reset. Instead treat it as a withdrawal
1314 * of the routes, if possible.
1316 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1317 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1318 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1319 return BGP_ATTR_PARSE_WITHDRAW
;
1321 /* default to reset */
1322 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1325 /* Find out what is wrong with the path attribute flag bits and log the error.
1326 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1327 Extended Length. Checking O/T/P bits at once implies, that the attribute
1328 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1329 non-transitive" attribute. */
1331 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1332 uint8_t desired_flags
/* how RFC says it must be */
1335 uint8_t seen
= 0, i
;
1336 uint8_t real_flags
= args
->flags
;
1337 const uint8_t attr_code
= args
->type
;
1339 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1340 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1341 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1342 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1343 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1344 flog_err(EC_BGP_ATTR_FLAG
,
1345 "%s attribute must%s be flagged as \"%s\"",
1346 lookup_msg(attr_str
, attr_code
, NULL
),
1347 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1350 attr_flag_str
[i
].str
);
1355 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1356 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1357 real_flags
, desired_flags
);
1361 /* Required flags for attributes. EXTLEN will be masked off when testing,
1362 * as will PARTIAL for optional+transitive attributes.
1364 const uint8_t attr_flags_values
[] = {
1365 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1366 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1367 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1368 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1369 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1370 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1371 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1372 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1373 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1374 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1375 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1376 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1377 [BGP_ATTR_EXT_COMMUNITIES
] =
1378 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1379 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1380 [BGP_ATTR_AS4_AGGREGATOR
] =
1381 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1382 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1383 [BGP_ATTR_LARGE_COMMUNITIES
] =
1384 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1385 [BGP_ATTR_OTC
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1386 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1387 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1388 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1390 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1392 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1394 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1395 const uint8_t flags
= args
->flags
;
1396 const uint8_t attr_code
= args
->type
;
1398 /* there may be attributes we don't know about */
1399 if (attr_code
> attr_flags_values_max
)
1401 if (attr_flags_values
[attr_code
] == 0)
1404 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1408 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1409 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1412 "%s well-known attributes must have transitive flag set (%x)",
1413 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1417 /* "For well-known attributes and for optional non-transitive
1419 * the Partial bit MUST be set to 0."
1421 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1422 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1423 flog_err(EC_BGP_ATTR_FLAG
,
1424 "%s well-known attribute must NOT have the partial flag set (%x)",
1425 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1428 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1429 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1430 flog_err(EC_BGP_ATTR_FLAG
,
1431 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1432 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1437 /* Optional transitive attributes may go through speakers that don't
1438 * reocgnise them and set the Partial bit.
1440 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1441 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1442 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1444 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1447 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1451 /* Get origin attribute of the update message. */
1452 static enum bgp_attr_parse_ret
1453 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 enum bgp_attr_parse_ret
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 enum bgp_attr_parse_ret
bgp_attr_nexthop_valid(struct peer
*peer
,
1609 struct bgp
*bgp
= peer
->bgp
;
1611 if (ipv4_martian(&attr
->nexthop
) && !bgp
->allow_martian
) {
1612 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1613 char buf
[INET_ADDRSTRLEN
];
1615 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1617 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1619 data
[0] = BGP_ATTR_FLAG_TRANS
;
1620 data
[1] = BGP_ATTR_NEXT_HOP
;
1621 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1622 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1623 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1624 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1626 return BGP_ATTR_PARSE_ERROR
;
1629 return BGP_ATTR_PARSE_PROCEED
;
1632 /* Nexthop attribute. */
1633 static enum bgp_attr_parse_ret
1634 bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1636 struct peer
*const peer
= args
->peer
;
1637 struct attr
*const attr
= args
->attr
;
1638 const bgp_size_t length
= args
->length
;
1640 /* Check nexthop attribute length. */
1642 flog_err(EC_BGP_ATTR_LEN
,
1643 "Nexthop attribute length isn't four [%d]", length
);
1645 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1649 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1650 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1652 return BGP_ATTR_PARSE_PROCEED
;
1655 /* MED atrribute. */
1656 static enum bgp_attr_parse_ret
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1658 struct peer
*const peer
= args
->peer
;
1659 struct attr
*const attr
= args
->attr
;
1660 const bgp_size_t length
= args
->length
;
1664 flog_err(EC_BGP_ATTR_LEN
,
1665 "MED attribute length isn't four [%d]", length
);
1667 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1671 attr
->med
= stream_getl(peer
->curr
);
1673 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1675 return BGP_ATTR_PARSE_PROCEED
;
1678 /* Local preference attribute. */
1679 static enum bgp_attr_parse_ret
1680 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1682 struct peer
*const peer
= args
->peer
;
1683 struct attr
*const attr
= args
->attr
;
1684 const bgp_size_t length
= args
->length
;
1686 /* if received from an internal neighbor, it SHALL be considered
1687 * malformed if its length is not equal to 4. If malformed, the
1688 * UPDATE message SHALL be handled using the approach of "treat-as-
1691 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1692 flog_err(EC_BGP_ATTR_LEN
,
1693 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1694 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1698 /* If it is contained in an UPDATE message that is received from an
1699 external peer, then this attribute MUST be ignored by the
1700 receiving speaker. */
1701 if (peer
->sort
== BGP_PEER_EBGP
) {
1702 STREAM_FORWARD_GETP(peer
->curr
, length
);
1703 return BGP_ATTR_PARSE_PROCEED
;
1706 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1708 /* Set the local-pref flag. */
1709 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1711 return BGP_ATTR_PARSE_PROCEED
;
1714 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1718 /* Atomic aggregate. */
1719 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1721 struct attr
*const attr
= args
->attr
;
1722 const bgp_size_t length
= args
->length
;
1726 flog_err(EC_BGP_ATTR_LEN
,
1727 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1729 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1733 /* Set atomic aggregate flag. */
1734 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1736 return BGP_ATTR_PARSE_PROCEED
;
1739 /* Aggregator attribute */
1740 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1742 struct peer
*const peer
= args
->peer
;
1743 struct attr
*const attr
= args
->attr
;
1744 const bgp_size_t length
= args
->length
;
1749 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1750 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1751 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1754 if (length
!= wantedlen
) {
1755 flog_err(EC_BGP_ATTR_LEN
,
1756 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1758 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1762 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1763 aggregator_as
= stream_getl(peer
->curr
);
1765 aggregator_as
= stream_getw(peer
->curr
);
1767 attr
->aggregator_as
= aggregator_as
;
1768 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1770 /* Codification of AS 0 Processing */
1771 if (aggregator_as
== BGP_AS_ZERO
) {
1772 flog_err(EC_BGP_ATTR_LEN
,
1773 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1774 peer
->host
, aspath_print(attr
->aspath
));
1776 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1777 char attr_str
[BUFSIZ
] = {0};
1779 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1781 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1784 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1787 return BGP_ATTR_PARSE_PROCEED
;
1790 /* New Aggregator attribute */
1791 static enum bgp_attr_parse_ret
1792 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1793 as_t
*as4_aggregator_as
,
1794 struct in_addr
*as4_aggregator_addr
)
1796 struct peer
*const peer
= args
->peer
;
1797 struct attr
*const attr
= args
->attr
;
1798 const bgp_size_t length
= args
->length
;
1802 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1804 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1808 aggregator_as
= stream_getl(peer
->curr
);
1810 *as4_aggregator_as
= aggregator_as
;
1811 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1813 /* Codification of AS 0 Processing */
1814 if (aggregator_as
== BGP_AS_ZERO
) {
1815 flog_err(EC_BGP_ATTR_LEN
,
1816 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1817 peer
->host
, aspath_print(attr
->aspath
));
1819 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1820 char attr_str
[BUFSIZ
] = {0};
1822 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1824 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1827 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1830 return BGP_ATTR_PARSE_PROCEED
;
1833 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1835 static enum bgp_attr_parse_ret
1836 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1837 struct aspath
*as4_path
, as_t as4_aggregator
,
1838 struct in_addr
*as4_aggregator_addr
)
1840 int ignore_as4_path
= 0;
1841 struct aspath
*newpath
;
1843 if (!attr
->aspath
) {
1844 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1846 * checked that all well-known, mandatory attributes were
1849 * Can only be a problem with peer itself - hard error
1851 return BGP_ATTR_PARSE_ERROR
;
1854 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1855 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1857 * It is worth a warning though, because the peer really
1858 * should not send them
1860 if (BGP_DEBUG(as4
, AS4
)) {
1861 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1862 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1863 "AS4 capable peer, yet it sent");
1866 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1867 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1869 "AS4 capable peer, yet it sent");
1872 return BGP_ATTR_PARSE_PROCEED
;
1875 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1876 * because that may override AS4_PATH
1878 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1879 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1881 * if the as_number in aggregator is not AS_TRANS,
1882 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1883 * and the Aggregator shall be taken as
1884 * info on the aggregating node, and the AS_PATH
1885 * shall be taken as the AS_PATH
1887 * the Aggregator shall be ignored and the
1888 * AS4_AGGREGATOR shall be taken as the
1889 * Aggregating node and the AS_PATH is to be
1890 * constructed "as in all other cases"
1892 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1894 if (BGP_DEBUG(as4
, AS4
))
1896 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1898 ignore_as4_path
= 1;
1900 /* "New_aggregator shall be taken as aggregator"
1902 attr
->aggregator_as
= as4_aggregator
;
1903 attr
->aggregator_addr
.s_addr
=
1904 as4_aggregator_addr
->s_addr
;
1907 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1908 * That is bogus - but reading the conditions
1909 * we have to handle AS4_AGGREGATOR as if it were
1910 * AGGREGATOR in that case
1912 if (BGP_DEBUG(as4
, AS4
))
1914 "[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",
1916 attr
->aggregator_as
= as4_aggregator
;
1917 /* sweep it under the carpet and simulate a "good"
1919 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1923 /* need to reconcile NEW_AS_PATH and AS_PATH */
1924 if (!ignore_as4_path
1925 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1926 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1928 return BGP_ATTR_PARSE_ERROR
;
1930 aspath_unintern(&attr
->aspath
);
1931 attr
->aspath
= aspath_intern(newpath
);
1933 return BGP_ATTR_PARSE_PROCEED
;
1936 /* Community attribute. */
1937 static enum bgp_attr_parse_ret
1938 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1940 struct peer
*const peer
= args
->peer
;
1941 struct attr
*const attr
= args
->attr
;
1942 const bgp_size_t length
= args
->length
;
1945 bgp_attr_set_community(attr
, NULL
);
1946 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1950 bgp_attr_set_community(
1952 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
1954 /* XXX: fix community_parse to use stream API and remove this */
1955 stream_forward_getp(peer
->curr
, length
);
1957 /* The Community attribute SHALL be considered malformed if its
1958 * length is not a non-zero multiple of 4.
1960 if (!bgp_attr_get_community(attr
))
1961 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1964 return BGP_ATTR_PARSE_PROCEED
;
1967 /* Originator ID attribute. */
1968 static enum bgp_attr_parse_ret
1969 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1971 struct peer
*const peer
= args
->peer
;
1972 struct attr
*const attr
= args
->attr
;
1973 const bgp_size_t length
= args
->length
;
1975 /* if received from an internal neighbor, it SHALL be considered
1976 * malformed if its length is not equal to 4. If malformed, the
1977 * UPDATE message SHALL be handled using the approach of "treat-as-
1981 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1984 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1988 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1990 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1992 return BGP_ATTR_PARSE_PROCEED
;
1995 /* Cluster list attribute. */
1996 static enum bgp_attr_parse_ret
1997 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1999 struct peer
*const peer
= args
->peer
;
2000 struct attr
*const attr
= args
->attr
;
2001 const bgp_size_t length
= args
->length
;
2003 /* if received from an internal neighbor, it SHALL be considered
2004 * malformed if its length is not a non-zero multiple of 4. If
2005 * malformed, the UPDATE message SHALL be handled using the approach
2006 * of "treat-as-withdraw".
2008 if (length
== 0 || length
% 4) {
2009 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2011 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2015 bgp_attr_set_cluster(
2016 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2019 /* XXX: Fix cluster_parse to use stream API and then remove this */
2020 stream_forward_getp(peer
->curr
, length
);
2022 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2024 return BGP_ATTR_PARSE_PROCEED
;
2027 /* Multiprotocol reachability information parse. */
2028 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2029 struct bgp_nlri
*mp_update
)
2033 iana_safi_t pkt_safi
;
2035 bgp_size_t nlri_len
;
2038 struct peer
*const peer
= args
->peer
;
2039 struct attr
*const attr
= args
->attr
;
2040 const bgp_size_t length
= args
->length
;
2042 /* Set end of packet. */
2043 s
= BGP_INPUT(peer
);
2044 start
= stream_get_getp(s
);
2046 /* safe to read statically sized header? */
2047 #define BGP_MP_REACH_MIN_SIZE 5
2048 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2049 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2050 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2051 __func__
, peer
->host
, (unsigned long)length
);
2052 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2055 /* Load AFI, SAFI. */
2056 pkt_afi
= stream_getw(s
);
2057 pkt_safi
= stream_getc(s
);
2059 /* Convert AFI, SAFI to internal values, check. */
2060 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2061 /* Log if AFI or SAFI is unrecognized. This is not an error
2063 * the attribute is otherwise malformed.
2065 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2067 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2068 peer
->host
, iana_afi2str(pkt_afi
),
2069 iana_safi2str(pkt_safi
));
2070 return BGP_ATTR_PARSE_ERROR
;
2073 /* Get nexthop length. */
2074 attr
->mp_nexthop_len
= stream_getc(s
);
2076 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2078 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2079 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2080 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2083 /* Nexthop length check. */
2084 switch (attr
->mp_nexthop_len
) {
2086 if (safi
!= SAFI_FLOWSPEC
) {
2087 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2088 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2089 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2092 case BGP_ATTR_NHLEN_VPNV4
:
2093 stream_getl(s
); /* RD high */
2094 stream_getl(s
); /* RD low */
2096 * NOTE: intentional fall through
2097 * - for consistency in rx processing
2099 * The following comment is to signal GCC this intention
2100 * and suppress the warning
2103 case BGP_ATTR_NHLEN_IPV4
:
2104 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2105 /* Probably needed for RFC 2283 */
2106 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2107 memcpy(&attr
->nexthop
.s_addr
,
2108 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2110 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2111 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2112 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2113 stream_getl(s
); /* RD high */
2114 stream_getl(s
); /* RD low */
2116 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2117 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2118 if (!peer
->nexthop
.ifp
) {
2119 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2121 return BGP_ATTR_PARSE_WITHDRAW
;
2123 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2126 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2127 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2128 if (attr
->mp_nexthop_len
2129 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2130 stream_getl(s
); /* RD high */
2131 stream_getl(s
); /* RD low */
2133 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2134 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2135 if (!peer
->nexthop
.ifp
) {
2136 zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2138 return BGP_ATTR_PARSE_WITHDRAW
;
2140 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2142 if (attr
->mp_nexthop_len
2143 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2144 stream_getl(s
); /* RD high */
2145 stream_getl(s
); /* RD low */
2147 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2148 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2149 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2151 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2152 peer
->host
, &attr
->mp_nexthop_global
,
2153 &attr
->mp_nexthop_local
);
2155 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2157 if (!peer
->nexthop
.ifp
) {
2158 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2160 return BGP_ATTR_PARSE_WITHDRAW
;
2162 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2165 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2166 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2167 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2171 zlog_info("%s: %s sent SNPA which couldn't be read",
2172 __func__
, peer
->host
);
2173 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2178 if ((val
= stream_getc(s
)))
2180 EC_BGP_DEFUNCT_SNPA_LEN
,
2181 "%s sent non-zero value, %u, for defunct SNPA-length field",
2185 /* must have nrli_len, what is left of the attribute */
2186 nlri_len
= LEN_LEFT
;
2187 if (nlri_len
> STREAM_READABLE(s
)) {
2188 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2189 __func__
, peer
->host
);
2190 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2194 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2195 __func__
, peer
->host
);
2197 mp_update
->afi
= afi
;
2198 mp_update
->safi
= safi
;
2199 return BGP_ATTR_PARSE_EOR
;
2202 mp_update
->afi
= afi
;
2203 mp_update
->safi
= safi
;
2204 mp_update
->nlri
= stream_pnt(s
);
2205 mp_update
->length
= nlri_len
;
2207 stream_forward_getp(s
, nlri_len
);
2209 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2211 return BGP_ATTR_PARSE_PROCEED
;
2215 /* Multiprotocol unreachable parse */
2216 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2217 struct bgp_nlri
*mp_withdraw
)
2222 iana_safi_t pkt_safi
;
2224 uint16_t withdraw_len
;
2225 struct peer
*const peer
= args
->peer
;
2226 struct attr
*const attr
= args
->attr
;
2227 const bgp_size_t length
= args
->length
;
2231 #define BGP_MP_UNREACH_MIN_SIZE 3
2232 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2233 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2235 pkt_afi
= stream_getw(s
);
2236 pkt_safi
= stream_getc(s
);
2238 /* Convert AFI, SAFI to internal values, check. */
2239 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2240 /* Log if AFI or SAFI is unrecognized. This is not an error
2242 * the attribute is otherwise malformed.
2244 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2246 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2247 peer
->host
, iana_afi2str(pkt_afi
),
2248 iana_safi2str(pkt_safi
));
2249 return BGP_ATTR_PARSE_ERROR
;
2252 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2254 mp_withdraw
->afi
= afi
;
2255 mp_withdraw
->safi
= safi
;
2256 mp_withdraw
->nlri
= stream_pnt(s
);
2257 mp_withdraw
->length
= withdraw_len
;
2259 stream_forward_getp(s
, withdraw_len
);
2261 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2263 return BGP_ATTR_PARSE_PROCEED
;
2266 /* Large Community attribute. */
2267 static enum bgp_attr_parse_ret
2268 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2270 struct peer
*const peer
= args
->peer
;
2271 struct attr
*const attr
= args
->attr
;
2272 const bgp_size_t length
= args
->length
;
2275 * Large community follows new attribute format.
2278 bgp_attr_set_lcommunity(attr
, NULL
);
2279 /* Empty extcomm doesn't seem to be invalid per se */
2280 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2284 bgp_attr_set_lcommunity(
2285 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2286 /* XXX: fix ecommunity_parse to use stream API */
2287 stream_forward_getp(peer
->curr
, length
);
2289 if (!bgp_attr_get_lcommunity(attr
))
2290 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2293 return BGP_ATTR_PARSE_PROCEED
;
2296 /* Extended Community attribute. */
2297 static enum bgp_attr_parse_ret
2298 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2300 struct peer
*const peer
= args
->peer
;
2301 struct attr
*const attr
= args
->attr
;
2302 const bgp_size_t length
= args
->length
;
2305 struct ecommunity
*ecomm
;
2308 bgp_attr_set_ecommunity(attr
, NULL
);
2309 /* Empty extcomm doesn't seem to be invalid per se */
2310 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2314 ecomm
= ecommunity_parse(
2315 stream_pnt(peer
->curr
), length
,
2316 CHECK_FLAG(peer
->flags
,
2317 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2318 bgp_attr_set_ecommunity(attr
, ecomm
);
2319 /* XXX: fix ecommunity_parse to use stream API */
2320 stream_forward_getp(peer
->curr
, length
);
2322 /* The Extended Community attribute SHALL be considered malformed if
2323 * its length is not a non-zero multiple of 8.
2325 if (!bgp_attr_get_ecommunity(attr
))
2326 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2329 /* Extract DF election preference and mobility sequence number */
2330 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2332 /* Extract MAC mobility sequence number, if any. */
2333 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2334 attr
->sticky
= sticky
;
2336 /* Check if this is a Gateway MAC-IP advertisement */
2337 attr
->default_gw
= bgp_attr_default_gw(attr
);
2339 /* Handle scenario where router flag ecommunity is not
2340 * set but default gw ext community is present.
2341 * Use default gateway, set and propogate R-bit.
2343 if (attr
->default_gw
)
2344 attr
->router_flag
= 1;
2346 /* Check EVPN Neighbor advertisement flags, R-bit */
2347 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2349 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2351 /* Extract the Rmac, if any */
2352 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2353 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2354 && bgp_mac_exist(&attr
->rmac
))
2355 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2359 /* Get the tunnel type from encap extended community */
2360 bgp_attr_extcom_tunnel_type(attr
,
2361 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2363 /* Extract link bandwidth, if any. */
2364 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2367 return BGP_ATTR_PARSE_PROCEED
;
2370 /* IPv6 Extended Community attribute. */
2371 static enum bgp_attr_parse_ret
2372 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2374 struct peer
*const peer
= args
->peer
;
2375 struct attr
*const attr
= args
->attr
;
2376 const bgp_size_t length
= args
->length
;
2377 struct ecommunity
*ipv6_ecomm
= NULL
;
2380 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2381 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2385 ipv6_ecomm
= ecommunity_parse_ipv6(
2386 stream_pnt(peer
->curr
), length
,
2387 CHECK_FLAG(peer
->flags
,
2388 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2389 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2391 /* XXX: fix ecommunity_parse to use stream API */
2392 stream_forward_getp(peer
->curr
, length
);
2395 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2398 return BGP_ATTR_PARSE_PROCEED
;
2401 /* Parse Tunnel Encap attribute in an UPDATE */
2402 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2403 bgp_size_t length
, /* IN: attr's length field */
2404 struct attr
*attr
, /* IN: caller already allocated */
2405 uint8_t flag
, /* IN: attr's flags field */
2409 uint16_t tunneltype
= 0;
2411 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2413 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2414 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2416 "Tunnel Encap attribute flag isn't optional and transitive %d",
2418 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2419 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2424 if (BGP_ATTR_ENCAP
== type
) {
2425 /* read outer TLV type and length */
2426 uint16_t tlv_length
;
2430 "Tunnel Encap attribute not long enough to contain outer T,L");
2431 bgp_notify_send_with_data(
2432 peer
, BGP_NOTIFY_UPDATE_ERR
,
2433 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2436 tunneltype
= stream_getw(BGP_INPUT(peer
));
2437 tlv_length
= stream_getw(BGP_INPUT(peer
));
2440 if (tlv_length
!= length
) {
2441 zlog_info("%s: tlv_length(%d) != length(%d)",
2442 __func__
, tlv_length
, length
);
2446 while (length
>= 4) {
2447 uint16_t subtype
= 0;
2448 uint16_t sublength
= 0;
2449 struct bgp_attr_encap_subtlv
*tlv
;
2451 if (BGP_ATTR_ENCAP
== type
) {
2452 subtype
= stream_getc(BGP_INPUT(peer
));
2453 sublength
= stream_getc(BGP_INPUT(peer
));
2455 #ifdef ENABLE_BGP_VNC
2457 subtype
= stream_getw(BGP_INPUT(peer
));
2458 sublength
= stream_getw(BGP_INPUT(peer
));
2463 if (sublength
> length
) {
2465 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2467 bgp_notify_send_with_data(
2468 peer
, BGP_NOTIFY_UPDATE_ERR
,
2469 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2473 /* alloc and copy sub-tlv */
2474 /* TBD make sure these are freed when attributes are released */
2475 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2476 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2477 tlv
->type
= subtype
;
2478 tlv
->length
= sublength
;
2479 stream_get(tlv
->value
, peer
->curr
, sublength
);
2480 length
-= sublength
;
2482 /* attach tlv to encap chain */
2483 if (BGP_ATTR_ENCAP
== type
) {
2484 struct bgp_attr_encap_subtlv
*stlv_last
;
2485 for (stlv_last
= attr
->encap_subtlvs
;
2486 stlv_last
&& stlv_last
->next
;
2487 stlv_last
= stlv_last
->next
)
2490 stlv_last
->next
= tlv
;
2492 attr
->encap_subtlvs
= tlv
;
2494 #ifdef ENABLE_BGP_VNC
2496 struct bgp_attr_encap_subtlv
*stlv_last
;
2497 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2498 bgp_attr_get_vnc_subtlvs(attr
);
2500 for (stlv_last
= vnc_subtlvs
;
2501 stlv_last
&& stlv_last
->next
;
2502 stlv_last
= stlv_last
->next
)
2505 stlv_last
->next
= tlv
;
2507 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2512 if (BGP_ATTR_ENCAP
== type
) {
2513 attr
->encap_tunneltype
= tunneltype
;
2517 /* spurious leftover data */
2519 "Tunnel Encap attribute length is bad: %d leftover octets",
2521 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2522 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2531 /* SRv6 Service Data Sub-Sub-TLV attribute
2532 * draft-ietf-bess-srv6-services-07
2534 static enum bgp_attr_parse_ret
2535 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2537 struct peer
*const peer
= args
->peer
;
2538 struct attr
*const attr
= args
->attr
;
2539 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2540 transposition_len
, transposition_offset
;
2542 size_t headersz
= sizeof(type
) + sizeof(length
);
2544 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2547 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2548 headersz
, STREAM_READABLE(peer
->curr
));
2549 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2553 type
= stream_getc(peer
->curr
);
2554 length
= stream_getw(peer
->curr
);
2556 if (STREAM_READABLE(peer
->curr
) < length
) {
2559 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2560 length
, STREAM_READABLE(peer
->curr
));
2561 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2565 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2568 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2569 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
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 enum bgp_attr_parse_ret
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 enum bgp_attr_parse_ret 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 enum bgp_attr_parse_ret
2711 bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2712 struct bgp_attr_parser_args
*args
)
2714 struct peer
*const peer
= args
->peer
;
2715 struct attr
*const attr
= args
->attr
;
2716 uint32_t label_index
;
2717 struct in6_addr ipv6_sid
;
2719 uint32_t srgb_range
;
2721 uint8_t sid_type
, sid_flags
;
2724 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2725 if (STREAM_READABLE(peer
->curr
) < length
2726 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2727 flog_err(EC_BGP_ATTR_LEN
,
2728 "Prefix SID label index length is %hu instead of %u",
2729 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2730 return bgp_attr_malformed(args
,
2731 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2735 /* Ignore flags and reserved */
2736 stream_getc(peer
->curr
);
2737 stream_getw(peer
->curr
);
2739 /* Fetch the label index and see if it is valid. */
2740 label_index
= stream_getl(peer
->curr
);
2741 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2742 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2745 /* Store label index; subsequently, we'll check on
2747 attr
->label_index
= label_index
;
2750 /* Placeholder code for the IPv6 SID type */
2751 else if (type
== BGP_PREFIX_SID_IPV6
) {
2752 if (STREAM_READABLE(peer
->curr
) < length
2753 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2754 flog_err(EC_BGP_ATTR_LEN
,
2755 "Prefix SID IPv6 length is %hu instead of %u",
2756 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2757 return bgp_attr_malformed(args
,
2758 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2762 /* Ignore reserved */
2763 stream_getc(peer
->curr
);
2764 stream_getw(peer
->curr
);
2766 stream_get(&ipv6_sid
, peer
->curr
, 16);
2769 /* Placeholder code for the Originator SRGB type */
2770 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2772 * ietf-idr-bgp-prefix-sid-05:
2773 * Length is the total length of the value portion of the
2774 * TLV: 2 + multiple of 6.
2776 * peer->curr stream readp should be at the beginning of the 16
2777 * bit flag field at this point in the code.
2781 * Check that the TLV length field is sane: at least 2 bytes of
2782 * flag, and at least 1 SRGB (these are 6 bytes each)
2784 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2787 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2789 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2790 return bgp_attr_malformed(
2791 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2796 * Check that we actually have at least as much data as
2797 * specified by the length field
2799 if (STREAM_READABLE(peer
->curr
) < length
) {
2800 flog_err(EC_BGP_ATTR_LEN
,
2801 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2802 length
, STREAM_READABLE(peer
->curr
));
2803 return bgp_attr_malformed(
2804 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2809 * Check that the portion of the TLV containing the sequence of
2810 * SRGBs corresponds to a multiple of the SRGB size; to get
2811 * that length, we skip the 16 bit flags field
2813 stream_getw(peer
->curr
);
2815 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2818 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2819 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2820 return bgp_attr_malformed(
2821 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2825 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2827 for (int i
= 0; i
< srgb_count
; i
++) {
2828 stream_get(&srgb_base
, peer
->curr
, 3);
2829 stream_get(&srgb_range
, peer
->curr
, 3);
2833 /* Placeholder code for the VPN-SID Service type */
2834 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2835 if (STREAM_READABLE(peer
->curr
) < length
2836 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2837 flog_err(EC_BGP_ATTR_LEN
,
2838 "Prefix SID VPN SID length is %hu instead of %u",
2839 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2840 return bgp_attr_malformed(args
,
2841 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2845 /* Parse VPN-SID Sub-TLV */
2846 stream_getc(peer
->curr
); /* reserved */
2847 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2848 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2849 stream_get(&ipv6_sid
, peer
->curr
,
2850 sizeof(ipv6_sid
)); /* sid_value */
2852 /* Log VPN-SID Sub-TLV */
2853 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2854 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2856 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2857 __func__
, buf
, sid_type
, sid_flags
);
2860 /* Configure from Info */
2861 if (attr
->srv6_vpn
) {
2862 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2863 "Prefix SID SRv6 VPN field repeated");
2864 return bgp_attr_malformed(
2865 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2867 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2868 sizeof(struct bgp_attr_srv6_vpn
));
2869 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2870 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2871 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2874 /* Placeholder code for the SRv6 L3 Service type */
2875 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2876 if (STREAM_READABLE(peer
->curr
) < length
) {
2879 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
2880 length
, STREAM_READABLE(peer
->curr
));
2881 return bgp_attr_malformed(args
,
2882 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2886 /* ignore reserved */
2887 stream_getc(peer
->curr
);
2889 return bgp_attr_srv6_service(args
);
2892 /* Placeholder code for Unsupported TLV */
2895 if (STREAM_READABLE(peer
->curr
) < length
) {
2898 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2899 length
, STREAM_READABLE(peer
->curr
));
2900 return bgp_attr_malformed(
2901 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2905 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2907 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2910 stream_forward_getp(peer
->curr
, length
);
2913 return BGP_ATTR_PARSE_PROCEED
;
2916 /* Prefix SID attribute
2917 * draft-ietf-idr-bgp-prefix-sid-05
2919 enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2921 struct peer
*const peer
= args
->peer
;
2922 struct attr
*const attr
= args
->attr
;
2923 enum bgp_attr_parse_ret ret
;
2925 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2929 size_t headersz
= sizeof(type
) + sizeof(length
);
2930 size_t psid_parsed_length
= 0;
2932 while (STREAM_READABLE(peer
->curr
) > 0
2933 && psid_parsed_length
< args
->length
) {
2935 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2938 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2939 headersz
, STREAM_READABLE(peer
->curr
));
2940 return bgp_attr_malformed(
2941 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2945 type
= stream_getc(peer
->curr
);
2946 length
= stream_getw(peer
->curr
);
2948 if (STREAM_READABLE(peer
->curr
) < length
) {
2951 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2952 length
, STREAM_READABLE(peer
->curr
));
2953 return bgp_attr_malformed(args
,
2954 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2958 ret
= bgp_attr_psid_sub(type
, length
, args
);
2960 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2963 psid_parsed_length
+= length
+ headersz
;
2965 if (psid_parsed_length
> args
->length
) {
2968 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2969 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2970 return bgp_attr_malformed(
2971 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2976 return BGP_ATTR_PARSE_PROCEED
;
2979 /* PMSI tunnel attribute (RFC 6514)
2980 * Basic validation checks done here.
2982 static enum bgp_attr_parse_ret
2983 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2985 struct peer
*const peer
= args
->peer
;
2986 struct attr
*const attr
= args
->attr
;
2987 const bgp_size_t length
= args
->length
;
2989 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2991 /* Verify that the receiver is expecting "ingress replication" as we
2992 * can only support that.
2994 if (length
< attr_parse_len
) {
2995 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2997 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3000 stream_getc(peer
->curr
); /* Flags */
3001 tnl_type
= stream_getc(peer
->curr
);
3002 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3003 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3004 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3005 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3008 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3010 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3011 "Bad PMSI tunnel attribute length %d for IR",
3013 return bgp_attr_malformed(
3014 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3019 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3020 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3021 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3023 /* Forward read pointer of input stream. */
3024 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3026 return BGP_ATTR_PARSE_PROCEED
;
3029 /* OTC attribute. */
3030 static enum bgp_attr_parse_ret
bgp_attr_otc(struct bgp_attr_parser_args
*args
)
3032 struct peer
*const peer
= args
->peer
;
3033 struct attr
*const attr
= args
->attr
;
3034 const bgp_size_t length
= args
->length
;
3038 flog_err(EC_BGP_ATTR_LEN
, "OTC attribute length isn't 4 [%u]",
3040 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3044 attr
->otc
= stream_getl(peer
->curr
);
3046 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_OTC
);
3048 return BGP_ATTR_PARSE_PROCEED
;
3051 /* BGP unknown attribute treatment. */
3052 static enum bgp_attr_parse_ret
3053 bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3055 bgp_size_t total
= args
->total
;
3056 struct transit
*transit
;
3057 struct peer
*const peer
= args
->peer
;
3058 struct attr
*const attr
= args
->attr
;
3059 uint8_t *const startp
= args
->startp
;
3060 const uint8_t type
= args
->type
;
3061 const uint8_t flag
= args
->flags
;
3062 const bgp_size_t length
= args
->length
;
3064 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3066 "%s Unknown attribute is received (type %d, length %d)",
3067 peer
->host
, type
, length
);
3069 /* Forward read pointer of input stream. */
3070 stream_forward_getp(peer
->curr
, length
);
3072 /* If any of the mandatory well-known attributes are not recognized,
3073 then the Error Subcode is set to Unrecognized Well-known
3074 Attribute. The Data field contains the unrecognized attribute
3075 (type, length and value). */
3076 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3077 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3081 /* Unrecognized non-transitive optional attributes must be quietly
3082 ignored and not passed along to other BGP peers. */
3083 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3084 return BGP_ATTR_PARSE_PROCEED
;
3086 /* If a path with recognized transitive optional attribute is
3087 accepted and passed along to other BGP peers and the Partial bit
3088 in the Attribute Flags octet is set to 1 by some previous AS, it
3089 is not set back to 0 by the current AS. */
3090 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3092 /* Store transitive attribute to the end of attr->transit. */
3093 transit
= bgp_attr_get_transit(attr
);
3095 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3097 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3098 transit
->length
+ total
);
3100 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3101 transit
->length
+= total
;
3102 bgp_attr_set_transit(attr
, transit
);
3104 return BGP_ATTR_PARSE_PROCEED
;
3107 /* Well-known attribute check. */
3108 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3112 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3114 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3115 return BGP_ATTR_PARSE_PROCEED
;
3117 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3118 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3119 are present, it should. Check for any other attribute being present
3122 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3123 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3124 return BGP_ATTR_PARSE_PROCEED
;
3126 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3127 type
= BGP_ATTR_ORIGIN
;
3129 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3130 type
= BGP_ATTR_AS_PATH
;
3132 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3134 * NLRI is empty. We can't easily check NLRI empty here though.
3136 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3137 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3138 type
= BGP_ATTR_NEXT_HOP
;
3140 if (peer
->sort
== BGP_PEER_IBGP
3141 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3142 type
= BGP_ATTR_LOCAL_PREF
;
3144 /* If any of the well-known mandatory attributes are not present
3145 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3148 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3149 "%s Missing well-known attribute %s.", peer
->host
,
3150 lookup_msg(attr_str
, type
, NULL
));
3151 return BGP_ATTR_PARSE_WITHDRAW
;
3153 return BGP_ATTR_PARSE_PROCEED
;
3156 /* Read attribute of update packet. This function is called from
3157 bgp_update_receive() in bgp_packet.c. */
3158 enum bgp_attr_parse_ret
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3160 struct bgp_nlri
*mp_update
,
3161 struct bgp_nlri
*mp_withdraw
)
3163 enum bgp_attr_parse_ret ret
;
3167 uint8_t *startp
, *endp
;
3169 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3170 /* we need the as4_path only until we have synthesized the as_path with
3172 /* same goes for as4_aggregator */
3173 struct aspath
*as4_path
= NULL
;
3174 as_t as4_aggregator
= 0;
3175 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3176 struct transit
*transit
;
3178 /* Initialize bitmap. */
3179 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3181 /* End pointer of BGP attribute. */
3182 endp
= BGP_INPUT_PNT(peer
) + size
;
3184 /* Get attributes to the end of attribute length. */
3185 while (BGP_INPUT_PNT(peer
) < endp
) {
3186 /* Check remaining length check.*/
3187 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3188 /* XXX warning: long int format, int arg (arg 5) */
3190 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3191 "%s: error BGP attribute length %lu is smaller than min len",
3193 (unsigned long)(endp
3194 - stream_pnt(BGP_INPUT(peer
))));
3196 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3197 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3198 ret
= BGP_ATTR_PARSE_ERROR
;
3202 /* Fetch attribute flag and type. */
3203 startp
= BGP_INPUT_PNT(peer
);
3204 /* "The lower-order four bits of the Attribute Flags octet are
3205 unused. They MUST be zero when sent and MUST be ignored when
3207 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3208 type
= stream_getc(BGP_INPUT(peer
));
3210 /* Check whether Extended-Length applies and is in bounds */
3211 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3212 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3214 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3215 "%s: Extended length set, but just %lu bytes of attr header",
3217 (unsigned long)(endp
3218 - stream_pnt(BGP_INPUT(peer
))));
3220 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3221 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3222 ret
= BGP_ATTR_PARSE_ERROR
;
3226 /* Check extended attribue length bit. */
3227 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3228 length
= stream_getw(BGP_INPUT(peer
));
3230 length
= stream_getc(BGP_INPUT(peer
));
3232 /* If any attribute appears more than once in the UPDATE
3233 message, then the Error Subcode is set to Malformed Attribute
3236 if (CHECK_BITMAP(seen
, type
)) {
3238 EC_BGP_ATTRIBUTE_REPEATED
,
3239 "%s: error BGP attribute type %d appears twice in a message",
3242 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3243 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3244 ret
= BGP_ATTR_PARSE_ERROR
;
3248 /* Set type to bitmap to check duplicate attribute. `type' is
3249 unsigned char so it never overflow bitmap range. */
3251 SET_BITMAP(seen
, type
);
3253 /* Overflow check. */
3254 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3256 if (attr_endp
> endp
) {
3258 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3259 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3260 peer
->host
, type
, length
, size
, attr_endp
,
3264 * If any recognized attribute has an Attribute
3265 * Length that conflicts with the expected length
3266 * (based on the attribute type code), then the
3267 * Error Subcode MUST be set to Attribute Length
3268 * Error. The Data field MUST contain the erroneous
3269 * attribute (type, length, and value).
3271 * We do not currently have a good way to determine the
3272 * length of the attribute independent of the length
3273 * received in the message. Instead we send the
3274 * minimum between the amount of data we have and the
3275 * amount specified by the attribute length field.
3277 * Instead of directly passing in the packet buffer and
3278 * offset we use the stream_get* functions to read into
3279 * a stack buffer, since they perform bounds checking
3280 * and we are working with untrusted data.
3282 unsigned char ndata
[peer
->max_packet_size
];
3283 memset(ndata
, 0x00, sizeof(ndata
));
3285 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3286 /* Rewind to end of flag field */
3287 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3289 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3291 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3293 size_t atl
= attr_endp
- startp
;
3294 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3295 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3297 bgp_notify_send_with_data(
3298 peer
, BGP_NOTIFY_UPDATE_ERR
,
3299 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3302 ret
= BGP_ATTR_PARSE_ERROR
;
3306 struct bgp_attr_parser_args attr_args
= {
3313 .total
= attr_endp
- startp
,
3317 /* If any recognized attribute has Attribute Flags that conflict
3318 with the Attribute Type Code, then the Error Subcode is set
3320 Attribute Flags Error. The Data field contains the erroneous
3321 attribute (type, length and value). */
3322 if (bgp_attr_flag_invalid(&attr_args
)) {
3323 ret
= bgp_attr_malformed(
3324 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3326 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3331 /* OK check attribute and store it's value. */
3333 case BGP_ATTR_ORIGIN
:
3334 ret
= bgp_attr_origin(&attr_args
);
3336 case BGP_ATTR_AS_PATH
:
3337 ret
= bgp_attr_aspath(&attr_args
);
3339 case BGP_ATTR_AS4_PATH
:
3340 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3342 case BGP_ATTR_NEXT_HOP
:
3343 ret
= bgp_attr_nexthop(&attr_args
);
3345 case BGP_ATTR_MULTI_EXIT_DISC
:
3346 ret
= bgp_attr_med(&attr_args
);
3348 case BGP_ATTR_LOCAL_PREF
:
3349 ret
= bgp_attr_local_pref(&attr_args
);
3351 case BGP_ATTR_ATOMIC_AGGREGATE
:
3352 ret
= bgp_attr_atomic(&attr_args
);
3354 case BGP_ATTR_AGGREGATOR
:
3355 ret
= bgp_attr_aggregator(&attr_args
);
3357 case BGP_ATTR_AS4_AGGREGATOR
:
3358 ret
= bgp_attr_as4_aggregator(&attr_args
,
3360 &as4_aggregator_addr
);
3362 case BGP_ATTR_COMMUNITIES
:
3363 ret
= bgp_attr_community(&attr_args
);
3365 case BGP_ATTR_LARGE_COMMUNITIES
:
3366 ret
= bgp_attr_large_community(&attr_args
);
3368 case BGP_ATTR_ORIGINATOR_ID
:
3369 ret
= bgp_attr_originator_id(&attr_args
);
3371 case BGP_ATTR_CLUSTER_LIST
:
3372 ret
= bgp_attr_cluster_list(&attr_args
);
3374 case BGP_ATTR_MP_REACH_NLRI
:
3375 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3377 case BGP_ATTR_MP_UNREACH_NLRI
:
3378 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3380 case BGP_ATTR_EXT_COMMUNITIES
:
3381 ret
= bgp_attr_ext_communities(&attr_args
);
3383 #ifdef ENABLE_BGP_VNC_ATTR
3386 case BGP_ATTR_ENCAP
:
3387 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3390 case BGP_ATTR_PREFIX_SID
:
3391 ret
= bgp_attr_prefix_sid(&attr_args
);
3393 case BGP_ATTR_PMSI_TUNNEL
:
3394 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3396 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3397 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3400 ret
= bgp_attr_otc(&attr_args
);
3403 ret
= bgp_attr_unknown(&attr_args
);
3407 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3408 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3409 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3410 ret
= BGP_ATTR_PARSE_ERROR
;
3414 if (ret
== BGP_ATTR_PARSE_EOR
) {
3418 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3419 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3420 "%s: Attribute %s, parse error", peer
->host
,
3421 lookup_msg(attr_str
, type
, NULL
));
3424 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3426 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3427 "%s: Attribute %s, parse error - treating as withdrawal",
3428 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3432 /* Check the fetched length. */
3433 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3434 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3435 "%s: BGP attribute %s, fetch error",
3436 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3437 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3438 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3439 ret
= BGP_ATTR_PARSE_ERROR
;
3445 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3446 * About Prefix-SID path attribute,
3447 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3448 * may only appear in a BGP Prefix-SID attribute attached to
3449 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3450 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3452 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3453 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3455 /* Check final read pointer is same as end pointer. */
3456 if (BGP_INPUT_PNT(peer
) != endp
) {
3457 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3458 "%s: BGP attribute %s, length mismatch", peer
->host
,
3459 lookup_msg(attr_str
, type
, NULL
));
3460 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3461 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3463 ret
= BGP_ATTR_PARSE_ERROR
;
3468 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3469 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3470 * This is implemented below and will result in a NOTIFICATION. If the
3471 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3472 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3473 * message SHOULD NOT be sent. This is implemented elsewhere.
3475 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3476 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3477 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3478 * speaker that receives the message SHOULD ignore this attribute.
3480 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3481 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3482 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3483 ret
= BGP_ATTR_PARSE_ERROR
;
3488 /* Check all mandatory well-known attributes are present */
3489 ret
= bgp_attr_check(peer
, attr
);
3494 * At this place we can see whether we got AS4_PATH and/or
3495 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3496 * We can not do this before we've read all attributes because
3497 * the as4 handling does not say whether AS4_PATH has to be sent
3498 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3499 * in relationship to AGGREGATOR.
3500 * So, to be defensive, we are not relying on any order and read
3501 * all attributes first, including these 32bit ones, and now,
3502 * afterwards, we look what and if something is to be done for as4.
3504 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3507 /* actually... this doesn't ever return failure currently, but
3508 * better safe than sorry */
3509 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3510 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3511 &as4_aggregator_addr
)) {
3512 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3513 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3514 ret
= BGP_ATTR_PARSE_ERROR
;
3519 * Finally do the checks on the aspath we did not do yet
3520 * because we waited for a potentially synthesized aspath.
3522 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3523 ret
= bgp_attr_aspath_check(peer
, attr
);
3524 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3528 ret
= BGP_ATTR_PARSE_PROCEED
;
3532 * At this stage, we have done all fiddling with as4, and the
3533 * resulting info is in attr->aggregator resp. attr->aspath so
3534 * we can chuck as4_aggregator and as4_path alltogether in order
3538 * unintern - it is in the hash
3539 * The flag that we got this is still there, but that
3540 * does not do any trouble
3542 aspath_unintern(&as4_path
);
3544 transit
= bgp_attr_get_transit(attr
);
3545 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3546 /* Finally intern unknown attribute. */
3548 bgp_attr_set_transit(attr
, transit_intern(transit
));
3549 if (attr
->encap_subtlvs
)
3550 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3552 #ifdef ENABLE_BGP_VNC
3553 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3554 bgp_attr_get_vnc_subtlvs(attr
);
3557 bgp_attr_set_vnc_subtlvs(
3559 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3563 transit_free(transit
);
3564 bgp_attr_set_transit(attr
, NULL
);
3567 bgp_attr_flush_encap(attr
);
3571 transit
= bgp_attr_get_transit(attr
);
3573 assert(transit
->refcnt
> 0);
3574 if (attr
->encap_subtlvs
)
3575 assert(attr
->encap_subtlvs
->refcnt
> 0);
3576 #ifdef ENABLE_BGP_VNC
3577 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3578 bgp_attr_get_vnc_subtlvs(attr
);
3581 assert(vnc_subtlvs
->refcnt
> 0);
3588 * Extract the tunnel type from extended community
3590 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3591 bgp_encap_types
*tunnel_type
)
3593 struct ecommunity
*ecom
;
3599 ecom
= bgp_attr_get_ecommunity(attr
);
3600 if (!ecom
|| !ecom
->size
)
3603 for (i
= 0; i
< ecom
->size
; i
++) {
3605 uint8_t type
, sub_type
;
3607 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3610 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3611 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3613 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3620 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3621 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3625 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
3626 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
3629 /* Set extended bit always to encode the attribute length as 2 bytes */
3630 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3631 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3632 sizep
= stream_get_endp(s
);
3633 stream_putw(s
, 0); /* Marker: Attribute length. */
3636 /* Convert AFI, SAFI to values for packet. */
3637 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3639 stream_putw(s
, pkt_afi
); /* AFI */
3640 stream_putc(s
, pkt_safi
); /* SAFI */
3644 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3645 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3646 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3647 else if (safi
== SAFI_FLOWSPEC
)
3650 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3653 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3658 case SAFI_MULTICAST
:
3659 case SAFI_LABELED_UNICAST
:
3661 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3665 stream_putl(s
, 0); /* RD = 0, per RFC */
3667 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3672 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3675 if (attr
->mp_nexthop_len
== 0)
3676 stream_putc(s
, 0); /* no nexthop for flowspec */
3678 stream_putc(s
, attr
->mp_nexthop_len
);
3679 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3688 case SAFI_MULTICAST
:
3689 case SAFI_LABELED_UNICAST
:
3691 if (attr
->mp_nexthop_len
3692 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3694 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3695 stream_put(s
, &attr
->mp_nexthop_global
,
3697 stream_put(s
, &attr
->mp_nexthop_local
,
3700 stream_putc(s
, IPV6_MAX_BYTELEN
);
3701 stream_put(s
, &attr
->mp_nexthop_global
,
3705 case SAFI_MPLS_VPN
: {
3706 if (attr
->mp_nexthop_len
3707 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3709 stream_putl(s
, 0); /* RD = 0, per RFC */
3711 stream_put(s
, &attr
->mp_nexthop_global
,
3713 } else if (attr
->mp_nexthop_len
3714 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3716 stream_putl(s
, 0); /* RD = 0, per RFC */
3718 stream_put(s
, &attr
->mp_nexthop_global
,
3720 stream_putl(s
, 0); /* RD = 0, per RFC */
3722 stream_put(s
, &attr
->mp_nexthop_local
,
3727 stream_putc(s
, IPV6_MAX_BYTELEN
);
3728 stream_put(s
, &attr
->mp_nexthop_global
,
3732 stream_putc(s
, 0); /* no nexthop for flowspec */
3738 if (safi
!= SAFI_FLOWSPEC
)
3740 EC_BGP_ATTR_NH_SEND_LEN
,
3741 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3742 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3751 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3752 const struct prefix
*p
,
3753 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3754 uint32_t num_labels
, bool addpath_capable
,
3755 uint32_t addpath_tx_id
, struct attr
*attr
)
3757 if (safi
== SAFI_MPLS_VPN
) {
3758 if (addpath_capable
)
3759 stream_putl(s
, addpath_tx_id
);
3760 /* Label, RD, Prefix write. */
3761 stream_putc(s
, p
->prefixlen
+ 88);
3762 stream_put(s
, label
, BGP_LABEL_BYTES
);
3763 stream_put(s
, prd
->val
, 8);
3764 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3765 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3766 /* EVPN prefix - contents depend on type */
3767 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3768 addpath_capable
, addpath_tx_id
);
3769 } else if (safi
== SAFI_LABELED_UNICAST
) {
3770 /* Prefix write with label. */
3771 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3773 } else if (safi
== SAFI_FLOWSPEC
) {
3774 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3775 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3776 p
->u
.prefix_flowspec
.prefixlen
);
3778 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
3781 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3782 const struct prefix
*p
)
3784 int size
= PSIZE(p
->prefixlen
);
3785 if (safi
== SAFI_MPLS_VPN
)
3787 else if (safi
== SAFI_LABELED_UNICAST
)
3788 size
+= BGP_LABEL_BYTES
;
3789 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3790 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3796 * Encodes the tunnel encapsulation attribute,
3797 * and with ENABLE_BGP_VNC the VNC attribute which uses
3798 * almost the same TLV format
3800 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3801 struct stream
*s
, struct attr
*attr
,
3804 unsigned int attrlenfield
= 0;
3805 unsigned int attrhdrlen
= 0;
3806 struct bgp_attr_encap_subtlv
*subtlvs
;
3807 struct bgp_attr_encap_subtlv
*st
;
3808 const char *attrname
;
3810 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3811 && (!attr
->encap_tunneltype
3812 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3816 case BGP_ATTR_ENCAP
:
3817 attrname
= "Tunnel Encap";
3818 subtlvs
= attr
->encap_subtlvs
;
3819 if (subtlvs
== NULL
) /* nothing to do */
3822 * The tunnel encap attr has an "outer" tlv.
3824 * L = total length of subtlvs,
3825 * V = concatenated subtlvs.
3827 attrlenfield
= 2 + 2; /* T + L */
3828 attrhdrlen
= 1 + 1; /* subTLV T + L */
3831 #ifdef ENABLE_BGP_VNC_ATTR
3834 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3835 if (subtlvs
== NULL
) /* nothing to do */
3837 attrlenfield
= 0; /* no outer T + L */
3838 attrhdrlen
= 2 + 2; /* subTLV T + L */
3846 /* compute attr length */
3847 for (st
= subtlvs
; st
; st
= st
->next
) {
3848 attrlenfield
+= (attrhdrlen
+ st
->length
);
3851 if (attrlenfield
> 0xffff) {
3852 zlog_info("%s attribute is too long (length=%d), can't send it",
3853 attrname
, attrlenfield
);
3857 if (attrlenfield
> 0xff) {
3858 /* 2-octet length field */
3860 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3861 | BGP_ATTR_FLAG_EXTLEN
);
3862 stream_putc(s
, attrtype
);
3863 stream_putw(s
, attrlenfield
& 0xffff);
3865 /* 1-octet length field */
3866 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3867 stream_putc(s
, attrtype
);
3868 stream_putc(s
, attrlenfield
& 0xff);
3871 if (attrtype
== BGP_ATTR_ENCAP
) {
3872 /* write outer T+L */
3873 stream_putw(s
, attr
->encap_tunneltype
);
3874 stream_putw(s
, attrlenfield
- 4);
3877 /* write each sub-tlv */
3878 for (st
= subtlvs
; st
; st
= st
->next
) {
3879 if (attrtype
== BGP_ATTR_ENCAP
) {
3880 stream_putc(s
, st
->type
);
3881 stream_putc(s
, st
->length
);
3882 #ifdef ENABLE_BGP_VNC
3884 stream_putw(s
, st
->type
);
3885 stream_putw(s
, st
->length
);
3888 stream_put(s
, st
->value
, st
->length
);
3892 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3894 /* Set MP attribute length. Don't count the (2) bytes used to encode
3896 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3899 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3901 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3902 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3903 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3904 PEER_FLAG_REMOVE_PRIVATE_AS
)
3905 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3906 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3907 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3908 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3909 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3910 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3915 /* Make attribute packet. */
3916 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3917 struct stream
*s
, struct attr
*attr
,
3918 struct bpacket_attr_vec_arr
*vecarr
,
3919 struct prefix
*p
, afi_t afi
, safi_t safi
,
3920 struct peer
*from
, struct prefix_rd
*prd
,
3921 mpls_label_t
*label
, uint32_t num_labels
,
3922 bool addpath_capable
, uint32_t addpath_tx_id
)
3925 size_t aspath_sizep
;
3926 struct aspath
*aspath
;
3927 int send_as4_path
= 0;
3928 int send_as4_aggregator
= 0;
3929 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
3930 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
3935 /* Remember current pointer. */
3936 cp
= stream_get_endp(s
);
3939 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3940 && !peer_cap_enhe(peer
, afi
, safi
))) {
3941 size_t mpattrlen_pos
= 0;
3943 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3945 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3946 num_labels
, addpath_capable
,
3947 addpath_tx_id
, attr
);
3948 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3951 /* Origin attribute. */
3952 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3953 stream_putc(s
, BGP_ATTR_ORIGIN
);
3955 stream_putc(s
, attr
->origin
);
3957 /* AS path attribute. */
3959 /* If remote-peer is EBGP */
3960 if (peer
->sort
== BGP_PEER_EBGP
3961 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3962 PEER_FLAG_AS_PATH_UNCHANGED
)
3963 || attr
->aspath
->segments
== NULL
)
3964 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3965 PEER_FLAG_RSERVER_CLIENT
))) {
3966 aspath
= aspath_dup(attr
->aspath
);
3968 /* Even though we may not be configured for confederations we
3970 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3971 aspath
= aspath_delete_confed_seq(aspath
);
3973 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3974 /* Stuff our path CONFED_ID on the front */
3975 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3977 if (peer
->change_local_as
) {
3978 /* If replace-as is specified, we only use the
3979 change_local_as when
3980 advertising routes. */
3981 if (!CHECK_FLAG(peer
->flags
,
3982 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3983 if (bgp_append_local_as(peer
, afi
,
3985 aspath
= aspath_add_seq(
3986 aspath
, peer
->local_as
);
3987 aspath
= aspath_add_seq(aspath
,
3988 peer
->change_local_as
);
3990 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3993 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3994 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3996 aspath
= aspath_dup(attr
->aspath
);
3997 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3999 aspath
= attr
->aspath
;
4001 /* If peer is not AS4 capable, then:
4002 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4003 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4005 * types are in it (i.e. exclude them if they are there)
4006 * AND do this only if there is at least one asnum > 65535 in the
4008 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4010 * all ASnums > 65535 to BGP_AS_TRANS
4013 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4014 stream_putc(s
, BGP_ATTR_AS_PATH
);
4015 aspath_sizep
= stream_get_endp(s
);
4017 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4019 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4022 if (!use32bit
&& aspath_has_as4(aspath
))
4024 1; /* we'll do this later, at the correct place */
4026 /* Nexthop attribute. */
4027 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4028 && !peer_cap_enhe(peer
, afi
, safi
)) {
4029 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4031 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4032 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4033 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4034 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4037 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4038 } else if (peer_cap_enhe(from
, afi
, safi
)
4039 || (nh_afi
== AFI_IP6
)) {
4041 * Likely this is the case when an IPv4 prefix was
4042 * received with Extended Next-hop capability in this
4043 * or another vrf and is now being advertised to
4044 * non-ENHE peers. Since peer_cap_enhe only checks
4045 * peers in this vrf, also check the nh_afi to catch
4046 * the case where the originator was in another vrf.
4047 * Setting the mandatory (ipv4) next-hop attribute here
4048 * to enable implicit next-hop self with correct A-F
4049 * (ipv4 address family).
4051 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4052 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4053 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4056 stream_put_ipv4(s
, 0);
4060 /* MED attribute. */
4061 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4062 || bgp
->maxmed_active
) {
4063 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4064 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4066 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4070 /* Local preference. */
4071 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4072 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4073 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4075 stream_putl(s
, attr
->local_pref
);
4078 /* Atomic aggregate. */
4079 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4080 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4081 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4086 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4087 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4088 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4089 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4092 /* AS4 capable peer */
4094 stream_putl(s
, attr
->aggregator_as
);
4096 /* 2-byte AS peer */
4099 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4101 if (attr
->aggregator_as
> UINT16_MAX
) {
4102 stream_putw(s
, BGP_AS_TRANS
);
4104 /* we have to send AS4_AGGREGATOR, too.
4105 * we'll do that later in order to send
4106 * attributes in ascending
4109 send_as4_aggregator
= 1;
4111 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4113 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4116 /* Community attribute. */
4117 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4118 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4119 struct community
*comm
= NULL
;
4121 comm
= bgp_attr_get_community(attr
);
4122 if (comm
->size
* 4 > 255) {
4124 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4125 | BGP_ATTR_FLAG_EXTLEN
);
4126 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4127 stream_putw(s
, comm
->size
* 4);
4130 BGP_ATTR_FLAG_OPTIONAL
4131 | BGP_ATTR_FLAG_TRANS
);
4132 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4133 stream_putc(s
, comm
->size
* 4);
4135 stream_put(s
, comm
->val
, comm
->size
* 4);
4139 * Large Community attribute.
4141 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4142 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4143 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4144 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4146 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4147 | BGP_ATTR_FLAG_EXTLEN
);
4148 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4150 lcom_length(bgp_attr_get_lcommunity(attr
)));
4153 BGP_ATTR_FLAG_OPTIONAL
4154 | BGP_ATTR_FLAG_TRANS
);
4155 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4157 lcom_length(bgp_attr_get_lcommunity(attr
)));
4159 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4160 lcom_length(bgp_attr_get_lcommunity(attr
)));
4163 /* Route Reflector. */
4164 if (peer
->sort
== BGP_PEER_IBGP
&& from
4165 && from
->sort
== BGP_PEER_IBGP
) {
4166 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4168 /* Originator ID. */
4169 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4170 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4173 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4174 stream_put_in_addr(s
, &attr
->originator_id
);
4176 stream_put_in_addr(s
, &from
->remote_id
);
4179 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4180 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4183 stream_putc(s
, cluster
->length
+ 4);
4184 /* If this peer configuration's parent BGP has
4186 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4187 stream_put_in_addr(s
, &bgp
->cluster_id
);
4189 stream_put_in_addr(s
, &bgp
->router_id
);
4190 stream_put(s
, cluster
->list
, cluster
->length
);
4193 /* If this peer configuration's parent BGP has
4195 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4196 stream_put_in_addr(s
, &bgp
->cluster_id
);
4198 stream_put_in_addr(s
, &bgp
->router_id
);
4202 /* Extended Communities attribute. */
4203 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4204 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4205 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4206 bool transparent
= CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4207 PEER_FLAG_RSERVER_CLIENT
) &&
4209 CHECK_FLAG(from
->af_flags
[afi
][safi
],
4210 PEER_FLAG_RSERVER_CLIENT
);
4212 if (peer
->sort
== BGP_PEER_IBGP
||
4213 peer
->sort
== BGP_PEER_CONFED
|| transparent
) {
4214 if (ecomm
->size
* 8 > 255) {
4216 BGP_ATTR_FLAG_OPTIONAL
4217 | BGP_ATTR_FLAG_TRANS
4218 | BGP_ATTR_FLAG_EXTLEN
);
4219 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4220 stream_putw(s
, ecomm
->size
* 8);
4223 BGP_ATTR_FLAG_OPTIONAL
4224 | BGP_ATTR_FLAG_TRANS
);
4225 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4226 stream_putc(s
, ecomm
->size
* 8);
4228 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4232 int ecom_tr_size
= 0;
4235 for (i
= 0; i
< ecomm
->size
; i
++) {
4236 pnt
= ecomm
->val
+ (i
* 8);
4239 if (CHECK_FLAG(tbit
,
4240 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4247 if (ecom_tr_size
* 8 > 255) {
4250 BGP_ATTR_FLAG_OPTIONAL
4251 | BGP_ATTR_FLAG_TRANS
4252 | BGP_ATTR_FLAG_EXTLEN
);
4254 BGP_ATTR_EXT_COMMUNITIES
);
4255 stream_putw(s
, ecom_tr_size
* 8);
4259 BGP_ATTR_FLAG_OPTIONAL
4260 | BGP_ATTR_FLAG_TRANS
);
4262 BGP_ATTR_EXT_COMMUNITIES
);
4263 stream_putc(s
, ecom_tr_size
* 8);
4266 for (i
= 0; i
< ecomm
->size
; i
++) {
4267 pnt
= ecomm
->val
+ (i
* 8);
4272 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4275 stream_put(s
, pnt
, 8);
4281 /* Label index attribute. */
4282 if (safi
== SAFI_LABELED_UNICAST
) {
4283 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4284 uint32_t label_index
;
4286 label_index
= attr
->label_index
;
4288 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4290 BGP_ATTR_FLAG_OPTIONAL
4291 | BGP_ATTR_FLAG_TRANS
);
4292 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4294 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4296 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4297 stream_putc(s
, 0); // reserved
4298 stream_putw(s
, 0); // flags
4299 stream_putl(s
, label_index
);
4304 /* SRv6 Service Information Attribute. */
4305 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4306 if (attr
->srv6_l3vpn
) {
4307 uint8_t subtlv_len
=
4308 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4310 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4311 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4312 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4313 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4314 | BGP_ATTR_FLAG_TRANS
);
4315 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4316 stream_putc(s
, attr_len
);
4317 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4318 stream_putw(s
, tlv_len
);
4319 stream_putc(s
, 0); /* reserved */
4320 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4321 stream_putw(s
, subtlv_len
);
4322 stream_putc(s
, 0); /* reserved */
4323 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4324 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4325 stream_putc(s
, 0); /* sid_flags */
4326 stream_putw(s
, 0xffff); /* endpoint */
4327 stream_putc(s
, 0); /* reserved */
4330 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4333 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4334 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4335 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4336 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4337 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4338 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4339 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4340 } else if (attr
->srv6_vpn
) {
4341 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4342 | BGP_ATTR_FLAG_TRANS
);
4343 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4344 stream_putc(s
, 22); /* tlv len */
4345 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4346 stream_putw(s
, 0x13); /* tlv len */
4347 stream_putc(s
, 0x00); /* reserved */
4348 stream_putc(s
, 0x01); /* sid_type */
4349 stream_putc(s
, 0x00); /* sif_flags */
4350 stream_put(s
, &attr
->srv6_vpn
->sid
,
4351 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4355 if (send_as4_path
) {
4356 /* If the peer is NOT As4 capable, AND */
4357 /* there are ASnums > 65535 in path THEN
4358 * give out AS4_PATH */
4360 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4362 * Hm, I wonder... confederation things *should* only be at
4363 * the beginning of an aspath, right? Then we should use
4364 * aspath_delete_confed_seq for this, because it is already
4366 * Folks, talk to me: what is reasonable here!?
4368 aspath
= aspath_delete_confed_seq(aspath
);
4371 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4372 | BGP_ATTR_FLAG_EXTLEN
);
4373 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4374 aspath_sizep
= stream_get_endp(s
);
4376 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4379 if (aspath
!= attr
->aspath
)
4380 aspath_free(aspath
);
4382 if (send_as4_aggregator
) {
4383 /* send AS4_AGGREGATOR, at this place */
4384 /* this section of code moved here in order to ensure the
4386 * *ascending* order of attributes
4388 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4389 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4391 stream_putl(s
, attr
->aggregator_as
);
4392 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4395 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4396 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4397 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4398 /* Tunnel Encap attribute */
4399 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4401 #ifdef ENABLE_BGP_VNC_ATTR
4403 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4408 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4409 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4410 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4411 stream_putc(s
, 9); // Length
4412 stream_putc(s
, 0); // Flags
4413 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4414 stream_put(s
, &(attr
->label
),
4415 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4416 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4417 // Unicast tunnel endpoint IP address
4421 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4422 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4423 stream_putc(s
, BGP_ATTR_OTC
);
4425 stream_putl(s
, attr
->otc
);
4428 /* Unknown transit attribute. */
4429 struct transit
*transit
= bgp_attr_get_transit(attr
);
4432 stream_put(s
, transit
->val
, transit
->length
);
4434 /* Return total size of attribute. */
4435 return stream_get_endp(s
) - cp
;
4438 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4440 unsigned long attrlen_pnt
;
4441 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
4442 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
4444 /* Set extended bit always to encode the attribute length as 2 bytes */
4445 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4446 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4448 attrlen_pnt
= stream_get_endp(s
);
4449 stream_putw(s
, 0); /* Length of this attribute. */
4451 /* Convert AFI, SAFI to values for packet. */
4452 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4454 stream_putw(s
, pkt_afi
);
4455 stream_putc(s
, pkt_safi
);
4460 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4461 afi_t afi
, safi_t safi
,
4462 const struct prefix_rd
*prd
,
4463 mpls_label_t
*label
, uint32_t num_labels
,
4464 bool addpath_capable
, uint32_t addpath_tx_id
,
4467 uint8_t wlabel
[4] = {0x80, 0x00, 0x00};
4469 if (safi
== SAFI_LABELED_UNICAST
) {
4470 label
= (mpls_label_t
*)wlabel
;
4474 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4475 addpath_capable
, addpath_tx_id
, attr
);
4478 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4480 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4483 /* Initialization of attribute. */
4484 void bgp_attr_init(void)
4497 void bgp_attr_finish(void)
4502 ecommunity_finish();
4503 lcommunity_finish();
4510 /* Make attribute packet. */
4511 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4512 const struct prefix
*prefix
)
4517 struct aspath
*aspath
;
4518 bool addpath_capable
= false;
4519 uint32_t addpath_tx_id
= 0;
4521 /* Remember current pointer. */
4522 cp
= stream_get_endp(s
);
4524 /* Place holder of length. */
4527 /* Origin attribute. */
4528 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4529 stream_putc(s
, BGP_ATTR_ORIGIN
);
4531 stream_putc(s
, attr
->origin
);
4533 aspath
= attr
->aspath
;
4535 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4536 stream_putc(s
, BGP_ATTR_AS_PATH
);
4537 aspath_lenp
= stream_get_endp(s
);
4540 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4542 /* Nexthop attribute. */
4543 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4544 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4545 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4546 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4548 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4551 /* MED attribute. */
4552 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4553 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4554 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4556 stream_putl(s
, attr
->med
);
4559 /* Local preference. */
4560 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4561 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4562 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4564 stream_putl(s
, attr
->local_pref
);
4567 /* Atomic aggregate. */
4568 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4569 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4570 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4575 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4576 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4577 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4579 stream_putl(s
, attr
->aggregator_as
);
4580 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4583 /* Community attribute. */
4584 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4585 struct community
*comm
= NULL
;
4587 comm
= bgp_attr_get_community(attr
);
4588 if (comm
->size
* 4 > 255) {
4590 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4591 | BGP_ATTR_FLAG_EXTLEN
);
4592 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4593 stream_putw(s
, comm
->size
* 4);
4596 BGP_ATTR_FLAG_OPTIONAL
4597 | BGP_ATTR_FLAG_TRANS
);
4598 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4599 stream_putc(s
, comm
->size
* 4);
4601 stream_put(s
, comm
->val
, comm
->size
* 4);
4604 /* Large Community attribute. */
4605 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4606 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4608 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4609 | BGP_ATTR_FLAG_EXTLEN
);
4610 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4612 lcom_length(bgp_attr_get_lcommunity(attr
)));
4615 BGP_ATTR_FLAG_OPTIONAL
4616 | BGP_ATTR_FLAG_TRANS
);
4617 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4619 lcom_length(bgp_attr_get_lcommunity(attr
)));
4622 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4623 lcom_length(bgp_attr_get_lcommunity(attr
)));
4626 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4627 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4628 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4629 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4632 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4633 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4634 sizep
= stream_get_endp(s
);
4637 stream_putc(s
, 0); /* Marker: Attribute length. */
4638 stream_putw(s
, AFI_IP6
); /* AFI */
4639 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4642 stream_putc(s
, attr
->mp_nexthop_len
);
4643 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4644 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4645 stream_put(s
, &attr
->mp_nexthop_local
,
4652 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4655 /* Set MP attribute length. */
4656 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4660 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4661 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4663 BGP_ATTR_FLAG_OPTIONAL
4664 | BGP_ATTR_FLAG_TRANS
);
4665 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4667 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4668 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4669 stream_putc(s
, 0); // reserved
4670 stream_putw(s
, 0); // flags
4671 stream_putl(s
, attr
->label_index
);
4676 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_OTC
)) {
4677 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4678 stream_putc(s
, BGP_ATTR_OTC
);
4680 stream_putl(s
, attr
->otc
);
4683 /* Return total size of attribute. */
4684 len
= stream_get_endp(s
) - cp
- 2;
4685 stream_putw_at(s
, cp
, len
);