1 /* BGP attributes management routines.
2 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_aspath.h"
41 #include "bgpd/bgp_community.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_errors.h"
44 #include "bgpd/bgp_label.h"
45 #include "bgpd/bgp_packet.h"
46 #include "bgpd/bgp_ecommunity.h"
47 #include "bgpd/bgp_lcommunity.h"
48 #include "bgpd/bgp_updgrp.h"
49 #include "bgpd/bgp_encap_types.h"
51 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
52 #include "bgp_encap_types.h"
53 #include "bgp_vnc_types.h"
56 #include "bgp_flowspec_private.h"
59 /* Attribute strings for logging. */
60 static const struct message attr_str
[] = {
61 {BGP_ATTR_ORIGIN
, "ORIGIN"},
62 {BGP_ATTR_AS_PATH
, "AS_PATH"},
63 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
64 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
65 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
66 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
67 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
68 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
69 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
70 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
71 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
72 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
73 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
74 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
75 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
76 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
77 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
78 {BGP_ATTR_ENCAP
, "ENCAP"},
79 #ifdef ENABLE_BGP_VNC_ATTR
80 {BGP_ATTR_VNC
, "VNC"},
82 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
83 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
84 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
87 static const struct message attr_flag_str
[] = {
88 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
89 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
90 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
91 /* bgp_attr_flags_diagnose() relies on this bit being last in
93 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
96 static struct hash
*cluster_hash
;
98 static void *cluster_hash_alloc(void *p
)
100 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
101 struct cluster_list
*cluster
;
103 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
104 cluster
->length
= val
->length
;
106 if (cluster
->length
) {
107 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
108 memcpy(cluster
->list
, val
->list
, val
->length
);
110 cluster
->list
= NULL
;
117 /* Cluster list related functions. */
118 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
120 struct cluster_list tmp
= {};
121 struct cluster_list
*cluster
;
124 tmp
.list
= length
== 0 ? NULL
: pnt
;
126 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
131 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
135 for (i
= 0; i
< cluster
->length
/ 4; i
++)
136 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
141 static unsigned int cluster_hash_key_make(const void *p
)
143 const struct cluster_list
*cluster
= p
;
145 return jhash(cluster
->list
, cluster
->length
, 0);
148 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
150 const struct cluster_list
*cluster1
= p1
;
151 const struct cluster_list
*cluster2
= p2
;
153 if (cluster1
->list
== cluster2
->list
)
156 if (!cluster1
->list
|| !cluster2
->list
)
159 if (cluster1
->length
!= cluster2
->length
)
162 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
165 static void cluster_free(struct cluster_list
*cluster
)
167 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
168 XFREE(MTYPE_CLUSTER
, cluster
);
171 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
173 struct cluster_list
*find
;
175 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
181 static void cluster_unintern(struct cluster_list
**cluster
)
183 if ((*cluster
)->refcnt
)
184 (*cluster
)->refcnt
--;
186 if ((*cluster
)->refcnt
== 0) {
187 void *p
= hash_release(cluster_hash
, *cluster
);
188 assert(p
== *cluster
);
189 cluster_free(*cluster
);
194 static void cluster_init(void)
196 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
200 static void cluster_finish(void)
202 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
203 hash_free(cluster_hash
);
207 static struct hash
*encap_hash
= NULL
;
208 #ifdef ENABLE_BGP_VNC
209 static struct hash
*vnc_hash
= NULL
;
211 static struct hash
*srv6_l3vpn_hash
;
212 static struct hash
*srv6_vpn_hash
;
214 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
216 struct bgp_attr_encap_subtlv
*new;
217 struct bgp_attr_encap_subtlv
*tail
;
218 struct bgp_attr_encap_subtlv
*p
;
220 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
221 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
223 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
226 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
229 memcpy(tail
, p
, size
);
236 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
238 struct bgp_attr_encap_subtlv
*next
;
242 XFREE(MTYPE_ENCAP_TLV
, p
);
247 void bgp_attr_flush_encap(struct attr
*attr
)
252 if (attr
->encap_subtlvs
) {
253 encap_free(attr
->encap_subtlvs
);
254 attr
->encap_subtlvs
= NULL
;
256 #ifdef ENABLE_BGP_VNC
257 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
258 bgp_attr_get_vnc_subtlvs(attr
);
261 encap_free(vnc_subtlvs
);
262 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
268 * Compare encap sub-tlv chains
273 * This algorithm could be made faster if needed
275 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
276 const struct bgp_attr_encap_subtlv
*h2
)
278 const struct bgp_attr_encap_subtlv
*p
;
279 const struct bgp_attr_encap_subtlv
*q
;
283 if (h1
== NULL
|| h2
== NULL
)
286 for (p
= h1
; p
; p
= p
->next
) {
287 for (q
= h2
; q
; q
= q
->next
) {
288 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
289 && !memcmp(p
->value
, q
->value
, p
->length
)) {
298 for (p
= h2
; p
; p
= p
->next
) {
299 for (q
= h1
; q
; q
= q
->next
) {
300 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
301 && !memcmp(p
->value
, q
->value
, p
->length
)) {
313 static void *encap_hash_alloc(void *p
)
315 /* Encap structure is already allocated. */
321 #ifdef ENABLE_BGP_VNC
326 static struct bgp_attr_encap_subtlv
*
327 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
329 struct bgp_attr_encap_subtlv
*find
;
330 struct hash
*hash
= encap_hash
;
331 #ifdef ENABLE_BGP_VNC
332 if (type
== VNC_SUBTLV_TYPE
)
336 find
= hash_get(hash
, encap
, encap_hash_alloc
);
344 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
345 encap_subtlv_type type
)
347 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
351 if (encap
->refcnt
== 0) {
352 struct hash
*hash
= encap_hash
;
353 #ifdef ENABLE_BGP_VNC
354 if (type
== VNC_SUBTLV_TYPE
)
357 hash_release(hash
, encap
);
363 static unsigned int encap_hash_key_make(const void *p
)
365 const struct bgp_attr_encap_subtlv
*encap
= p
;
367 return jhash(encap
->value
, encap
->length
, 0);
370 static bool encap_hash_cmp(const void *p1
, const void *p2
)
372 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
373 (const struct bgp_attr_encap_subtlv
*)p2
);
376 static void encap_init(void)
378 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
380 #ifdef ENABLE_BGP_VNC
381 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
386 static void encap_finish(void)
388 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
389 hash_free(encap_hash
);
391 #ifdef ENABLE_BGP_VNC
392 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
398 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
407 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
408 bgp_attr_get_evpn_overlay(a2
));
411 /* Unknown transit attribute. */
412 static struct hash
*transit_hash
;
414 static void transit_free(struct transit
*transit
)
416 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
417 XFREE(MTYPE_TRANSIT
, transit
);
420 static void *transit_hash_alloc(void *p
)
422 /* Transit structure is already allocated. */
426 static struct transit
*transit_intern(struct transit
*transit
)
428 struct transit
*find
;
430 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
432 transit_free(transit
);
438 static void transit_unintern(struct transit
**transit
)
440 if ((*transit
)->refcnt
)
441 (*transit
)->refcnt
--;
443 if ((*transit
)->refcnt
== 0) {
444 hash_release(transit_hash
, *transit
);
445 transit_free(*transit
);
450 static void *srv6_l3vpn_hash_alloc(void *p
)
455 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
457 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
460 static struct bgp_attr_srv6_l3vpn
*
461 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
463 struct bgp_attr_srv6_l3vpn
*find
;
465 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
467 srv6_l3vpn_free(l3vpn
);
472 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
474 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
479 if (l3vpn
->refcnt
== 0) {
480 hash_release(srv6_l3vpn_hash
, l3vpn
);
481 srv6_l3vpn_free(l3vpn
);
486 static void *srv6_vpn_hash_alloc(void *p
)
491 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
493 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
496 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
498 struct bgp_attr_srv6_vpn
*find
;
500 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
507 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
509 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
514 if (vpn
->refcnt
== 0) {
515 hash_release(srv6_vpn_hash
, vpn
);
521 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
523 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
526 key
= jhash(&l3vpn
->sid
, 16, key
);
527 key
= jhash_1word(l3vpn
->sid_flags
, key
);
528 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
529 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
530 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
531 key
= jhash_1word(l3vpn
->func_len
, key
);
532 key
= jhash_1word(l3vpn
->arg_len
, key
);
533 key
= jhash_1word(l3vpn
->transposition_len
, key
);
534 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
538 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
540 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
541 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
543 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
544 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
545 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
546 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
547 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
548 && l3vpn1
->func_len
== l3vpn2
->func_len
549 && l3vpn1
->arg_len
== l3vpn2
->arg_len
550 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
551 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
554 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
555 const struct bgp_attr_srv6_l3vpn
*h2
)
559 else if (h1
== NULL
|| h2
== NULL
)
562 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
565 static unsigned int srv6_vpn_hash_key_make(const void *p
)
567 const struct bgp_attr_srv6_vpn
*vpn
= p
;
570 key
= jhash(&vpn
->sid
, 16, key
);
571 key
= jhash_1word(vpn
->sid_flags
, key
);
575 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
577 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
578 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
580 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
581 && vpn1
->sid_flags
== vpn2
->sid_flags
;
584 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
585 const struct bgp_attr_srv6_vpn
*h2
)
589 else if (h1
== NULL
|| h2
== NULL
)
592 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
595 static void srv6_init(void)
598 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
599 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
600 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
601 "BGP Prefix-SID SRv6-VPN-Service-TLV");
604 static void srv6_finish(void)
606 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
607 hash_free(srv6_l3vpn_hash
);
608 srv6_l3vpn_hash
= NULL
;
609 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
610 hash_free(srv6_vpn_hash
);
611 srv6_vpn_hash
= NULL
;
614 static unsigned int transit_hash_key_make(const void *p
)
616 const struct transit
*transit
= p
;
618 return jhash(transit
->val
, transit
->length
, 0);
621 static bool transit_hash_cmp(const void *p1
, const void *p2
)
623 const struct transit
*transit1
= p1
;
624 const struct transit
*transit2
= p2
;
626 return (transit1
->length
== transit2
->length
627 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
630 static void transit_init(void)
632 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
636 static void transit_finish(void)
638 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
639 hash_free(transit_hash
);
643 /* Attribute hash routines. */
644 static struct hash
*attrhash
;
646 unsigned long int attr_count(void)
648 return attrhash
->count
;
651 unsigned long int attr_unknown_count(void)
653 return transit_hash
->count
;
656 unsigned int attrhash_key_make(const void *p
)
658 const struct attr
*attr
= (struct attr
*)p
;
660 #define MIX(val) key = jhash_1word(val, key)
661 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
663 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
664 MIX3(attr
->local_pref
, attr
->aggregator_as
,
665 attr
->aggregator_addr
.s_addr
);
666 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
667 attr
->originator_id
.s_addr
);
668 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
671 MIX(aspath_key_make(attr
->aspath
));
672 if (bgp_attr_get_community(attr
))
673 MIX(community_hash_make(bgp_attr_get_community(attr
)));
674 if (bgp_attr_get_lcommunity(attr
))
675 MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr
)));
676 if (bgp_attr_get_ecommunity(attr
))
677 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
678 if (bgp_attr_get_ipv6_ecommunity(attr
))
679 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
680 if (bgp_attr_get_cluster(attr
))
681 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
682 if (bgp_attr_get_transit(attr
))
683 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
684 if (attr
->encap_subtlvs
)
685 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
686 if (attr
->srv6_l3vpn
)
687 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
689 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
690 #ifdef ENABLE_BGP_VNC
691 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
692 bgp_attr_get_vnc_subtlvs(attr
);
694 MIX(encap_hash_key_make(vnc_subtlvs
));
696 MIX(attr
->mp_nexthop_len
);
697 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
698 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
699 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
700 MIX(attr
->rmap_table_id
);
707 bool attrhash_cmp(const void *p1
, const void *p2
)
709 const struct attr
*attr1
= p1
;
710 const struct attr
*attr2
= p2
;
712 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
713 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
714 && attr1
->aspath
== attr2
->aspath
715 && bgp_attr_get_community(attr1
)
716 == bgp_attr_get_community(attr2
)
717 && attr1
->med
== attr2
->med
718 && attr1
->local_pref
== attr2
->local_pref
719 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
720 if (attr1
->aggregator_as
== attr2
->aggregator_as
721 && attr1
->aggregator_addr
.s_addr
722 == attr2
->aggregator_addr
.s_addr
723 && attr1
->weight
== attr2
->weight
724 && attr1
->tag
== attr2
->tag
725 && attr1
->label_index
== attr2
->label_index
726 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
727 && bgp_attr_get_ecommunity(attr1
)
728 == bgp_attr_get_ecommunity(attr2
)
729 && bgp_attr_get_ipv6_ecommunity(attr1
)
730 == bgp_attr_get_ipv6_ecommunity(attr2
)
731 && bgp_attr_get_lcommunity(attr1
)
732 == bgp_attr_get_lcommunity(attr2
)
733 && bgp_attr_get_cluster(attr1
)
734 == bgp_attr_get_cluster(attr2
)
735 && bgp_attr_get_transit(attr1
)
736 == bgp_attr_get_transit(attr2
)
737 && attr1
->rmap_table_id
== attr2
->rmap_table_id
738 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
739 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
740 #ifdef ENABLE_BGP_VNC
741 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
742 bgp_attr_get_vnc_subtlvs(attr2
))
744 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
745 &attr2
->mp_nexthop_global
)
746 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
747 &attr2
->mp_nexthop_local
)
748 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
749 &attr2
->mp_nexthop_global_in
)
750 && IPV4_ADDR_SAME(&attr1
->originator_id
,
751 &attr2
->originator_id
)
752 && overlay_index_same(attr1
, attr2
)
753 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
754 && attr1
->es_flags
== attr2
->es_flags
755 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
756 && attr1
->df_pref
== attr2
->df_pref
757 && attr1
->df_alg
== attr2
->df_alg
758 && attr1
->nh_ifindex
== attr2
->nh_ifindex
759 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
760 && attr1
->distance
== attr2
->distance
761 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
762 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
763 && attr1
->srte_color
== attr2
->srte_color
764 && attr1
->nh_type
== attr2
->nh_type
765 && attr1
->bh_type
== attr2
->bh_type
)
772 static void attrhash_init(void)
775 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
779 * special for hash_clean below
781 static void attr_vfree(void *attr
)
783 XFREE(MTYPE_ATTR
, attr
);
786 static void attrhash_finish(void)
788 hash_clean(attrhash
, attr_vfree
);
793 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
795 struct attr
*attr
= bucket
->data
;
796 char sid_str
[BUFSIZ
];
798 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
801 if (attr
->srv6_l3vpn
)
802 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
803 else if (attr
->srv6_vpn
)
804 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
807 "\tflags: %" PRIu64
" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
808 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
809 attr
->origin
, attr
->weight
, attr
->label
, sid_str
);
812 void attr_show_all(struct vty
*vty
)
814 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
815 void *))attr_show_all_iterator
,
819 static void *bgp_attr_hash_alloc(void *p
)
821 struct attr
*val
= (struct attr
*)p
;
824 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
826 if (val
->encap_subtlvs
) {
827 val
->encap_subtlvs
= NULL
;
829 #ifdef ENABLE_BGP_VNC
830 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
831 bgp_attr_get_vnc_subtlvs(val
);
834 bgp_attr_set_vnc_subtlvs(val
, NULL
);
841 /* Internet argument attribute. */
842 struct attr
*bgp_attr_intern(struct attr
*attr
)
845 struct ecommunity
*ecomm
= NULL
;
846 struct ecommunity
*ipv6_ecomm
= NULL
;
847 struct lcommunity
*lcomm
= NULL
;
848 struct community
*comm
= NULL
;
850 /* Intern referenced strucutre. */
852 if (!attr
->aspath
->refcnt
)
853 attr
->aspath
= aspath_intern(attr
->aspath
);
855 attr
->aspath
->refcnt
++;
858 comm
= bgp_attr_get_community(attr
);
861 bgp_attr_set_community(attr
, community_intern(comm
));
866 ecomm
= bgp_attr_get_ecommunity(attr
);
869 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
874 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
876 if (!ipv6_ecomm
->refcnt
)
877 bgp_attr_set_ipv6_ecommunity(
878 attr
, ecommunity_intern(ipv6_ecomm
));
880 ipv6_ecomm
->refcnt
++;
883 lcomm
= bgp_attr_get_lcommunity(attr
);
886 bgp_attr_set_lcommunity(attr
, lcommunity_intern(lcomm
));
891 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
894 if (!cluster
->refcnt
)
895 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
900 struct transit
*transit
= bgp_attr_get_transit(attr
);
903 if (!transit
->refcnt
)
904 bgp_attr_set_transit(attr
, transit_intern(transit
));
908 if (attr
->encap_subtlvs
) {
909 if (!attr
->encap_subtlvs
->refcnt
)
910 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
913 attr
->encap_subtlvs
->refcnt
++;
915 if (attr
->srv6_l3vpn
) {
916 if (!attr
->srv6_l3vpn
->refcnt
)
917 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
919 attr
->srv6_l3vpn
->refcnt
++;
921 if (attr
->srv6_vpn
) {
922 if (!attr
->srv6_vpn
->refcnt
)
923 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
925 attr
->srv6_vpn
->refcnt
++;
927 #ifdef ENABLE_BGP_VNC
928 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
929 bgp_attr_get_vnc_subtlvs(attr
);
932 if (!vnc_subtlvs
->refcnt
)
933 bgp_attr_set_vnc_subtlvs(
935 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
937 vnc_subtlvs
->refcnt
++;
941 /* At this point, attr only contains intern'd pointers. that means
942 * if we find it in attrhash, it has all the same pointers and we
943 * correctly updated the refcounts on these.
944 * If we don't find it, we need to allocate a one because in all
945 * cases this returns a new reference to a hashed attr, but the input
947 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
953 /* Make network statement's attribute. */
954 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
956 memset(attr
, 0, sizeof(struct attr
));
958 attr
->origin
= origin
;
959 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
960 attr
->aspath
= aspath_empty();
961 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
962 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
964 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
965 attr
->label
= MPLS_INVALID_LABEL
;
966 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
967 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
972 /* Create the attributes for an aggregate */
973 struct attr
*bgp_attr_aggregate_intern(
974 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
975 struct community
*community
, struct ecommunity
*ecommunity
,
976 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
977 uint8_t atomic_aggregate
, const struct prefix
*p
)
983 memset(&attr
, 0, sizeof(struct attr
));
985 /* Origin attribute. */
986 attr
.origin
= origin
;
987 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
989 /* AS path attribute. */
991 attr
.aspath
= aspath_intern(aspath
);
993 attr
.aspath
= aspath_empty();
994 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
996 /* Next hop attribute. */
997 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1000 uint32_t gshut
= COMMUNITY_GSHUT
;
1002 /* If we are not shutting down ourselves and we are
1003 * aggregating a route that contains the GSHUT community we
1004 * need to remove that community when creating the aggregate */
1005 if (!bgp_in_graceful_shutdown(bgp
)
1006 && community_include(community
, gshut
)) {
1007 community_del_val(community
, &gshut
);
1010 bgp_attr_set_community(&attr
, community
);
1014 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1017 bgp_attr_set_lcommunity(&attr
, lcommunity
);
1019 if (bgp_in_graceful_shutdown(bgp
))
1020 bgp_attr_add_gshut_community(&attr
);
1022 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1023 attr
.label
= MPLS_INVALID_LABEL
;
1024 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1025 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1026 if (!aggregate
->as_set
|| atomic_aggregate
)
1027 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1028 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1029 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1030 attr
.aggregator_as
= bgp
->confed_id
;
1032 attr
.aggregator_as
= bgp
->as
;
1033 attr
.aggregator_addr
= bgp
->router_id
;
1034 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1035 attr
.label
= MPLS_INVALID_LABEL
;
1037 /* Apply route-map */
1038 if (aggregate
->rmap
.name
) {
1039 struct attr attr_tmp
= attr
;
1040 struct bgp_path_info rmap_path
;
1042 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1043 rmap_path
.peer
= bgp
->peer_self
;
1044 rmap_path
.attr
= &attr_tmp
;
1046 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1048 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1050 bgp
->peer_self
->rmap_type
= 0;
1052 if (ret
== RMAP_DENYMATCH
) {
1053 /* Free uninterned attribute. */
1054 bgp_attr_flush(&attr_tmp
);
1056 /* Unintern original. */
1057 aspath_unintern(&attr
.aspath
);
1061 if (bgp_in_graceful_shutdown(bgp
))
1062 bgp_attr_add_gshut_community(&attr_tmp
);
1064 new = bgp_attr_intern(&attr_tmp
);
1067 if (bgp_in_graceful_shutdown(bgp
))
1068 bgp_attr_add_gshut_community(&attr
);
1070 new = bgp_attr_intern(&attr
);
1073 /* Always release the 'intern()'ed AS Path. */
1074 aspath_unintern(&attr
.aspath
);
1079 /* Unintern just the sub-components of the attr, but not the attr */
1080 void bgp_attr_unintern_sub(struct attr
*attr
)
1082 struct ecommunity
*ecomm
= NULL
;
1083 struct ecommunity
*ipv6_ecomm
= NULL
;
1084 struct cluster_list
*cluster
;
1085 struct lcommunity
*lcomm
= NULL
;
1086 struct community
*comm
= NULL
;
1088 /* aspath refcount shoud be decrement. */
1089 aspath_unintern(&attr
->aspath
);
1090 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1092 comm
= bgp_attr_get_community(attr
);
1093 community_unintern(&comm
);
1094 bgp_attr_set_community(attr
, NULL
);
1096 ecomm
= bgp_attr_get_ecommunity(attr
);
1097 ecommunity_unintern(&ecomm
);
1098 bgp_attr_set_ecommunity(attr
, NULL
);
1100 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1101 ecommunity_unintern(&ipv6_ecomm
);
1102 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1104 lcomm
= bgp_attr_get_lcommunity(attr
);
1105 lcommunity_unintern(&lcomm
);
1106 bgp_attr_set_lcommunity(attr
, NULL
);
1108 cluster
= bgp_attr_get_cluster(attr
);
1110 cluster_unintern(&cluster
);
1111 bgp_attr_set_cluster(attr
, cluster
);
1113 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1115 struct transit
*transit
= bgp_attr_get_transit(attr
);
1118 transit_unintern(&transit
);
1119 bgp_attr_set_transit(attr
, transit
);
1122 if (attr
->encap_subtlvs
)
1123 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1125 #ifdef ENABLE_BGP_VNC
1126 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1127 bgp_attr_get_vnc_subtlvs(attr
);
1130 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1131 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1135 if (attr
->srv6_l3vpn
)
1136 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1139 srv6_vpn_unintern(&attr
->srv6_vpn
);
1142 /* Free bgp attribute and aspath. */
1143 void bgp_attr_unintern(struct attr
**pattr
)
1145 struct attr
*attr
= *pattr
;
1149 /* Decrement attribute reference. */
1154 /* If reference becomes zero then free attribute object. */
1155 if (attr
->refcnt
== 0) {
1156 ret
= hash_release(attrhash
, attr
);
1157 assert(ret
!= NULL
);
1158 XFREE(MTYPE_ATTR
, attr
);
1162 bgp_attr_unintern_sub(&tmp
);
1165 void bgp_attr_flush(struct attr
*attr
)
1167 struct ecommunity
*ecomm
;
1168 struct ecommunity
*ipv6_ecomm
;
1169 struct cluster_list
*cluster
;
1170 struct lcommunity
*lcomm
;
1171 struct community
*comm
;
1173 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1174 aspath_free(attr
->aspath
);
1175 attr
->aspath
= NULL
;
1177 comm
= bgp_attr_get_community(attr
);
1178 if (comm
&& !comm
->refcnt
)
1179 community_free(&comm
);
1180 bgp_attr_set_community(attr
, NULL
);
1182 ecomm
= bgp_attr_get_ecommunity(attr
);
1183 if (ecomm
&& !ecomm
->refcnt
)
1184 ecommunity_free(&ecomm
);
1185 bgp_attr_set_ecommunity(attr
, NULL
);
1187 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1188 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1189 ecommunity_free(&ipv6_ecomm
);
1190 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1192 lcomm
= bgp_attr_get_lcommunity(attr
);
1193 if (lcomm
&& !lcomm
->refcnt
)
1194 lcommunity_free(&lcomm
);
1195 bgp_attr_set_lcommunity(attr
, NULL
);
1197 cluster
= bgp_attr_get_cluster(attr
);
1198 if (cluster
&& !cluster
->refcnt
) {
1199 cluster_free(cluster
);
1200 bgp_attr_set_cluster(attr
, NULL
);
1203 struct transit
*transit
= bgp_attr_get_transit(attr
);
1205 if (transit
&& !transit
->refcnt
) {
1206 transit_free(transit
);
1207 bgp_attr_set_transit(attr
, NULL
);
1209 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1210 encap_free(attr
->encap_subtlvs
);
1211 attr
->encap_subtlvs
= NULL
;
1213 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1214 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1215 attr
->srv6_l3vpn
= NULL
;
1217 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1218 srv6_vpn_free(attr
->srv6_vpn
);
1219 attr
->srv6_vpn
= NULL
;
1221 #ifdef ENABLE_BGP_VNC
1222 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1223 bgp_attr_get_vnc_subtlvs(attr
);
1225 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1226 encap_free(vnc_subtlvs
);
1227 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1232 /* Implement draft-scudder-idr-optional-transitive behaviour and
1233 * avoid resetting sessions for malformed attributes which are
1234 * are partial/optional and hence where the error likely was not
1235 * introduced by the sending neighbour.
1237 static bgp_attr_parse_ret_t
1238 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1241 struct peer
*const peer
= args
->peer
;
1242 struct attr
*const attr
= args
->attr
;
1243 const uint8_t flags
= args
->flags
;
1244 /* startp and length must be special-cased, as whether or not to
1245 * send the attribute data with the NOTIFY depends on the error,
1246 * the caller therefore signals this with the seperate length argument
1248 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1250 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1251 char attr_str
[BUFSIZ
] = {0};
1253 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1255 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1258 /* Only relax error handling for eBGP peers */
1259 if (peer
->sort
!= BGP_PEER_EBGP
) {
1260 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1261 notify_datap
, length
);
1262 return BGP_ATTR_PARSE_ERROR
;
1265 /* Adjust the stream getp to the end of the attribute, in case we can
1266 * still proceed but the caller hasn't read all the attribute.
1268 stream_set_getp(BGP_INPUT(peer
),
1269 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1272 switch (args
->type
) {
1273 /* where an attribute is relatively inconsequential, e.g. it does not
1274 * affect route selection, and can be safely ignored, then any such
1275 * attributes which are malformed should just be ignored and the route
1276 * processed as normal.
1278 case BGP_ATTR_AS4_AGGREGATOR
:
1279 case BGP_ATTR_AGGREGATOR
:
1280 case BGP_ATTR_ATOMIC_AGGREGATE
:
1281 return BGP_ATTR_PARSE_PROCEED
;
1283 /* Core attributes, particularly ones which may influence route
1284 * selection, should be treat-as-withdraw.
1286 case BGP_ATTR_ORIGIN
:
1287 case BGP_ATTR_AS_PATH
:
1288 case BGP_ATTR_NEXT_HOP
:
1289 case BGP_ATTR_MULTI_EXIT_DISC
:
1290 case BGP_ATTR_LOCAL_PREF
:
1291 case BGP_ATTR_COMMUNITIES
:
1292 case BGP_ATTR_EXT_COMMUNITIES
:
1293 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1294 case BGP_ATTR_LARGE_COMMUNITIES
:
1295 case BGP_ATTR_ORIGINATOR_ID
:
1296 case BGP_ATTR_CLUSTER_LIST
:
1297 return BGP_ATTR_PARSE_WITHDRAW
;
1298 case BGP_ATTR_MP_REACH_NLRI
:
1299 case BGP_ATTR_MP_UNREACH_NLRI
:
1300 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1301 notify_datap
, length
);
1302 return BGP_ATTR_PARSE_ERROR
;
1305 /* Partial optional attributes that are malformed should not cause
1306 * the whole session to be reset. Instead treat it as a withdrawal
1307 * of the routes, if possible.
1309 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1310 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1311 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1312 return BGP_ATTR_PARSE_WITHDRAW
;
1314 /* default to reset */
1315 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1318 /* Find out what is wrong with the path attribute flag bits and log the error.
1319 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1320 Extended Length. Checking O/T/P bits at once implies, that the attribute
1321 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1322 non-transitive" attribute. */
1324 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1325 uint8_t desired_flags
/* how RFC says it must be */
1328 uint8_t seen
= 0, i
;
1329 uint8_t real_flags
= args
->flags
;
1330 const uint8_t attr_code
= args
->type
;
1332 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1333 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1334 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1335 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1336 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1337 flog_err(EC_BGP_ATTR_FLAG
,
1338 "%s attribute must%s be flagged as \"%s\"",
1339 lookup_msg(attr_str
, attr_code
, NULL
),
1340 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1343 attr_flag_str
[i
].str
);
1348 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1349 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1350 real_flags
, desired_flags
);
1354 /* Required flags for attributes. EXTLEN will be masked off when testing,
1355 * as will PARTIAL for optional+transitive attributes.
1357 const uint8_t attr_flags_values
[] = {
1358 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1359 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1360 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1361 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1362 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1363 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1364 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1365 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1366 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1367 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1368 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1369 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1370 [BGP_ATTR_EXT_COMMUNITIES
] =
1371 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1372 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1373 [BGP_ATTR_AS4_AGGREGATOR
] =
1374 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1375 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1376 [BGP_ATTR_LARGE_COMMUNITIES
] =
1377 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1378 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1379 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1380 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1382 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1384 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1386 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1387 const uint8_t flags
= args
->flags
;
1388 const uint8_t attr_code
= args
->type
;
1390 /* there may be attributes we don't know about */
1391 if (attr_code
> attr_flags_values_max
)
1393 if (attr_flags_values
[attr_code
] == 0)
1396 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1400 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1401 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1404 "%s well-known attributes must have transitive flag set (%x)",
1405 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1409 /* "For well-known attributes and for optional non-transitive
1411 * the Partial bit MUST be set to 0."
1413 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1414 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1415 flog_err(EC_BGP_ATTR_FLAG
,
1416 "%s well-known attribute must NOT have the partial flag set (%x)",
1417 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1420 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1421 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1422 flog_err(EC_BGP_ATTR_FLAG
,
1423 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1424 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1429 /* Optional transitive attributes may go through speakers that don't
1430 * reocgnise them and set the Partial bit.
1432 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1433 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1434 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1436 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1439 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1443 /* Get origin attribute of the update message. */
1444 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1446 struct peer
*const peer
= args
->peer
;
1447 struct attr
*const attr
= args
->attr
;
1448 const bgp_size_t length
= args
->length
;
1450 /* If any recognized attribute has Attribute Length that conflicts
1451 with the expected length (based on the attribute type code), then
1452 the Error Subcode is set to Attribute Length Error. The Data
1453 field contains the erroneous attribute (type, length and
1456 flog_err(EC_BGP_ATTR_LEN
,
1457 "Origin attribute length is not one %d", length
);
1458 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1462 /* Fetch origin attribute. */
1463 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1465 /* If the ORIGIN attribute has an undefined value, then the Error
1466 Subcode is set to Invalid Origin Attribute. The Data field
1467 contains the unrecognized attribute (type, length and value). */
1468 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1469 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1470 flog_err(EC_BGP_ATTR_ORIGIN
,
1471 "Origin attribute value is invalid %d", attr
->origin
);
1472 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1476 /* Set oring attribute flag. */
1477 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1482 /* Parse AS path information. This function is wrapper of
1484 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1486 struct attr
*const attr
= args
->attr
;
1487 struct peer
*const peer
= args
->peer
;
1488 const bgp_size_t length
= args
->length
;
1491 * peer with AS4 => will get 4Byte ASnums
1492 * otherwise, will get 16 Bit
1494 attr
->aspath
= aspath_parse(
1496 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1497 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1499 /* In case of IBGP, length will be zero. */
1500 if (!attr
->aspath
) {
1501 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1502 "Malformed AS path from %s, length is %d", peer
->host
,
1504 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1508 /* Set aspath attribute flag. */
1509 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1511 return BGP_ATTR_PARSE_PROCEED
;
1514 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1515 struct attr
*const attr
)
1517 /* These checks were part of bgp_attr_aspath, but with
1518 * as4 we should to check aspath things when
1519 * aspath synthesizing with as4_path has already taken place.
1520 * Otherwise we check ASPATH and use the synthesized thing, and that is
1522 * So do the checks later, i.e. here
1524 struct aspath
*aspath
;
1526 /* Confederation sanity check. */
1527 if ((peer
->sort
== BGP_PEER_CONFED
1528 && !aspath_left_confed_check(attr
->aspath
))
1529 || (peer
->sort
== BGP_PEER_EBGP
1530 && aspath_confed_check(attr
->aspath
))) {
1531 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1533 return BGP_ATTR_PARSE_WITHDRAW
;
1536 /* First AS check for EBGP. */
1537 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1538 if (peer
->sort
== BGP_PEER_EBGP
1539 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1540 flog_err(EC_BGP_ATTR_FIRST_AS
,
1541 "%s incorrect first AS (must be %u)",
1542 peer
->host
, peer
->as
);
1543 return BGP_ATTR_PARSE_WITHDRAW
;
1547 /* Codification of AS 0 Processing */
1548 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1550 EC_BGP_ATTR_MAL_AS_PATH
,
1551 "Malformed AS path, AS number is 0 in the path from %s",
1553 return BGP_ATTR_PARSE_WITHDRAW
;
1556 /* local-as prepend */
1557 if (peer
->change_local_as
1558 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1559 aspath
= aspath_dup(attr
->aspath
);
1560 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1561 aspath_unintern(&attr
->aspath
);
1562 attr
->aspath
= aspath_intern(aspath
);
1565 return BGP_ATTR_PARSE_PROCEED
;
1568 /* Parse AS4 path information. This function is another wrapper of
1570 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1571 struct aspath
**as4_path
)
1573 struct peer
*const peer
= args
->peer
;
1574 struct attr
*const attr
= args
->attr
;
1575 const bgp_size_t length
= args
->length
;
1577 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1579 /* In case of IBGP, length will be zero. */
1581 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1582 "Malformed AS4 path from %s, length is %d", peer
->host
,
1584 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1588 /* Set aspath attribute flag. */
1589 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1591 return BGP_ATTR_PARSE_PROCEED
;
1595 * Check that the nexthop attribute is valid.
1597 bgp_attr_parse_ret_t
1598 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1600 in_addr_t nexthop_h
;
1602 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1603 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1604 || IPV4_CLASS_DE(nexthop_h
))
1605 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1606 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1607 char buf
[INET_ADDRSTRLEN
];
1609 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1611 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1613 data
[0] = BGP_ATTR_FLAG_TRANS
;
1614 data
[1] = BGP_ATTR_NEXT_HOP
;
1615 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1616 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1617 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1618 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1620 return BGP_ATTR_PARSE_ERROR
;
1623 return BGP_ATTR_PARSE_PROCEED
;
1626 /* Nexthop attribute. */
1627 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1629 struct peer
*const peer
= args
->peer
;
1630 struct attr
*const attr
= args
->attr
;
1631 const bgp_size_t length
= args
->length
;
1633 /* Check nexthop attribute length. */
1635 flog_err(EC_BGP_ATTR_LEN
,
1636 "Nexthop attribute length isn't four [%d]", length
);
1638 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1642 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1643 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1645 return BGP_ATTR_PARSE_PROCEED
;
1648 /* MED atrribute. */
1649 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1651 struct peer
*const peer
= args
->peer
;
1652 struct attr
*const attr
= args
->attr
;
1653 const bgp_size_t length
= args
->length
;
1657 flog_err(EC_BGP_ATTR_LEN
,
1658 "MED attribute length isn't four [%d]", length
);
1660 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1664 attr
->med
= stream_getl(peer
->curr
);
1666 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1668 return BGP_ATTR_PARSE_PROCEED
;
1671 /* Local preference attribute. */
1672 static bgp_attr_parse_ret_t
1673 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1675 struct peer
*const peer
= args
->peer
;
1676 struct attr
*const attr
= args
->attr
;
1677 const bgp_size_t length
= args
->length
;
1679 /* if received from an internal neighbor, it SHALL be considered
1680 * malformed if its length is not equal to 4. If malformed, the
1681 * UPDATE message SHALL be handled using the approach of "treat-as-
1684 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1685 flog_err(EC_BGP_ATTR_LEN
,
1686 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1687 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1691 /* If it is contained in an UPDATE message that is received from an
1692 external peer, then this attribute MUST be ignored by the
1693 receiving speaker. */
1694 if (peer
->sort
== BGP_PEER_EBGP
) {
1695 STREAM_FORWARD_GETP(peer
->curr
, length
);
1696 return BGP_ATTR_PARSE_PROCEED
;
1699 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1701 /* Set the local-pref flag. */
1702 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1704 return BGP_ATTR_PARSE_PROCEED
;
1707 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1711 /* Atomic aggregate. */
1712 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1714 struct attr
*const attr
= args
->attr
;
1715 const bgp_size_t length
= args
->length
;
1719 flog_err(EC_BGP_ATTR_LEN
,
1720 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1722 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1726 /* Set atomic aggregate flag. */
1727 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1729 return BGP_ATTR_PARSE_PROCEED
;
1732 /* Aggregator attribute */
1733 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1735 struct peer
*const peer
= args
->peer
;
1736 struct attr
*const attr
= args
->attr
;
1737 const bgp_size_t length
= args
->length
;
1742 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1743 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1744 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1747 if (length
!= wantedlen
) {
1748 flog_err(EC_BGP_ATTR_LEN
,
1749 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1751 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1755 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1756 aggregator_as
= stream_getl(peer
->curr
);
1758 aggregator_as
= stream_getw(peer
->curr
);
1760 attr
->aggregator_as
= aggregator_as
;
1761 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1763 /* Codification of AS 0 Processing */
1764 if (aggregator_as
== BGP_AS_ZERO
) {
1765 flog_err(EC_BGP_ATTR_LEN
,
1766 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1767 peer
->host
, aspath_print(attr
->aspath
));
1769 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1770 char attr_str
[BUFSIZ
] = {0};
1772 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1774 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1777 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1780 return BGP_ATTR_PARSE_PROCEED
;
1783 /* New Aggregator attribute */
1784 static bgp_attr_parse_ret_t
1785 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1786 as_t
*as4_aggregator_as
,
1787 struct in_addr
*as4_aggregator_addr
)
1789 struct peer
*const peer
= args
->peer
;
1790 struct attr
*const attr
= args
->attr
;
1791 const bgp_size_t length
= args
->length
;
1795 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1797 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1801 aggregator_as
= stream_getl(peer
->curr
);
1803 *as4_aggregator_as
= aggregator_as
;
1804 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1806 /* Codification of AS 0 Processing */
1807 if (aggregator_as
== BGP_AS_ZERO
) {
1808 flog_err(EC_BGP_ATTR_LEN
,
1809 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1810 peer
->host
, aspath_print(attr
->aspath
));
1812 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1813 char attr_str
[BUFSIZ
] = {0};
1815 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1817 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1820 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1823 return BGP_ATTR_PARSE_PROCEED
;
1826 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1828 static bgp_attr_parse_ret_t
1829 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1830 struct aspath
*as4_path
, as_t as4_aggregator
,
1831 struct in_addr
*as4_aggregator_addr
)
1833 int ignore_as4_path
= 0;
1834 struct aspath
*newpath
;
1836 if (!attr
->aspath
) {
1837 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1839 * checked that all well-known, mandatory attributes were
1842 * Can only be a problem with peer itself - hard error
1844 return BGP_ATTR_PARSE_ERROR
;
1847 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1848 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1850 * It is worth a warning though, because the peer really
1851 * should not send them
1853 if (BGP_DEBUG(as4
, AS4
)) {
1854 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1855 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1856 "AS4 capable peer, yet it sent");
1859 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1860 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1862 "AS4 capable peer, yet it sent");
1865 return BGP_ATTR_PARSE_PROCEED
;
1868 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1869 * because that may override AS4_PATH
1871 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1872 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1874 * if the as_number in aggregator is not AS_TRANS,
1875 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1876 * and the Aggregator shall be taken as
1877 * info on the aggregating node, and the AS_PATH
1878 * shall be taken as the AS_PATH
1880 * the Aggregator shall be ignored and the
1881 * AS4_AGGREGATOR shall be taken as the
1882 * Aggregating node and the AS_PATH is to be
1883 * constructed "as in all other cases"
1885 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1887 if (BGP_DEBUG(as4
, AS4
))
1889 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1891 ignore_as4_path
= 1;
1893 /* "New_aggregator shall be taken as aggregator"
1895 attr
->aggregator_as
= as4_aggregator
;
1896 attr
->aggregator_addr
.s_addr
=
1897 as4_aggregator_addr
->s_addr
;
1900 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1901 * That is bogus - but reading the conditions
1902 * we have to handle AS4_AGGREGATOR as if it were
1903 * AGGREGATOR in that case
1905 if (BGP_DEBUG(as4
, AS4
))
1907 "[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",
1909 attr
->aggregator_as
= as4_aggregator
;
1910 /* sweep it under the carpet and simulate a "good"
1912 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1916 /* need to reconcile NEW_AS_PATH and AS_PATH */
1917 if (!ignore_as4_path
1918 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1919 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1921 return BGP_ATTR_PARSE_ERROR
;
1923 aspath_unintern(&attr
->aspath
);
1924 attr
->aspath
= aspath_intern(newpath
);
1926 return BGP_ATTR_PARSE_PROCEED
;
1929 /* Community attribute. */
1930 static bgp_attr_parse_ret_t
1931 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1933 struct peer
*const peer
= args
->peer
;
1934 struct attr
*const attr
= args
->attr
;
1935 const bgp_size_t length
= args
->length
;
1938 bgp_attr_set_community(attr
, NULL
);
1939 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1943 bgp_attr_set_community(
1945 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
));
1947 /* XXX: fix community_parse to use stream API and remove this */
1948 stream_forward_getp(peer
->curr
, length
);
1950 /* The Community attribute SHALL be considered malformed if its
1951 * length is not a non-zero multiple of 4.
1953 if (!bgp_attr_get_community(attr
))
1954 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1957 return BGP_ATTR_PARSE_PROCEED
;
1960 /* Originator ID attribute. */
1961 static bgp_attr_parse_ret_t
1962 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1964 struct peer
*const peer
= args
->peer
;
1965 struct attr
*const attr
= args
->attr
;
1966 const bgp_size_t length
= args
->length
;
1968 /* if received from an internal neighbor, it SHALL be considered
1969 * malformed if its length is not equal to 4. If malformed, the
1970 * UPDATE message SHALL be handled using the approach of "treat-as-
1974 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1977 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1981 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1983 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1985 return BGP_ATTR_PARSE_PROCEED
;
1988 /* Cluster list attribute. */
1989 static bgp_attr_parse_ret_t
1990 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1992 struct peer
*const peer
= args
->peer
;
1993 struct attr
*const attr
= args
->attr
;
1994 const bgp_size_t length
= args
->length
;
1996 /* if received from an internal neighbor, it SHALL be considered
1997 * malformed if its length is not a non-zero multiple of 4. If
1998 * malformed, the UPDATE message SHALL be handled using the approach
1999 * of "treat-as-withdraw".
2001 if (length
== 0 || length
% 4) {
2002 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2004 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2008 bgp_attr_set_cluster(
2009 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2012 /* XXX: Fix cluster_parse to use stream API and then remove this */
2013 stream_forward_getp(peer
->curr
, length
);
2015 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2017 return BGP_ATTR_PARSE_PROCEED
;
2020 /* Multiprotocol reachability information parse. */
2021 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2022 struct bgp_nlri
*mp_update
)
2026 iana_safi_t pkt_safi
;
2028 bgp_size_t nlri_len
;
2031 struct peer
*const peer
= args
->peer
;
2032 struct attr
*const attr
= args
->attr
;
2033 const bgp_size_t length
= args
->length
;
2035 /* Set end of packet. */
2036 s
= BGP_INPUT(peer
);
2037 start
= stream_get_getp(s
);
2039 /* safe to read statically sized header? */
2040 #define BGP_MP_REACH_MIN_SIZE 5
2041 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2042 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2043 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2044 __func__
, peer
->host
, (unsigned long)length
);
2045 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2048 /* Load AFI, SAFI. */
2049 pkt_afi
= stream_getw(s
);
2050 pkt_safi
= stream_getc(s
);
2052 /* Convert AFI, SAFI to internal values, check. */
2053 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2054 /* Log if AFI or SAFI is unrecognized. This is not an error
2056 * the attribute is otherwise malformed.
2058 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2060 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2061 peer
->host
, iana_afi2str(pkt_afi
),
2062 iana_safi2str(pkt_safi
));
2063 return BGP_ATTR_PARSE_ERROR
;
2066 /* Get nexthop length. */
2067 attr
->mp_nexthop_len
= stream_getc(s
);
2069 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2071 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2072 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2073 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2076 /* Nexthop length check. */
2077 switch (attr
->mp_nexthop_len
) {
2079 if (safi
!= SAFI_FLOWSPEC
) {
2080 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2081 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2082 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2085 case BGP_ATTR_NHLEN_VPNV4
:
2086 stream_getl(s
); /* RD high */
2087 stream_getl(s
); /* RD low */
2089 * NOTE: intentional fall through
2090 * - for consistency in rx processing
2092 * The following comment is to signal GCC this intention
2093 * and suppress the warning
2096 case BGP_ATTR_NHLEN_IPV4
:
2097 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2098 /* Probably needed for RFC 2283 */
2099 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2100 memcpy(&attr
->nexthop
.s_addr
,
2101 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2103 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2104 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2105 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2106 stream_getl(s
); /* RD high */
2107 stream_getl(s
); /* RD low */
2109 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2110 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2111 if (!peer
->nexthop
.ifp
) {
2112 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2114 return BGP_ATTR_PARSE_WITHDRAW
;
2116 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2119 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2120 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2121 if (attr
->mp_nexthop_len
2122 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2123 stream_getl(s
); /* RD high */
2124 stream_getl(s
); /* RD low */
2126 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2127 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2128 if (!peer
->nexthop
.ifp
) {
2129 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",
2131 return BGP_ATTR_PARSE_WITHDRAW
;
2133 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2135 if (attr
->mp_nexthop_len
2136 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2137 stream_getl(s
); /* RD high */
2138 stream_getl(s
); /* RD low */
2140 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2141 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2142 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2144 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2145 peer
->host
, &attr
->mp_nexthop_global
,
2146 &attr
->mp_nexthop_local
);
2148 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2150 if (!peer
->nexthop
.ifp
) {
2151 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2153 return BGP_ATTR_PARSE_WITHDRAW
;
2155 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2158 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2159 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2160 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2164 zlog_info("%s: %s sent SNPA which couldn't be read",
2165 __func__
, peer
->host
);
2166 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2171 if ((val
= stream_getc(s
)))
2173 EC_BGP_DEFUNCT_SNPA_LEN
,
2174 "%s sent non-zero value, %u, for defunct SNPA-length field",
2178 /* must have nrli_len, what is left of the attribute */
2179 nlri_len
= LEN_LEFT
;
2180 if (nlri_len
> STREAM_READABLE(s
)) {
2181 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2182 __func__
, peer
->host
);
2183 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2187 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2188 __func__
, peer
->host
);
2190 mp_update
->afi
= afi
;
2191 mp_update
->safi
= safi
;
2192 return BGP_ATTR_PARSE_EOR
;
2195 mp_update
->afi
= afi
;
2196 mp_update
->safi
= safi
;
2197 mp_update
->nlri
= stream_pnt(s
);
2198 mp_update
->length
= nlri_len
;
2200 stream_forward_getp(s
, nlri_len
);
2202 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2204 return BGP_ATTR_PARSE_PROCEED
;
2208 /* Multiprotocol unreachable parse */
2209 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2210 struct bgp_nlri
*mp_withdraw
)
2215 iana_safi_t pkt_safi
;
2217 uint16_t withdraw_len
;
2218 struct peer
*const peer
= args
->peer
;
2219 struct attr
*const attr
= args
->attr
;
2220 const bgp_size_t length
= args
->length
;
2224 #define BGP_MP_UNREACH_MIN_SIZE 3
2225 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2226 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2228 pkt_afi
= stream_getw(s
);
2229 pkt_safi
= stream_getc(s
);
2231 /* Convert AFI, SAFI to internal values, check. */
2232 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2233 /* Log if AFI or SAFI is unrecognized. This is not an error
2235 * the attribute is otherwise malformed.
2237 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2239 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2240 peer
->host
, iana_afi2str(pkt_afi
),
2241 iana_safi2str(pkt_safi
));
2242 return BGP_ATTR_PARSE_ERROR
;
2245 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2247 mp_withdraw
->afi
= afi
;
2248 mp_withdraw
->safi
= safi
;
2249 mp_withdraw
->nlri
= stream_pnt(s
);
2250 mp_withdraw
->length
= withdraw_len
;
2252 stream_forward_getp(s
, withdraw_len
);
2254 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2256 return BGP_ATTR_PARSE_PROCEED
;
2259 /* Large Community attribute. */
2260 static bgp_attr_parse_ret_t
2261 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2263 struct peer
*const peer
= args
->peer
;
2264 struct attr
*const attr
= args
->attr
;
2265 const bgp_size_t length
= args
->length
;
2268 * Large community follows new attribute format.
2271 bgp_attr_set_lcommunity(attr
, NULL
);
2272 /* Empty extcomm doesn't seem to be invalid per se */
2273 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2277 bgp_attr_set_lcommunity(
2278 attr
, lcommunity_parse(stream_pnt(peer
->curr
), length
));
2279 /* XXX: fix ecommunity_parse to use stream API */
2280 stream_forward_getp(peer
->curr
, length
);
2282 if (!bgp_attr_get_lcommunity(attr
))
2283 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2286 return BGP_ATTR_PARSE_PROCEED
;
2289 /* Extended Community attribute. */
2290 static bgp_attr_parse_ret_t
2291 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2293 struct peer
*const peer
= args
->peer
;
2294 struct attr
*const attr
= args
->attr
;
2295 const bgp_size_t length
= args
->length
;
2298 struct ecommunity
*ecomm
;
2301 bgp_attr_set_ecommunity(attr
, NULL
);
2302 /* Empty extcomm doesn't seem to be invalid per se */
2303 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2307 ecomm
= ecommunity_parse(
2308 stream_pnt(peer
->curr
), length
,
2309 CHECK_FLAG(peer
->flags
,
2310 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2311 bgp_attr_set_ecommunity(attr
, ecomm
);
2312 /* XXX: fix ecommunity_parse to use stream API */
2313 stream_forward_getp(peer
->curr
, length
);
2315 /* The Extended Community attribute SHALL be considered malformed if
2316 * its length is not a non-zero multiple of 8.
2318 if (!bgp_attr_get_ecommunity(attr
))
2319 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2322 /* Extract DF election preference and mobility sequence number */
2323 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2325 /* Extract MAC mobility sequence number, if any. */
2326 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2327 attr
->sticky
= sticky
;
2329 /* Check if this is a Gateway MAC-IP advertisement */
2330 attr
->default_gw
= bgp_attr_default_gw(attr
);
2332 /* Handle scenario where router flag ecommunity is not
2333 * set but default gw ext community is present.
2334 * Use default gateway, set and propogate R-bit.
2336 if (attr
->default_gw
)
2337 attr
->router_flag
= 1;
2339 /* Check EVPN Neighbor advertisement flags, R-bit */
2340 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2342 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2344 /* Extract the Rmac, if any */
2345 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2346 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2347 && bgp_mac_exist(&attr
->rmac
))
2348 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2352 /* Get the tunnel type from encap extended community */
2353 bgp_attr_extcom_tunnel_type(attr
,
2354 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2356 /* Extract link bandwidth, if any. */
2357 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2360 return BGP_ATTR_PARSE_PROCEED
;
2363 /* IPv6 Extended Community attribute. */
2364 static bgp_attr_parse_ret_t
2365 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2367 struct peer
*const peer
= args
->peer
;
2368 struct attr
*const attr
= args
->attr
;
2369 const bgp_size_t length
= args
->length
;
2370 struct ecommunity
*ipv6_ecomm
= NULL
;
2373 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2374 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2378 ipv6_ecomm
= ecommunity_parse_ipv6(
2379 stream_pnt(peer
->curr
), length
,
2380 CHECK_FLAG(peer
->flags
,
2381 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2382 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2384 /* XXX: fix ecommunity_parse to use stream API */
2385 stream_forward_getp(peer
->curr
, length
);
2388 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2391 return BGP_ATTR_PARSE_PROCEED
;
2394 /* Parse Tunnel Encap attribute in an UPDATE */
2395 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2396 bgp_size_t length
, /* IN: attr's length field */
2397 struct attr
*attr
, /* IN: caller already allocated */
2398 uint8_t flag
, /* IN: attr's flags field */
2402 uint16_t tunneltype
= 0;
2404 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2406 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2407 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2409 "Tunnel Encap attribute flag isn't optional and transitive %d",
2411 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2412 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2417 if (BGP_ATTR_ENCAP
== type
) {
2418 /* read outer TLV type and length */
2419 uint16_t tlv_length
;
2423 "Tunnel Encap attribute not long enough to contain outer T,L");
2424 bgp_notify_send_with_data(
2425 peer
, BGP_NOTIFY_UPDATE_ERR
,
2426 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2429 tunneltype
= stream_getw(BGP_INPUT(peer
));
2430 tlv_length
= stream_getw(BGP_INPUT(peer
));
2433 if (tlv_length
!= length
) {
2434 zlog_info("%s: tlv_length(%d) != length(%d)",
2435 __func__
, tlv_length
, length
);
2439 while (length
>= 4) {
2440 uint16_t subtype
= 0;
2441 uint16_t sublength
= 0;
2442 struct bgp_attr_encap_subtlv
*tlv
;
2444 if (BGP_ATTR_ENCAP
== type
) {
2445 subtype
= stream_getc(BGP_INPUT(peer
));
2446 sublength
= stream_getc(BGP_INPUT(peer
));
2448 #ifdef ENABLE_BGP_VNC
2450 subtype
= stream_getw(BGP_INPUT(peer
));
2451 sublength
= stream_getw(BGP_INPUT(peer
));
2456 if (sublength
> length
) {
2458 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2460 bgp_notify_send_with_data(
2461 peer
, BGP_NOTIFY_UPDATE_ERR
,
2462 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2466 /* alloc and copy sub-tlv */
2467 /* TBD make sure these are freed when attributes are released */
2468 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2469 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2470 tlv
->type
= subtype
;
2471 tlv
->length
= sublength
;
2472 stream_get(tlv
->value
, peer
->curr
, sublength
);
2473 length
-= sublength
;
2475 /* attach tlv to encap chain */
2476 if (BGP_ATTR_ENCAP
== type
) {
2477 struct bgp_attr_encap_subtlv
*stlv_last
;
2478 for (stlv_last
= attr
->encap_subtlvs
;
2479 stlv_last
&& stlv_last
->next
;
2480 stlv_last
= stlv_last
->next
)
2483 stlv_last
->next
= tlv
;
2485 attr
->encap_subtlvs
= tlv
;
2487 #ifdef ENABLE_BGP_VNC
2489 struct bgp_attr_encap_subtlv
*stlv_last
;
2490 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2491 bgp_attr_get_vnc_subtlvs(attr
);
2493 for (stlv_last
= vnc_subtlvs
;
2494 stlv_last
&& stlv_last
->next
;
2495 stlv_last
= stlv_last
->next
)
2498 stlv_last
->next
= tlv
;
2500 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2505 if (BGP_ATTR_ENCAP
== type
) {
2506 attr
->encap_tunneltype
= tunneltype
;
2510 /* spurious leftover data */
2512 "Tunnel Encap attribute length is bad: %d leftover octets",
2514 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2515 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2524 /* SRv6 Service Data Sub-Sub-TLV attribute
2525 * draft-ietf-bess-srv6-services-07
2527 static bgp_attr_parse_ret_t
2528 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2530 struct peer
*const peer
= args
->peer
;
2531 struct attr
*const attr
= args
->attr
;
2532 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2533 transposition_len
, transposition_offset
;
2535 size_t headersz
= sizeof(type
) + sizeof(length
);
2537 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2540 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2541 headersz
, STREAM_READABLE(peer
->curr
));
2542 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2546 type
= stream_getc(peer
->curr
);
2547 length
= stream_getw(peer
->curr
);
2549 if (STREAM_READABLE(peer
->curr
) < length
) {
2552 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2553 length
, STREAM_READABLE(peer
->curr
));
2554 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2558 if (length
< BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
) {
2561 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2562 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
,
2564 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2568 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2569 loc_block_len
= stream_getc(peer
->curr
);
2570 loc_node_len
= stream_getc(peer
->curr
);
2571 func_len
= stream_getc(peer
->curr
);
2572 arg_len
= stream_getc(peer
->curr
);
2573 transposition_len
= stream_getc(peer
->curr
);
2574 transposition_offset
= stream_getc(peer
->curr
);
2576 /* Log SRv6 Service Data Sub-Sub-TLV */
2577 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2579 "%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",
2580 __func__
, loc_block_len
, loc_node_len
, func_len
,
2581 arg_len
, transposition_len
,
2582 transposition_offset
);
2585 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2586 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2587 attr
->srv6_l3vpn
->func_len
= func_len
;
2588 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2589 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2590 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2594 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2596 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2599 stream_forward_getp(peer
->curr
, length
);
2602 return BGP_ATTR_PARSE_PROCEED
;
2605 /* SRv6 Service Sub-TLV attribute
2606 * draft-ietf-bess-srv6-services-07
2608 static bgp_attr_parse_ret_t
2609 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2611 struct peer
*const peer
= args
->peer
;
2612 struct attr
*const attr
= args
->attr
;
2613 struct in6_addr ipv6_sid
;
2614 uint8_t type
, sid_flags
;
2615 uint16_t length
, endpoint_behavior
;
2616 size_t headersz
= sizeof(type
) + sizeof(length
);
2617 bgp_attr_parse_ret_t err
;
2620 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2623 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2624 headersz
, STREAM_READABLE(peer
->curr
));
2625 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2629 type
= stream_getc(peer
->curr
);
2630 length
= stream_getw(peer
->curr
);
2632 if (STREAM_READABLE(peer
->curr
) < length
) {
2635 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2636 length
, STREAM_READABLE(peer
->curr
));
2637 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2641 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2642 stream_getc(peer
->curr
);
2643 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2644 sid_flags
= stream_getc(peer
->curr
);
2645 endpoint_behavior
= stream_getw(peer
->curr
);
2646 stream_getc(peer
->curr
);
2648 /* Log SRv6 Service Sub-TLV */
2649 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2650 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2652 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2653 __func__
, buf
, sid_flags
, endpoint_behavior
);
2656 /* Configure from Info */
2657 if (attr
->srv6_l3vpn
) {
2658 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2659 "Prefix SID SRv6 L3VPN field repeated");
2660 return bgp_attr_malformed(
2661 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2663 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2664 sizeof(struct bgp_attr_srv6_l3vpn
));
2665 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2666 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2667 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2668 attr
->srv6_l3vpn
->loc_block_len
= 0;
2669 attr
->srv6_l3vpn
->loc_node_len
= 0;
2670 attr
->srv6_l3vpn
->func_len
= 0;
2671 attr
->srv6_l3vpn
->arg_len
= 0;
2672 attr
->srv6_l3vpn
->transposition_len
= 0;
2673 attr
->srv6_l3vpn
->transposition_offset
= 0;
2675 // Sub-Sub-TLV found
2676 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2677 err
= bgp_attr_srv6_service_data(args
);
2679 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2683 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2686 /* Placeholder code for unsupported type */
2688 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2690 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2693 stream_forward_getp(peer
->curr
, length
);
2696 return BGP_ATTR_PARSE_PROCEED
;
2700 * Read an individual SID value returning how much data we have read
2701 * Returns 0 if there was an error that needs to be passed up the stack
2703 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2704 struct bgp_attr_parser_args
*args
)
2706 struct peer
*const peer
= args
->peer
;
2707 struct attr
*const attr
= args
->attr
;
2708 uint32_t label_index
;
2709 struct in6_addr ipv6_sid
;
2711 uint32_t srgb_range
;
2713 uint8_t sid_type
, sid_flags
;
2716 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2717 if (STREAM_READABLE(peer
->curr
) < length
2718 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2719 flog_err(EC_BGP_ATTR_LEN
,
2720 "Prefix SID label index length is %hu instead of %u",
2721 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2722 return bgp_attr_malformed(args
,
2723 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2727 /* Ignore flags and reserved */
2728 stream_getc(peer
->curr
);
2729 stream_getw(peer
->curr
);
2731 /* Fetch the label index and see if it is valid. */
2732 label_index
= stream_getl(peer
->curr
);
2733 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2734 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2737 /* Store label index; subsequently, we'll check on
2739 attr
->label_index
= label_index
;
2742 /* Placeholder code for the IPv6 SID type */
2743 else if (type
== BGP_PREFIX_SID_IPV6
) {
2744 if (STREAM_READABLE(peer
->curr
) < length
2745 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2746 flog_err(EC_BGP_ATTR_LEN
,
2747 "Prefix SID IPv6 length is %hu instead of %u",
2748 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2749 return bgp_attr_malformed(args
,
2750 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2754 /* Ignore reserved */
2755 stream_getc(peer
->curr
);
2756 stream_getw(peer
->curr
);
2758 stream_get(&ipv6_sid
, peer
->curr
, 16);
2761 /* Placeholder code for the Originator SRGB type */
2762 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2764 * ietf-idr-bgp-prefix-sid-05:
2765 * Length is the total length of the value portion of the
2766 * TLV: 2 + multiple of 6.
2768 * peer->curr stream readp should be at the beginning of the 16
2769 * bit flag field at this point in the code.
2773 * Check that the TLV length field is sane: at least 2 bytes of
2774 * flag, and at least 1 SRGB (these are 6 bytes each)
2776 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2779 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2781 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2782 return bgp_attr_malformed(
2783 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2788 * Check that we actually have at least as much data as
2789 * specified by the length field
2791 if (STREAM_READABLE(peer
->curr
) < length
) {
2792 flog_err(EC_BGP_ATTR_LEN
,
2793 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2794 length
, STREAM_READABLE(peer
->curr
));
2795 return bgp_attr_malformed(
2796 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2801 * Check that the portion of the TLV containing the sequence of
2802 * SRGBs corresponds to a multiple of the SRGB size; to get
2803 * that length, we skip the 16 bit flags field
2805 stream_getw(peer
->curr
);
2807 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2810 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2811 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2812 return bgp_attr_malformed(
2813 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2817 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2819 for (int i
= 0; i
< srgb_count
; i
++) {
2820 stream_get(&srgb_base
, peer
->curr
, 3);
2821 stream_get(&srgb_range
, peer
->curr
, 3);
2825 /* Placeholder code for the VPN-SID Service type */
2826 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2827 if (STREAM_READABLE(peer
->curr
) < length
2828 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2829 flog_err(EC_BGP_ATTR_LEN
,
2830 "Prefix SID VPN SID length is %hu instead of %u",
2831 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2832 return bgp_attr_malformed(args
,
2833 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2837 /* Parse VPN-SID Sub-TLV */
2838 stream_getc(peer
->curr
); /* reserved */
2839 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2840 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2841 stream_get(&ipv6_sid
, peer
->curr
,
2842 sizeof(ipv6_sid
)); /* sid_value */
2844 /* Log VPN-SID Sub-TLV */
2845 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2846 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2848 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2849 __func__
, buf
, sid_type
, sid_flags
);
2852 /* Configure from Info */
2853 if (attr
->srv6_vpn
) {
2854 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2855 "Prefix SID SRv6 VPN field repeated");
2856 return bgp_attr_malformed(
2857 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2859 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2860 sizeof(struct bgp_attr_srv6_vpn
));
2861 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2862 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2863 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2866 /* Placeholder code for the SRv6 L3 Service type */
2867 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2868 if (STREAM_READABLE(peer
->curr
) < length
) {
2871 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
2872 length
, STREAM_READABLE(peer
->curr
));
2873 return bgp_attr_malformed(args
,
2874 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2878 /* ignore reserved */
2879 stream_getc(peer
->curr
);
2881 return bgp_attr_srv6_service(args
);
2884 /* Placeholder code for Unsupported TLV */
2887 if (STREAM_READABLE(peer
->curr
) < length
) {
2890 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2891 length
, STREAM_READABLE(peer
->curr
));
2892 return bgp_attr_malformed(
2893 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2897 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2899 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2902 stream_forward_getp(peer
->curr
, length
);
2905 return BGP_ATTR_PARSE_PROCEED
;
2908 /* Prefix SID attribute
2909 * draft-ietf-idr-bgp-prefix-sid-05
2911 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2913 struct peer
*const peer
= args
->peer
;
2914 struct attr
*const attr
= args
->attr
;
2915 bgp_attr_parse_ret_t ret
;
2917 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2921 size_t headersz
= sizeof(type
) + sizeof(length
);
2922 size_t psid_parsed_length
= 0;
2924 while (STREAM_READABLE(peer
->curr
) > 0
2925 && psid_parsed_length
< args
->length
) {
2927 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2930 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2931 headersz
, STREAM_READABLE(peer
->curr
));
2932 return bgp_attr_malformed(
2933 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2937 type
= stream_getc(peer
->curr
);
2938 length
= stream_getw(peer
->curr
);
2940 if (STREAM_READABLE(peer
->curr
) < length
) {
2943 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2944 length
, STREAM_READABLE(peer
->curr
));
2945 return bgp_attr_malformed(args
,
2946 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2950 ret
= bgp_attr_psid_sub(type
, length
, args
);
2952 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2955 psid_parsed_length
+= length
+ headersz
;
2957 if (psid_parsed_length
> args
->length
) {
2960 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2961 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2962 return bgp_attr_malformed(
2963 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2968 return BGP_ATTR_PARSE_PROCEED
;
2971 /* PMSI tunnel attribute (RFC 6514)
2972 * Basic validation checks done here.
2974 static bgp_attr_parse_ret_t
2975 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2977 struct peer
*const peer
= args
->peer
;
2978 struct attr
*const attr
= args
->attr
;
2979 const bgp_size_t length
= args
->length
;
2981 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2983 /* Verify that the receiver is expecting "ingress replication" as we
2984 * can only support that.
2986 if (length
< attr_parse_len
) {
2987 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2989 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2992 stream_getc(peer
->curr
); /* Flags */
2993 tnl_type
= stream_getc(peer
->curr
);
2994 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2995 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2996 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2997 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3000 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3002 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3003 "Bad PMSI tunnel attribute length %d for IR",
3005 return bgp_attr_malformed(
3006 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3011 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3012 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3013 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3015 /* Forward read pointer of input stream. */
3016 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3018 return BGP_ATTR_PARSE_PROCEED
;
3021 /* BGP unknown attribute treatment. */
3022 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3024 bgp_size_t total
= args
->total
;
3025 struct transit
*transit
;
3026 struct peer
*const peer
= args
->peer
;
3027 struct attr
*const attr
= args
->attr
;
3028 uint8_t *const startp
= args
->startp
;
3029 const uint8_t type
= args
->type
;
3030 const uint8_t flag
= args
->flags
;
3031 const bgp_size_t length
= args
->length
;
3033 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3035 "%s Unknown attribute is received (type %d, length %d)",
3036 peer
->host
, type
, length
);
3038 /* Forward read pointer of input stream. */
3039 stream_forward_getp(peer
->curr
, length
);
3041 /* If any of the mandatory well-known attributes are not recognized,
3042 then the Error Subcode is set to Unrecognized Well-known
3043 Attribute. The Data field contains the unrecognized attribute
3044 (type, length and value). */
3045 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3046 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3050 /* Unrecognized non-transitive optional attributes must be quietly
3051 ignored and not passed along to other BGP peers. */
3052 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3053 return BGP_ATTR_PARSE_PROCEED
;
3055 /* If a path with recognized transitive optional attribute is
3056 accepted and passed along to other BGP peers and the Partial bit
3057 in the Attribute Flags octet is set to 1 by some previous AS, it
3058 is not set back to 0 by the current AS. */
3059 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3061 /* Store transitive attribute to the end of attr->transit. */
3062 transit
= bgp_attr_get_transit(attr
);
3064 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3066 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3067 transit
->length
+ total
);
3069 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3070 transit
->length
+= total
;
3071 bgp_attr_set_transit(attr
, transit
);
3073 return BGP_ATTR_PARSE_PROCEED
;
3076 /* Well-known attribute check. */
3077 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3081 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3083 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3084 return BGP_ATTR_PARSE_PROCEED
;
3086 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3087 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3088 are present, it should. Check for any other attribute being present
3091 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3092 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3093 return BGP_ATTR_PARSE_PROCEED
;
3095 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3096 type
= BGP_ATTR_ORIGIN
;
3098 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3099 type
= BGP_ATTR_AS_PATH
;
3101 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3103 * NLRI is empty. We can't easily check NLRI empty here though.
3105 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3106 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3107 type
= BGP_ATTR_NEXT_HOP
;
3109 if (peer
->sort
== BGP_PEER_IBGP
3110 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3111 type
= BGP_ATTR_LOCAL_PREF
;
3113 /* If any of the well-known mandatory attributes are not present
3114 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3117 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3118 "%s Missing well-known attribute %s.", peer
->host
,
3119 lookup_msg(attr_str
, type
, NULL
));
3120 return BGP_ATTR_PARSE_WITHDRAW
;
3122 return BGP_ATTR_PARSE_PROCEED
;
3125 /* Read attribute of update packet. This function is called from
3126 bgp_update_receive() in bgp_packet.c. */
3127 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3128 bgp_size_t size
, struct bgp_nlri
*mp_update
,
3129 struct bgp_nlri
*mp_withdraw
)
3131 bgp_attr_parse_ret_t ret
;
3135 uint8_t *startp
, *endp
;
3137 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3138 /* we need the as4_path only until we have synthesized the as_path with
3140 /* same goes for as4_aggregator */
3141 struct aspath
*as4_path
= NULL
;
3142 as_t as4_aggregator
= 0;
3143 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3144 struct transit
*transit
;
3146 /* Initialize bitmap. */
3147 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3149 /* End pointer of BGP attribute. */
3150 endp
= BGP_INPUT_PNT(peer
) + size
;
3152 /* Get attributes to the end of attribute length. */
3153 while (BGP_INPUT_PNT(peer
) < endp
) {
3154 /* Check remaining length check.*/
3155 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3156 /* XXX warning: long int format, int arg (arg 5) */
3158 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3159 "%s: error BGP attribute length %lu is smaller than min len",
3161 (unsigned long)(endp
3162 - stream_pnt(BGP_INPUT(peer
))));
3164 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3165 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3166 ret
= BGP_ATTR_PARSE_ERROR
;
3170 /* Fetch attribute flag and type. */
3171 startp
= BGP_INPUT_PNT(peer
);
3172 /* "The lower-order four bits of the Attribute Flags octet are
3173 unused. They MUST be zero when sent and MUST be ignored when
3175 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3176 type
= stream_getc(BGP_INPUT(peer
));
3178 /* Check whether Extended-Length applies and is in bounds */
3179 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3180 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3182 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3183 "%s: Extended length set, but just %lu bytes of attr header",
3185 (unsigned long)(endp
3186 - stream_pnt(BGP_INPUT(peer
))));
3188 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3189 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3190 ret
= BGP_ATTR_PARSE_ERROR
;
3194 /* Check extended attribue length bit. */
3195 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3196 length
= stream_getw(BGP_INPUT(peer
));
3198 length
= stream_getc(BGP_INPUT(peer
));
3200 /* If any attribute appears more than once in the UPDATE
3201 message, then the Error Subcode is set to Malformed Attribute
3204 if (CHECK_BITMAP(seen
, type
)) {
3206 EC_BGP_ATTRIBUTE_REPEATED
,
3207 "%s: error BGP attribute type %d appears twice in a message",
3210 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3211 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3212 ret
= BGP_ATTR_PARSE_ERROR
;
3216 /* Set type to bitmap to check duplicate attribute. `type' is
3217 unsigned char so it never overflow bitmap range. */
3219 SET_BITMAP(seen
, type
);
3221 /* Overflow check. */
3222 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3224 if (attr_endp
> endp
) {
3226 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3227 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3228 peer
->host
, type
, length
, size
, attr_endp
,
3232 * If any recognized attribute has an Attribute
3233 * Length that conflicts with the expected length
3234 * (based on the attribute type code), then the
3235 * Error Subcode MUST be set to Attribute Length
3236 * Error. The Data field MUST contain the erroneous
3237 * attribute (type, length, and value).
3239 * We do not currently have a good way to determine the
3240 * length of the attribute independent of the length
3241 * received in the message. Instead we send the
3242 * minimum between the amount of data we have and the
3243 * amount specified by the attribute length field.
3245 * Instead of directly passing in the packet buffer and
3246 * offset we use the stream_get* functions to read into
3247 * a stack buffer, since they perform bounds checking
3248 * and we are working with untrusted data.
3250 unsigned char ndata
[peer
->max_packet_size
];
3251 memset(ndata
, 0x00, sizeof(ndata
));
3253 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3254 /* Rewind to end of flag field */
3255 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3257 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3259 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3261 size_t atl
= attr_endp
- startp
;
3262 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3263 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3265 bgp_notify_send_with_data(
3266 peer
, BGP_NOTIFY_UPDATE_ERR
,
3267 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3270 ret
= BGP_ATTR_PARSE_ERROR
;
3274 struct bgp_attr_parser_args attr_args
= {
3281 .total
= attr_endp
- startp
,
3285 /* If any recognized attribute has Attribute Flags that conflict
3286 with the Attribute Type Code, then the Error Subcode is set
3288 Attribute Flags Error. The Data field contains the erroneous
3289 attribute (type, length and value). */
3290 if (bgp_attr_flag_invalid(&attr_args
)) {
3291 ret
= bgp_attr_malformed(
3292 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3294 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3299 /* OK check attribute and store it's value. */
3301 case BGP_ATTR_ORIGIN
:
3302 ret
= bgp_attr_origin(&attr_args
);
3304 case BGP_ATTR_AS_PATH
:
3305 ret
= bgp_attr_aspath(&attr_args
);
3307 case BGP_ATTR_AS4_PATH
:
3308 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3310 case BGP_ATTR_NEXT_HOP
:
3311 ret
= bgp_attr_nexthop(&attr_args
);
3313 case BGP_ATTR_MULTI_EXIT_DISC
:
3314 ret
= bgp_attr_med(&attr_args
);
3316 case BGP_ATTR_LOCAL_PREF
:
3317 ret
= bgp_attr_local_pref(&attr_args
);
3319 case BGP_ATTR_ATOMIC_AGGREGATE
:
3320 ret
= bgp_attr_atomic(&attr_args
);
3322 case BGP_ATTR_AGGREGATOR
:
3323 ret
= bgp_attr_aggregator(&attr_args
);
3325 case BGP_ATTR_AS4_AGGREGATOR
:
3326 ret
= bgp_attr_as4_aggregator(&attr_args
,
3328 &as4_aggregator_addr
);
3330 case BGP_ATTR_COMMUNITIES
:
3331 ret
= bgp_attr_community(&attr_args
);
3333 case BGP_ATTR_LARGE_COMMUNITIES
:
3334 ret
= bgp_attr_large_community(&attr_args
);
3336 case BGP_ATTR_ORIGINATOR_ID
:
3337 ret
= bgp_attr_originator_id(&attr_args
);
3339 case BGP_ATTR_CLUSTER_LIST
:
3340 ret
= bgp_attr_cluster_list(&attr_args
);
3342 case BGP_ATTR_MP_REACH_NLRI
:
3343 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3345 case BGP_ATTR_MP_UNREACH_NLRI
:
3346 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3348 case BGP_ATTR_EXT_COMMUNITIES
:
3349 ret
= bgp_attr_ext_communities(&attr_args
);
3351 #ifdef ENABLE_BGP_VNC_ATTR
3354 case BGP_ATTR_ENCAP
:
3355 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3358 case BGP_ATTR_PREFIX_SID
:
3359 ret
= bgp_attr_prefix_sid(&attr_args
);
3361 case BGP_ATTR_PMSI_TUNNEL
:
3362 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3364 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3365 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3368 ret
= bgp_attr_unknown(&attr_args
);
3372 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3373 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3374 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3375 ret
= BGP_ATTR_PARSE_ERROR
;
3379 if (ret
== BGP_ATTR_PARSE_EOR
) {
3383 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3384 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3385 "%s: Attribute %s, parse error", peer
->host
,
3386 lookup_msg(attr_str
, type
, NULL
));
3389 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3391 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3392 "%s: Attribute %s, parse error - treating as withdrawal",
3393 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3397 /* Check the fetched length. */
3398 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3399 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3400 "%s: BGP attribute %s, fetch error",
3401 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3402 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3403 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3404 ret
= BGP_ATTR_PARSE_ERROR
;
3410 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3411 * About Prefix-SID path attribute,
3412 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3413 * may only appear in a BGP Prefix-SID attribute attached to
3414 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3415 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3417 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3418 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3420 /* Check final read pointer is same as end pointer. */
3421 if (BGP_INPUT_PNT(peer
) != endp
) {
3422 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3423 "%s: BGP attribute %s, length mismatch", peer
->host
,
3424 lookup_msg(attr_str
, type
, NULL
));
3425 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3426 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3428 ret
= BGP_ATTR_PARSE_ERROR
;
3433 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3434 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3435 * This is implemented below and will result in a NOTIFICATION. If the
3436 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3437 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3438 * message SHOULD NOT be sent. This is implemented elsewhere.
3440 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3441 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3442 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3443 * speaker that receives the message SHOULD ignore this attribute.
3445 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3446 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3447 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3448 ret
= BGP_ATTR_PARSE_ERROR
;
3453 /* Check all mandatory well-known attributes are present */
3454 ret
= bgp_attr_check(peer
, attr
);
3459 * At this place we can see whether we got AS4_PATH and/or
3460 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3461 * We can not do this before we've read all attributes because
3462 * the as4 handling does not say whether AS4_PATH has to be sent
3463 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3464 * in relationship to AGGREGATOR.
3465 * So, to be defensive, we are not relying on any order and read
3466 * all attributes first, including these 32bit ones, and now,
3467 * afterwards, we look what and if something is to be done for as4.
3469 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3472 /* actually... this doesn't ever return failure currently, but
3473 * better safe than sorry */
3474 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3475 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3476 &as4_aggregator_addr
)) {
3477 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3478 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3479 ret
= BGP_ATTR_PARSE_ERROR
;
3484 * Finally do the checks on the aspath we did not do yet
3485 * because we waited for a potentially synthesized aspath.
3487 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3488 ret
= bgp_attr_aspath_check(peer
, attr
);
3489 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3493 ret
= BGP_ATTR_PARSE_PROCEED
;
3497 * At this stage, we have done all fiddling with as4, and the
3498 * resulting info is in attr->aggregator resp. attr->aspath so
3499 * we can chuck as4_aggregator and as4_path alltogether in order
3503 * unintern - it is in the hash
3504 * The flag that we got this is still there, but that
3505 * does not do any trouble
3507 aspath_unintern(&as4_path
);
3509 transit
= bgp_attr_get_transit(attr
);
3510 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3511 /* Finally intern unknown attribute. */
3513 bgp_attr_set_transit(attr
, transit_intern(transit
));
3514 if (attr
->encap_subtlvs
)
3515 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3517 #ifdef ENABLE_BGP_VNC
3518 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3519 bgp_attr_get_vnc_subtlvs(attr
);
3522 bgp_attr_set_vnc_subtlvs(
3524 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3528 transit_free(transit
);
3529 bgp_attr_set_transit(attr
, NULL
);
3532 bgp_attr_flush_encap(attr
);
3536 transit
= bgp_attr_get_transit(attr
);
3538 assert(transit
->refcnt
> 0);
3539 if (attr
->encap_subtlvs
)
3540 assert(attr
->encap_subtlvs
->refcnt
> 0);
3541 #ifdef ENABLE_BGP_VNC
3542 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3543 bgp_attr_get_vnc_subtlvs(attr
);
3546 assert(vnc_subtlvs
->refcnt
> 0);
3553 * Extract the tunnel type from extended community
3555 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3556 bgp_encap_types
*tunnel_type
)
3558 struct ecommunity
*ecom
;
3564 ecom
= bgp_attr_get_ecommunity(attr
);
3565 if (!ecom
|| !ecom
->size
)
3568 for (i
= 0; i
< ecom
->size
; i
++) {
3570 uint8_t type
, sub_type
;
3572 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3575 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3576 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3578 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3585 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3586 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3591 iana_safi_t pkt_safi
;
3594 /* Set extended bit always to encode the attribute length as 2 bytes */
3595 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3596 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3597 sizep
= stream_get_endp(s
);
3598 stream_putw(s
, 0); /* Marker: Attribute length. */
3601 /* Convert AFI, SAFI to values for packet. */
3602 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3604 stream_putw(s
, pkt_afi
); /* AFI */
3605 stream_putc(s
, pkt_safi
); /* SAFI */
3609 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3610 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3611 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3612 else if (safi
== SAFI_FLOWSPEC
)
3615 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3618 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3623 case SAFI_MULTICAST
:
3624 case SAFI_LABELED_UNICAST
:
3626 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3630 stream_putl(s
, 0); /* RD = 0, per RFC */
3632 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3637 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3640 if (attr
->mp_nexthop_len
== 0)
3641 stream_putc(s
, 0); /* no nexthop for flowspec */
3643 stream_putc(s
, attr
->mp_nexthop_len
);
3644 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3653 case SAFI_MULTICAST
:
3654 case SAFI_LABELED_UNICAST
:
3656 if (attr
->mp_nexthop_len
3657 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3659 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3660 stream_put(s
, &attr
->mp_nexthop_global
,
3662 stream_put(s
, &attr
->mp_nexthop_local
,
3665 stream_putc(s
, IPV6_MAX_BYTELEN
);
3666 stream_put(s
, &attr
->mp_nexthop_global
,
3670 case SAFI_MPLS_VPN
: {
3671 if (attr
->mp_nexthop_len
3672 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3674 stream_putl(s
, 0); /* RD = 0, per RFC */
3676 stream_put(s
, &attr
->mp_nexthop_global
,
3678 } else if (attr
->mp_nexthop_len
3679 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3681 stream_putl(s
, 0); /* RD = 0, per RFC */
3683 stream_put(s
, &attr
->mp_nexthop_global
,
3685 stream_putl(s
, 0); /* RD = 0, per RFC */
3687 stream_put(s
, &attr
->mp_nexthop_local
,
3692 stream_putc(s
, IPV6_MAX_BYTELEN
);
3693 stream_put(s
, &attr
->mp_nexthop_global
,
3697 stream_putc(s
, 0); /* no nexthop for flowspec */
3703 if (safi
!= SAFI_FLOWSPEC
)
3705 EC_BGP_ATTR_NH_SEND_LEN
,
3706 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3707 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3716 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3717 const struct prefix
*p
,
3718 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3719 uint32_t num_labels
, bool addpath_capable
,
3720 uint32_t addpath_tx_id
, struct attr
*attr
)
3722 if (safi
== SAFI_MPLS_VPN
) {
3723 if (addpath_capable
)
3724 stream_putl(s
, addpath_tx_id
);
3725 /* Label, RD, Prefix write. */
3726 stream_putc(s
, p
->prefixlen
+ 88);
3727 stream_put(s
, label
, BGP_LABEL_BYTES
);
3728 stream_put(s
, prd
->val
, 8);
3729 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3730 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3731 /* EVPN prefix - contents depend on type */
3732 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3733 addpath_capable
, addpath_tx_id
);
3734 } else if (safi
== SAFI_LABELED_UNICAST
) {
3735 /* Prefix write with label. */
3736 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3738 } else if (safi
== SAFI_FLOWSPEC
) {
3739 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3740 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3741 p
->u
.prefix_flowspec
.prefixlen
);
3743 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
3746 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3747 const struct prefix
*p
)
3749 int size
= PSIZE(p
->prefixlen
);
3750 if (safi
== SAFI_MPLS_VPN
)
3752 else if (safi
== SAFI_LABELED_UNICAST
)
3753 size
+= BGP_LABEL_BYTES
;
3754 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3755 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3761 * Encodes the tunnel encapsulation attribute,
3762 * and with ENABLE_BGP_VNC the VNC attribute which uses
3763 * almost the same TLV format
3765 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3766 struct stream
*s
, struct attr
*attr
,
3769 unsigned int attrlenfield
= 0;
3770 unsigned int attrhdrlen
= 0;
3771 struct bgp_attr_encap_subtlv
*subtlvs
;
3772 struct bgp_attr_encap_subtlv
*st
;
3773 const char *attrname
;
3775 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3776 && (!attr
->encap_tunneltype
3777 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3781 case BGP_ATTR_ENCAP
:
3782 attrname
= "Tunnel Encap";
3783 subtlvs
= attr
->encap_subtlvs
;
3784 if (subtlvs
== NULL
) /* nothing to do */
3787 * The tunnel encap attr has an "outer" tlv.
3789 * L = total length of subtlvs,
3790 * V = concatenated subtlvs.
3792 attrlenfield
= 2 + 2; /* T + L */
3793 attrhdrlen
= 1 + 1; /* subTLV T + L */
3796 #ifdef ENABLE_BGP_VNC_ATTR
3799 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3800 if (subtlvs
== NULL
) /* nothing to do */
3802 attrlenfield
= 0; /* no outer T + L */
3803 attrhdrlen
= 2 + 2; /* subTLV T + L */
3811 /* compute attr length */
3812 for (st
= subtlvs
; st
; st
= st
->next
) {
3813 attrlenfield
+= (attrhdrlen
+ st
->length
);
3816 if (attrlenfield
> 0xffff) {
3817 zlog_info("%s attribute is too long (length=%d), can't send it",
3818 attrname
, attrlenfield
);
3822 if (attrlenfield
> 0xff) {
3823 /* 2-octet length field */
3825 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3826 | BGP_ATTR_FLAG_EXTLEN
);
3827 stream_putc(s
, attrtype
);
3828 stream_putw(s
, attrlenfield
& 0xffff);
3830 /* 1-octet length field */
3831 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3832 stream_putc(s
, attrtype
);
3833 stream_putc(s
, attrlenfield
& 0xff);
3836 if (attrtype
== BGP_ATTR_ENCAP
) {
3837 /* write outer T+L */
3838 stream_putw(s
, attr
->encap_tunneltype
);
3839 stream_putw(s
, attrlenfield
- 4);
3842 /* write each sub-tlv */
3843 for (st
= subtlvs
; st
; st
= st
->next
) {
3844 if (attrtype
== BGP_ATTR_ENCAP
) {
3845 stream_putc(s
, st
->type
);
3846 stream_putc(s
, st
->length
);
3847 #ifdef ENABLE_BGP_VNC
3849 stream_putw(s
, st
->type
);
3850 stream_putw(s
, st
->length
);
3853 stream_put(s
, st
->value
, st
->length
);
3857 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3859 /* Set MP attribute length. Don't count the (2) bytes used to encode
3861 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3864 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3866 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3867 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3868 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3869 PEER_FLAG_REMOVE_PRIVATE_AS
)
3870 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3871 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3872 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3873 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3874 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3875 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3880 /* Make attribute packet. */
3881 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3882 struct stream
*s
, struct attr
*attr
,
3883 struct bpacket_attr_vec_arr
*vecarr
,
3884 struct prefix
*p
, afi_t afi
, safi_t safi
,
3885 struct peer
*from
, struct prefix_rd
*prd
,
3886 mpls_label_t
*label
, uint32_t num_labels
,
3887 bool addpath_capable
, uint32_t addpath_tx_id
)
3890 size_t aspath_sizep
;
3891 struct aspath
*aspath
;
3892 int send_as4_path
= 0;
3893 int send_as4_aggregator
= 0;
3894 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
3895 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
3900 /* Remember current pointer. */
3901 cp
= stream_get_endp(s
);
3904 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3905 && !peer_cap_enhe(peer
, afi
, safi
))) {
3906 size_t mpattrlen_pos
= 0;
3908 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3910 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3911 num_labels
, addpath_capable
,
3912 addpath_tx_id
, attr
);
3913 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3916 /* Origin attribute. */
3917 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3918 stream_putc(s
, BGP_ATTR_ORIGIN
);
3920 stream_putc(s
, attr
->origin
);
3922 /* AS path attribute. */
3924 /* If remote-peer is EBGP */
3925 if (peer
->sort
== BGP_PEER_EBGP
3926 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3927 PEER_FLAG_AS_PATH_UNCHANGED
)
3928 || attr
->aspath
->segments
== NULL
)
3929 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3930 PEER_FLAG_RSERVER_CLIENT
))) {
3931 aspath
= aspath_dup(attr
->aspath
);
3933 /* Even though we may not be configured for confederations we
3935 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3936 aspath
= aspath_delete_confed_seq(aspath
);
3938 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3939 /* Stuff our path CONFED_ID on the front */
3940 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3942 if (peer
->change_local_as
) {
3943 /* If replace-as is specified, we only use the
3944 change_local_as when
3945 advertising routes. */
3946 if (!CHECK_FLAG(peer
->flags
,
3947 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3948 if (bgp_append_local_as(peer
, afi
,
3950 aspath
= aspath_add_seq(
3951 aspath
, peer
->local_as
);
3952 aspath
= aspath_add_seq(aspath
,
3953 peer
->change_local_as
);
3955 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3958 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3959 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3961 aspath
= aspath_dup(attr
->aspath
);
3962 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3964 aspath
= attr
->aspath
;
3966 /* If peer is not AS4 capable, then:
3967 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3968 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3970 * types are in it (i.e. exclude them if they are there)
3971 * AND do this only if there is at least one asnum > 65535 in the
3973 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3975 * all ASnums > 65535 to BGP_AS_TRANS
3978 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3979 stream_putc(s
, BGP_ATTR_AS_PATH
);
3980 aspath_sizep
= stream_get_endp(s
);
3982 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3984 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3987 if (!use32bit
&& aspath_has_as4(aspath
))
3989 1; /* we'll do this later, at the correct place */
3991 /* Nexthop attribute. */
3992 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3993 && !peer_cap_enhe(peer
, afi
, safi
)) {
3994 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3996 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3997 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3998 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3999 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4002 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4003 } else if (peer_cap_enhe(from
, afi
, safi
)
4004 || (nh_afi
== AFI_IP6
)) {
4006 * Likely this is the case when an IPv4 prefix was
4007 * received with Extended Next-hop capability in this
4008 * or another vrf and is now being advertised to
4009 * non-ENHE peers. Since peer_cap_enhe only checks
4010 * peers in this vrf, also check the nh_afi to catch
4011 * the case where the originator was in another vrf.
4012 * Setting the mandatory (ipv4) next-hop attribute here
4013 * to enable implicit next-hop self with correct A-F
4014 * (ipv4 address family).
4016 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4017 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4018 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4021 stream_put_ipv4(s
, 0);
4025 /* MED attribute. */
4026 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4027 || bgp
->maxmed_active
) {
4028 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4029 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4031 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4035 /* Local preference. */
4036 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4037 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4038 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4040 stream_putl(s
, attr
->local_pref
);
4043 /* Atomic aggregate. */
4044 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4045 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4046 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4051 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4052 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4053 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4054 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4057 /* AS4 capable peer */
4059 stream_putl(s
, attr
->aggregator_as
);
4061 /* 2-byte AS peer */
4064 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4066 if (attr
->aggregator_as
> UINT16_MAX
) {
4067 stream_putw(s
, BGP_AS_TRANS
);
4069 /* we have to send AS4_AGGREGATOR, too.
4070 * we'll do that later in order to send
4071 * attributes in ascending
4074 send_as4_aggregator
= 1;
4076 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4078 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4081 /* Community attribute. */
4082 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4083 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4084 struct community
*comm
= NULL
;
4086 comm
= bgp_attr_get_community(attr
);
4087 if (comm
->size
* 4 > 255) {
4089 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4090 | BGP_ATTR_FLAG_EXTLEN
);
4091 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4092 stream_putw(s
, comm
->size
* 4);
4095 BGP_ATTR_FLAG_OPTIONAL
4096 | BGP_ATTR_FLAG_TRANS
);
4097 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4098 stream_putc(s
, comm
->size
* 4);
4100 stream_put(s
, comm
->val
, comm
->size
* 4);
4104 * Large Community attribute.
4106 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4107 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4108 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4109 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4111 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4112 | BGP_ATTR_FLAG_EXTLEN
);
4113 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4115 lcom_length(bgp_attr_get_lcommunity(attr
)));
4118 BGP_ATTR_FLAG_OPTIONAL
4119 | BGP_ATTR_FLAG_TRANS
);
4120 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4122 lcom_length(bgp_attr_get_lcommunity(attr
)));
4124 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4125 lcom_length(bgp_attr_get_lcommunity(attr
)));
4128 /* Route Reflector. */
4129 if (peer
->sort
== BGP_PEER_IBGP
&& from
4130 && from
->sort
== BGP_PEER_IBGP
) {
4131 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4133 /* Originator ID. */
4134 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4135 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4138 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4139 stream_put_in_addr(s
, &attr
->originator_id
);
4141 stream_put_in_addr(s
, &from
->remote_id
);
4144 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4145 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4148 stream_putc(s
, cluster
->length
+ 4);
4149 /* If this peer configuration's parent BGP has
4151 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4152 stream_put_in_addr(s
, &bgp
->cluster_id
);
4154 stream_put_in_addr(s
, &bgp
->router_id
);
4155 stream_put(s
, cluster
->list
, cluster
->length
);
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
);
4167 /* Extended Communities attribute. */
4168 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4169 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4170 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4172 if (peer
->sort
== BGP_PEER_IBGP
4173 || peer
->sort
== BGP_PEER_CONFED
) {
4174 if (ecomm
->size
* 8 > 255) {
4176 BGP_ATTR_FLAG_OPTIONAL
4177 | BGP_ATTR_FLAG_TRANS
4178 | BGP_ATTR_FLAG_EXTLEN
);
4179 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4180 stream_putw(s
, ecomm
->size
* 8);
4183 BGP_ATTR_FLAG_OPTIONAL
4184 | BGP_ATTR_FLAG_TRANS
);
4185 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4186 stream_putc(s
, ecomm
->size
* 8);
4188 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4192 int ecom_tr_size
= 0;
4195 for (i
= 0; i
< ecomm
->size
; i
++) {
4196 pnt
= ecomm
->val
+ (i
* 8);
4199 if (CHECK_FLAG(tbit
,
4200 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4207 if (ecom_tr_size
* 8 > 255) {
4210 BGP_ATTR_FLAG_OPTIONAL
4211 | BGP_ATTR_FLAG_TRANS
4212 | BGP_ATTR_FLAG_EXTLEN
);
4214 BGP_ATTR_EXT_COMMUNITIES
);
4215 stream_putw(s
, ecom_tr_size
* 8);
4219 BGP_ATTR_FLAG_OPTIONAL
4220 | BGP_ATTR_FLAG_TRANS
);
4222 BGP_ATTR_EXT_COMMUNITIES
);
4223 stream_putc(s
, ecom_tr_size
* 8);
4226 for (i
= 0; i
< ecomm
->size
; i
++) {
4227 pnt
= ecomm
->val
+ (i
* 8);
4232 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4235 stream_put(s
, pnt
, 8);
4241 /* Label index attribute. */
4242 if (safi
== SAFI_LABELED_UNICAST
) {
4243 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4244 uint32_t label_index
;
4246 label_index
= attr
->label_index
;
4248 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4250 BGP_ATTR_FLAG_OPTIONAL
4251 | BGP_ATTR_FLAG_TRANS
);
4252 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4254 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4256 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4257 stream_putc(s
, 0); // reserved
4258 stream_putw(s
, 0); // flags
4259 stream_putl(s
, label_index
);
4264 /* SRv6 Service Information Attribute. */
4265 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4266 if (attr
->srv6_l3vpn
) {
4267 uint8_t subtlv_len
=
4268 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4270 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4271 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4272 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4273 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4274 | BGP_ATTR_FLAG_TRANS
);
4275 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4276 stream_putc(s
, attr_len
);
4277 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4278 stream_putw(s
, tlv_len
);
4279 stream_putc(s
, 0); /* reserved */
4280 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4281 stream_putw(s
, subtlv_len
);
4282 stream_putc(s
, 0); /* reserved */
4283 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4284 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4285 stream_putc(s
, 0); /* sid_flags */
4286 stream_putw(s
, 0xffff); /* endpoint */
4287 stream_putc(s
, 0); /* reserved */
4290 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4293 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4294 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4295 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4296 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4297 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4298 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4299 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4300 } else if (attr
->srv6_vpn
) {
4301 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4302 | BGP_ATTR_FLAG_TRANS
);
4303 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4304 stream_putc(s
, 22); /* tlv len */
4305 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4306 stream_putw(s
, 0x13); /* tlv len */
4307 stream_putc(s
, 0x00); /* reserved */
4308 stream_putc(s
, 0x01); /* sid_type */
4309 stream_putc(s
, 0x00); /* sif_flags */
4310 stream_put(s
, &attr
->srv6_vpn
->sid
,
4311 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4315 if (send_as4_path
) {
4316 /* If the peer is NOT As4 capable, AND */
4317 /* there are ASnums > 65535 in path THEN
4318 * give out AS4_PATH */
4320 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4322 * Hm, I wonder... confederation things *should* only be at
4323 * the beginning of an aspath, right? Then we should use
4324 * aspath_delete_confed_seq for this, because it is already
4326 * Folks, talk to me: what is reasonable here!?
4328 aspath
= aspath_delete_confed_seq(aspath
);
4331 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4332 | BGP_ATTR_FLAG_EXTLEN
);
4333 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4334 aspath_sizep
= stream_get_endp(s
);
4336 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4339 if (aspath
!= attr
->aspath
)
4340 aspath_free(aspath
);
4342 if (send_as4_aggregator
) {
4343 /* send AS4_AGGREGATOR, at this place */
4344 /* this section of code moved here in order to ensure the
4346 * *ascending* order of attributes
4348 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4349 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4351 stream_putl(s
, attr
->aggregator_as
);
4352 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4355 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4356 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4357 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4358 /* Tunnel Encap attribute */
4359 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4361 #ifdef ENABLE_BGP_VNC_ATTR
4363 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4368 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4369 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4370 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4371 stream_putc(s
, 9); // Length
4372 stream_putc(s
, 0); // Flags
4373 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4374 stream_put(s
, &(attr
->label
),
4375 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4376 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4377 // Unicast tunnel endpoint IP address
4380 /* Unknown transit attribute. */
4381 struct transit
*transit
= bgp_attr_get_transit(attr
);
4384 stream_put(s
, transit
->val
, transit
->length
);
4386 /* Return total size of attribute. */
4387 return stream_get_endp(s
) - cp
;
4390 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4392 unsigned long attrlen_pnt
;
4394 iana_safi_t pkt_safi
;
4396 /* Set extended bit always to encode the attribute length as 2 bytes */
4397 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4398 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4400 attrlen_pnt
= stream_get_endp(s
);
4401 stream_putw(s
, 0); /* Length of this attribute. */
4403 /* Convert AFI, SAFI to values for packet. */
4404 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4406 stream_putw(s
, pkt_afi
);
4407 stream_putc(s
, pkt_safi
);
4412 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4413 afi_t afi
, safi_t safi
,
4414 const struct prefix_rd
*prd
,
4415 mpls_label_t
*label
, uint32_t num_labels
,
4416 bool addpath_capable
, uint32_t addpath_tx_id
,
4419 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4421 if (safi
== SAFI_LABELED_UNICAST
) {
4422 label
= (mpls_label_t
*)wlabel
;
4426 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4427 addpath_capable
, addpath_tx_id
, attr
);
4430 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4432 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4435 /* Initialization of attribute. */
4436 void bgp_attr_init(void)
4449 void bgp_attr_finish(void)
4454 ecommunity_finish();
4455 lcommunity_finish();
4462 /* Make attribute packet. */
4463 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4464 const struct prefix
*prefix
)
4469 struct aspath
*aspath
;
4470 bool addpath_capable
= false;
4471 uint32_t addpath_tx_id
= 0;
4473 /* Remember current pointer. */
4474 cp
= stream_get_endp(s
);
4476 /* Place holder of length. */
4479 /* Origin attribute. */
4480 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4481 stream_putc(s
, BGP_ATTR_ORIGIN
);
4483 stream_putc(s
, attr
->origin
);
4485 aspath
= attr
->aspath
;
4487 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4488 stream_putc(s
, BGP_ATTR_AS_PATH
);
4489 aspath_lenp
= stream_get_endp(s
);
4492 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4494 /* Nexthop attribute. */
4495 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4496 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4497 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4498 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4500 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4503 /* MED attribute. */
4504 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4505 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4506 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4508 stream_putl(s
, attr
->med
);
4511 /* Local preference. */
4512 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4513 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4514 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4516 stream_putl(s
, attr
->local_pref
);
4519 /* Atomic aggregate. */
4520 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4521 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4522 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4527 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4528 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4529 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4531 stream_putl(s
, attr
->aggregator_as
);
4532 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4535 /* Community attribute. */
4536 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4537 struct community
*comm
= NULL
;
4539 comm
= bgp_attr_get_community(attr
);
4540 if (comm
->size
* 4 > 255) {
4542 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4543 | BGP_ATTR_FLAG_EXTLEN
);
4544 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4545 stream_putw(s
, comm
->size
* 4);
4548 BGP_ATTR_FLAG_OPTIONAL
4549 | BGP_ATTR_FLAG_TRANS
);
4550 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4551 stream_putc(s
, comm
->size
* 4);
4553 stream_put(s
, comm
->val
, comm
->size
* 4);
4556 /* Large Community attribute. */
4557 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4558 if (lcom_length(bgp_attr_get_lcommunity(attr
)) > 255) {
4560 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4561 | BGP_ATTR_FLAG_EXTLEN
);
4562 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4564 lcom_length(bgp_attr_get_lcommunity(attr
)));
4567 BGP_ATTR_FLAG_OPTIONAL
4568 | BGP_ATTR_FLAG_TRANS
);
4569 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4571 lcom_length(bgp_attr_get_lcommunity(attr
)));
4574 stream_put(s
, bgp_attr_get_lcommunity(attr
)->val
,
4575 lcom_length(bgp_attr_get_lcommunity(attr
)));
4578 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4579 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4580 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4581 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4584 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4585 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4586 sizep
= stream_get_endp(s
);
4589 stream_putc(s
, 0); /* Marker: Attribute length. */
4590 stream_putw(s
, AFI_IP6
); /* AFI */
4591 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4594 stream_putc(s
, attr
->mp_nexthop_len
);
4595 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4596 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4597 stream_put(s
, &attr
->mp_nexthop_local
,
4604 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4607 /* Set MP attribute length. */
4608 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4612 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4613 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4615 BGP_ATTR_FLAG_OPTIONAL
4616 | BGP_ATTR_FLAG_TRANS
);
4617 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4619 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4620 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4621 stream_putc(s
, 0); // reserved
4622 stream_putw(s
, 0); // flags
4623 stream_putl(s
, attr
->label_index
);
4627 /* Return total size of attribute. */
4628 len
= stream_get_endp(s
) - cp
- 2;
4629 stream_putw_at(s
, cp
, len
);