1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_aspath.h"
41 #include "bgpd/bgp_community.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_errors.h"
44 #include "bgpd/bgp_label.h"
45 #include "bgpd/bgp_packet.h"
46 #include "bgpd/bgp_ecommunity.h"
47 #include "bgpd/bgp_lcommunity.h"
48 #include "bgpd/bgp_updgrp.h"
49 #include "bgpd/bgp_encap_types.h"
51 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
52 #include "bgp_encap_types.h"
53 #include "bgp_vnc_types.h"
56 #include "bgp_flowspec_private.h"
59 /* Attribute strings for logging. */
60 static const struct message attr_str
[] = {
61 {BGP_ATTR_ORIGIN
, "ORIGIN"},
62 {BGP_ATTR_AS_PATH
, "AS_PATH"},
63 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
64 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
65 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
66 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
67 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
68 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
69 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
70 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
71 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
72 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
73 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
74 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
75 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
76 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
77 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
78 {BGP_ATTR_ENCAP
, "ENCAP"},
79 #ifdef ENABLE_BGP_VNC_ATTR
80 {BGP_ATTR_VNC
, "VNC"},
82 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
83 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
84 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
87 static const struct message attr_flag_str
[] = {
88 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
89 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
90 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
91 /* bgp_attr_flags_diagnose() relies on this bit being last in
93 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
96 static struct hash
*cluster_hash
;
98 static void *cluster_hash_alloc(void *p
)
100 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
101 struct cluster_list
*cluster
;
103 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
104 cluster
->length
= val
->length
;
106 if (cluster
->length
) {
107 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
108 memcpy(cluster
->list
, val
->list
, val
->length
);
110 cluster
->list
= NULL
;
117 /* Cluster list related functions. */
118 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
120 struct cluster_list tmp
= {};
121 struct cluster_list
*cluster
;
124 tmp
.list
= length
== 0 ? NULL
: pnt
;
126 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
131 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
135 for (i
= 0; i
< cluster
->length
/ 4; i
++)
136 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
141 static unsigned int cluster_hash_key_make(const void *p
)
143 const struct cluster_list
*cluster
= p
;
145 return jhash(cluster
->list
, cluster
->length
, 0);
148 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
150 const struct cluster_list
*cluster1
= p1
;
151 const struct cluster_list
*cluster2
= p2
;
153 if (cluster1
->list
== cluster2
->list
)
156 if (!cluster1
->list
|| !cluster2
->list
)
159 if (cluster1
->length
!= cluster2
->length
)
162 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
165 static void cluster_free(struct cluster_list
*cluster
)
167 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
168 XFREE(MTYPE_CLUSTER
, cluster
);
171 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
173 struct cluster_list
*find
;
175 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
181 static void cluster_unintern(struct cluster_list
**cluster
)
183 if ((*cluster
)->refcnt
)
184 (*cluster
)->refcnt
--;
186 if ((*cluster
)->refcnt
== 0) {
187 void *p
= hash_release(cluster_hash
, *cluster
);
188 assert(p
== *cluster
);
189 cluster_free(*cluster
);
194 static void cluster_init(void)
196 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
200 static void cluster_finish(void)
202 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
203 hash_free(cluster_hash
);
207 static struct hash
*encap_hash
= NULL
;
208 #ifdef ENABLE_BGP_VNC
209 static struct hash
*vnc_hash
= NULL
;
211 static struct hash
*srv6_l3vpn_hash
;
212 static struct hash
*srv6_vpn_hash
;
214 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
216 struct bgp_attr_encap_subtlv
*new;
217 struct bgp_attr_encap_subtlv
*tail
;
218 struct bgp_attr_encap_subtlv
*p
;
220 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
221 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
223 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
226 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
229 memcpy(tail
, p
, size
);
236 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
238 struct bgp_attr_encap_subtlv
*next
;
242 XFREE(MTYPE_ENCAP_TLV
, p
);
247 void bgp_attr_flush_encap(struct attr
*attr
)
252 if (attr
->encap_subtlvs
) {
253 encap_free(attr
->encap_subtlvs
);
254 attr
->encap_subtlvs
= NULL
;
256 #ifdef ENABLE_BGP_VNC
257 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
258 bgp_attr_get_vnc_subtlvs(attr
);
261 encap_free(vnc_subtlvs
);
262 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
268 * Compare encap sub-tlv chains
273 * This algorithm could be made faster if needed
275 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
276 const struct bgp_attr_encap_subtlv
*h2
)
278 const struct bgp_attr_encap_subtlv
*p
;
279 const struct bgp_attr_encap_subtlv
*q
;
283 if (h1
== NULL
|| h2
== NULL
)
286 for (p
= h1
; p
; p
= p
->next
) {
287 for (q
= h2
; q
; q
= q
->next
) {
288 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
289 && !memcmp(p
->value
, q
->value
, p
->length
)) {
298 for (p
= h2
; p
; p
= p
->next
) {
299 for (q
= h1
; q
; q
= q
->next
) {
300 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
301 && !memcmp(p
->value
, q
->value
, p
->length
)) {
313 static void *encap_hash_alloc(void *p
)
315 /* Encap structure is already allocated. */
321 #ifdef ENABLE_BGP_VNC
326 static struct bgp_attr_encap_subtlv
*
327 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
329 struct bgp_attr_encap_subtlv
*find
;
330 struct hash
*hash
= encap_hash
;
331 #ifdef ENABLE_BGP_VNC
332 if (type
== VNC_SUBTLV_TYPE
)
336 find
= hash_get(hash
, encap
, encap_hash_alloc
);
344 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
345 encap_subtlv_type type
)
347 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
351 if (encap
->refcnt
== 0) {
352 struct hash
*hash
= encap_hash
;
353 #ifdef ENABLE_BGP_VNC
354 if (type
== VNC_SUBTLV_TYPE
)
357 hash_release(hash
, encap
);
363 static unsigned int encap_hash_key_make(const void *p
)
365 const struct bgp_attr_encap_subtlv
*encap
= p
;
367 return jhash(encap
->value
, encap
->length
, 0);
370 static bool encap_hash_cmp(const void *p1
, const void *p2
)
372 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
373 (const struct bgp_attr_encap_subtlv
*)p2
);
376 static void encap_init(void)
378 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
380 #ifdef ENABLE_BGP_VNC
381 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
386 static void encap_finish(void)
388 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
389 hash_free(encap_hash
);
391 #ifdef ENABLE_BGP_VNC
392 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
398 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
407 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
408 bgp_attr_get_evpn_overlay(a2
));
411 /* Unknown transit attribute. */
412 static struct hash
*transit_hash
;
414 static void transit_free(struct transit
*transit
)
416 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
417 XFREE(MTYPE_TRANSIT
, transit
);
420 static void *transit_hash_alloc(void *p
)
422 /* Transit structure is already allocated. */
426 static struct transit
*transit_intern(struct transit
*transit
)
428 struct transit
*find
;
430 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
432 transit_free(transit
);
438 static void transit_unintern(struct transit
**transit
)
440 if ((*transit
)->refcnt
)
441 (*transit
)->refcnt
--;
443 if ((*transit
)->refcnt
== 0) {
444 hash_release(transit_hash
, *transit
);
445 transit_free(*transit
);
450 static void *srv6_l3vpn_hash_alloc(void *p
)
455 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
457 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
460 static struct bgp_attr_srv6_l3vpn
*
461 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
463 struct bgp_attr_srv6_l3vpn
*find
;
465 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
467 srv6_l3vpn_free(l3vpn
);
472 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
474 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
479 if (l3vpn
->refcnt
== 0) {
480 hash_release(srv6_l3vpn_hash
, l3vpn
);
481 srv6_l3vpn_free(l3vpn
);
486 static void *srv6_vpn_hash_alloc(void *p
)
491 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
493 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
496 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
498 struct bgp_attr_srv6_vpn
*find
;
500 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
507 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
509 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
514 if (vpn
->refcnt
== 0) {
515 hash_release(srv6_vpn_hash
, vpn
);
521 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
523 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
526 key
= jhash(&l3vpn
->sid
, 16, key
);
527 key
= jhash_1word(l3vpn
->sid_flags
, key
);
528 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
529 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
530 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
531 key
= jhash_1word(l3vpn
->func_len
, key
);
532 key
= jhash_1word(l3vpn
->arg_len
, key
);
533 key
= jhash_1word(l3vpn
->transposition_len
, key
);
534 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
538 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
540 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
541 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
543 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
544 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
545 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
546 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
547 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
548 && l3vpn1
->func_len
== l3vpn2
->func_len
549 && l3vpn1
->arg_len
== l3vpn2
->arg_len
550 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
551 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
554 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
555 const struct bgp_attr_srv6_l3vpn
*h2
)
559 else if (h1
== NULL
|| h2
== NULL
)
562 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
565 static unsigned int srv6_vpn_hash_key_make(const void *p
)
567 const struct bgp_attr_srv6_vpn
*vpn
= p
;
570 key
= jhash(&vpn
->sid
, 16, key
);
571 key
= jhash_1word(vpn
->sid_flags
, key
);
575 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
577 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
578 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
580 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
581 && vpn1
->sid_flags
== vpn2
->sid_flags
;
584 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
585 const struct bgp_attr_srv6_vpn
*h2
)
589 else if (h1
== NULL
|| h2
== NULL
)
592 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
595 static void srv6_init(void)
598 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
599 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
600 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
601 "BGP Prefix-SID SRv6-VPN-Service-TLV");
604 static void srv6_finish(void)
606 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
607 hash_free(srv6_l3vpn_hash
);
608 srv6_l3vpn_hash
= NULL
;
609 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
610 hash_free(srv6_vpn_hash
);
611 srv6_vpn_hash
= NULL
;
614 static unsigned int transit_hash_key_make(const void *p
)
616 const struct transit
*transit
= p
;
618 return jhash(transit
->val
, transit
->length
, 0);
621 static bool transit_hash_cmp(const void *p1
, const void *p2
)
623 const struct transit
*transit1
= p1
;
624 const struct transit
*transit2
= p2
;
626 return (transit1
->length
== transit2
->length
627 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
630 static void transit_init(void)
632 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
636 static void transit_finish(void)
638 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
639 hash_free(transit_hash
);
643 /* Attribute hash routines. */
644 static struct hash
*attrhash
;
646 unsigned long int attr_count(void)
648 return attrhash
->count
;
651 unsigned long int attr_unknown_count(void)
653 return transit_hash
->count
;
656 unsigned int attrhash_key_make(const void *p
)
658 const struct attr
*attr
= (struct attr
*)p
;
660 #define MIX(val) key = jhash_1word(val, key)
661 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
663 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
664 MIX3(attr
->local_pref
, attr
->aggregator_as
,
665 attr
->aggregator_addr
.s_addr
);
666 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
667 attr
->originator_id
.s_addr
);
668 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
671 MIX(aspath_key_make(attr
->aspath
));
672 if (bgp_attr_get_community(attr
))
673 MIX(community_hash_make(bgp_attr_get_community(attr
)));
674 if (bgp_attr_get_lcommunity(attr
))
675 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
676 if (bgp_attr_get_ecommunity(attr
))
677 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
678 if (bgp_attr_get_ipv6_ecommunity(attr
))
679 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
680 if (bgp_attr_get_cluster(attr
))
681 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
682 if (bgp_attr_get_transit(attr
))
683 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
684 if (attr
->encap_subtlvs
)
685 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
686 if (attr
->srv6_l3vpn
)
687 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
689 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
690 #ifdef ENABLE_BGP_VNC
691 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
692 bgp_attr_get_vnc_subtlvs(attr
);
694 MIX(encap_hash_key_make(vnc_subtlvs
));
696 MIX(attr
->mp_nexthop_len
);
697 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
698 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
699 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
700 MIX(attr
->rmap_table_id
);
707 bool attrhash_cmp(const void *p1
, const void *p2
)
709 const struct attr
*attr1
= p1
;
710 const struct attr
*attr2
= p2
;
712 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
713 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
714 && attr1
->aspath
== attr2
->aspath
715 && bgp_attr_get_community(attr1
)
716 == bgp_attr_get_community(attr2
)
717 && attr1
->med
== attr2
->med
718 && attr1
->local_pref
== attr2
->local_pref
719 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
720 if (attr1
->aggregator_as
== attr2
->aggregator_as
721 && attr1
->aggregator_addr
.s_addr
722 == attr2
->aggregator_addr
.s_addr
723 && attr1
->weight
== attr2
->weight
724 && attr1
->tag
== attr2
->tag
725 && attr1
->label_index
== attr2
->label_index
726 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
727 && bgp_attr_get_ecommunity(attr1
)
728 == bgp_attr_get_ecommunity(attr2
)
729 && bgp_attr_get_ipv6_ecommunity(attr1
)
730 == bgp_attr_get_ipv6_ecommunity(attr2
)
731 && bgp_attr_get_lcommunity(attr1
)
732 == bgp_attr_get_lcommunity(attr2
)
733 && bgp_attr_get_cluster(attr1
)
734 == bgp_attr_get_cluster(attr2
)
735 && bgp_attr_get_transit(attr1
)
736 == bgp_attr_get_transit(attr2
)
737 && attr1
->rmap_table_id
== attr2
->rmap_table_id
738 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
739 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
740 #ifdef ENABLE_BGP_VNC
741 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
742 bgp_attr_get_vnc_subtlvs(attr2
))
744 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
745 &attr2
->mp_nexthop_global
)
746 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
747 &attr2
->mp_nexthop_local
)
748 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
749 &attr2
->mp_nexthop_global_in
)
750 && IPV4_ADDR_SAME(&attr1
->originator_id
,
751 &attr2
->originator_id
)
752 && overlay_index_same(attr1
, attr2
)
753 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
754 && attr1
->es_flags
== attr2
->es_flags
755 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
756 && attr1
->df_pref
== attr2
->df_pref
757 && attr1
->df_alg
== attr2
->df_alg
758 && attr1
->nh_ifindex
== attr2
->nh_ifindex
759 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
760 && attr1
->distance
== attr2
->distance
761 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
762 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
763 && attr1
->srte_color
== attr2
->srte_color
764 && attr1
->nh_type
== attr2
->nh_type
765 && attr1
->bh_type
== attr2
->bh_type
)
772 static void attrhash_init(void)
775 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
779 * special for hash_clean below
781 static void attr_vfree(void *attr
)
783 XFREE(MTYPE_ATTR
, attr
);
786 static void attrhash_finish(void)
788 hash_clean(attrhash
, attr_vfree
);
793 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
795 struct attr
*attr
= bucket
->data
;
796 char sid_str
[BUFSIZ
];
798 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
801 if (attr
->srv6_l3vpn
)
802 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
803 else if (attr
->srv6_vpn
)
804 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
807 "\tflags: %" PRIu64
" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
808 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
809 attr
->origin
, attr
->weight
, attr
->label
, sid_str
);
812 void attr_show_all(struct vty
*vty
)
814 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
815 void *))attr_show_all_iterator
,
819 static void *bgp_attr_hash_alloc(void *p
)
821 struct attr
*val
= (struct attr
*)p
;
824 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
826 if (val
->encap_subtlvs
) {
827 val
->encap_subtlvs
= NULL
;
829 #ifdef ENABLE_BGP_VNC
830 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
831 bgp_attr_get_vnc_subtlvs(val
);
834 bgp_attr_set_vnc_subtlvs(val
, NULL
);
841 /* Internet argument attribute. */
842 struct attr
*bgp_attr_intern(struct attr
*attr
)
845 struct ecommunity
*ecomm
= NULL
;
846 struct ecommunity
*ipv6_ecomm
= NULL
;
847 struct lcommunity
*lcomm
= NULL
;
848 struct community
*comm
= NULL
;
850 /* Intern referenced structure. */
852 if (!attr
->aspath
->refcnt
)
853 attr
->aspath
= aspath_intern(attr
->aspath
);
855 attr
->aspath
->refcnt
++;
858 comm
= bgp_attr_get_community(attr
);
861 bgp_attr_set_community(attr
, community_intern(comm
));
866 ecomm
= bgp_attr_get_ecommunity(attr
);
869 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
874 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
876 if (!ipv6_ecomm
->refcnt
)
877 bgp_attr_set_ipv6_ecommunity(
878 attr
, ecommunity_intern(ipv6_ecomm
));
880 ipv6_ecomm
->refcnt
++;
883 lcomm
= bgp_attr_get_lcommunity(attr
);
886 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
891 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
894 if (!cluster
->refcnt
)
895 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
900 struct transit
*transit
= bgp_attr_get_transit(attr
);
903 if (!transit
->refcnt
)
904 bgp_attr_set_transit(attr
, transit_intern(transit
));
908 if (attr
->encap_subtlvs
) {
909 if (!attr
->encap_subtlvs
->refcnt
)
910 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
913 attr
->encap_subtlvs
->refcnt
++;
915 if (attr
->srv6_l3vpn
) {
916 if (!attr
->srv6_l3vpn
->refcnt
)
917 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
919 attr
->srv6_l3vpn
->refcnt
++;
921 if (attr
->srv6_vpn
) {
922 if (!attr
->srv6_vpn
->refcnt
)
923 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
925 attr
->srv6_vpn
->refcnt
++;
927 #ifdef ENABLE_BGP_VNC
928 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
929 bgp_attr_get_vnc_subtlvs(attr
);
932 if (!vnc_subtlvs
->refcnt
)
933 bgp_attr_set_vnc_subtlvs(
935 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
937 vnc_subtlvs
->refcnt
++;
941 /* At this point, attr only contains intern'd pointers. that means
942 * if we find it in attrhash, it has all the same pointers and we
943 * correctly updated the refcounts on these.
944 * If we don't find it, we need to allocate a one because in all
945 * cases this returns a new reference to a hashed attr, but the input
947 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
953 /* Make network statement's attribute. */
954 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
956 memset(attr
, 0, sizeof(struct attr
));
958 attr
->origin
= origin
;
959 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
960 attr
->aspath
= aspath_empty();
961 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
962 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
964 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
965 attr
->label
= MPLS_INVALID_LABEL
;
966 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
967 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
972 /* Create the attributes for an aggregate */
973 struct attr
*bgp_attr_aggregate_intern(
974 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
975 struct community
*community
, struct ecommunity
*ecommunity
,
976 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
977 uint8_t atomic_aggregate
, const struct prefix
*p
)
983 memset(&attr
, 0, sizeof(struct attr
));
985 /* Origin attribute. */
986 attr
.origin
= origin
;
987 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
991 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
993 /* AS path attribute. */
995 attr
.aspath
= aspath_intern(aspath
);
997 attr
.aspath
= aspath_empty();
998 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1000 /* Next hop attribute. */
1001 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1004 uint32_t gshut
= COMMUNITY_GSHUT
;
1006 /* If we are not shutting down ourselves and we are
1007 * aggregating a route that contains the GSHUT community we
1008 * need to remove that community when creating the aggregate */
1009 if (!bgp_in_graceful_shutdown(bgp
)
1010 && community_include(community
, gshut
)) {
1011 community_del_val(community
, &gshut
);
1014 bgp_attr_set_community(&attr
, community
);
1018 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1021 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1023 if (bgp_in_graceful_shutdown(bgp
))
1024 bgp_attr_add_gshut_community(&attr
);
1026 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1027 attr
.label
= MPLS_INVALID_LABEL
;
1028 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1029 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1030 if (!aggregate
->as_set
|| atomic_aggregate
)
1031 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1032 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1033 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1034 attr
.aggregator_as
= bgp
->confed_id
;
1036 attr
.aggregator_as
= bgp
->as
;
1037 attr
.aggregator_addr
= bgp
->router_id
;
1038 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1039 attr
.label
= MPLS_INVALID_LABEL
;
1041 /* Apply route-map */
1042 if (aggregate
->rmap
.name
) {
1043 struct attr attr_tmp
= attr
;
1044 struct bgp_path_info rmap_path
;
1046 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1047 rmap_path
.peer
= bgp
->peer_self
;
1048 rmap_path
.attr
= &attr_tmp
;
1050 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1052 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1054 bgp
->peer_self
->rmap_type
= 0;
1056 if (ret
== RMAP_DENYMATCH
) {
1057 /* Free uninterned attribute. */
1058 bgp_attr_flush(&attr_tmp
);
1060 /* Unintern original. */
1061 aspath_unintern(&attr
.aspath
);
1065 if (bgp_in_graceful_shutdown(bgp
))
1066 bgp_attr_add_gshut_community(&attr_tmp
);
1068 new = bgp_attr_intern(&attr_tmp
);
1071 if (bgp_in_graceful_shutdown(bgp
))
1072 bgp_attr_add_gshut_community(&attr
);
1074 new = bgp_attr_intern(&attr
);
1077 /* Always release the 'intern()'ed AS Path. */
1078 aspath_unintern(&attr
.aspath
);
1083 /* Unintern just the sub-components of the attr, but not the attr */
1084 void bgp_attr_unintern_sub(struct attr
*attr
)
1086 struct ecommunity
*ecomm
= NULL
;
1087 struct ecommunity
*ipv6_ecomm
= NULL
;
1088 struct cluster_list
*cluster
;
1089 struct lcommunity
*lcomm
= NULL
;
1090 struct community
*comm
= NULL
;
1092 /* aspath refcount shoud be decrement. */
1093 aspath_unintern(&attr
->aspath
);
1094 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1096 comm
= bgp_attr_get_community(attr
);
1097 community_unintern(&comm
);
1098 bgp_attr_set_community(attr
, NULL
);
1100 ecomm
= bgp_attr_get_ecommunity(attr
);
1101 ecommunity_unintern(&ecomm
);
1102 bgp_attr_set_ecommunity(attr
, NULL
);
1104 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1105 ecommunity_unintern(&ipv6_ecomm
);
1106 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1108 lcomm
= bgp_attr_get_lcommunity(attr
);
1109 lcommunity_unintern(&lcomm
);
1110 bgp_attr_set_lcommunity(attr
, NULL
);
1112 cluster
= bgp_attr_get_cluster(attr
);
1114 cluster_unintern(&cluster
);
1115 bgp_attr_set_cluster(attr
, cluster
);
1117 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1119 struct transit
*transit
= bgp_attr_get_transit(attr
);
1122 transit_unintern(&transit
);
1123 bgp_attr_set_transit(attr
, transit
);
1126 if (attr
->encap_subtlvs
)
1127 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1129 #ifdef ENABLE_BGP_VNC
1130 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1131 bgp_attr_get_vnc_subtlvs(attr
);
1134 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1135 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1139 if (attr
->srv6_l3vpn
)
1140 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1143 srv6_vpn_unintern(&attr
->srv6_vpn
);
1146 /* Free bgp attribute and aspath. */
1147 void bgp_attr_unintern(struct attr
**pattr
)
1149 struct attr
*attr
= *pattr
;
1153 /* Decrement attribute reference. */
1158 /* If reference becomes zero then free attribute object. */
1159 if (attr
->refcnt
== 0) {
1160 ret
= hash_release(attrhash
, attr
);
1161 assert(ret
!= NULL
);
1162 XFREE(MTYPE_ATTR
, attr
);
1166 bgp_attr_unintern_sub(&tmp
);
1169 void bgp_attr_flush(struct attr
*attr
)
1171 struct ecommunity
*ecomm
;
1172 struct ecommunity
*ipv6_ecomm
;
1173 struct cluster_list
*cluster
;
1174 struct lcommunity
*lcomm
;
1175 struct community
*comm
;
1177 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1178 aspath_free(attr
->aspath
);
1179 attr
->aspath
= NULL
;
1181 comm
= bgp_attr_get_community(attr
);
1182 if (comm
&& !comm
->refcnt
)
1183 community_free(&comm
);
1184 bgp_attr_set_community(attr
, NULL
);
1186 ecomm
= bgp_attr_get_ecommunity(attr
);
1187 if (ecomm
&& !ecomm
->refcnt
)
1188 ecommunity_free(&ecomm
);
1189 bgp_attr_set_ecommunity(attr
, NULL
);
1191 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1192 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1193 ecommunity_free(&ipv6_ecomm
);
1194 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1196 lcomm
= bgp_attr_get_lcommunity(attr
);
1197 if (lcomm
&& !lcomm
->refcnt
)
1198 lcommunity_free(&lcomm
);
1199 bgp_attr_set_lcommunity(attr
, NULL
);
1201 cluster
= bgp_attr_get_cluster(attr
);
1202 if (cluster
&& !cluster
->refcnt
) {
1203 cluster_free(cluster
);
1204 bgp_attr_set_cluster(attr
, NULL
);
1207 struct transit
*transit
= bgp_attr_get_transit(attr
);
1209 if (transit
&& !transit
->refcnt
) {
1210 transit_free(transit
);
1211 bgp_attr_set_transit(attr
, NULL
);
1213 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1214 encap_free(attr
->encap_subtlvs
);
1215 attr
->encap_subtlvs
= NULL
;
1217 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1218 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1219 attr
->srv6_l3vpn
= NULL
;
1221 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1222 srv6_vpn_free(attr
->srv6_vpn
);
1223 attr
->srv6_vpn
= NULL
;
1225 #ifdef ENABLE_BGP_VNC
1226 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1227 bgp_attr_get_vnc_subtlvs(attr
);
1229 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1230 encap_free(vnc_subtlvs
);
1231 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1236 /* Implement draft-scudder-idr-optional-transitive behaviour and
1237 * avoid resetting sessions for malformed attributes which are
1238 * are partial/optional and hence where the error likely was not
1239 * introduced by the sending neighbour.
1241 static enum bgp_attr_parse_ret
1242 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1245 struct peer
*const peer
= args
->peer
;
1246 struct attr
*const attr
= args
->attr
;
1247 const uint8_t flags
= args
->flags
;
1248 /* startp and length must be special-cased, as whether or not to
1249 * send the attribute data with the NOTIFY depends on the error,
1250 * the caller therefore signals this with the seperate length argument
1252 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1254 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1255 char attr_str
[BUFSIZ
] = {0};
1257 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1259 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1262 /* Only relax error handling for eBGP peers */
1263 if (peer
->sort
!= BGP_PEER_EBGP
) {
1264 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1265 notify_datap
, length
);
1266 return BGP_ATTR_PARSE_ERROR
;
1269 /* Adjust the stream getp to the end of the attribute, in case we can
1270 * still proceed but the caller hasn't read all the attribute.
1272 stream_set_getp(BGP_INPUT(peer
),
1273 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1276 switch (args
->type
) {
1277 /* where an attribute is relatively inconsequential, e.g. it does not
1278 * affect route selection, and can be safely ignored, then any such
1279 * attributes which are malformed should just be ignored and the route
1280 * processed as normal.
1282 case BGP_ATTR_AS4_AGGREGATOR
:
1283 case BGP_ATTR_AGGREGATOR
:
1284 case BGP_ATTR_ATOMIC_AGGREGATE
:
1285 return BGP_ATTR_PARSE_PROCEED
;
1287 /* Core attributes, particularly ones which may influence route
1288 * selection, should be treat-as-withdraw.
1290 case BGP_ATTR_ORIGIN
:
1291 case BGP_ATTR_AS_PATH
:
1292 case BGP_ATTR_NEXT_HOP
:
1293 case BGP_ATTR_MULTI_EXIT_DISC
:
1294 case BGP_ATTR_LOCAL_PREF
:
1295 case BGP_ATTR_COMMUNITIES
:
1296 case BGP_ATTR_EXT_COMMUNITIES
:
1297 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1298 case BGP_ATTR_LARGE_COMMUNITIES
:
1299 case BGP_ATTR_ORIGINATOR_ID
:
1300 case BGP_ATTR_CLUSTER_LIST
:
1301 return BGP_ATTR_PARSE_WITHDRAW
;
1302 case BGP_ATTR_MP_REACH_NLRI
:
1303 case BGP_ATTR_MP_UNREACH_NLRI
:
1304 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1305 notify_datap
, length
);
1306 return BGP_ATTR_PARSE_ERROR
;
1309 /* Partial optional attributes that are malformed should not cause
1310 * the whole session to be reset. Instead treat it as a withdrawal
1311 * of the routes, if possible.
1313 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1314 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1315 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1316 return BGP_ATTR_PARSE_WITHDRAW
;
1318 /* default to reset */
1319 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1322 /* Find out what is wrong with the path attribute flag bits and log the error.
1323 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1324 Extended Length. Checking O/T/P bits at once implies, that the attribute
1325 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1326 non-transitive" attribute. */
1328 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1329 uint8_t desired_flags
/* how RFC says it must be */
1332 uint8_t seen
= 0, i
;
1333 uint8_t real_flags
= args
->flags
;
1334 const uint8_t attr_code
= args
->type
;
1336 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1337 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1338 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1339 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1340 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1341 flog_err(EC_BGP_ATTR_FLAG
,
1342 "%s attribute must%s be flagged as \"%s\"",
1343 lookup_msg(attr_str
, attr_code
, NULL
),
1344 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1347 attr_flag_str
[i
].str
);
1352 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1353 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1354 real_flags
, desired_flags
);
1358 /* Required flags for attributes. EXTLEN will be masked off when testing,
1359 * as will PARTIAL for optional+transitive attributes.
1361 const uint8_t attr_flags_values
[] = {
1362 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1363 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1364 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1365 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1366 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1367 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1368 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1369 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1370 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1371 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1372 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1373 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1374 [BGP_ATTR_EXT_COMMUNITIES
] =
1375 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1376 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1377 [BGP_ATTR_AS4_AGGREGATOR
] =
1378 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1379 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1380 [BGP_ATTR_LARGE_COMMUNITIES
] =
1381 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1382 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1383 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1384 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1386 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1388 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1390 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1391 const uint8_t flags
= args
->flags
;
1392 const uint8_t attr_code
= args
->type
;
1394 /* there may be attributes we don't know about */
1395 if (attr_code
> attr_flags_values_max
)
1397 if (attr_flags_values
[attr_code
] == 0)
1400 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1404 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1405 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1408 "%s well-known attributes must have transitive flag set (%x)",
1409 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1413 /* "For well-known attributes and for optional non-transitive
1415 * the Partial bit MUST be set to 0."
1417 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1418 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1419 flog_err(EC_BGP_ATTR_FLAG
,
1420 "%s well-known attribute must NOT have the partial flag set (%x)",
1421 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1424 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1425 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1426 flog_err(EC_BGP_ATTR_FLAG
,
1427 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1428 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1433 /* Optional transitive attributes may go through speakers that don't
1434 * reocgnise them and set the Partial bit.
1436 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1437 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1438 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1440 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1443 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1447 /* Get origin attribute of the update message. */
1448 static enum bgp_attr_parse_ret
1449 bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1451 struct peer
*const peer
= args
->peer
;
1452 struct attr
*const attr
= args
->attr
;
1453 const bgp_size_t length
= args
->length
;
1455 /* If any recognized attribute has Attribute Length that conflicts
1456 with the expected length (based on the attribute type code), then
1457 the Error Subcode is set to Attribute Length Error. The Data
1458 field contains the erroneous attribute (type, length and
1461 flog_err(EC_BGP_ATTR_LEN
,
1462 "Origin attribute length is not one %d", length
);
1463 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1467 /* Fetch origin attribute. */
1468 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1470 /* If the ORIGIN attribute has an undefined value, then the Error
1471 Subcode is set to Invalid Origin Attribute. The Data field
1472 contains the unrecognized attribute (type, length and value). */
1473 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1474 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1475 flog_err(EC_BGP_ATTR_ORIGIN
,
1476 "Origin attribute value is invalid %d", attr
->origin
);
1477 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1481 /* Set oring attribute flag. */
1482 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1487 /* Parse AS path information. This function is wrapper of
1489 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1491 struct attr
*const attr
= args
->attr
;
1492 struct peer
*const peer
= args
->peer
;
1493 const bgp_size_t length
= args
->length
;
1496 * peer with AS4 => will get 4Byte ASnums
1497 * otherwise, will get 16 Bit
1499 attr
->aspath
= aspath_parse(
1501 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1502 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1504 /* In case of IBGP, length will be zero. */
1505 if (!attr
->aspath
) {
1506 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1507 "Malformed AS path from %s, length is %d", peer
->host
,
1509 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1513 /* Set aspath attribute flag. */
1514 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1516 return BGP_ATTR_PARSE_PROCEED
;
1519 static enum bgp_attr_parse_ret
bgp_attr_aspath_check(struct peer
*const peer
,
1520 struct attr
*const attr
)
1522 /* These checks were part of bgp_attr_aspath, but with
1523 * as4 we should to check aspath things when
1524 * aspath synthesizing with as4_path has already taken place.
1525 * Otherwise we check ASPATH and use the synthesized thing, and that is
1527 * So do the checks later, i.e. here
1529 struct aspath
*aspath
;
1531 /* Confederation sanity check. */
1532 if ((peer
->sort
== BGP_PEER_CONFED
1533 && !aspath_left_confed_check(attr
->aspath
))
1534 || (peer
->sort
== BGP_PEER_EBGP
1535 && aspath_confed_check(attr
->aspath
))) {
1536 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1538 return BGP_ATTR_PARSE_WITHDRAW
;
1541 /* First AS check for EBGP. */
1542 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1543 if (peer
->sort
== BGP_PEER_EBGP
1544 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1545 flog_err(EC_BGP_ATTR_FIRST_AS
,
1546 "%s incorrect first AS (must be %u)",
1547 peer
->host
, peer
->as
);
1548 return BGP_ATTR_PARSE_WITHDRAW
;
1552 /* Codification of AS 0 Processing */
1553 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1555 EC_BGP_ATTR_MAL_AS_PATH
,
1556 "Malformed AS path, AS number is 0 in the path from %s",
1558 return BGP_ATTR_PARSE_WITHDRAW
;
1561 /* local-as prepend */
1562 if (peer
->change_local_as
1563 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1564 aspath
= aspath_dup(attr
->aspath
);
1565 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1566 aspath_unintern(&attr
->aspath
);
1567 attr
->aspath
= aspath_intern(aspath
);
1570 return BGP_ATTR_PARSE_PROCEED
;
1573 /* Parse AS4 path information. This function is another wrapper of
1575 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1576 struct aspath
**as4_path
)
1578 struct peer
*const peer
= args
->peer
;
1579 struct attr
*const attr
= args
->attr
;
1580 const bgp_size_t length
= args
->length
;
1582 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1584 /* In case of IBGP, length will be zero. */
1586 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1587 "Malformed AS4 path from %s, length is %d", peer
->host
,
1589 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1593 /* Set aspath attribute flag. */
1594 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1596 return BGP_ATTR_PARSE_PROCEED
;
1600 * Check that the nexthop attribute is valid.
1602 enum bgp_attr_parse_ret
bgp_attr_nexthop_valid(struct peer
*peer
,
1605 in_addr_t nexthop_h
;
1607 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1608 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1609 || IPV4_CLASS_DE(nexthop_h
))
1610 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1611 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1612 char buf
[INET_ADDRSTRLEN
];
1614 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1616 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1618 data
[0] = BGP_ATTR_FLAG_TRANS
;
1619 data
[1] = BGP_ATTR_NEXT_HOP
;
1620 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1621 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1622 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1623 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1625 return BGP_ATTR_PARSE_ERROR
;
1628 return BGP_ATTR_PARSE_PROCEED
;
1631 /* Nexthop attribute. */
1632 static enum bgp_attr_parse_ret
1633 bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1635 struct peer
*const peer
= args
->peer
;
1636 struct attr
*const attr
= args
->attr
;
1637 const bgp_size_t length
= args
->length
;
1639 /* Check nexthop attribute length. */
1641 flog_err(EC_BGP_ATTR_LEN
,
1642 "Nexthop attribute length isn't four [%d]", length
);
1644 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1648 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1649 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1651 return BGP_ATTR_PARSE_PROCEED
;
1654 /* MED atrribute. */
1655 static enum bgp_attr_parse_ret
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1657 struct peer
*const peer
= args
->peer
;
1658 struct attr
*const attr
= args
->attr
;
1659 const bgp_size_t length
= args
->length
;
1663 flog_err(EC_BGP_ATTR_LEN
,
1664 "MED attribute length isn't four [%d]", length
);
1666 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1670 attr
->med
= stream_getl(peer
->curr
);
1672 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1674 return BGP_ATTR_PARSE_PROCEED
;
1677 /* Local preference attribute. */
1678 static enum bgp_attr_parse_ret
1679 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1681 struct peer
*const peer
= args
->peer
;
1682 struct attr
*const attr
= args
->attr
;
1683 const bgp_size_t length
= args
->length
;
1685 /* if received from an internal neighbor, it SHALL be considered
1686 * malformed if its length is not equal to 4. If malformed, the
1687 * UPDATE message SHALL be handled using the approach of "treat-as-
1690 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1691 flog_err(EC_BGP_ATTR_LEN
,
1692 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1693 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1697 /* If it is contained in an UPDATE message that is received from an
1698 external peer, then this attribute MUST be ignored by the
1699 receiving speaker. */
1700 if (peer
->sort
== BGP_PEER_EBGP
) {
1701 STREAM_FORWARD_GETP(peer
->curr
, length
);
1702 return BGP_ATTR_PARSE_PROCEED
;
1705 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1707 /* Set the local-pref flag. */
1708 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1710 return BGP_ATTR_PARSE_PROCEED
;
1713 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1717 /* Atomic aggregate. */
1718 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1720 struct attr
*const attr
= args
->attr
;
1721 const bgp_size_t length
= args
->length
;
1725 flog_err(EC_BGP_ATTR_LEN
,
1726 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1728 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1732 /* Set atomic aggregate flag. */
1733 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1735 return BGP_ATTR_PARSE_PROCEED
;
1738 /* Aggregator attribute */
1739 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1741 struct peer
*const peer
= args
->peer
;
1742 struct attr
*const attr
= args
->attr
;
1743 const bgp_size_t length
= args
->length
;
1748 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1749 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1750 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1753 if (length
!= wantedlen
) {
1754 flog_err(EC_BGP_ATTR_LEN
,
1755 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1757 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1761 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1762 aggregator_as
= stream_getl(peer
->curr
);
1764 aggregator_as
= stream_getw(peer
->curr
);
1766 attr
->aggregator_as
= aggregator_as
;
1767 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1769 /* Codification of AS 0 Processing */
1770 if (aggregator_as
== BGP_AS_ZERO
) {
1771 flog_err(EC_BGP_ATTR_LEN
,
1772 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1773 peer
->host
, aspath_print(attr
->aspath
));
1775 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1776 char attr_str
[BUFSIZ
] = {0};
1778 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1780 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1783 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1786 return BGP_ATTR_PARSE_PROCEED
;
1789 /* New Aggregator attribute */
1790 static enum bgp_attr_parse_ret
1791 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1792 as_t
*as4_aggregator_as
,
1793 struct in_addr
*as4_aggregator_addr
)
1795 struct peer
*const peer
= args
->peer
;
1796 struct attr
*const attr
= args
->attr
;
1797 const bgp_size_t length
= args
->length
;
1801 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1803 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1807 aggregator_as
= stream_getl(peer
->curr
);
1809 *as4_aggregator_as
= aggregator_as
;
1810 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1812 /* Codification of AS 0 Processing */
1813 if (aggregator_as
== BGP_AS_ZERO
) {
1814 flog_err(EC_BGP_ATTR_LEN
,
1815 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1816 peer
->host
, aspath_print(attr
->aspath
));
1818 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1819 char attr_str
[BUFSIZ
] = {0};
1821 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1823 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1826 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1829 return BGP_ATTR_PARSE_PROCEED
;
1832 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1834 static enum bgp_attr_parse_ret
1835 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1836 struct aspath
*as4_path
, as_t as4_aggregator
,
1837 struct in_addr
*as4_aggregator_addr
)
1839 int ignore_as4_path
= 0;
1840 struct aspath
*newpath
;
1842 if (!attr
->aspath
) {
1843 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1845 * checked that all well-known, mandatory attributes were
1848 * Can only be a problem with peer itself - hard error
1850 return BGP_ATTR_PARSE_ERROR
;
1853 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1854 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1856 * It is worth a warning though, because the peer really
1857 * should not send them
1859 if (BGP_DEBUG(as4
, AS4
)) {
1860 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1861 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1862 "AS4 capable peer, yet it sent");
1865 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1866 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1868 "AS4 capable peer, yet it sent");
1871 return BGP_ATTR_PARSE_PROCEED
;
1874 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1875 * because that may override AS4_PATH
1877 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1878 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1880 * if the as_number in aggregator is not AS_TRANS,
1881 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1882 * and the Aggregator shall be taken as
1883 * info on the aggregating node, and the AS_PATH
1884 * shall be taken as the AS_PATH
1886 * the Aggregator shall be ignored and the
1887 * AS4_AGGREGATOR shall be taken as the
1888 * Aggregating node and the AS_PATH is to be
1889 * constructed "as in all other cases"
1891 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1893 if (BGP_DEBUG(as4
, AS4
))
1895 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1897 ignore_as4_path
= 1;
1899 /* "New_aggregator shall be taken as aggregator"
1901 attr
->aggregator_as
= as4_aggregator
;
1902 attr
->aggregator_addr
.s_addr
=
1903 as4_aggregator_addr
->s_addr
;
1906 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1907 * That is bogus - but reading the conditions
1908 * we have to handle AS4_AGGREGATOR as if it were
1909 * AGGREGATOR in that case
1911 if (BGP_DEBUG(as4
, AS4
))
1913 "[AS4] %s BGP not AS4 capable peer send AS4_AGGREGATOR but no AGGREGATOR, will take it as if AGGREGATOR with AS_TRANS had been there",
1915 attr
->aggregator_as
= as4_aggregator
;
1916 /* sweep it under the carpet and simulate a "good"
1918 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1922 /* need to reconcile NEW_AS_PATH and AS_PATH */
1923 if (!ignore_as4_path
1924 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1925 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1927 return BGP_ATTR_PARSE_ERROR
;
1929 aspath_unintern(&attr
->aspath
);
1930 attr
->aspath
= aspath_intern(newpath
);
1932 return BGP_ATTR_PARSE_PROCEED
;
1935 /* Community attribute. */
1936 static enum bgp_attr_parse_ret
1937 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1939 struct peer
*const peer
= args
->peer
;
1940 struct attr
*const attr
= args
->attr
;
1941 const bgp_size_t length
= args
->length
;
1944 bgp_attr_set_community(attr
, NULL
);
1945 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1949 bgp_attr_set_community(
1951 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
1953 /* XXX: fix community_parse to use stream API and remove this */
1954 stream_forward_getp(peer
->curr
, length
);
1956 /* The Community attribute SHALL be considered malformed if its
1957 * length is not a non-zero multiple of 4.
1959 if (!bgp_attr_get_community(attr
))
1960 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1963 return BGP_ATTR_PARSE_PROCEED
;
1966 /* Originator ID attribute. */
1967 static enum bgp_attr_parse_ret
1968 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1970 struct peer
*const peer
= args
->peer
;
1971 struct attr
*const attr
= args
->attr
;
1972 const bgp_size_t length
= args
->length
;
1974 /* if received from an internal neighbor, it SHALL be considered
1975 * malformed if its length is not equal to 4. If malformed, the
1976 * UPDATE message SHALL be handled using the approach of "treat-as-
1980 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1983 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1987 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1989 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1991 return BGP_ATTR_PARSE_PROCEED
;
1994 /* Cluster list attribute. */
1995 static enum bgp_attr_parse_ret
1996 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1998 struct peer
*const peer
= args
->peer
;
1999 struct attr
*const attr
= args
->attr
;
2000 const bgp_size_t length
= args
->length
;
2002 /* if received from an internal neighbor, it SHALL be considered
2003 * malformed if its length is not a non-zero multiple of 4. If
2004 * malformed, the UPDATE message SHALL be handled using the approach
2005 * of "treat-as-withdraw".
2007 if (length
== 0 || length
% 4) {
2008 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2010 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2014 bgp_attr_set_cluster(
2015 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2018 /* XXX: Fix cluster_parse to use stream API and then remove this */
2019 stream_forward_getp(peer
->curr
, length
);
2021 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2023 return BGP_ATTR_PARSE_PROCEED
;
2026 /* Multiprotocol reachability information parse. */
2027 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2028 struct bgp_nlri
*mp_update
)
2032 iana_safi_t pkt_safi
;
2034 bgp_size_t nlri_len
;
2037 struct peer
*const peer
= args
->peer
;
2038 struct attr
*const attr
= args
->attr
;
2039 const bgp_size_t length
= args
->length
;
2041 /* Set end of packet. */
2042 s
= BGP_INPUT(peer
);
2043 start
= stream_get_getp(s
);
2045 /* safe to read statically sized header? */
2046 #define BGP_MP_REACH_MIN_SIZE 5
2047 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2048 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2049 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2050 __func__
, peer
->host
, (unsigned long)length
);
2051 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2054 /* Load AFI, SAFI. */
2055 pkt_afi
= stream_getw(s
);
2056 pkt_safi
= stream_getc(s
);
2058 /* Convert AFI, SAFI to internal values, check. */
2059 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2060 /* Log if AFI or SAFI is unrecognized. This is not an error
2062 * the attribute is otherwise malformed.
2064 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2066 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2067 peer
->host
, iana_afi2str(pkt_afi
),
2068 iana_safi2str(pkt_safi
));
2069 return BGP_ATTR_PARSE_ERROR
;
2072 /* Get nexthop length. */
2073 attr
->mp_nexthop_len
= stream_getc(s
);
2075 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2077 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2078 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2079 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2082 /* Nexthop length check. */
2083 switch (attr
->mp_nexthop_len
) {
2085 if (safi
!= SAFI_FLOWSPEC
) {
2086 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2087 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2088 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2091 case BGP_ATTR_NHLEN_VPNV4
:
2092 stream_getl(s
); /* RD high */
2093 stream_getl(s
); /* RD low */
2095 * NOTE: intentional fall through
2096 * - for consistency in rx processing
2098 * The following comment is to signal GCC this intention
2099 * and suppress the warning
2102 case BGP_ATTR_NHLEN_IPV4
:
2103 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2104 /* Probably needed for RFC 2283 */
2105 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2106 memcpy(&attr
->nexthop
.s_addr
,
2107 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2109 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2110 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2111 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2112 stream_getl(s
); /* RD high */
2113 stream_getl(s
); /* RD low */
2115 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2116 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2117 if (!peer
->nexthop
.ifp
) {
2118 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2120 return BGP_ATTR_PARSE_WITHDRAW
;
2122 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2125 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2126 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2127 if (attr
->mp_nexthop_len
2128 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2129 stream_getl(s
); /* RD high */
2130 stream_getl(s
); /* RD low */
2132 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2133 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2134 if (!peer
->nexthop
.ifp
) {
2135 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",
2137 return BGP_ATTR_PARSE_WITHDRAW
;
2139 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2141 if (attr
->mp_nexthop_len
2142 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2143 stream_getl(s
); /* RD high */
2144 stream_getl(s
); /* RD low */
2146 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2147 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2148 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2150 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2151 peer
->host
, &attr
->mp_nexthop_global
,
2152 &attr
->mp_nexthop_local
);
2154 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2156 if (!peer
->nexthop
.ifp
) {
2157 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2159 return BGP_ATTR_PARSE_WITHDRAW
;
2161 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2164 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2165 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2166 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2170 zlog_info("%s: %s sent SNPA which couldn't be read",
2171 __func__
, peer
->host
);
2172 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2177 if ((val
= stream_getc(s
)))
2179 EC_BGP_DEFUNCT_SNPA_LEN
,
2180 "%s sent non-zero value, %u, for defunct SNPA-length field",
2184 /* must have nrli_len, what is left of the attribute */
2185 nlri_len
= LEN_LEFT
;
2186 if (nlri_len
> STREAM_READABLE(s
)) {
2187 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2188 __func__
, peer
->host
);
2189 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2193 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2194 __func__
, peer
->host
);
2196 mp_update
->afi
= afi
;
2197 mp_update
->safi
= safi
;
2198 return BGP_ATTR_PARSE_EOR
;
2201 mp_update
->afi
= afi
;
2202 mp_update
->safi
= safi
;
2203 mp_update
->nlri
= stream_pnt(s
);
2204 mp_update
->length
= nlri_len
;
2206 stream_forward_getp(s
, nlri_len
);
2208 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2210 return BGP_ATTR_PARSE_PROCEED
;
2214 /* Multiprotocol unreachable parse */
2215 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2216 struct bgp_nlri
*mp_withdraw
)
2221 iana_safi_t pkt_safi
;
2223 uint16_t withdraw_len
;
2224 struct peer
*const peer
= args
->peer
;
2225 struct attr
*const attr
= args
->attr
;
2226 const bgp_size_t length
= args
->length
;
2230 #define BGP_MP_UNREACH_MIN_SIZE 3
2231 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2232 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2234 pkt_afi
= stream_getw(s
);
2235 pkt_safi
= stream_getc(s
);
2237 /* Convert AFI, SAFI to internal values, check. */
2238 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2239 /* Log if AFI or SAFI is unrecognized. This is not an error
2241 * the attribute is otherwise malformed.
2243 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2245 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2246 peer
->host
, iana_afi2str(pkt_afi
),
2247 iana_safi2str(pkt_safi
));
2248 return BGP_ATTR_PARSE_ERROR
;
2251 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2253 mp_withdraw
->afi
= afi
;
2254 mp_withdraw
->safi
= safi
;
2255 mp_withdraw
->nlri
= stream_pnt(s
);
2256 mp_withdraw
->length
= withdraw_len
;
2258 stream_forward_getp(s
, withdraw_len
);
2260 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2262 return BGP_ATTR_PARSE_PROCEED
;
2265 /* Large Community attribute. */
2266 static enum bgp_attr_parse_ret
2267 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2269 struct peer
*const peer
= args
->peer
;
2270 struct attr
*const attr
= args
->attr
;
2271 const bgp_size_t length
= args
->length
;
2274 * Large community follows new attribute format.
2277 bgp_attr_set_lcommunity(attr
, NULL
);
2278 /* Empty extcomm doesn't seem to be invalid per se */
2279 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2283 bgp_attr_set_lcommunity(
2284 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2285 /* XXX: fix ecommunity_parse to use stream API */
2286 stream_forward_getp(peer
->curr
, length
);
2288 if (!bgp_attr_get_lcommunity(attr
))
2289 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2292 return BGP_ATTR_PARSE_PROCEED
;
2295 /* Extended Community attribute. */
2296 static enum bgp_attr_parse_ret
2297 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2299 struct peer
*const peer
= args
->peer
;
2300 struct attr
*const attr
= args
->attr
;
2301 const bgp_size_t length
= args
->length
;
2304 struct ecommunity
*ecomm
;
2307 bgp_attr_set_ecommunity(attr
, NULL
);
2308 /* Empty extcomm doesn't seem to be invalid per se */
2309 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2313 ecomm
= ecommunity_parse(
2314 stream_pnt(peer
->curr
), length
,
2315 CHECK_FLAG(peer
->flags
,
2316 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2317 bgp_attr_set_ecommunity(attr
, ecomm
);
2318 /* XXX: fix ecommunity_parse to use stream API */
2319 stream_forward_getp(peer
->curr
, length
);
2321 /* The Extended Community attribute SHALL be considered malformed if
2322 * its length is not a non-zero multiple of 8.
2324 if (!bgp_attr_get_ecommunity(attr
))
2325 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2328 /* Extract DF election preference and mobility sequence number */
2329 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2331 /* Extract MAC mobility sequence number, if any. */
2332 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2333 attr
->sticky
= sticky
;
2335 /* Check if this is a Gateway MAC-IP advertisement */
2336 attr
->default_gw
= bgp_attr_default_gw(attr
);
2338 /* Handle scenario where router flag ecommunity is not
2339 * set but default gw ext community is present.
2340 * Use default gateway, set and propogate R-bit.
2342 if (attr
->default_gw
)
2343 attr
->router_flag
= 1;
2345 /* Check EVPN Neighbor advertisement flags, R-bit */
2346 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2348 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2350 /* Extract the Rmac, if any */
2351 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2352 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2353 && bgp_mac_exist(&attr
->rmac
))
2354 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2358 /* Get the tunnel type from encap extended community */
2359 bgp_attr_extcom_tunnel_type(attr
,
2360 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2362 /* Extract link bandwidth, if any. */
2363 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2366 return BGP_ATTR_PARSE_PROCEED
;
2369 /* IPv6 Extended Community attribute. */
2370 static enum bgp_attr_parse_ret
2371 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2373 struct peer
*const peer
= args
->peer
;
2374 struct attr
*const attr
= args
->attr
;
2375 const bgp_size_t length
= args
->length
;
2376 struct ecommunity
*ipv6_ecomm
= NULL
;
2379 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2380 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2384 ipv6_ecomm
= ecommunity_parse_ipv6(
2385 stream_pnt(peer
->curr
), length
,
2386 CHECK_FLAG(peer
->flags
,
2387 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2388 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2390 /* XXX: fix ecommunity_parse to use stream API */
2391 stream_forward_getp(peer
->curr
, length
);
2394 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2397 return BGP_ATTR_PARSE_PROCEED
;
2400 /* Parse Tunnel Encap attribute in an UPDATE */
2401 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2402 bgp_size_t length
, /* IN: attr's length field */
2403 struct attr
*attr
, /* IN: caller already allocated */
2404 uint8_t flag
, /* IN: attr's flags field */
2408 uint16_t tunneltype
= 0;
2410 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2412 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2413 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2415 "Tunnel Encap attribute flag isn't optional and transitive %d",
2417 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2418 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2423 if (BGP_ATTR_ENCAP
== type
) {
2424 /* read outer TLV type and length */
2425 uint16_t tlv_length
;
2429 "Tunnel Encap attribute not long enough to contain outer T,L");
2430 bgp_notify_send_with_data(
2431 peer
, BGP_NOTIFY_UPDATE_ERR
,
2432 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2435 tunneltype
= stream_getw(BGP_INPUT(peer
));
2436 tlv_length
= stream_getw(BGP_INPUT(peer
));
2439 if (tlv_length
!= length
) {
2440 zlog_info("%s: tlv_length(%d) != length(%d)",
2441 __func__
, tlv_length
, length
);
2445 while (length
>= 4) {
2446 uint16_t subtype
= 0;
2447 uint16_t sublength
= 0;
2448 struct bgp_attr_encap_subtlv
*tlv
;
2450 if (BGP_ATTR_ENCAP
== type
) {
2451 subtype
= stream_getc(BGP_INPUT(peer
));
2452 sublength
= stream_getc(BGP_INPUT(peer
));
2454 #ifdef ENABLE_BGP_VNC
2456 subtype
= stream_getw(BGP_INPUT(peer
));
2457 sublength
= stream_getw(BGP_INPUT(peer
));
2462 if (sublength
> length
) {
2464 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2466 bgp_notify_send_with_data(
2467 peer
, BGP_NOTIFY_UPDATE_ERR
,
2468 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2472 /* alloc and copy sub-tlv */
2473 /* TBD make sure these are freed when attributes are released */
2474 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2475 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2476 tlv
->type
= subtype
;
2477 tlv
->length
= sublength
;
2478 stream_get(tlv
->value
, peer
->curr
, sublength
);
2479 length
-= sublength
;
2481 /* attach tlv to encap chain */
2482 if (BGP_ATTR_ENCAP
== type
) {
2483 struct bgp_attr_encap_subtlv
*stlv_last
;
2484 for (stlv_last
= attr
->encap_subtlvs
;
2485 stlv_last
&& stlv_last
->next
;
2486 stlv_last
= stlv_last
->next
)
2489 stlv_last
->next
= tlv
;
2491 attr
->encap_subtlvs
= tlv
;
2493 #ifdef ENABLE_BGP_VNC
2495 struct bgp_attr_encap_subtlv
*stlv_last
;
2496 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2497 bgp_attr_get_vnc_subtlvs(attr
);
2499 for (stlv_last
= vnc_subtlvs
;
2500 stlv_last
&& stlv_last
->next
;
2501 stlv_last
= stlv_last
->next
)
2504 stlv_last
->next
= tlv
;
2506 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2511 if (BGP_ATTR_ENCAP
== type
) {
2512 attr
->encap_tunneltype
= tunneltype
;
2516 /* spurious leftover data */
2518 "Tunnel Encap attribute length is bad: %d leftover octets",
2520 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2521 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2530 /* SRv6 Service Data Sub-Sub-TLV attribute
2531 * draft-ietf-bess-srv6-services-07
2533 static enum bgp_attr_parse_ret
2534 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2536 struct peer
*const peer
= args
->peer
;
2537 struct attr
*const attr
= args
->attr
;
2538 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2539 transposition_len
, transposition_offset
;
2541 size_t headersz
= sizeof(type
) + sizeof(length
);
2543 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2546 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2547 headersz
, STREAM_READABLE(peer
->curr
));
2548 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2552 type
= stream_getc(peer
->curr
);
2553 length
= stream_getw(peer
->curr
);
2555 if (STREAM_READABLE(peer
->curr
) < length
) {
2558 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2559 length
, STREAM_READABLE(peer
->curr
));
2560 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2564 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2567 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2568 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2570 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2574 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2575 loc_block_len
= stream_getc(peer
->curr
);
2576 loc_node_len
= stream_getc(peer
->curr
);
2577 func_len
= stream_getc(peer
->curr
);
2578 arg_len
= stream_getc(peer
->curr
);
2579 transposition_len
= stream_getc(peer
->curr
);
2580 transposition_offset
= stream_getc(peer
->curr
);
2582 /* Log SRv6 Service Data Sub-Sub-TLV */
2583 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2585 "%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",
2586 __func__
, loc_block_len
, loc_node_len
, func_len
,
2587 arg_len
, transposition_len
,
2588 transposition_offset
);
2591 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2592 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2593 attr
->srv6_l3vpn
->func_len
= func_len
;
2594 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2595 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2596 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2600 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2602 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2605 stream_forward_getp(peer
->curr
, length
);
2608 return BGP_ATTR_PARSE_PROCEED
;
2611 /* SRv6 Service Sub-TLV attribute
2612 * draft-ietf-bess-srv6-services-07
2614 static enum bgp_attr_parse_ret
2615 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2617 struct peer
*const peer
= args
->peer
;
2618 struct attr
*const attr
= args
->attr
;
2619 struct in6_addr ipv6_sid
;
2620 uint8_t type
, sid_flags
;
2621 uint16_t length
, endpoint_behavior
;
2622 size_t headersz
= sizeof(type
) + sizeof(length
);
2623 enum bgp_attr_parse_ret err
;
2626 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2629 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2630 headersz
, STREAM_READABLE(peer
->curr
));
2631 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2635 type
= stream_getc(peer
->curr
);
2636 length
= stream_getw(peer
->curr
);
2638 if (STREAM_READABLE(peer
->curr
) < length
) {
2641 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2642 length
, STREAM_READABLE(peer
->curr
));
2643 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2647 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2648 stream_getc(peer
->curr
);
2649 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2650 sid_flags
= stream_getc(peer
->curr
);
2651 endpoint_behavior
= stream_getw(peer
->curr
);
2652 stream_getc(peer
->curr
);
2654 /* Log SRv6 Service Sub-TLV */
2655 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2656 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2658 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2659 __func__
, buf
, sid_flags
, endpoint_behavior
);
2662 /* Configure from Info */
2663 if (attr
->srv6_l3vpn
) {
2664 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2665 "Prefix SID SRv6 L3VPN field repeated");
2666 return bgp_attr_malformed(
2667 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2669 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2670 sizeof(struct bgp_attr_srv6_l3vpn
));
2671 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2672 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2673 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2674 attr
->srv6_l3vpn
->loc_block_len
= 0;
2675 attr
->srv6_l3vpn
->loc_node_len
= 0;
2676 attr
->srv6_l3vpn
->func_len
= 0;
2677 attr
->srv6_l3vpn
->arg_len
= 0;
2678 attr
->srv6_l3vpn
->transposition_len
= 0;
2679 attr
->srv6_l3vpn
->transposition_offset
= 0;
2681 // Sub-Sub-TLV found
2682 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2683 err
= bgp_attr_srv6_service_data(args
);
2685 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2689 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2692 /* Placeholder code for unsupported type */
2694 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2696 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2699 stream_forward_getp(peer
->curr
, length
);
2702 return BGP_ATTR_PARSE_PROCEED
;
2706 * Read an individual SID value returning how much data we have read
2707 * Returns 0 if there was an error that needs to be passed up the stack
2709 static enum bgp_attr_parse_ret
2710 bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2711 struct bgp_attr_parser_args
*args
)
2713 struct peer
*const peer
= args
->peer
;
2714 struct attr
*const attr
= args
->attr
;
2715 uint32_t label_index
;
2716 struct in6_addr ipv6_sid
;
2718 uint32_t srgb_range
;
2720 uint8_t sid_type
, sid_flags
;
2723 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2724 if (STREAM_READABLE(peer
->curr
) < length
2725 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2726 flog_err(EC_BGP_ATTR_LEN
,
2727 "Prefix SID label index length is %hu instead of %u",
2728 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2729 return bgp_attr_malformed(args
,
2730 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2734 /* Ignore flags and reserved */
2735 stream_getc(peer
->curr
);
2736 stream_getw(peer
->curr
);
2738 /* Fetch the label index and see if it is valid. */
2739 label_index
= stream_getl(peer
->curr
);
2740 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2741 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2744 /* Store label index; subsequently, we'll check on
2746 attr
->label_index
= label_index
;
2749 /* Placeholder code for the IPv6 SID type */
2750 else if (type
== BGP_PREFIX_SID_IPV6
) {
2751 if (STREAM_READABLE(peer
->curr
) < length
2752 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2753 flog_err(EC_BGP_ATTR_LEN
,
2754 "Prefix SID IPv6 length is %hu instead of %u",
2755 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2756 return bgp_attr_malformed(args
,
2757 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2761 /* Ignore reserved */
2762 stream_getc(peer
->curr
);
2763 stream_getw(peer
->curr
);
2765 stream_get(&ipv6_sid
, peer
->curr
, 16);
2768 /* Placeholder code for the Originator SRGB type */
2769 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2771 * ietf-idr-bgp-prefix-sid-05:
2772 * Length is the total length of the value portion of the
2773 * TLV: 2 + multiple of 6.
2775 * peer->curr stream readp should be at the beginning of the 16
2776 * bit flag field at this point in the code.
2780 * Check that the TLV length field is sane: at least 2 bytes of
2781 * flag, and at least 1 SRGB (these are 6 bytes each)
2783 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2786 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2788 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2789 return bgp_attr_malformed(
2790 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2795 * Check that we actually have at least as much data as
2796 * specified by the length field
2798 if (STREAM_READABLE(peer
->curr
) < length
) {
2799 flog_err(EC_BGP_ATTR_LEN
,
2800 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2801 length
, STREAM_READABLE(peer
->curr
));
2802 return bgp_attr_malformed(
2803 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2808 * Check that the portion of the TLV containing the sequence of
2809 * SRGBs corresponds to a multiple of the SRGB size; to get
2810 * that length, we skip the 16 bit flags field
2812 stream_getw(peer
->curr
);
2814 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2817 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2818 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2819 return bgp_attr_malformed(
2820 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2824 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2826 for (int i
= 0; i
< srgb_count
; i
++) {
2827 stream_get(&srgb_base
, peer
->curr
, 3);
2828 stream_get(&srgb_range
, peer
->curr
, 3);
2832 /* Placeholder code for the VPN-SID Service type */
2833 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2834 if (STREAM_READABLE(peer
->curr
) < length
2835 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2836 flog_err(EC_BGP_ATTR_LEN
,
2837 "Prefix SID VPN SID length is %hu instead of %u",
2838 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2839 return bgp_attr_malformed(args
,
2840 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2844 /* Parse VPN-SID Sub-TLV */
2845 stream_getc(peer
->curr
); /* reserved */
2846 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2847 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2848 stream_get(&ipv6_sid
, peer
->curr
,
2849 sizeof(ipv6_sid
)); /* sid_value */
2851 /* Log VPN-SID Sub-TLV */
2852 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2853 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2855 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2856 __func__
, buf
, sid_type
, sid_flags
);
2859 /* Configure from Info */
2860 if (attr
->srv6_vpn
) {
2861 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2862 "Prefix SID SRv6 VPN field repeated");
2863 return bgp_attr_malformed(
2864 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2866 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2867 sizeof(struct bgp_attr_srv6_vpn
));
2868 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2869 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2870 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2873 /* Placeholder code for the SRv6 L3 Service type */
2874 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2875 if (STREAM_READABLE(peer
->curr
) < length
) {
2878 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
2879 length
, STREAM_READABLE(peer
->curr
));
2880 return bgp_attr_malformed(args
,
2881 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2885 /* ignore reserved */
2886 stream_getc(peer
->curr
);
2888 return bgp_attr_srv6_service(args
);
2891 /* Placeholder code for Unsupported TLV */
2894 if (STREAM_READABLE(peer
->curr
) < length
) {
2897 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2898 length
, STREAM_READABLE(peer
->curr
));
2899 return bgp_attr_malformed(
2900 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2904 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2906 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2909 stream_forward_getp(peer
->curr
, length
);
2912 return BGP_ATTR_PARSE_PROCEED
;
2915 /* Prefix SID attribute
2916 * draft-ietf-idr-bgp-prefix-sid-05
2918 enum bgp_attr_parse_ret
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2920 struct peer
*const peer
= args
->peer
;
2921 struct attr
*const attr
= args
->attr
;
2922 enum bgp_attr_parse_ret ret
;
2924 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2928 size_t headersz
= sizeof(type
) + sizeof(length
);
2929 size_t psid_parsed_length
= 0;
2931 while (STREAM_READABLE(peer
->curr
) > 0
2932 && psid_parsed_length
< args
->length
) {
2934 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2937 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2938 headersz
, STREAM_READABLE(peer
->curr
));
2939 return bgp_attr_malformed(
2940 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2944 type
= stream_getc(peer
->curr
);
2945 length
= stream_getw(peer
->curr
);
2947 if (STREAM_READABLE(peer
->curr
) < length
) {
2950 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2951 length
, STREAM_READABLE(peer
->curr
));
2952 return bgp_attr_malformed(args
,
2953 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2957 ret
= bgp_attr_psid_sub(type
, length
, args
);
2959 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2962 psid_parsed_length
+= length
+ headersz
;
2964 if (psid_parsed_length
> args
->length
) {
2967 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2968 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2969 return bgp_attr_malformed(
2970 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2975 return BGP_ATTR_PARSE_PROCEED
;
2978 /* PMSI tunnel attribute (RFC 6514)
2979 * Basic validation checks done here.
2981 static enum bgp_attr_parse_ret
2982 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2984 struct peer
*const peer
= args
->peer
;
2985 struct attr
*const attr
= args
->attr
;
2986 const bgp_size_t length
= args
->length
;
2988 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2990 /* Verify that the receiver is expecting "ingress replication" as we
2991 * can only support that.
2993 if (length
< attr_parse_len
) {
2994 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2996 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2999 stream_getc(peer
->curr
); /* Flags */
3000 tnl_type
= stream_getc(peer
->curr
);
3001 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3002 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3003 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3004 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3007 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3009 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3010 "Bad PMSI tunnel attribute length %d for IR",
3012 return bgp_attr_malformed(
3013 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3018 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3019 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3020 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3022 /* Forward read pointer of input stream. */
3023 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3025 return BGP_ATTR_PARSE_PROCEED
;
3028 /* BGP unknown attribute treatment. */
3029 static enum bgp_attr_parse_ret
3030 bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3032 bgp_size_t total
= args
->total
;
3033 struct transit
*transit
;
3034 struct peer
*const peer
= args
->peer
;
3035 struct attr
*const attr
= args
->attr
;
3036 uint8_t *const startp
= args
->startp
;
3037 const uint8_t type
= args
->type
;
3038 const uint8_t flag
= args
->flags
;
3039 const bgp_size_t length
= args
->length
;
3041 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3043 "%s Unknown attribute is received (type %d, length %d)",
3044 peer
->host
, type
, length
);
3046 /* Forward read pointer of input stream. */
3047 stream_forward_getp(peer
->curr
, length
);
3049 /* If any of the mandatory well-known attributes are not recognized,
3050 then the Error Subcode is set to Unrecognized Well-known
3051 Attribute. The Data field contains the unrecognized attribute
3052 (type, length and value). */
3053 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3054 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3058 /* Unrecognized non-transitive optional attributes must be quietly
3059 ignored and not passed along to other BGP peers. */
3060 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3061 return BGP_ATTR_PARSE_PROCEED
;
3063 /* If a path with recognized transitive optional attribute is
3064 accepted and passed along to other BGP peers and the Partial bit
3065 in the Attribute Flags octet is set to 1 by some previous AS, it
3066 is not set back to 0 by the current AS. */
3067 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3069 /* Store transitive attribute to the end of attr->transit. */
3070 transit
= bgp_attr_get_transit(attr
);
3072 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3074 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3075 transit
->length
+ total
);
3077 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3078 transit
->length
+= total
;
3079 bgp_attr_set_transit(attr
, transit
);
3081 return BGP_ATTR_PARSE_PROCEED
;
3084 /* Well-known attribute check. */
3085 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3089 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3091 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3092 return BGP_ATTR_PARSE_PROCEED
;
3094 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3095 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3096 are present, it should. Check for any other attribute being present
3099 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3100 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3101 return BGP_ATTR_PARSE_PROCEED
;
3103 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3104 type
= BGP_ATTR_ORIGIN
;
3106 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3107 type
= BGP_ATTR_AS_PATH
;
3109 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3111 * NLRI is empty. We can't easily check NLRI empty here though.
3113 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3114 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3115 type
= BGP_ATTR_NEXT_HOP
;
3117 if (peer
->sort
== BGP_PEER_IBGP
3118 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3119 type
= BGP_ATTR_LOCAL_PREF
;
3121 /* If any of the well-known mandatory attributes are not present
3122 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3125 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3126 "%s Missing well-known attribute %s.", peer
->host
,
3127 lookup_msg(attr_str
, type
, NULL
));
3128 return BGP_ATTR_PARSE_WITHDRAW
;
3130 return BGP_ATTR_PARSE_PROCEED
;
3133 /* Read attribute of update packet. This function is called from
3134 bgp_update_receive() in bgp_packet.c. */
3135 enum bgp_attr_parse_ret
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3137 struct bgp_nlri
*mp_update
,
3138 struct bgp_nlri
*mp_withdraw
)
3140 enum bgp_attr_parse_ret ret
;
3144 uint8_t *startp
, *endp
;
3146 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3147 /* we need the as4_path only until we have synthesized the as_path with
3149 /* same goes for as4_aggregator */
3150 struct aspath
*as4_path
= NULL
;
3151 as_t as4_aggregator
= 0;
3152 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3153 struct transit
*transit
;
3155 /* Initialize bitmap. */
3156 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3158 /* End pointer of BGP attribute. */
3159 endp
= BGP_INPUT_PNT(peer
) + size
;
3161 /* Get attributes to the end of attribute length. */
3162 while (BGP_INPUT_PNT(peer
) < endp
) {
3163 /* Check remaining length check.*/
3164 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3165 /* XXX warning: long int format, int arg (arg 5) */
3167 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3168 "%s: error BGP attribute length %lu is smaller than min len",
3170 (unsigned long)(endp
3171 - stream_pnt(BGP_INPUT(peer
))));
3173 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3174 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3175 ret
= BGP_ATTR_PARSE_ERROR
;
3179 /* Fetch attribute flag and type. */
3180 startp
= BGP_INPUT_PNT(peer
);
3181 /* "The lower-order four bits of the Attribute Flags octet are
3182 unused. They MUST be zero when sent and MUST be ignored when
3184 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3185 type
= stream_getc(BGP_INPUT(peer
));
3187 /* Check whether Extended-Length applies and is in bounds */
3188 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3189 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3191 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3192 "%s: Extended length set, but just %lu bytes of attr header",
3194 (unsigned long)(endp
3195 - stream_pnt(BGP_INPUT(peer
))));
3197 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3198 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3199 ret
= BGP_ATTR_PARSE_ERROR
;
3203 /* Check extended attribue length bit. */
3204 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3205 length
= stream_getw(BGP_INPUT(peer
));
3207 length
= stream_getc(BGP_INPUT(peer
));
3209 /* If any attribute appears more than once in the UPDATE
3210 message, then the Error Subcode is set to Malformed Attribute
3213 if (CHECK_BITMAP(seen
, type
)) {
3215 EC_BGP_ATTRIBUTE_REPEATED
,
3216 "%s: error BGP attribute type %d appears twice in a message",
3219 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3220 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3221 ret
= BGP_ATTR_PARSE_ERROR
;
3225 /* Set type to bitmap to check duplicate attribute. `type' is
3226 unsigned char so it never overflow bitmap range. */
3228 SET_BITMAP(seen
, type
);
3230 /* Overflow check. */
3231 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3233 if (attr_endp
> endp
) {
3235 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3236 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3237 peer
->host
, type
, length
, size
, attr_endp
,
3241 * If any recognized attribute has an Attribute
3242 * Length that conflicts with the expected length
3243 * (based on the attribute type code), then the
3244 * Error Subcode MUST be set to Attribute Length
3245 * Error. The Data field MUST contain the erroneous
3246 * attribute (type, length, and value).
3248 * We do not currently have a good way to determine the
3249 * length of the attribute independent of the length
3250 * received in the message. Instead we send the
3251 * minimum between the amount of data we have and the
3252 * amount specified by the attribute length field.
3254 * Instead of directly passing in the packet buffer and
3255 * offset we use the stream_get* functions to read into
3256 * a stack buffer, since they perform bounds checking
3257 * and we are working with untrusted data.
3259 unsigned char ndata
[peer
->max_packet_size
];
3260 memset(ndata
, 0x00, sizeof(ndata
));
3262 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3263 /* Rewind to end of flag field */
3264 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3266 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3268 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3270 size_t atl
= attr_endp
- startp
;
3271 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3272 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3274 bgp_notify_send_with_data(
3275 peer
, BGP_NOTIFY_UPDATE_ERR
,
3276 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3279 ret
= BGP_ATTR_PARSE_ERROR
;
3283 struct bgp_attr_parser_args attr_args
= {
3290 .total
= attr_endp
- startp
,
3294 /* If any recognized attribute has Attribute Flags that conflict
3295 with the Attribute Type Code, then the Error Subcode is set
3297 Attribute Flags Error. The Data field contains the erroneous
3298 attribute (type, length and value). */
3299 if (bgp_attr_flag_invalid(&attr_args
)) {
3300 ret
= bgp_attr_malformed(
3301 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3303 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3308 /* OK check attribute and store it's value. */
3310 case BGP_ATTR_ORIGIN
:
3311 ret
= bgp_attr_origin(&attr_args
);
3313 case BGP_ATTR_AS_PATH
:
3314 ret
= bgp_attr_aspath(&attr_args
);
3316 case BGP_ATTR_AS4_PATH
:
3317 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3319 case BGP_ATTR_NEXT_HOP
:
3320 ret
= bgp_attr_nexthop(&attr_args
);
3322 case BGP_ATTR_MULTI_EXIT_DISC
:
3323 ret
= bgp_attr_med(&attr_args
);
3325 case BGP_ATTR_LOCAL_PREF
:
3326 ret
= bgp_attr_local_pref(&attr_args
);
3328 case BGP_ATTR_ATOMIC_AGGREGATE
:
3329 ret
= bgp_attr_atomic(&attr_args
);
3331 case BGP_ATTR_AGGREGATOR
:
3332 ret
= bgp_attr_aggregator(&attr_args
);
3334 case BGP_ATTR_AS4_AGGREGATOR
:
3335 ret
= bgp_attr_as4_aggregator(&attr_args
,
3337 &as4_aggregator_addr
);
3339 case BGP_ATTR_COMMUNITIES
:
3340 ret
= bgp_attr_community(&attr_args
);
3342 case BGP_ATTR_LARGE_COMMUNITIES
:
3343 ret
= bgp_attr_large_community(&attr_args
);
3345 case BGP_ATTR_ORIGINATOR_ID
:
3346 ret
= bgp_attr_originator_id(&attr_args
);
3348 case BGP_ATTR_CLUSTER_LIST
:
3349 ret
= bgp_attr_cluster_list(&attr_args
);
3351 case BGP_ATTR_MP_REACH_NLRI
:
3352 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3354 case BGP_ATTR_MP_UNREACH_NLRI
:
3355 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3357 case BGP_ATTR_EXT_COMMUNITIES
:
3358 ret
= bgp_attr_ext_communities(&attr_args
);
3360 #ifdef ENABLE_BGP_VNC_ATTR
3363 case BGP_ATTR_ENCAP
:
3364 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3367 case BGP_ATTR_PREFIX_SID
:
3368 ret
= bgp_attr_prefix_sid(&attr_args
);
3370 case BGP_ATTR_PMSI_TUNNEL
:
3371 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3373 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3374 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3377 ret
= bgp_attr_unknown(&attr_args
);
3381 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3382 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3383 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3384 ret
= BGP_ATTR_PARSE_ERROR
;
3388 if (ret
== BGP_ATTR_PARSE_EOR
) {
3392 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3393 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3394 "%s: Attribute %s, parse error", peer
->host
,
3395 lookup_msg(attr_str
, type
, NULL
));
3398 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3400 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3401 "%s: Attribute %s, parse error - treating as withdrawal",
3402 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3406 /* Check the fetched length. */
3407 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3408 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3409 "%s: BGP attribute %s, fetch error",
3410 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3411 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3412 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3413 ret
= BGP_ATTR_PARSE_ERROR
;
3419 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3420 * About Prefix-SID path attribute,
3421 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3422 * may only appear in a BGP Prefix-SID attribute attached to
3423 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3424 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3426 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3427 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3429 /* Check final read pointer is same as end pointer. */
3430 if (BGP_INPUT_PNT(peer
) != endp
) {
3431 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3432 "%s: BGP attribute %s, length mismatch", peer
->host
,
3433 lookup_msg(attr_str
, type
, NULL
));
3434 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3435 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3437 ret
= BGP_ATTR_PARSE_ERROR
;
3442 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3443 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3444 * This is implemented below and will result in a NOTIFICATION. If the
3445 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3446 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3447 * message SHOULD NOT be sent. This is implemented elsewhere.
3449 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3450 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3451 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3452 * speaker that receives the message SHOULD ignore this attribute.
3454 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3455 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3456 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3457 ret
= BGP_ATTR_PARSE_ERROR
;
3462 /* Check all mandatory well-known attributes are present */
3463 ret
= bgp_attr_check(peer
, attr
);
3468 * At this place we can see whether we got AS4_PATH and/or
3469 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3470 * We can not do this before we've read all attributes because
3471 * the as4 handling does not say whether AS4_PATH has to be sent
3472 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3473 * in relationship to AGGREGATOR.
3474 * So, to be defensive, we are not relying on any order and read
3475 * all attributes first, including these 32bit ones, and now,
3476 * afterwards, we look what and if something is to be done for as4.
3478 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3481 /* actually... this doesn't ever return failure currently, but
3482 * better safe than sorry */
3483 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3484 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3485 &as4_aggregator_addr
)) {
3486 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3487 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3488 ret
= BGP_ATTR_PARSE_ERROR
;
3493 * Finally do the checks on the aspath we did not do yet
3494 * because we waited for a potentially synthesized aspath.
3496 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3497 ret
= bgp_attr_aspath_check(peer
, attr
);
3498 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3502 ret
= BGP_ATTR_PARSE_PROCEED
;
3506 * At this stage, we have done all fiddling with as4, and the
3507 * resulting info is in attr->aggregator resp. attr->aspath so
3508 * we can chuck as4_aggregator and as4_path alltogether in order
3512 * unintern - it is in the hash
3513 * The flag that we got this is still there, but that
3514 * does not do any trouble
3516 aspath_unintern(&as4_path
);
3518 transit
= bgp_attr_get_transit(attr
);
3519 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3520 /* Finally intern unknown attribute. */
3522 bgp_attr_set_transit(attr
, transit_intern(transit
));
3523 if (attr
->encap_subtlvs
)
3524 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3526 #ifdef ENABLE_BGP_VNC
3527 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3528 bgp_attr_get_vnc_subtlvs(attr
);
3531 bgp_attr_set_vnc_subtlvs(
3533 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3537 transit_free(transit
);
3538 bgp_attr_set_transit(attr
, NULL
);
3541 bgp_attr_flush_encap(attr
);
3545 transit
= bgp_attr_get_transit(attr
);
3547 assert(transit
->refcnt
> 0);
3548 if (attr
->encap_subtlvs
)
3549 assert(attr
->encap_subtlvs
->refcnt
> 0);
3550 #ifdef ENABLE_BGP_VNC
3551 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3552 bgp_attr_get_vnc_subtlvs(attr
);
3555 assert(vnc_subtlvs
->refcnt
> 0);
3562 * Extract the tunnel type from extended community
3564 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3565 bgp_encap_types
*tunnel_type
)
3567 struct ecommunity
*ecom
;
3573 ecom
= bgp_attr_get_ecommunity(attr
);
3574 if (!ecom
|| !ecom
->size
)
3577 for (i
= 0; i
< ecom
->size
; i
++) {
3579 uint8_t type
, sub_type
;
3581 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3584 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3585 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3587 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3594 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3595 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3599 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
3600 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
3603 /* Set extended bit always to encode the attribute length as 2 bytes */
3604 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3605 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3606 sizep
= stream_get_endp(s
);
3607 stream_putw(s
, 0); /* Marker: Attribute length. */
3610 /* Convert AFI, SAFI to values for packet. */
3611 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3613 stream_putw(s
, pkt_afi
); /* AFI */
3614 stream_putc(s
, pkt_safi
); /* SAFI */
3618 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3619 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3620 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3621 else if (safi
== SAFI_FLOWSPEC
)
3624 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3627 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3632 case SAFI_MULTICAST
:
3633 case SAFI_LABELED_UNICAST
:
3635 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3639 stream_putl(s
, 0); /* RD = 0, per RFC */
3641 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3646 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3649 if (attr
->mp_nexthop_len
== 0)
3650 stream_putc(s
, 0); /* no nexthop for flowspec */
3652 stream_putc(s
, attr
->mp_nexthop_len
);
3653 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3662 case SAFI_MULTICAST
:
3663 case SAFI_LABELED_UNICAST
:
3665 if (attr
->mp_nexthop_len
3666 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3668 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3669 stream_put(s
, &attr
->mp_nexthop_global
,
3671 stream_put(s
, &attr
->mp_nexthop_local
,
3674 stream_putc(s
, IPV6_MAX_BYTELEN
);
3675 stream_put(s
, &attr
->mp_nexthop_global
,
3679 case SAFI_MPLS_VPN
: {
3680 if (attr
->mp_nexthop_len
3681 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3683 stream_putl(s
, 0); /* RD = 0, per RFC */
3685 stream_put(s
, &attr
->mp_nexthop_global
,
3687 } else if (attr
->mp_nexthop_len
3688 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3690 stream_putl(s
, 0); /* RD = 0, per RFC */
3692 stream_put(s
, &attr
->mp_nexthop_global
,
3694 stream_putl(s
, 0); /* RD = 0, per RFC */
3696 stream_put(s
, &attr
->mp_nexthop_local
,
3701 stream_putc(s
, IPV6_MAX_BYTELEN
);
3702 stream_put(s
, &attr
->mp_nexthop_global
,
3706 stream_putc(s
, 0); /* no nexthop for flowspec */
3712 if (safi
!= SAFI_FLOWSPEC
)
3714 EC_BGP_ATTR_NH_SEND_LEN
,
3715 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3716 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3725 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3726 const struct prefix
*p
,
3727 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3728 uint32_t num_labels
, bool addpath_capable
,
3729 uint32_t addpath_tx_id
, struct attr
*attr
)
3731 if (safi
== SAFI_MPLS_VPN
) {
3732 if (addpath_capable
)
3733 stream_putl(s
, addpath_tx_id
);
3734 /* Label, RD, Prefix write. */
3735 stream_putc(s
, p
->prefixlen
+ 88);
3736 stream_put(s
, label
, BGP_LABEL_BYTES
);
3737 stream_put(s
, prd
->val
, 8);
3738 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3739 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3740 /* EVPN prefix - contents depend on type */
3741 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3742 addpath_capable
, addpath_tx_id
);
3743 } else if (safi
== SAFI_LABELED_UNICAST
) {
3744 /* Prefix write with label. */
3745 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3747 } else if (safi
== SAFI_FLOWSPEC
) {
3748 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3749 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3750 p
->u
.prefix_flowspec
.prefixlen
);
3752 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
3755 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3756 const struct prefix
*p
)
3758 int size
= PSIZE(p
->prefixlen
);
3759 if (safi
== SAFI_MPLS_VPN
)
3761 else if (safi
== SAFI_LABELED_UNICAST
)
3762 size
+= BGP_LABEL_BYTES
;
3763 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3764 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3770 * Encodes the tunnel encapsulation attribute,
3771 * and with ENABLE_BGP_VNC the VNC attribute which uses
3772 * almost the same TLV format
3774 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3775 struct stream
*s
, struct attr
*attr
,
3778 unsigned int attrlenfield
= 0;
3779 unsigned int attrhdrlen
= 0;
3780 struct bgp_attr_encap_subtlv
*subtlvs
;
3781 struct bgp_attr_encap_subtlv
*st
;
3782 const char *attrname
;
3784 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3785 && (!attr
->encap_tunneltype
3786 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3790 case BGP_ATTR_ENCAP
:
3791 attrname
= "Tunnel Encap";
3792 subtlvs
= attr
->encap_subtlvs
;
3793 if (subtlvs
== NULL
) /* nothing to do */
3796 * The tunnel encap attr has an "outer" tlv.
3798 * L = total length of subtlvs,
3799 * V = concatenated subtlvs.
3801 attrlenfield
= 2 + 2; /* T + L */
3802 attrhdrlen
= 1 + 1; /* subTLV T + L */
3805 #ifdef ENABLE_BGP_VNC_ATTR
3808 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3809 if (subtlvs
== NULL
) /* nothing to do */
3811 attrlenfield
= 0; /* no outer T + L */
3812 attrhdrlen
= 2 + 2; /* subTLV T + L */
3820 /* compute attr length */
3821 for (st
= subtlvs
; st
; st
= st
->next
) {
3822 attrlenfield
+= (attrhdrlen
+ st
->length
);
3825 if (attrlenfield
> 0xffff) {
3826 zlog_info("%s attribute is too long (length=%d), can't send it",
3827 attrname
, attrlenfield
);
3831 if (attrlenfield
> 0xff) {
3832 /* 2-octet length field */
3834 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3835 | BGP_ATTR_FLAG_EXTLEN
);
3836 stream_putc(s
, attrtype
);
3837 stream_putw(s
, attrlenfield
& 0xffff);
3839 /* 1-octet length field */
3840 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3841 stream_putc(s
, attrtype
);
3842 stream_putc(s
, attrlenfield
& 0xff);
3845 if (attrtype
== BGP_ATTR_ENCAP
) {
3846 /* write outer T+L */
3847 stream_putw(s
, attr
->encap_tunneltype
);
3848 stream_putw(s
, attrlenfield
- 4);
3851 /* write each sub-tlv */
3852 for (st
= subtlvs
; st
; st
= st
->next
) {
3853 if (attrtype
== BGP_ATTR_ENCAP
) {
3854 stream_putc(s
, st
->type
);
3855 stream_putc(s
, st
->length
);
3856 #ifdef ENABLE_BGP_VNC
3858 stream_putw(s
, st
->type
);
3859 stream_putw(s
, st
->length
);
3862 stream_put(s
, st
->value
, st
->length
);
3866 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3868 /* Set MP attribute length. Don't count the (2) bytes used to encode
3870 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3873 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3875 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3876 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3877 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3878 PEER_FLAG_REMOVE_PRIVATE_AS
)
3879 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3880 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3881 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3882 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3883 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3884 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3889 /* Make attribute packet. */
3890 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3891 struct stream
*s
, struct attr
*attr
,
3892 struct bpacket_attr_vec_arr
*vecarr
,
3893 struct prefix
*p
, afi_t afi
, safi_t safi
,
3894 struct peer
*from
, struct prefix_rd
*prd
,
3895 mpls_label_t
*label
, uint32_t num_labels
,
3896 bool addpath_capable
, uint32_t addpath_tx_id
)
3899 size_t aspath_sizep
;
3900 struct aspath
*aspath
;
3901 int send_as4_path
= 0;
3902 int send_as4_aggregator
= 0;
3903 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
3904 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
3909 /* Remember current pointer. */
3910 cp
= stream_get_endp(s
);
3913 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3914 && !peer_cap_enhe(peer
, afi
, safi
))) {
3915 size_t mpattrlen_pos
= 0;
3917 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3919 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3920 num_labels
, addpath_capable
,
3921 addpath_tx_id
, attr
);
3922 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3925 /* Origin attribute. */
3926 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3927 stream_putc(s
, BGP_ATTR_ORIGIN
);
3929 stream_putc(s
, attr
->origin
);
3931 /* AS path attribute. */
3933 /* If remote-peer is EBGP */
3934 if (peer
->sort
== BGP_PEER_EBGP
3935 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3936 PEER_FLAG_AS_PATH_UNCHANGED
)
3937 || attr
->aspath
->segments
== NULL
)
3938 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3939 PEER_FLAG_RSERVER_CLIENT
))) {
3940 aspath
= aspath_dup(attr
->aspath
);
3942 /* Even though we may not be configured for confederations we
3944 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3945 aspath
= aspath_delete_confed_seq(aspath
);
3947 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3948 /* Stuff our path CONFED_ID on the front */
3949 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3951 if (peer
->change_local_as
) {
3952 /* If replace-as is specified, we only use the
3953 change_local_as when
3954 advertising routes. */
3955 if (!CHECK_FLAG(peer
->flags
,
3956 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3957 if (bgp_append_local_as(peer
, afi
,
3959 aspath
= aspath_add_seq(
3960 aspath
, peer
->local_as
);
3961 aspath
= aspath_add_seq(aspath
,
3962 peer
->change_local_as
);
3964 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3967 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3968 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3970 aspath
= aspath_dup(attr
->aspath
);
3971 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3973 aspath
= attr
->aspath
;
3975 /* If peer is not AS4 capable, then:
3976 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3977 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3979 * types are in it (i.e. exclude them if they are there)
3980 * AND do this only if there is at least one asnum > 65535 in the
3982 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3984 * all ASnums > 65535 to BGP_AS_TRANS
3987 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3988 stream_putc(s
, BGP_ATTR_AS_PATH
);
3989 aspath_sizep
= stream_get_endp(s
);
3991 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3993 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3996 if (!use32bit
&& aspath_has_as4(aspath
))
3998 1; /* we'll do this later, at the correct place */
4000 /* Nexthop attribute. */
4001 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4002 && !peer_cap_enhe(peer
, afi
, safi
)) {
4003 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4005 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4006 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4007 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4008 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4011 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4012 } else if (peer_cap_enhe(from
, afi
, safi
)
4013 || (nh_afi
== AFI_IP6
)) {
4015 * Likely this is the case when an IPv4 prefix was
4016 * received with Extended Next-hop capability in this
4017 * or another vrf and is now being advertised to
4018 * non-ENHE peers. Since peer_cap_enhe only checks
4019 * peers in this vrf, also check the nh_afi to catch
4020 * the case where the originator was in another vrf.
4021 * Setting the mandatory (ipv4) next-hop attribute here
4022 * to enable implicit next-hop self with correct A-F
4023 * (ipv4 address family).
4025 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4026 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4027 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4030 stream_put_ipv4(s
, 0);
4034 /* MED attribute. */
4035 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4036 || bgp
->maxmed_active
) {
4037 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4038 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4040 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4044 /* Local preference. */
4045 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4046 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4047 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4049 stream_putl(s
, attr
->local_pref
);
4052 /* Atomic aggregate. */
4053 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4054 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4055 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4060 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4061 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4062 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4063 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4066 /* AS4 capable peer */
4068 stream_putl(s
, attr
->aggregator_as
);
4070 /* 2-byte AS peer */
4073 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4075 if (attr
->aggregator_as
> UINT16_MAX
) {
4076 stream_putw(s
, BGP_AS_TRANS
);
4078 /* we have to send AS4_AGGREGATOR, too.
4079 * we'll do that later in order to send
4080 * attributes in ascending
4083 send_as4_aggregator
= 1;
4085 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4087 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4090 /* Community attribute. */
4091 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4092 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4093 struct community
*comm
= NULL
;
4095 comm
= bgp_attr_get_community(attr
);
4096 if (comm
->size
* 4 > 255) {
4098 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4099 | BGP_ATTR_FLAG_EXTLEN
);
4100 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4101 stream_putw(s
, comm
->size
* 4);
4104 BGP_ATTR_FLAG_OPTIONAL
4105 | BGP_ATTR_FLAG_TRANS
);
4106 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4107 stream_putc(s
, comm
->size
* 4);
4109 stream_put(s
, comm
->val
, comm
->size
* 4);
4113 * Large Community attribute.
4115 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4116 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4117 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4118 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4120 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4121 | BGP_ATTR_FLAG_EXTLEN
);
4122 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4124 lcom_length(bgp_attr_get_lcommunity(attr
)));
4127 BGP_ATTR_FLAG_OPTIONAL
4128 | BGP_ATTR_FLAG_TRANS
);
4129 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4131 lcom_length(bgp_attr_get_lcommunity(attr
)));
4133 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4134 lcom_length(bgp_attr_get_lcommunity(attr
)));
4137 /* Route Reflector. */
4138 if (peer
->sort
== BGP_PEER_IBGP
&& from
4139 && from
->sort
== BGP_PEER_IBGP
) {
4140 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4142 /* Originator ID. */
4143 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4144 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4147 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4148 stream_put_in_addr(s
, &attr
->originator_id
);
4150 stream_put_in_addr(s
, &from
->remote_id
);
4153 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4154 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4157 stream_putc(s
, cluster
->length
+ 4);
4158 /* If this peer configuration's parent BGP has
4160 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4161 stream_put_in_addr(s
, &bgp
->cluster_id
);
4163 stream_put_in_addr(s
, &bgp
->router_id
);
4164 stream_put(s
, cluster
->list
, cluster
->length
);
4167 /* If this peer configuration's parent BGP has
4169 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4170 stream_put_in_addr(s
, &bgp
->cluster_id
);
4172 stream_put_in_addr(s
, &bgp
->router_id
);
4176 /* Extended Communities attribute. */
4177 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4178 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4179 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4180 bool transparent
= CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4181 PEER_FLAG_RSERVER_CLIENT
) &&
4183 CHECK_FLAG(from
->af_flags
[afi
][safi
],
4184 PEER_FLAG_RSERVER_CLIENT
);
4186 if (peer
->sort
== BGP_PEER_IBGP
||
4187 peer
->sort
== BGP_PEER_CONFED
|| transparent
) {
4188 if (ecomm
->size
* 8 > 255) {
4190 BGP_ATTR_FLAG_OPTIONAL
4191 | BGP_ATTR_FLAG_TRANS
4192 | BGP_ATTR_FLAG_EXTLEN
);
4193 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4194 stream_putw(s
, ecomm
->size
* 8);
4197 BGP_ATTR_FLAG_OPTIONAL
4198 | BGP_ATTR_FLAG_TRANS
);
4199 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4200 stream_putc(s
, ecomm
->size
* 8);
4202 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4206 int ecom_tr_size
= 0;
4209 for (i
= 0; i
< ecomm
->size
; i
++) {
4210 pnt
= ecomm
->val
+ (i
* 8);
4213 if (CHECK_FLAG(tbit
,
4214 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4221 if (ecom_tr_size
* 8 > 255) {
4224 BGP_ATTR_FLAG_OPTIONAL
4225 | BGP_ATTR_FLAG_TRANS
4226 | BGP_ATTR_FLAG_EXTLEN
);
4228 BGP_ATTR_EXT_COMMUNITIES
);
4229 stream_putw(s
, ecom_tr_size
* 8);
4233 BGP_ATTR_FLAG_OPTIONAL
4234 | BGP_ATTR_FLAG_TRANS
);
4236 BGP_ATTR_EXT_COMMUNITIES
);
4237 stream_putc(s
, ecom_tr_size
* 8);
4240 for (i
= 0; i
< ecomm
->size
; i
++) {
4241 pnt
= ecomm
->val
+ (i
* 8);
4246 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4249 stream_put(s
, pnt
, 8);
4255 /* Label index attribute. */
4256 if (safi
== SAFI_LABELED_UNICAST
) {
4257 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4258 uint32_t label_index
;
4260 label_index
= attr
->label_index
;
4262 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4264 BGP_ATTR_FLAG_OPTIONAL
4265 | BGP_ATTR_FLAG_TRANS
);
4266 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4268 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4270 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4271 stream_putc(s
, 0); // reserved
4272 stream_putw(s
, 0); // flags
4273 stream_putl(s
, label_index
);
4278 /* SRv6 Service Information Attribute. */
4279 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4280 if (attr
->srv6_l3vpn
) {
4281 uint8_t subtlv_len
=
4282 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4284 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4285 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4286 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4287 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4288 | BGP_ATTR_FLAG_TRANS
);
4289 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4290 stream_putc(s
, attr_len
);
4291 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4292 stream_putw(s
, tlv_len
);
4293 stream_putc(s
, 0); /* reserved */
4294 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4295 stream_putw(s
, subtlv_len
);
4296 stream_putc(s
, 0); /* reserved */
4297 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4298 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4299 stream_putc(s
, 0); /* sid_flags */
4300 stream_putw(s
, 0xffff); /* endpoint */
4301 stream_putc(s
, 0); /* reserved */
4304 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4307 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4308 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4309 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4310 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4311 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4312 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4313 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4314 } else if (attr
->srv6_vpn
) {
4315 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4316 | BGP_ATTR_FLAG_TRANS
);
4317 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4318 stream_putc(s
, 22); /* tlv len */
4319 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4320 stream_putw(s
, 0x13); /* tlv len */
4321 stream_putc(s
, 0x00); /* reserved */
4322 stream_putc(s
, 0x01); /* sid_type */
4323 stream_putc(s
, 0x00); /* sif_flags */
4324 stream_put(s
, &attr
->srv6_vpn
->sid
,
4325 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4329 if (send_as4_path
) {
4330 /* If the peer is NOT As4 capable, AND */
4331 /* there are ASnums > 65535 in path THEN
4332 * give out AS4_PATH */
4334 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4336 * Hm, I wonder... confederation things *should* only be at
4337 * the beginning of an aspath, right? Then we should use
4338 * aspath_delete_confed_seq for this, because it is already
4340 * Folks, talk to me: what is reasonable here!?
4342 aspath
= aspath_delete_confed_seq(aspath
);
4345 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4346 | BGP_ATTR_FLAG_EXTLEN
);
4347 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4348 aspath_sizep
= stream_get_endp(s
);
4350 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4353 if (aspath
!= attr
->aspath
)
4354 aspath_free(aspath
);
4356 if (send_as4_aggregator
) {
4357 /* send AS4_AGGREGATOR, at this place */
4358 /* this section of code moved here in order to ensure the
4360 * *ascending* order of attributes
4362 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4363 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4365 stream_putl(s
, attr
->aggregator_as
);
4366 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4369 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4370 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4371 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4372 /* Tunnel Encap attribute */
4373 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4375 #ifdef ENABLE_BGP_VNC_ATTR
4377 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4382 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4383 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4384 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4385 stream_putc(s
, 9); // Length
4386 stream_putc(s
, 0); // Flags
4387 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4388 stream_put(s
, &(attr
->label
),
4389 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4390 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4391 // Unicast tunnel endpoint IP address
4394 /* Unknown transit attribute. */
4395 struct transit
*transit
= bgp_attr_get_transit(attr
);
4398 stream_put(s
, transit
->val
, transit
->length
);
4400 /* Return total size of attribute. */
4401 return stream_get_endp(s
) - cp
;
4404 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4406 unsigned long attrlen_pnt
;
4407 iana_afi_t pkt_afi
= IANA_AFI_IPV4
;
4408 iana_safi_t pkt_safi
= IANA_SAFI_UNICAST
;
4410 /* Set extended bit always to encode the attribute length as 2 bytes */
4411 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4412 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4414 attrlen_pnt
= stream_get_endp(s
);
4415 stream_putw(s
, 0); /* Length of this attribute. */
4417 /* Convert AFI, SAFI to values for packet. */
4418 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4420 stream_putw(s
, pkt_afi
);
4421 stream_putc(s
, pkt_safi
);
4426 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4427 afi_t afi
, safi_t safi
,
4428 const struct prefix_rd
*prd
,
4429 mpls_label_t
*label
, uint32_t num_labels
,
4430 bool addpath_capable
, uint32_t addpath_tx_id
,
4433 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4435 if (safi
== SAFI_LABELED_UNICAST
) {
4436 label
= (mpls_label_t
*)wlabel
;
4440 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4441 addpath_capable
, addpath_tx_id
, attr
);
4444 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4446 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4449 /* Initialization of attribute. */
4450 void bgp_attr_init(void)
4463 void bgp_attr_finish(void)
4468 ecommunity_finish();
4469 lcommunity_finish();
4476 /* Make attribute packet. */
4477 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4478 const struct prefix
*prefix
)
4483 struct aspath
*aspath
;
4484 bool addpath_capable
= false;
4485 uint32_t addpath_tx_id
= 0;
4487 /* Remember current pointer. */
4488 cp
= stream_get_endp(s
);
4490 /* Place holder of length. */
4493 /* Origin attribute. */
4494 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4495 stream_putc(s
, BGP_ATTR_ORIGIN
);
4497 stream_putc(s
, attr
->origin
);
4499 aspath
= attr
->aspath
;
4501 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4502 stream_putc(s
, BGP_ATTR_AS_PATH
);
4503 aspath_lenp
= stream_get_endp(s
);
4506 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4508 /* Nexthop attribute. */
4509 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4510 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4511 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4512 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4514 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4517 /* MED attribute. */
4518 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4519 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4520 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4522 stream_putl(s
, attr
->med
);
4525 /* Local preference. */
4526 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4527 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4528 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4530 stream_putl(s
, attr
->local_pref
);
4533 /* Atomic aggregate. */
4534 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4535 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4536 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4541 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4542 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4543 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4545 stream_putl(s
, attr
->aggregator_as
);
4546 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4549 /* Community attribute. */
4550 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4551 struct community
*comm
= NULL
;
4553 comm
= bgp_attr_get_community(attr
);
4554 if (comm
->size
* 4 > 255) {
4556 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4557 | BGP_ATTR_FLAG_EXTLEN
);
4558 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4559 stream_putw(s
, comm
->size
* 4);
4562 BGP_ATTR_FLAG_OPTIONAL
4563 | BGP_ATTR_FLAG_TRANS
);
4564 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4565 stream_putc(s
, comm
->size
* 4);
4567 stream_put(s
, comm
->val
, comm
->size
* 4);
4570 /* Large Community attribute. */
4571 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4572 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4574 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4575 | BGP_ATTR_FLAG_EXTLEN
);
4576 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4578 lcom_length(bgp_attr_get_lcommunity(attr
)));
4581 BGP_ATTR_FLAG_OPTIONAL
4582 | BGP_ATTR_FLAG_TRANS
);
4583 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4585 lcom_length(bgp_attr_get_lcommunity(attr
)));
4588 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4589 lcom_length(bgp_attr_get_lcommunity(attr
)));
4592 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4593 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4594 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4595 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4598 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4599 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4600 sizep
= stream_get_endp(s
);
4603 stream_putc(s
, 0); /* Marker: Attribute length. */
4604 stream_putw(s
, AFI_IP6
); /* AFI */
4605 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4608 stream_putc(s
, attr
->mp_nexthop_len
);
4609 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4610 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4611 stream_put(s
, &attr
->mp_nexthop_local
,
4618 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4621 /* Set MP attribute length. */
4622 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4626 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4627 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4629 BGP_ATTR_FLAG_OPTIONAL
4630 | BGP_ATTR_FLAG_TRANS
);
4631 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4633 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4634 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4635 stream_putc(s
, 0); // reserved
4636 stream_putw(s
, 0); // flags
4637 stream_putl(s
, attr
->label_index
);
4641 /* Return total size of attribute. */
4642 len
= stream_get_endp(s
) - cp
- 2;
4643 stream_putw_at(s
, cp
, len
);