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 struct attr_extra
*bgp_attr_extra_alloc(void)
100 return XCALLOC(MTYPE_ATTR_EXTRA
, sizeof(struct attr_extra
));
103 void bgp_attr_extra_free(struct attr
*attr
)
105 XFREE(MTYPE_ATTR_EXTRA
, attr
->extra
);
108 static void *cluster_hash_alloc(void *p
)
110 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
111 struct cluster_list
*cluster
;
113 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
114 cluster
->length
= val
->length
;
116 if (cluster
->length
) {
117 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
118 memcpy(cluster
->list
, val
->list
, val
->length
);
120 cluster
->list
= NULL
;
127 /* Cluster list related functions. */
128 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
130 struct cluster_list tmp
= {};
131 struct cluster_list
*cluster
;
134 tmp
.list
= length
== 0 ? NULL
: pnt
;
136 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
141 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
145 for (i
= 0; i
< cluster
->length
/ 4; i
++)
146 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
151 static unsigned int cluster_hash_key_make(const void *p
)
153 const struct cluster_list
*cluster
= p
;
155 return jhash(cluster
->list
, cluster
->length
, 0);
158 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
160 const struct cluster_list
*cluster1
= p1
;
161 const struct cluster_list
*cluster2
= p2
;
163 if (cluster1
->list
== cluster2
->list
)
166 if (!cluster1
->list
|| !cluster2
->list
)
169 if (cluster1
->length
!= cluster2
->length
)
172 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
175 static void cluster_free(struct cluster_list
*cluster
)
177 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
178 XFREE(MTYPE_CLUSTER
, cluster
);
181 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
183 struct cluster_list
*find
;
185 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
191 static void cluster_unintern(struct cluster_list
**cluster
)
193 if ((*cluster
)->refcnt
)
194 (*cluster
)->refcnt
--;
196 if ((*cluster
)->refcnt
== 0) {
197 void *p
= hash_release(cluster_hash
, *cluster
);
198 assert(p
== *cluster
);
199 cluster_free(*cluster
);
204 static void cluster_init(void)
206 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
210 static void cluster_finish(void)
212 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
213 hash_free(cluster_hash
);
217 static struct hash
*encap_hash
= NULL
;
218 #ifdef ENABLE_BGP_VNC
219 static struct hash
*vnc_hash
= NULL
;
221 static struct hash
*srv6_l3vpn_hash
;
222 static struct hash
*srv6_vpn_hash
;
224 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
226 struct bgp_attr_encap_subtlv
*new;
227 struct bgp_attr_encap_subtlv
*tail
;
228 struct bgp_attr_encap_subtlv
*p
;
230 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
231 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
233 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
236 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
239 memcpy(tail
, p
, size
);
246 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
248 struct bgp_attr_encap_subtlv
*next
;
252 XFREE(MTYPE_ENCAP_TLV
, p
);
257 void bgp_attr_flush_encap(struct attr
*attr
)
262 if (attr
->encap_subtlvs
) {
263 encap_free(attr
->encap_subtlvs
);
264 attr
->encap_subtlvs
= NULL
;
266 #ifdef ENABLE_BGP_VNC
267 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
268 bgp_attr_get_vnc_subtlvs(attr
);
271 encap_free(vnc_subtlvs
);
272 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
278 * Compare encap sub-tlv chains
283 * This algorithm could be made faster if needed
285 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
286 const struct bgp_attr_encap_subtlv
*h2
)
288 const struct bgp_attr_encap_subtlv
*p
;
289 const struct bgp_attr_encap_subtlv
*q
;
293 if (h1
== NULL
|| h2
== NULL
)
296 for (p
= h1
; p
; p
= p
->next
) {
297 for (q
= h2
; q
; q
= q
->next
) {
298 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
299 && !memcmp(p
->value
, q
->value
, p
->length
)) {
308 for (p
= h2
; p
; p
= p
->next
) {
309 for (q
= h1
; q
; q
= q
->next
) {
310 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
311 && !memcmp(p
->value
, q
->value
, p
->length
)) {
323 static void *encap_hash_alloc(void *p
)
325 /* Encap structure is already allocated. */
331 #ifdef ENABLE_BGP_VNC
336 static struct bgp_attr_encap_subtlv
*
337 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
339 struct bgp_attr_encap_subtlv
*find
;
340 struct hash
*hash
= encap_hash
;
341 #ifdef ENABLE_BGP_VNC
342 if (type
== VNC_SUBTLV_TYPE
)
346 find
= hash_get(hash
, encap
, encap_hash_alloc
);
354 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
355 encap_subtlv_type type
)
357 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
361 if (encap
->refcnt
== 0) {
362 struct hash
*hash
= encap_hash
;
363 #ifdef ENABLE_BGP_VNC
364 if (type
== VNC_SUBTLV_TYPE
)
367 hash_release(hash
, encap
);
373 static unsigned int encap_hash_key_make(const void *p
)
375 const struct bgp_attr_encap_subtlv
*encap
= p
;
377 return jhash(encap
->value
, encap
->length
, 0);
380 static bool encap_hash_cmp(const void *p1
, const void *p2
)
382 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
383 (const struct bgp_attr_encap_subtlv
*)p2
);
386 static void encap_init(void)
388 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
390 #ifdef ENABLE_BGP_VNC
391 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
396 static void encap_finish(void)
398 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
399 hash_free(encap_hash
);
401 #ifdef ENABLE_BGP_VNC
402 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
408 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
417 return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1
),
418 bgp_attr_get_evpn_overlay(a2
));
421 /* Unknown transit attribute. */
422 static struct hash
*transit_hash
;
424 static void transit_free(struct transit
*transit
)
426 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
427 XFREE(MTYPE_TRANSIT
, transit
);
430 static void *transit_hash_alloc(void *p
)
432 /* Transit structure is already allocated. */
436 static struct transit
*transit_intern(struct transit
*transit
)
438 struct transit
*find
;
440 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
442 transit_free(transit
);
448 static void transit_unintern(struct transit
**transit
)
450 if ((*transit
)->refcnt
)
451 (*transit
)->refcnt
--;
453 if ((*transit
)->refcnt
== 0) {
454 hash_release(transit_hash
, *transit
);
455 transit_free(*transit
);
460 static void *srv6_l3vpn_hash_alloc(void *p
)
465 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
467 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
470 static struct bgp_attr_srv6_l3vpn
*
471 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
473 struct bgp_attr_srv6_l3vpn
*find
;
475 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
477 srv6_l3vpn_free(l3vpn
);
482 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
484 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
489 if (l3vpn
->refcnt
== 0) {
490 hash_release(srv6_l3vpn_hash
, l3vpn
);
491 srv6_l3vpn_free(l3vpn
);
496 static void *srv6_vpn_hash_alloc(void *p
)
501 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
503 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
506 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
508 struct bgp_attr_srv6_vpn
*find
;
510 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
517 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
519 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
524 if (vpn
->refcnt
== 0) {
525 hash_release(srv6_vpn_hash
, vpn
);
531 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
533 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
536 key
= jhash(&l3vpn
->sid
, 16, key
);
537 key
= jhash_1word(l3vpn
->sid_flags
, key
);
538 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
539 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
540 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
541 key
= jhash_1word(l3vpn
->func_len
, key
);
542 key
= jhash_1word(l3vpn
->arg_len
, key
);
543 key
= jhash_1word(l3vpn
->transposition_len
, key
);
544 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
548 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
550 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
551 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
553 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
554 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
555 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
556 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
557 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
558 && l3vpn1
->func_len
== l3vpn2
->func_len
559 && l3vpn1
->arg_len
== l3vpn2
->arg_len
560 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
561 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
564 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
565 const struct bgp_attr_srv6_l3vpn
*h2
)
569 else if (h1
== NULL
|| h2
== NULL
)
572 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
575 static unsigned int srv6_vpn_hash_key_make(const void *p
)
577 const struct bgp_attr_srv6_vpn
*vpn
= p
;
580 key
= jhash(&vpn
->sid
, 16, key
);
581 key
= jhash_1word(vpn
->sid_flags
, key
);
585 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
587 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
588 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
590 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
591 && vpn1
->sid_flags
== vpn2
->sid_flags
;
594 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
595 const struct bgp_attr_srv6_vpn
*h2
)
599 else if (h1
== NULL
|| h2
== NULL
)
602 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
605 static void srv6_init(void)
608 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
609 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
610 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
611 "BGP Prefix-SID SRv6-VPN-Service-TLV");
614 static void srv6_finish(void)
616 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
617 hash_free(srv6_l3vpn_hash
);
618 srv6_l3vpn_hash
= NULL
;
619 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
620 hash_free(srv6_vpn_hash
);
621 srv6_vpn_hash
= NULL
;
624 static unsigned int transit_hash_key_make(const void *p
)
626 const struct transit
*transit
= p
;
628 return jhash(transit
->val
, transit
->length
, 0);
631 static bool transit_hash_cmp(const void *p1
, const void *p2
)
633 const struct transit
*transit1
= p1
;
634 const struct transit
*transit2
= p2
;
636 return (transit1
->length
== transit2
->length
637 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
640 static void transit_init(void)
642 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
646 static void transit_finish(void)
648 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
649 hash_free(transit_hash
);
653 /* Attribute hash routines. */
654 static struct hash
*attrhash
;
656 unsigned long int attr_count(void)
658 return attrhash
->count
;
661 unsigned long int attr_unknown_count(void)
663 return transit_hash
->count
;
666 unsigned int attrhash_key_make(const void *p
)
668 const struct attr
*attr
= (struct attr
*)p
;
670 #define MIX(val) key = jhash_1word(val, key)
671 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
673 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
674 MIX3(attr
->local_pref
, attr
->aggregator_as
,
675 attr
->aggregator_addr
.s_addr
);
676 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
677 attr
->originator_id
.s_addr
);
678 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
681 MIX(aspath_key_make(attr
->aspath
));
683 MIX(community_hash_make(attr
->community
));
685 if (attr
->lcommunity
)
686 MIX(lcommunity_hash_make(attr
->lcommunity
));
687 if (bgp_attr_get_ecommunity(attr
))
688 MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr
)));
689 if (bgp_attr_get_ipv6_ecommunity(attr
))
690 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
691 if (bgp_attr_get_cluster(attr
))
692 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
693 if (bgp_attr_get_transit(attr
))
694 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
695 if (attr
->encap_subtlvs
)
696 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
697 if (attr
->srv6_l3vpn
)
698 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
700 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
701 #ifdef ENABLE_BGP_VNC
702 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
703 bgp_attr_get_vnc_subtlvs(attr
);
705 MIX(encap_hash_key_make(vnc_subtlvs
));
707 MIX(attr
->mp_nexthop_len
);
708 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
709 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
710 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
711 MIX(attr
->rmap_table_id
);
718 bool attrhash_cmp(const void *p1
, const void *p2
)
720 const struct attr
*attr1
= p1
;
721 const struct attr
*attr2
= p2
;
723 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
724 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
725 && attr1
->aspath
== attr2
->aspath
726 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
727 && attr1
->local_pref
== attr2
->local_pref
728 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
729 if (attr1
->aggregator_as
== attr2
->aggregator_as
730 && attr1
->aggregator_addr
.s_addr
731 == attr2
->aggregator_addr
.s_addr
732 && attr1
->weight
== attr2
->weight
733 && attr1
->tag
== attr2
->tag
734 && attr1
->label_index
== attr2
->label_index
735 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
736 && bgp_attr_get_ecommunity(attr1
)
737 == bgp_attr_get_ecommunity(attr2
)
738 && bgp_attr_get_ipv6_ecommunity(attr1
)
739 == bgp_attr_get_ipv6_ecommunity(attr2
)
740 && attr1
->lcommunity
== attr2
->lcommunity
741 && bgp_attr_get_cluster(attr1
)
742 == bgp_attr_get_cluster(attr2
)
743 && bgp_attr_get_transit(attr1
)
744 == bgp_attr_get_transit(attr2
)
745 && attr1
->rmap_table_id
== attr2
->rmap_table_id
746 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
747 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
748 #ifdef ENABLE_BGP_VNC
749 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
750 bgp_attr_get_vnc_subtlvs(attr2
))
752 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
753 &attr2
->mp_nexthop_global
)
754 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
755 &attr2
->mp_nexthop_local
)
756 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
757 &attr2
->mp_nexthop_global_in
)
758 && IPV4_ADDR_SAME(&attr1
->originator_id
,
759 &attr2
->originator_id
)
760 && overlay_index_same(attr1
, attr2
)
761 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
762 && attr1
->es_flags
== attr2
->es_flags
763 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
764 && attr1
->df_pref
== attr2
->df_pref
765 && attr1
->df_alg
== attr2
->df_alg
766 && attr1
->nh_ifindex
== attr2
->nh_ifindex
767 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
768 && attr1
->distance
== attr2
->distance
769 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
770 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
771 && attr1
->srte_color
== attr2
->srte_color
772 && attr1
->nh_type
== attr2
->nh_type
773 && attr1
->bh_type
== attr2
->bh_type
)
780 static void attrhash_init(void)
783 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
787 * special for hash_clean below
789 static void attr_vfree(void *attr
)
791 bgp_attr_extra_free(attr
);
792 XFREE(MTYPE_ATTR
, attr
);
795 static void attrhash_finish(void)
797 hash_clean(attrhash
, attr_vfree
);
802 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
804 struct attr
*attr
= bucket
->data
;
805 char sid_str
[BUFSIZ
];
807 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
810 if (attr
->srv6_l3vpn
)
811 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
812 else if (attr
->srv6_vpn
)
813 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
816 "\tflags: %" PRIu64
" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
817 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
818 attr
->origin
, attr
->weight
, attr
->label
, sid_str
);
821 void attr_show_all(struct vty
*vty
)
823 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
824 void *))attr_show_all_iterator
,
828 static void *bgp_attr_hash_alloc(void *p
)
830 struct attr
*val
= (struct attr
*)p
;
833 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
835 if (val
->encap_subtlvs
) {
836 val
->encap_subtlvs
= NULL
;
838 #ifdef ENABLE_BGP_VNC
839 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
840 bgp_attr_get_vnc_subtlvs(val
);
843 bgp_attr_set_vnc_subtlvs(val
, NULL
);
850 /* Internet argument attribute. */
851 struct attr
*bgp_attr_intern(struct attr
*attr
)
854 struct ecommunity
*ecomm
= NULL
;
855 struct ecommunity
*ipv6_ecomm
= NULL
;
857 /* Intern referenced strucutre. */
859 if (!attr
->aspath
->refcnt
)
860 attr
->aspath
= aspath_intern(attr
->aspath
);
862 attr
->aspath
->refcnt
++;
864 if (attr
->community
) {
865 if (!attr
->community
->refcnt
)
866 attr
->community
= community_intern(attr
->community
);
868 attr
->community
->refcnt
++;
871 ecomm
= bgp_attr_get_ecommunity(attr
);
874 bgp_attr_set_ecommunity(attr
, ecommunity_intern(ecomm
));
879 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
881 if (!ipv6_ecomm
->refcnt
)
882 bgp_attr_set_ipv6_ecommunity(
883 attr
, ecommunity_intern(ipv6_ecomm
));
885 ipv6_ecomm
->refcnt
++;
888 if (attr
->lcommunity
) {
889 if (!attr
->lcommunity
->refcnt
)
890 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
892 attr
->lcommunity
->refcnt
++;
895 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
898 if (!cluster
->refcnt
)
899 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
904 struct transit
*transit
= bgp_attr_get_transit(attr
);
907 if (!transit
->refcnt
)
908 bgp_attr_set_transit(attr
, transit_intern(transit
));
912 if (attr
->encap_subtlvs
) {
913 if (!attr
->encap_subtlvs
->refcnt
)
914 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
917 attr
->encap_subtlvs
->refcnt
++;
919 if (attr
->srv6_l3vpn
) {
920 if (!attr
->srv6_l3vpn
->refcnt
)
921 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
923 attr
->srv6_l3vpn
->refcnt
++;
925 if (attr
->srv6_vpn
) {
926 if (!attr
->srv6_vpn
->refcnt
)
927 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
929 attr
->srv6_vpn
->refcnt
++;
931 #ifdef ENABLE_BGP_VNC
932 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
933 bgp_attr_get_vnc_subtlvs(attr
);
936 if (!vnc_subtlvs
->refcnt
)
937 bgp_attr_set_vnc_subtlvs(
939 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
941 vnc_subtlvs
->refcnt
++;
945 /* At this point, attr only contains intern'd pointers. that means
946 * if we find it in attrhash, it has all the same pointers and we
947 * correctly updated the refcounts on these.
948 * If we don't find it, we need to allocate a one because in all
949 * cases this returns a new reference to a hashed attr, but the input
951 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
957 /* Make network statement's attribute. */
958 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
960 memset(attr
, 0, sizeof(struct attr
));
962 attr
->origin
= origin
;
963 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
964 attr
->aspath
= aspath_empty();
965 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
966 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
968 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
969 attr
->label
= MPLS_INVALID_LABEL
;
970 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
971 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
976 /* Create the attributes for an aggregate */
977 struct attr
*bgp_attr_aggregate_intern(
978 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
979 struct community
*community
, struct ecommunity
*ecommunity
,
980 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
981 uint8_t atomic_aggregate
, const struct prefix
*p
)
987 memset(&attr
, 0, sizeof(struct attr
));
989 /* Origin attribute. */
990 attr
.origin
= origin
;
991 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
993 /* AS path attribute. */
995 attr
.aspath
= aspath_intern(aspath
);
997 attr
.aspath
= aspath_empty();
998 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1000 /* Next hop attribute. */
1001 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1004 uint32_t gshut
= COMMUNITY_GSHUT
;
1006 /* If we are not shutting down ourselves and we are
1007 * aggregating a route that contains the GSHUT community we
1008 * need to remove that community when creating the aggregate */
1009 if (!bgp_in_graceful_shutdown(bgp
)
1010 && community_include(community
, gshut
)) {
1011 community_del_val(community
, &gshut
);
1014 attr
.community
= community
;
1015 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1019 bgp_attr_set_ecommunity(&attr
, ecommunity
);
1020 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1024 attr
.lcommunity
= lcommunity
;
1025 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1028 if (bgp_in_graceful_shutdown(bgp
))
1029 bgp_attr_add_gshut_community(&attr
);
1031 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1032 attr
.label
= MPLS_INVALID_LABEL
;
1033 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1034 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1035 if (!aggregate
->as_set
|| atomic_aggregate
)
1036 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1037 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1038 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1039 attr
.aggregator_as
= bgp
->confed_id
;
1041 attr
.aggregator_as
= bgp
->as
;
1042 attr
.aggregator_addr
= bgp
->router_id
;
1043 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1044 attr
.label
= MPLS_INVALID_LABEL
;
1046 /* Apply route-map */
1047 if (aggregate
->rmap
.name
) {
1048 struct attr attr_tmp
= attr
;
1049 struct bgp_path_info rmap_path
;
1051 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1052 rmap_path
.peer
= bgp
->peer_self
;
1053 rmap_path
.attr
= &attr_tmp
;
1055 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1057 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1059 bgp
->peer_self
->rmap_type
= 0;
1061 if (ret
== RMAP_DENYMATCH
) {
1062 /* Free uninterned attribute. */
1063 bgp_attr_flush(&attr_tmp
);
1065 /* Unintern original. */
1066 aspath_unintern(&attr
.aspath
);
1070 if (bgp_in_graceful_shutdown(bgp
))
1071 bgp_attr_add_gshut_community(&attr_tmp
);
1073 new = bgp_attr_intern(&attr_tmp
);
1076 if (bgp_in_graceful_shutdown(bgp
))
1077 bgp_attr_add_gshut_community(&attr
);
1079 new = bgp_attr_intern(&attr
);
1082 /* Always release the 'intern()'ed AS Path. */
1083 aspath_unintern(&attr
.aspath
);
1088 /* Unintern just the sub-components of the attr, but not the attr */
1089 void bgp_attr_unintern_sub(struct attr
*attr
)
1091 struct ecommunity
*ecomm
= NULL
;
1092 struct ecommunity
*ipv6_ecomm
= NULL
;
1093 struct cluster_list
*cluster
;
1095 /* aspath refcount shoud be decrement. */
1097 aspath_unintern(&attr
->aspath
);
1098 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1100 if (attr
->community
)
1101 community_unintern(&attr
->community
);
1102 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1104 ecomm
= bgp_attr_get_ecommunity(attr
);
1105 ecommunity_unintern(&ecomm
);
1106 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
1107 bgp_attr_set_ecommunity(attr
, NULL
);
1109 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1110 ecommunity_unintern(&ipv6_ecomm
);
1111 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
));
1112 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1114 if (attr
->lcommunity
)
1115 lcommunity_unintern(&attr
->lcommunity
);
1116 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1118 cluster
= bgp_attr_get_cluster(attr
);
1120 cluster_unintern(&cluster
);
1121 bgp_attr_set_cluster(attr
, cluster
);
1123 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1125 struct transit
*transit
= bgp_attr_get_transit(attr
);
1128 transit_unintern(&transit
);
1129 bgp_attr_set_transit(attr
, transit
);
1132 if (attr
->encap_subtlvs
)
1133 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1135 #ifdef ENABLE_BGP_VNC
1136 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1137 bgp_attr_get_vnc_subtlvs(attr
);
1140 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1141 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1145 if (attr
->srv6_l3vpn
)
1146 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1149 srv6_vpn_unintern(&attr
->srv6_vpn
);
1153 * We have some show commands that let you experimentally
1154 * apply a route-map. When we apply the route-map
1155 * we are reseting values but not saving them for
1156 * posterity via intern'ing( because route-maps don't
1157 * do that) but at this point in time we need
1158 * to compare the new attr to the old and if the
1159 * routemap has changed it we need to, as Snoop Dog says,
1160 * Drop it like it's hot
1162 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
1164 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(new);
1166 if (new->aspath
!= old
->aspath
)
1167 aspath_free(new->aspath
);
1169 if (new->community
!= old
->community
)
1170 community_free(&new->community
);
1172 if (ecomm
!= bgp_attr_get_ecommunity(old
))
1173 ecommunity_free(&ecomm
);
1175 if (new->lcommunity
!= old
->lcommunity
)
1176 lcommunity_free(&new->lcommunity
);
1178 if (new->srv6_l3vpn
!= old
->srv6_l3vpn
) {
1179 srv6_l3vpn_free(new->srv6_l3vpn
);
1180 new->srv6_l3vpn
= NULL
;
1183 if (new->srv6_vpn
!= old
->srv6_vpn
) {
1184 srv6_vpn_free(new->srv6_vpn
);
1185 new->srv6_vpn
= NULL
;
1189 /* Free bgp attribute and aspath. */
1190 void bgp_attr_unintern(struct attr
**pattr
)
1192 struct attr
*attr
= *pattr
;
1196 /* Decrement attribute reference. */
1201 /* If reference becomes zero then free attribute object. */
1202 if (attr
->refcnt
== 0) {
1203 ret
= hash_release(attrhash
, attr
);
1204 assert(ret
!= NULL
);
1205 XFREE(MTYPE_ATTR
, attr
);
1209 bgp_attr_unintern_sub(&tmp
);
1212 void bgp_attr_flush(struct attr
*attr
)
1214 struct ecommunity
*ecomm
;
1215 struct ecommunity
*ipv6_ecomm
;
1216 struct cluster_list
*cluster
;
1218 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1219 aspath_free(attr
->aspath
);
1220 attr
->aspath
= NULL
;
1222 if (attr
->community
&& !attr
->community
->refcnt
)
1223 community_free(&attr
->community
);
1224 ecomm
= bgp_attr_get_ecommunity(attr
);
1225 if (ecomm
&& !ecomm
->refcnt
)
1226 ecommunity_free(&ecomm
);
1227 bgp_attr_set_ecommunity(attr
, NULL
);
1228 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1229 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1230 ecommunity_free(&ipv6_ecomm
);
1231 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1232 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
1233 lcommunity_free(&attr
->lcommunity
);
1235 cluster
= bgp_attr_get_cluster(attr
);
1236 if (cluster
&& !cluster
->refcnt
) {
1237 cluster_free(cluster
);
1238 bgp_attr_set_cluster(attr
, NULL
);
1241 struct transit
*transit
= bgp_attr_get_transit(attr
);
1243 if (transit
&& !transit
->refcnt
) {
1244 transit_free(transit
);
1245 bgp_attr_set_transit(attr
, NULL
);
1247 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1248 encap_free(attr
->encap_subtlvs
);
1249 attr
->encap_subtlvs
= NULL
;
1251 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1252 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1253 attr
->srv6_l3vpn
= NULL
;
1255 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1256 srv6_vpn_free(attr
->srv6_vpn
);
1257 attr
->srv6_vpn
= NULL
;
1259 #ifdef ENABLE_BGP_VNC
1260 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1261 bgp_attr_get_vnc_subtlvs(attr
);
1263 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1264 encap_free(vnc_subtlvs
);
1265 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1268 bgp_attr_extra_free(attr
);
1271 /* Implement draft-scudder-idr-optional-transitive behaviour and
1272 * avoid resetting sessions for malformed attributes which are
1273 * are partial/optional and hence where the error likely was not
1274 * introduced by the sending neighbour.
1276 static bgp_attr_parse_ret_t
1277 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1280 struct peer
*const peer
= args
->peer
;
1281 struct attr
*const attr
= args
->attr
;
1282 const uint8_t flags
= args
->flags
;
1283 /* startp and length must be special-cased, as whether or not to
1284 * send the attribute data with the NOTIFY depends on the error,
1285 * the caller therefore signals this with the seperate length argument
1287 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1289 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1290 char attr_str
[BUFSIZ
] = {0};
1292 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1294 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1297 /* Only relax error handling for eBGP peers */
1298 if (peer
->sort
!= BGP_PEER_EBGP
) {
1299 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1300 notify_datap
, length
);
1301 return BGP_ATTR_PARSE_ERROR
;
1304 /* Adjust the stream getp to the end of the attribute, in case we can
1305 * still proceed but the caller hasn't read all the attribute.
1307 stream_set_getp(BGP_INPUT(peer
),
1308 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1311 switch (args
->type
) {
1312 /* where an attribute is relatively inconsequential, e.g. it does not
1313 * affect route selection, and can be safely ignored, then any such
1314 * attributes which are malformed should just be ignored and the route
1315 * processed as normal.
1317 case BGP_ATTR_AS4_AGGREGATOR
:
1318 case BGP_ATTR_AGGREGATOR
:
1319 case BGP_ATTR_ATOMIC_AGGREGATE
:
1320 return BGP_ATTR_PARSE_PROCEED
;
1322 /* Core attributes, particularly ones which may influence route
1323 * selection, should be treat-as-withdraw.
1325 case BGP_ATTR_ORIGIN
:
1326 case BGP_ATTR_AS_PATH
:
1327 case BGP_ATTR_NEXT_HOP
:
1328 case BGP_ATTR_MULTI_EXIT_DISC
:
1329 case BGP_ATTR_LOCAL_PREF
:
1330 case BGP_ATTR_COMMUNITIES
:
1331 case BGP_ATTR_EXT_COMMUNITIES
:
1332 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1333 case BGP_ATTR_LARGE_COMMUNITIES
:
1334 case BGP_ATTR_ORIGINATOR_ID
:
1335 case BGP_ATTR_CLUSTER_LIST
:
1336 return BGP_ATTR_PARSE_WITHDRAW
;
1337 case BGP_ATTR_MP_REACH_NLRI
:
1338 case BGP_ATTR_MP_UNREACH_NLRI
:
1339 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1340 notify_datap
, length
);
1341 return BGP_ATTR_PARSE_ERROR
;
1344 /* Partial optional attributes that are malformed should not cause
1345 * the whole session to be reset. Instead treat it as a withdrawal
1346 * of the routes, if possible.
1348 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1349 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1350 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1351 return BGP_ATTR_PARSE_WITHDRAW
;
1353 /* default to reset */
1354 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1357 /* Find out what is wrong with the path attribute flag bits and log the error.
1358 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1359 Extended Length. Checking O/T/P bits at once implies, that the attribute
1360 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1361 non-transitive" attribute. */
1363 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1364 uint8_t desired_flags
/* how RFC says it must be */
1367 uint8_t seen
= 0, i
;
1368 uint8_t real_flags
= args
->flags
;
1369 const uint8_t attr_code
= args
->type
;
1371 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1372 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1373 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1374 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1375 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1376 flog_err(EC_BGP_ATTR_FLAG
,
1377 "%s attribute must%s be flagged as \"%s\"",
1378 lookup_msg(attr_str
, attr_code
, NULL
),
1379 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1382 attr_flag_str
[i
].str
);
1387 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1388 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1389 real_flags
, desired_flags
);
1393 /* Required flags for attributes. EXTLEN will be masked off when testing,
1394 * as will PARTIAL for optional+transitive attributes.
1396 const uint8_t attr_flags_values
[] = {
1397 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1398 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1399 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1400 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1401 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1402 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1403 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1404 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1405 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1406 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1407 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1408 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1409 [BGP_ATTR_EXT_COMMUNITIES
] =
1410 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1411 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1412 [BGP_ATTR_AS4_AGGREGATOR
] =
1413 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1414 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1415 [BGP_ATTR_LARGE_COMMUNITIES
] =
1416 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1417 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1418 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1419 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1421 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1423 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1425 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1426 const uint8_t flags
= args
->flags
;
1427 const uint8_t attr_code
= args
->type
;
1429 /* there may be attributes we don't know about */
1430 if (attr_code
> attr_flags_values_max
)
1432 if (attr_flags_values
[attr_code
] == 0)
1435 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1439 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1440 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1443 "%s well-known attributes must have transitive flag set (%x)",
1444 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1448 /* "For well-known attributes and for optional non-transitive
1450 * the Partial bit MUST be set to 0."
1452 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1453 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1454 flog_err(EC_BGP_ATTR_FLAG
,
1455 "%s well-known attribute must NOT have the partial flag set (%x)",
1456 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1459 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1460 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1461 flog_err(EC_BGP_ATTR_FLAG
,
1462 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1463 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1468 /* Optional transitive attributes may go through speakers that don't
1469 * reocgnise them and set the Partial bit.
1471 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1472 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1473 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1475 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1478 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1482 /* Get origin attribute of the update message. */
1483 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1485 struct peer
*const peer
= args
->peer
;
1486 struct attr
*const attr
= args
->attr
;
1487 const bgp_size_t length
= args
->length
;
1489 /* If any recognized attribute has Attribute Length that conflicts
1490 with the expected length (based on the attribute type code), then
1491 the Error Subcode is set to Attribute Length Error. The Data
1492 field contains the erroneous attribute (type, length and
1495 flog_err(EC_BGP_ATTR_LEN
,
1496 "Origin attribute length is not one %d", length
);
1497 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1501 /* Fetch origin attribute. */
1502 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1504 /* If the ORIGIN attribute has an undefined value, then the Error
1505 Subcode is set to Invalid Origin Attribute. The Data field
1506 contains the unrecognized attribute (type, length and value). */
1507 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1508 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1509 flog_err(EC_BGP_ATTR_ORIGIN
,
1510 "Origin attribute value is invalid %d", attr
->origin
);
1511 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1515 /* Set oring attribute flag. */
1516 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1521 /* Parse AS path information. This function is wrapper of
1523 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1525 struct attr
*const attr
= args
->attr
;
1526 struct peer
*const peer
= args
->peer
;
1527 const bgp_size_t length
= args
->length
;
1530 * peer with AS4 => will get 4Byte ASnums
1531 * otherwise, will get 16 Bit
1533 attr
->aspath
= aspath_parse(
1535 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1536 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1538 /* In case of IBGP, length will be zero. */
1539 if (!attr
->aspath
) {
1540 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1541 "Malformed AS path from %s, length is %d", peer
->host
,
1543 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1547 /* Set aspath attribute flag. */
1548 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1550 return BGP_ATTR_PARSE_PROCEED
;
1553 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1554 struct attr
*const attr
)
1556 /* These checks were part of bgp_attr_aspath, but with
1557 * as4 we should to check aspath things when
1558 * aspath synthesizing with as4_path has already taken place.
1559 * Otherwise we check ASPATH and use the synthesized thing, and that is
1561 * So do the checks later, i.e. here
1563 struct aspath
*aspath
;
1565 /* Confederation sanity check. */
1566 if ((peer
->sort
== BGP_PEER_CONFED
1567 && !aspath_left_confed_check(attr
->aspath
))
1568 || (peer
->sort
== BGP_PEER_EBGP
1569 && aspath_confed_check(attr
->aspath
))) {
1570 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1572 return BGP_ATTR_PARSE_WITHDRAW
;
1575 /* First AS check for EBGP. */
1576 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1577 if (peer
->sort
== BGP_PEER_EBGP
1578 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1579 flog_err(EC_BGP_ATTR_FIRST_AS
,
1580 "%s incorrect first AS (must be %u)",
1581 peer
->host
, peer
->as
);
1582 return BGP_ATTR_PARSE_WITHDRAW
;
1586 /* Codification of AS 0 Processing */
1587 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1589 EC_BGP_ATTR_MAL_AS_PATH
,
1590 "Malformed AS path, AS number is 0 in the path from %s",
1592 return BGP_ATTR_PARSE_WITHDRAW
;
1595 /* local-as prepend */
1596 if (peer
->change_local_as
1597 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1598 aspath
= aspath_dup(attr
->aspath
);
1599 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1600 aspath_unintern(&attr
->aspath
);
1601 attr
->aspath
= aspath_intern(aspath
);
1604 return BGP_ATTR_PARSE_PROCEED
;
1607 /* Parse AS4 path information. This function is another wrapper of
1609 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1610 struct aspath
**as4_path
)
1612 struct peer
*const peer
= args
->peer
;
1613 struct attr
*const attr
= args
->attr
;
1614 const bgp_size_t length
= args
->length
;
1616 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1618 /* In case of IBGP, length will be zero. */
1620 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1621 "Malformed AS4 path from %s, length is %d", peer
->host
,
1623 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1627 /* Set aspath attribute flag. */
1628 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1630 return BGP_ATTR_PARSE_PROCEED
;
1634 * Check that the nexthop attribute is valid.
1636 bgp_attr_parse_ret_t
1637 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1639 in_addr_t nexthop_h
;
1641 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1642 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1643 || IPV4_CLASS_DE(nexthop_h
))
1644 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1645 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1646 char buf
[INET_ADDRSTRLEN
];
1648 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1650 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1652 data
[0] = BGP_ATTR_FLAG_TRANS
;
1653 data
[1] = BGP_ATTR_NEXT_HOP
;
1654 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1655 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1656 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1657 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1659 return BGP_ATTR_PARSE_ERROR
;
1662 return BGP_ATTR_PARSE_PROCEED
;
1665 /* Nexthop attribute. */
1666 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1668 struct peer
*const peer
= args
->peer
;
1669 struct attr
*const attr
= args
->attr
;
1670 const bgp_size_t length
= args
->length
;
1672 /* Check nexthop attribute length. */
1674 flog_err(EC_BGP_ATTR_LEN
,
1675 "Nexthop attribute length isn't four [%d]", length
);
1677 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1681 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1682 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1684 return BGP_ATTR_PARSE_PROCEED
;
1687 /* MED atrribute. */
1688 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1690 struct peer
*const peer
= args
->peer
;
1691 struct attr
*const attr
= args
->attr
;
1692 const bgp_size_t length
= args
->length
;
1696 flog_err(EC_BGP_ATTR_LEN
,
1697 "MED attribute length isn't four [%d]", length
);
1699 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1703 attr
->med
= stream_getl(peer
->curr
);
1705 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1707 return BGP_ATTR_PARSE_PROCEED
;
1710 /* Local preference attribute. */
1711 static bgp_attr_parse_ret_t
1712 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1714 struct peer
*const peer
= args
->peer
;
1715 struct attr
*const attr
= args
->attr
;
1716 const bgp_size_t length
= args
->length
;
1718 /* if received from an internal neighbor, it SHALL be considered
1719 * malformed if its length is not equal to 4. If malformed, the
1720 * UPDATE message SHALL be handled using the approach of "treat-as-
1723 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1724 flog_err(EC_BGP_ATTR_LEN
,
1725 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1726 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1730 /* If it is contained in an UPDATE message that is received from an
1731 external peer, then this attribute MUST be ignored by the
1732 receiving speaker. */
1733 if (peer
->sort
== BGP_PEER_EBGP
) {
1734 STREAM_FORWARD_GETP(peer
->curr
, length
);
1735 return BGP_ATTR_PARSE_PROCEED
;
1738 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1740 /* Set the local-pref flag. */
1741 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1743 return BGP_ATTR_PARSE_PROCEED
;
1746 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1750 /* Atomic aggregate. */
1751 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1753 struct attr
*const attr
= args
->attr
;
1754 const bgp_size_t length
= args
->length
;
1758 flog_err(EC_BGP_ATTR_LEN
,
1759 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1761 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1765 /* Set atomic aggregate flag. */
1766 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1768 return BGP_ATTR_PARSE_PROCEED
;
1771 /* Aggregator attribute */
1772 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1774 struct peer
*const peer
= args
->peer
;
1775 struct attr
*const attr
= args
->attr
;
1776 const bgp_size_t length
= args
->length
;
1781 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1782 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1783 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1786 if (length
!= wantedlen
) {
1787 flog_err(EC_BGP_ATTR_LEN
,
1788 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1790 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1794 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1795 aggregator_as
= stream_getl(peer
->curr
);
1797 aggregator_as
= stream_getw(peer
->curr
);
1799 attr
->aggregator_as
= aggregator_as
;
1800 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1802 /* Codification of AS 0 Processing */
1803 if (aggregator_as
== BGP_AS_ZERO
) {
1804 flog_err(EC_BGP_ATTR_LEN
,
1805 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1806 peer
->host
, aspath_print(attr
->aspath
));
1808 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1809 char attr_str
[BUFSIZ
] = {0};
1811 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1813 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1816 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1819 return BGP_ATTR_PARSE_PROCEED
;
1822 /* New Aggregator attribute */
1823 static bgp_attr_parse_ret_t
1824 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1825 as_t
*as4_aggregator_as
,
1826 struct in_addr
*as4_aggregator_addr
)
1828 struct peer
*const peer
= args
->peer
;
1829 struct attr
*const attr
= args
->attr
;
1830 const bgp_size_t length
= args
->length
;
1834 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1836 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1840 aggregator_as
= stream_getl(peer
->curr
);
1842 *as4_aggregator_as
= aggregator_as
;
1843 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1845 /* Codification of AS 0 Processing */
1846 if (aggregator_as
== BGP_AS_ZERO
) {
1847 flog_err(EC_BGP_ATTR_LEN
,
1848 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1849 peer
->host
, aspath_print(attr
->aspath
));
1851 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1852 char attr_str
[BUFSIZ
] = {0};
1854 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1856 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1859 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1862 return BGP_ATTR_PARSE_PROCEED
;
1865 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1867 static bgp_attr_parse_ret_t
1868 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1869 struct aspath
*as4_path
, as_t as4_aggregator
,
1870 struct in_addr
*as4_aggregator_addr
)
1872 int ignore_as4_path
= 0;
1873 struct aspath
*newpath
;
1875 if (!attr
->aspath
) {
1876 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1878 * checked that all well-known, mandatory attributes were
1881 * Can only be a problem with peer itself - hard error
1883 return BGP_ATTR_PARSE_ERROR
;
1886 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1887 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1889 * It is worth a warning though, because the peer really
1890 * should not send them
1892 if (BGP_DEBUG(as4
, AS4
)) {
1893 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1894 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1895 "AS4 capable peer, yet it sent");
1898 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1899 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1901 "AS4 capable peer, yet it sent");
1904 return BGP_ATTR_PARSE_PROCEED
;
1907 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1908 * because that may override AS4_PATH
1910 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1911 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1913 * if the as_number in aggregator is not AS_TRANS,
1914 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1915 * and the Aggregator shall be taken as
1916 * info on the aggregating node, and the AS_PATH
1917 * shall be taken as the AS_PATH
1919 * the Aggregator shall be ignored and the
1920 * AS4_AGGREGATOR shall be taken as the
1921 * Aggregating node and the AS_PATH is to be
1922 * constructed "as in all other cases"
1924 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1926 if (BGP_DEBUG(as4
, AS4
))
1928 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1930 ignore_as4_path
= 1;
1932 /* "New_aggregator shall be taken as aggregator"
1934 attr
->aggregator_as
= as4_aggregator
;
1935 attr
->aggregator_addr
.s_addr
=
1936 as4_aggregator_addr
->s_addr
;
1939 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1940 * That is bogus - but reading the conditions
1941 * we have to handle AS4_AGGREGATOR as if it were
1942 * AGGREGATOR in that case
1944 if (BGP_DEBUG(as4
, AS4
))
1946 "[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",
1948 attr
->aggregator_as
= as4_aggregator
;
1949 /* sweep it under the carpet and simulate a "good"
1951 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1955 /* need to reconcile NEW_AS_PATH and AS_PATH */
1956 if (!ignore_as4_path
1957 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1958 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1960 return BGP_ATTR_PARSE_ERROR
;
1962 aspath_unintern(&attr
->aspath
);
1963 attr
->aspath
= aspath_intern(newpath
);
1965 return BGP_ATTR_PARSE_PROCEED
;
1968 /* Community attribute. */
1969 static bgp_attr_parse_ret_t
1970 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1972 struct peer
*const peer
= args
->peer
;
1973 struct attr
*const attr
= args
->attr
;
1974 const bgp_size_t length
= args
->length
;
1977 attr
->community
= NULL
;
1978 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1983 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1985 /* XXX: fix community_parse to use stream API and remove this */
1986 stream_forward_getp(peer
->curr
, length
);
1988 /* The Community attribute SHALL be considered malformed if its
1989 * length is not a non-zero multiple of 4.
1991 if (!attr
->community
)
1992 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1995 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1997 return BGP_ATTR_PARSE_PROCEED
;
2000 /* Originator ID attribute. */
2001 static bgp_attr_parse_ret_t
2002 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
2004 struct peer
*const peer
= args
->peer
;
2005 struct attr
*const attr
= args
->attr
;
2006 const bgp_size_t length
= args
->length
;
2008 /* if received from an internal neighbor, it SHALL be considered
2009 * malformed if its length is not equal to 4. If malformed, the
2010 * UPDATE message SHALL be handled using the approach of "treat-as-
2014 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
2017 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2021 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
2023 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2025 return BGP_ATTR_PARSE_PROCEED
;
2028 /* Cluster list attribute. */
2029 static bgp_attr_parse_ret_t
2030 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2032 struct peer
*const peer
= args
->peer
;
2033 struct attr
*const attr
= args
->attr
;
2034 const bgp_size_t length
= args
->length
;
2036 /* if received from an internal neighbor, it SHALL be considered
2037 * malformed if its length is not a non-zero multiple of 4. If
2038 * malformed, the UPDATE message SHALL be handled using the approach
2039 * of "treat-as-withdraw".
2041 if (length
== 0 || length
% 4) {
2042 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2044 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2048 bgp_attr_set_cluster(
2049 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2052 /* XXX: Fix cluster_parse to use stream API and then remove this */
2053 stream_forward_getp(peer
->curr
, length
);
2055 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2057 return BGP_ATTR_PARSE_PROCEED
;
2060 /* Multiprotocol reachability information parse. */
2061 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2062 struct bgp_nlri
*mp_update
)
2066 iana_safi_t pkt_safi
;
2068 bgp_size_t nlri_len
;
2071 struct peer
*const peer
= args
->peer
;
2072 struct attr
*const attr
= args
->attr
;
2073 const bgp_size_t length
= args
->length
;
2075 /* Set end of packet. */
2076 s
= BGP_INPUT(peer
);
2077 start
= stream_get_getp(s
);
2079 /* safe to read statically sized header? */
2080 #define BGP_MP_REACH_MIN_SIZE 5
2081 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2082 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2083 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2084 __func__
, peer
->host
, (unsigned long)length
);
2085 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2088 /* Load AFI, SAFI. */
2089 pkt_afi
= stream_getw(s
);
2090 pkt_safi
= stream_getc(s
);
2092 /* Convert AFI, SAFI to internal values, check. */
2093 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2094 /* Log if AFI or SAFI is unrecognized. This is not an error
2096 * the attribute is otherwise malformed.
2098 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2100 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2101 peer
->host
, iana_afi2str(pkt_afi
),
2102 iana_safi2str(pkt_safi
));
2103 return BGP_ATTR_PARSE_ERROR
;
2106 /* Get nexthop length. */
2107 attr
->mp_nexthop_len
= stream_getc(s
);
2109 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2111 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2112 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2113 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2116 /* Nexthop length check. */
2117 switch (attr
->mp_nexthop_len
) {
2119 if (safi
!= SAFI_FLOWSPEC
) {
2120 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2121 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2122 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2125 case BGP_ATTR_NHLEN_VPNV4
:
2126 stream_getl(s
); /* RD high */
2127 stream_getl(s
); /* RD low */
2129 * NOTE: intentional fall through
2130 * - for consistency in rx processing
2132 * The following comment is to signal GCC this intention
2133 * and suppress the warning
2136 case BGP_ATTR_NHLEN_IPV4
:
2137 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2138 /* Probably needed for RFC 2283 */
2139 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2140 memcpy(&attr
->nexthop
.s_addr
,
2141 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2143 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2144 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2145 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2146 stream_getl(s
); /* RD high */
2147 stream_getl(s
); /* RD low */
2149 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2150 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2151 if (!peer
->nexthop
.ifp
) {
2152 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2154 return BGP_ATTR_PARSE_WITHDRAW
;
2156 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2159 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2160 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2161 if (attr
->mp_nexthop_len
2162 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2163 stream_getl(s
); /* RD high */
2164 stream_getl(s
); /* RD low */
2166 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2167 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2168 if (!peer
->nexthop
.ifp
) {
2169 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",
2171 return BGP_ATTR_PARSE_WITHDRAW
;
2173 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2175 if (attr
->mp_nexthop_len
2176 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2177 stream_getl(s
); /* RD high */
2178 stream_getl(s
); /* RD low */
2180 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2181 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2182 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2184 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2185 peer
->host
, &attr
->mp_nexthop_global
,
2186 &attr
->mp_nexthop_local
);
2188 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2190 if (!peer
->nexthop
.ifp
) {
2191 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2193 return BGP_ATTR_PARSE_WITHDRAW
;
2195 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2198 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2199 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2200 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2204 zlog_info("%s: %s sent SNPA which couldn't be read",
2205 __func__
, peer
->host
);
2206 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2211 if ((val
= stream_getc(s
)))
2213 EC_BGP_DEFUNCT_SNPA_LEN
,
2214 "%s sent non-zero value, %u, for defunct SNPA-length field",
2218 /* must have nrli_len, what is left of the attribute */
2219 nlri_len
= LEN_LEFT
;
2220 if (nlri_len
> STREAM_READABLE(s
)) {
2221 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2222 __func__
, peer
->host
);
2223 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2227 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2228 __func__
, peer
->host
);
2230 mp_update
->afi
= afi
;
2231 mp_update
->safi
= safi
;
2232 return BGP_ATTR_PARSE_EOR
;
2235 mp_update
->afi
= afi
;
2236 mp_update
->safi
= safi
;
2237 mp_update
->nlri
= stream_pnt(s
);
2238 mp_update
->length
= nlri_len
;
2240 stream_forward_getp(s
, nlri_len
);
2242 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2244 return BGP_ATTR_PARSE_PROCEED
;
2248 /* Multiprotocol unreachable parse */
2249 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2250 struct bgp_nlri
*mp_withdraw
)
2255 iana_safi_t pkt_safi
;
2257 uint16_t withdraw_len
;
2258 struct peer
*const peer
= args
->peer
;
2259 struct attr
*const attr
= args
->attr
;
2260 const bgp_size_t length
= args
->length
;
2264 #define BGP_MP_UNREACH_MIN_SIZE 3
2265 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2266 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2268 pkt_afi
= stream_getw(s
);
2269 pkt_safi
= stream_getc(s
);
2271 /* Convert AFI, SAFI to internal values, check. */
2272 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2273 /* Log if AFI or SAFI is unrecognized. This is not an error
2275 * the attribute is otherwise malformed.
2277 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2279 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2280 peer
->host
, iana_afi2str(pkt_afi
),
2281 iana_safi2str(pkt_safi
));
2282 return BGP_ATTR_PARSE_ERROR
;
2285 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2287 mp_withdraw
->afi
= afi
;
2288 mp_withdraw
->safi
= safi
;
2289 mp_withdraw
->nlri
= stream_pnt(s
);
2290 mp_withdraw
->length
= withdraw_len
;
2292 stream_forward_getp(s
, withdraw_len
);
2294 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2296 return BGP_ATTR_PARSE_PROCEED
;
2299 /* Large Community attribute. */
2300 static bgp_attr_parse_ret_t
2301 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2303 struct peer
*const peer
= args
->peer
;
2304 struct attr
*const attr
= args
->attr
;
2305 const bgp_size_t length
= args
->length
;
2308 * Large community follows new attribute format.
2311 attr
->lcommunity
= NULL
;
2312 /* Empty extcomm doesn't seem to be invalid per se */
2313 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2317 attr
->lcommunity
= lcommunity_parse(stream_pnt(peer
->curr
), length
);
2318 /* XXX: fix ecommunity_parse to use stream API */
2319 stream_forward_getp(peer
->curr
, length
);
2321 if (!attr
->lcommunity
)
2322 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2325 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2327 return BGP_ATTR_PARSE_PROCEED
;
2330 /* Extended Community attribute. */
2331 static bgp_attr_parse_ret_t
2332 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2334 struct peer
*const peer
= args
->peer
;
2335 struct attr
*const attr
= args
->attr
;
2336 const bgp_size_t length
= args
->length
;
2339 struct ecommunity
*ecomm
;
2342 bgp_attr_set_ecommunity(attr
, NULL
);
2343 /* Empty extcomm doesn't seem to be invalid per se */
2344 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2348 ecomm
= ecommunity_parse(
2349 stream_pnt(peer
->curr
), length
,
2350 CHECK_FLAG(peer
->flags
,
2351 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2352 bgp_attr_set_ecommunity(attr
, ecomm
);
2353 /* XXX: fix ecommunity_parse to use stream API */
2354 stream_forward_getp(peer
->curr
, length
);
2356 /* The Extended Community attribute SHALL be considered malformed if
2357 * its length is not a non-zero multiple of 8.
2359 if (!bgp_attr_get_ecommunity(attr
))
2360 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2363 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2365 /* Extract DF election preference and mobility sequence number */
2366 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2368 /* Extract MAC mobility sequence number, if any. */
2369 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2370 attr
->sticky
= sticky
;
2372 /* Check if this is a Gateway MAC-IP advertisement */
2373 attr
->default_gw
= bgp_attr_default_gw(attr
);
2375 /* Handle scenario where router flag ecommunity is not
2376 * set but default gw ext community is present.
2377 * Use default gateway, set and propogate R-bit.
2379 if (attr
->default_gw
)
2380 attr
->router_flag
= 1;
2382 /* Check EVPN Neighbor advertisement flags, R-bit */
2383 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2385 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2387 /* Extract the Rmac, if any */
2388 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2389 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2390 && bgp_mac_exist(&attr
->rmac
))
2391 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2395 /* Get the tunnel type from encap extended community */
2396 bgp_attr_extcom_tunnel_type(attr
,
2397 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2399 /* Extract link bandwidth, if any. */
2400 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2403 return BGP_ATTR_PARSE_PROCEED
;
2406 /* IPv6 Extended Community attribute. */
2407 static bgp_attr_parse_ret_t
2408 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2410 struct peer
*const peer
= args
->peer
;
2411 struct attr
*const attr
= args
->attr
;
2412 const bgp_size_t length
= args
->length
;
2413 struct ecommunity
*ipv6_ecomm
= NULL
;
2416 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2417 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2421 ipv6_ecomm
= ecommunity_parse_ipv6(
2422 stream_pnt(peer
->curr
), length
,
2423 CHECK_FLAG(peer
->flags
,
2424 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2425 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2427 /* XXX: fix ecommunity_parse to use stream API */
2428 stream_forward_getp(peer
->curr
, length
);
2431 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2434 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
);
2436 return BGP_ATTR_PARSE_PROCEED
;
2439 /* Parse Tunnel Encap attribute in an UPDATE */
2440 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2441 bgp_size_t length
, /* IN: attr's length field */
2442 struct attr
*attr
, /* IN: caller already allocated */
2443 uint8_t flag
, /* IN: attr's flags field */
2447 uint16_t tunneltype
= 0;
2449 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2451 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2452 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2454 "Tunnel Encap attribute flag isn't optional and transitive %d",
2456 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2457 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2462 if (BGP_ATTR_ENCAP
== type
) {
2463 /* read outer TLV type and length */
2464 uint16_t tlv_length
;
2468 "Tunnel Encap attribute not long enough to contain outer T,L");
2469 bgp_notify_send_with_data(
2470 peer
, BGP_NOTIFY_UPDATE_ERR
,
2471 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2474 tunneltype
= stream_getw(BGP_INPUT(peer
));
2475 tlv_length
= stream_getw(BGP_INPUT(peer
));
2478 if (tlv_length
!= length
) {
2479 zlog_info("%s: tlv_length(%d) != length(%d)",
2480 __func__
, tlv_length
, length
);
2484 while (length
>= 4) {
2485 uint16_t subtype
= 0;
2486 uint16_t sublength
= 0;
2487 struct bgp_attr_encap_subtlv
*tlv
;
2489 if (BGP_ATTR_ENCAP
== type
) {
2490 subtype
= stream_getc(BGP_INPUT(peer
));
2491 sublength
= stream_getc(BGP_INPUT(peer
));
2493 #ifdef ENABLE_BGP_VNC
2495 subtype
= stream_getw(BGP_INPUT(peer
));
2496 sublength
= stream_getw(BGP_INPUT(peer
));
2501 if (sublength
> length
) {
2503 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2505 bgp_notify_send_with_data(
2506 peer
, BGP_NOTIFY_UPDATE_ERR
,
2507 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2511 /* alloc and copy sub-tlv */
2512 /* TBD make sure these are freed when attributes are released */
2513 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2514 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2515 tlv
->type
= subtype
;
2516 tlv
->length
= sublength
;
2517 stream_get(tlv
->value
, peer
->curr
, sublength
);
2518 length
-= sublength
;
2520 /* attach tlv to encap chain */
2521 if (BGP_ATTR_ENCAP
== type
) {
2522 struct bgp_attr_encap_subtlv
*stlv_last
;
2523 for (stlv_last
= attr
->encap_subtlvs
;
2524 stlv_last
&& stlv_last
->next
;
2525 stlv_last
= stlv_last
->next
)
2528 stlv_last
->next
= tlv
;
2530 attr
->encap_subtlvs
= tlv
;
2532 #ifdef ENABLE_BGP_VNC
2534 struct bgp_attr_encap_subtlv
*stlv_last
;
2535 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2536 bgp_attr_get_vnc_subtlvs(attr
);
2538 for (stlv_last
= vnc_subtlvs
;
2539 stlv_last
&& stlv_last
->next
;
2540 stlv_last
= stlv_last
->next
)
2543 stlv_last
->next
= tlv
;
2545 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2550 if (BGP_ATTR_ENCAP
== type
) {
2551 attr
->encap_tunneltype
= tunneltype
;
2555 /* spurious leftover data */
2557 "Tunnel Encap attribute length is bad: %d leftover octets",
2559 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2560 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2569 /* SRv6 Service Data Sub-Sub-TLV attribute
2570 * draft-ietf-bess-srv6-services-07
2572 static bgp_attr_parse_ret_t
2573 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2575 struct peer
*const peer
= args
->peer
;
2576 struct attr
*const attr
= args
->attr
;
2577 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2578 transposition_len
, transposition_offset
;
2580 size_t headersz
= sizeof(type
) + sizeof(length
);
2582 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2585 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2586 headersz
, STREAM_READABLE(peer
->curr
));
2587 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2591 type
= stream_getc(peer
->curr
);
2592 length
= stream_getw(peer
->curr
);
2594 if (STREAM_READABLE(peer
->curr
) < length
) {
2597 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2598 length
, STREAM_READABLE(peer
->curr
));
2599 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2603 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2604 loc_block_len
= stream_getc(peer
->curr
);
2605 loc_node_len
= stream_getc(peer
->curr
);
2606 func_len
= stream_getc(peer
->curr
);
2607 arg_len
= stream_getc(peer
->curr
);
2608 transposition_len
= stream_getc(peer
->curr
);
2609 transposition_offset
= stream_getc(peer
->curr
);
2611 /* Log SRv6 Service Data Sub-Sub-TLV */
2612 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2614 "%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",
2615 __func__
, loc_block_len
, loc_node_len
, func_len
,
2616 arg_len
, transposition_len
,
2617 transposition_offset
);
2620 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2621 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2622 attr
->srv6_l3vpn
->func_len
= func_len
;
2623 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2624 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2625 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2629 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2631 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2634 stream_forward_getp(peer
->curr
, length
);
2637 return BGP_ATTR_PARSE_PROCEED
;
2640 /* SRv6 Service Sub-TLV attribute
2641 * draft-ietf-bess-srv6-services-07
2643 static bgp_attr_parse_ret_t
2644 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2646 struct peer
*const peer
= args
->peer
;
2647 struct attr
*const attr
= args
->attr
;
2648 struct in6_addr ipv6_sid
;
2649 uint8_t type
, sid_flags
;
2650 uint16_t length
, endpoint_behavior
;
2651 size_t headersz
= sizeof(type
) + sizeof(length
);
2652 bgp_attr_parse_ret_t err
;
2655 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2658 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2659 headersz
, STREAM_READABLE(peer
->curr
));
2660 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2664 type
= stream_getc(peer
->curr
);
2665 length
= stream_getw(peer
->curr
);
2667 if (STREAM_READABLE(peer
->curr
) < length
) {
2670 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2671 length
, STREAM_READABLE(peer
->curr
));
2672 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2676 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2677 stream_getc(peer
->curr
);
2678 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2679 sid_flags
= stream_getc(peer
->curr
);
2680 endpoint_behavior
= stream_getw(peer
->curr
);
2681 stream_getc(peer
->curr
);
2683 /* Log SRv6 Service Sub-TLV */
2684 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2685 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2687 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2688 __func__
, buf
, sid_flags
, endpoint_behavior
);
2691 /* Configure from Info */
2692 if (attr
->srv6_l3vpn
) {
2693 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2694 "Prefix SID SRv6 L3VPN field repeated");
2695 return bgp_attr_malformed(
2696 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2698 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2699 sizeof(struct bgp_attr_srv6_l3vpn
));
2700 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2701 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2702 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2703 attr
->srv6_l3vpn
->loc_block_len
= 0;
2704 attr
->srv6_l3vpn
->loc_node_len
= 0;
2705 attr
->srv6_l3vpn
->func_len
= 0;
2706 attr
->srv6_l3vpn
->arg_len
= 0;
2707 attr
->srv6_l3vpn
->transposition_len
= 0;
2708 attr
->srv6_l3vpn
->transposition_offset
= 0;
2710 // Sub-Sub-TLV found
2711 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2712 err
= bgp_attr_srv6_service_data(args
);
2714 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2718 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2721 /* Placeholder code for unsupported type */
2723 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2725 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2728 stream_forward_getp(peer
->curr
, length
);
2731 return BGP_ATTR_PARSE_PROCEED
;
2735 * Read an individual SID value returning how much data we have read
2736 * Returns 0 if there was an error that needs to be passed up the stack
2738 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2739 struct bgp_attr_parser_args
*args
)
2741 struct peer
*const peer
= args
->peer
;
2742 struct attr
*const attr
= args
->attr
;
2743 uint32_t label_index
;
2744 struct in6_addr ipv6_sid
;
2746 uint32_t srgb_range
;
2748 uint8_t sid_type
, sid_flags
;
2751 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2752 if (STREAM_READABLE(peer
->curr
) < length
2753 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2754 flog_err(EC_BGP_ATTR_LEN
,
2755 "Prefix SID label index length is %hu instead of %u",
2756 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2757 return bgp_attr_malformed(args
,
2758 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2762 /* Ignore flags and reserved */
2763 stream_getc(peer
->curr
);
2764 stream_getw(peer
->curr
);
2766 /* Fetch the label index and see if it is valid. */
2767 label_index
= stream_getl(peer
->curr
);
2768 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2769 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2772 /* Store label index; subsequently, we'll check on
2774 attr
->label_index
= label_index
;
2777 /* Placeholder code for the IPv6 SID type */
2778 else if (type
== BGP_PREFIX_SID_IPV6
) {
2779 if (STREAM_READABLE(peer
->curr
) < length
2780 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2781 flog_err(EC_BGP_ATTR_LEN
,
2782 "Prefix SID IPv6 length is %hu instead of %u",
2783 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2784 return bgp_attr_malformed(args
,
2785 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2789 /* Ignore reserved */
2790 stream_getc(peer
->curr
);
2791 stream_getw(peer
->curr
);
2793 stream_get(&ipv6_sid
, peer
->curr
, 16);
2796 /* Placeholder code for the Originator SRGB type */
2797 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2799 * ietf-idr-bgp-prefix-sid-05:
2800 * Length is the total length of the value portion of the
2801 * TLV: 2 + multiple of 6.
2803 * peer->curr stream readp should be at the beginning of the 16
2804 * bit flag field at this point in the code.
2808 * Check that the TLV length field is sane: at least 2 bytes of
2809 * flag, and at least 1 SRGB (these are 6 bytes each)
2811 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2814 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2816 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2817 return bgp_attr_malformed(
2818 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2823 * Check that we actually have at least as much data as
2824 * specified by the length field
2826 if (STREAM_READABLE(peer
->curr
) < length
) {
2827 flog_err(EC_BGP_ATTR_LEN
,
2828 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2829 length
, STREAM_READABLE(peer
->curr
));
2830 return bgp_attr_malformed(
2831 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2836 * Check that the portion of the TLV containing the sequence of
2837 * SRGBs corresponds to a multiple of the SRGB size; to get
2838 * that length, we skip the 16 bit flags field
2840 stream_getw(peer
->curr
);
2842 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2845 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2846 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2847 return bgp_attr_malformed(
2848 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2852 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2854 for (int i
= 0; i
< srgb_count
; i
++) {
2855 stream_get(&srgb_base
, peer
->curr
, 3);
2856 stream_get(&srgb_range
, peer
->curr
, 3);
2860 /* Placeholder code for the VPN-SID Service type */
2861 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2862 if (STREAM_READABLE(peer
->curr
) < length
2863 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2864 flog_err(EC_BGP_ATTR_LEN
,
2865 "Prefix SID VPN SID length is %hu instead of %u",
2866 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2867 return bgp_attr_malformed(args
,
2868 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2872 /* Parse VPN-SID Sub-TLV */
2873 stream_getc(peer
->curr
); /* reserved */
2874 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2875 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2876 stream_get(&ipv6_sid
, peer
->curr
,
2877 sizeof(ipv6_sid
)); /* sid_value */
2879 /* Log VPN-SID Sub-TLV */
2880 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2881 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2883 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2884 __func__
, buf
, sid_type
, sid_flags
);
2887 /* Configure from Info */
2888 if (attr
->srv6_vpn
) {
2889 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2890 "Prefix SID SRv6 VPN field repeated");
2891 return bgp_attr_malformed(
2892 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2894 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2895 sizeof(struct bgp_attr_srv6_vpn
));
2896 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2897 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2898 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2901 /* Placeholder code for the SRv6 L3 Service type */
2902 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2903 if (STREAM_READABLE(peer
->curr
) < length
) {
2906 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
2907 length
, STREAM_READABLE(peer
->curr
));
2908 return bgp_attr_malformed(args
,
2909 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2913 /* ignore reserved */
2914 stream_getc(peer
->curr
);
2916 return bgp_attr_srv6_service(args
);
2919 /* Placeholder code for Unsupported TLV */
2922 if (STREAM_READABLE(peer
->curr
) < length
) {
2925 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2926 length
, STREAM_READABLE(peer
->curr
));
2927 return bgp_attr_malformed(
2928 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2932 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2934 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2937 stream_forward_getp(peer
->curr
, length
);
2940 return BGP_ATTR_PARSE_PROCEED
;
2943 /* Prefix SID attribute
2944 * draft-ietf-idr-bgp-prefix-sid-05
2946 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2948 struct peer
*const peer
= args
->peer
;
2949 struct attr
*const attr
= args
->attr
;
2950 bgp_attr_parse_ret_t ret
;
2952 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2956 size_t headersz
= sizeof(type
) + sizeof(length
);
2957 size_t psid_parsed_length
= 0;
2959 while (STREAM_READABLE(peer
->curr
) > 0
2960 && psid_parsed_length
< args
->length
) {
2962 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2965 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2966 headersz
, STREAM_READABLE(peer
->curr
));
2967 return bgp_attr_malformed(
2968 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2972 type
= stream_getc(peer
->curr
);
2973 length
= stream_getw(peer
->curr
);
2975 if (STREAM_READABLE(peer
->curr
) < length
) {
2978 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2979 length
, STREAM_READABLE(peer
->curr
));
2980 return bgp_attr_malformed(args
,
2981 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2985 ret
= bgp_attr_psid_sub(type
, length
, args
);
2987 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2990 psid_parsed_length
+= length
+ headersz
;
2992 if (psid_parsed_length
> args
->length
) {
2995 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2996 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2997 return bgp_attr_malformed(
2998 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3003 return BGP_ATTR_PARSE_PROCEED
;
3006 /* PMSI tunnel attribute (RFC 6514)
3007 * Basic validation checks done here.
3009 static bgp_attr_parse_ret_t
3010 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
3012 struct peer
*const peer
= args
->peer
;
3013 struct attr
*const attr
= args
->attr
;
3014 const bgp_size_t length
= args
->length
;
3016 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
3018 /* Verify that the receiver is expecting "ingress replication" as we
3019 * can only support that.
3021 if (length
< attr_parse_len
) {
3022 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
3024 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3027 stream_getc(peer
->curr
); /* Flags */
3028 tnl_type
= stream_getc(peer
->curr
);
3029 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3030 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3031 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3032 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3035 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3037 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3038 "Bad PMSI tunnel attribute length %d for IR",
3040 return bgp_attr_malformed(
3041 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3046 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3047 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3048 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3050 /* Forward read pointer of input stream. */
3051 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3053 return BGP_ATTR_PARSE_PROCEED
;
3056 /* BGP unknown attribute treatment. */
3057 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3059 bgp_size_t total
= args
->total
;
3060 struct transit
*transit
;
3061 struct peer
*const peer
= args
->peer
;
3062 struct attr
*const attr
= args
->attr
;
3063 uint8_t *const startp
= args
->startp
;
3064 const uint8_t type
= args
->type
;
3065 const uint8_t flag
= args
->flags
;
3066 const bgp_size_t length
= args
->length
;
3068 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3070 "%s Unknown attribute is received (type %d, length %d)",
3071 peer
->host
, type
, length
);
3073 /* Forward read pointer of input stream. */
3074 stream_forward_getp(peer
->curr
, length
);
3076 /* If any of the mandatory well-known attributes are not recognized,
3077 then the Error Subcode is set to Unrecognized Well-known
3078 Attribute. The Data field contains the unrecognized attribute
3079 (type, length and value). */
3080 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3081 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3085 /* Unrecognized non-transitive optional attributes must be quietly
3086 ignored and not passed along to other BGP peers. */
3087 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3088 return BGP_ATTR_PARSE_PROCEED
;
3090 /* If a path with recognized transitive optional attribute is
3091 accepted and passed along to other BGP peers and the Partial bit
3092 in the Attribute Flags octet is set to 1 by some previous AS, it
3093 is not set back to 0 by the current AS. */
3094 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3096 /* Store transitive attribute to the end of attr->transit. */
3097 transit
= bgp_attr_get_transit(attr
);
3099 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3101 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3102 transit
->length
+ total
);
3104 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3105 transit
->length
+= total
;
3106 bgp_attr_set_transit(attr
, transit
);
3108 return BGP_ATTR_PARSE_PROCEED
;
3111 /* Well-known attribute check. */
3112 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3116 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3118 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3119 return BGP_ATTR_PARSE_PROCEED
;
3121 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3122 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3123 are present, it should. Check for any other attribute being present
3126 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3127 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3128 return BGP_ATTR_PARSE_PROCEED
;
3130 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3131 type
= BGP_ATTR_ORIGIN
;
3133 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3134 type
= BGP_ATTR_AS_PATH
;
3136 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3138 * NLRI is empty. We can't easily check NLRI empty here though.
3140 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3141 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3142 type
= BGP_ATTR_NEXT_HOP
;
3144 if (peer
->sort
== BGP_PEER_IBGP
3145 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3146 type
= BGP_ATTR_LOCAL_PREF
;
3148 /* If any of the well-known mandatory attributes are not present
3149 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3152 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3153 "%s Missing well-known attribute %s.", peer
->host
,
3154 lookup_msg(attr_str
, type
, NULL
));
3155 return BGP_ATTR_PARSE_WITHDRAW
;
3157 return BGP_ATTR_PARSE_PROCEED
;
3160 /* Read attribute of update packet. This function is called from
3161 bgp_update_receive() in bgp_packet.c. */
3162 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3163 bgp_size_t size
, struct bgp_nlri
*mp_update
,
3164 struct bgp_nlri
*mp_withdraw
)
3166 bgp_attr_parse_ret_t ret
;
3170 uint8_t *startp
, *endp
;
3172 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3173 /* we need the as4_path only until we have synthesized the as_path with
3175 /* same goes for as4_aggregator */
3176 struct aspath
*as4_path
= NULL
;
3177 as_t as4_aggregator
= 0;
3178 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3179 struct transit
*transit
;
3181 /* Initialize bitmap. */
3182 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3184 /* End pointer of BGP attribute. */
3185 endp
= BGP_INPUT_PNT(peer
) + size
;
3187 /* Get attributes to the end of attribute length. */
3188 while (BGP_INPUT_PNT(peer
) < endp
) {
3189 /* Check remaining length check.*/
3190 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3191 /* XXX warning: long int format, int arg (arg 5) */
3193 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3194 "%s: error BGP attribute length %lu is smaller than min len",
3196 (unsigned long)(endp
3197 - stream_pnt(BGP_INPUT(peer
))));
3199 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3200 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3201 ret
= BGP_ATTR_PARSE_ERROR
;
3205 /* Fetch attribute flag and type. */
3206 startp
= BGP_INPUT_PNT(peer
);
3207 /* "The lower-order four bits of the Attribute Flags octet are
3208 unused. They MUST be zero when sent and MUST be ignored when
3210 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3211 type
= stream_getc(BGP_INPUT(peer
));
3213 /* Check whether Extended-Length applies and is in bounds */
3214 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3215 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3217 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3218 "%s: Extended length set, but just %lu bytes of attr header",
3220 (unsigned long)(endp
3221 - stream_pnt(BGP_INPUT(peer
))));
3223 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3224 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3225 ret
= BGP_ATTR_PARSE_ERROR
;
3229 /* Check extended attribue length bit. */
3230 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3231 length
= stream_getw(BGP_INPUT(peer
));
3233 length
= stream_getc(BGP_INPUT(peer
));
3235 /* If any attribute appears more than once in the UPDATE
3236 message, then the Error Subcode is set to Malformed Attribute
3239 if (CHECK_BITMAP(seen
, type
)) {
3241 EC_BGP_ATTRIBUTE_REPEATED
,
3242 "%s: error BGP attribute type %d appears twice in a message",
3245 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3246 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3247 ret
= BGP_ATTR_PARSE_ERROR
;
3251 /* Set type to bitmap to check duplicate attribute. `type' is
3252 unsigned char so it never overflow bitmap range. */
3254 SET_BITMAP(seen
, type
);
3256 /* Overflow check. */
3257 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3259 if (attr_endp
> endp
) {
3261 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3262 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3263 peer
->host
, type
, length
, size
, attr_endp
,
3267 * If any recognized attribute has an Attribute
3268 * Length that conflicts with the expected length
3269 * (based on the attribute type code), then the
3270 * Error Subcode MUST be set to Attribute Length
3271 * Error. The Data field MUST contain the erroneous
3272 * attribute (type, length, and value).
3274 * We do not currently have a good way to determine the
3275 * length of the attribute independent of the length
3276 * received in the message. Instead we send the
3277 * minimum between the amount of data we have and the
3278 * amount specified by the attribute length field.
3280 * Instead of directly passing in the packet buffer and
3281 * offset we use the stream_get* functions to read into
3282 * a stack buffer, since they perform bounds checking
3283 * and we are working with untrusted data.
3285 unsigned char ndata
[peer
->max_packet_size
];
3286 memset(ndata
, 0x00, sizeof(ndata
));
3288 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3289 /* Rewind to end of flag field */
3290 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3292 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3294 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3296 size_t atl
= attr_endp
- startp
;
3297 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3298 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3300 bgp_notify_send_with_data(
3301 peer
, BGP_NOTIFY_UPDATE_ERR
,
3302 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3305 ret
= BGP_ATTR_PARSE_ERROR
;
3309 struct bgp_attr_parser_args attr_args
= {
3316 .total
= attr_endp
- startp
,
3320 /* If any recognized attribute has Attribute Flags that conflict
3321 with the Attribute Type Code, then the Error Subcode is set
3323 Attribute Flags Error. The Data field contains the erroneous
3324 attribute (type, length and value). */
3325 if (bgp_attr_flag_invalid(&attr_args
)) {
3326 ret
= bgp_attr_malformed(
3327 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3329 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3334 /* OK check attribute and store it's value. */
3336 case BGP_ATTR_ORIGIN
:
3337 ret
= bgp_attr_origin(&attr_args
);
3339 case BGP_ATTR_AS_PATH
:
3340 ret
= bgp_attr_aspath(&attr_args
);
3342 case BGP_ATTR_AS4_PATH
:
3343 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3345 case BGP_ATTR_NEXT_HOP
:
3346 ret
= bgp_attr_nexthop(&attr_args
);
3348 case BGP_ATTR_MULTI_EXIT_DISC
:
3349 ret
= bgp_attr_med(&attr_args
);
3351 case BGP_ATTR_LOCAL_PREF
:
3352 ret
= bgp_attr_local_pref(&attr_args
);
3354 case BGP_ATTR_ATOMIC_AGGREGATE
:
3355 ret
= bgp_attr_atomic(&attr_args
);
3357 case BGP_ATTR_AGGREGATOR
:
3358 ret
= bgp_attr_aggregator(&attr_args
);
3360 case BGP_ATTR_AS4_AGGREGATOR
:
3361 ret
= bgp_attr_as4_aggregator(&attr_args
,
3363 &as4_aggregator_addr
);
3365 case BGP_ATTR_COMMUNITIES
:
3366 ret
= bgp_attr_community(&attr_args
);
3368 case BGP_ATTR_LARGE_COMMUNITIES
:
3369 ret
= bgp_attr_large_community(&attr_args
);
3371 case BGP_ATTR_ORIGINATOR_ID
:
3372 ret
= bgp_attr_originator_id(&attr_args
);
3374 case BGP_ATTR_CLUSTER_LIST
:
3375 ret
= bgp_attr_cluster_list(&attr_args
);
3377 case BGP_ATTR_MP_REACH_NLRI
:
3378 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3380 case BGP_ATTR_MP_UNREACH_NLRI
:
3381 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3383 case BGP_ATTR_EXT_COMMUNITIES
:
3384 ret
= bgp_attr_ext_communities(&attr_args
);
3386 #ifdef ENABLE_BGP_VNC_ATTR
3389 case BGP_ATTR_ENCAP
:
3390 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3393 case BGP_ATTR_PREFIX_SID
:
3394 ret
= bgp_attr_prefix_sid(&attr_args
);
3396 case BGP_ATTR_PMSI_TUNNEL
:
3397 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3399 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3400 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3403 ret
= bgp_attr_unknown(&attr_args
);
3407 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3408 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3409 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3410 ret
= BGP_ATTR_PARSE_ERROR
;
3414 if (ret
== BGP_ATTR_PARSE_EOR
) {
3418 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3419 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3420 "%s: Attribute %s, parse error", peer
->host
,
3421 lookup_msg(attr_str
, type
, NULL
));
3424 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3426 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3427 "%s: Attribute %s, parse error - treating as withdrawal",
3428 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3432 /* Check the fetched length. */
3433 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3434 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3435 "%s: BGP attribute %s, fetch error",
3436 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3437 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3438 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3439 ret
= BGP_ATTR_PARSE_ERROR
;
3445 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3446 * About Prefix-SID path attribute,
3447 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3448 * may only appear in a BGP Prefix-SID attribute attached to
3449 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3450 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3452 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3453 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3455 /* Check final read pointer is same as end pointer. */
3456 if (BGP_INPUT_PNT(peer
) != endp
) {
3457 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3458 "%s: BGP attribute %s, length mismatch", peer
->host
,
3459 lookup_msg(attr_str
, type
, NULL
));
3460 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3461 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3463 ret
= BGP_ATTR_PARSE_ERROR
;
3468 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3469 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3470 * This is implemented below and will result in a NOTIFICATION. If the
3471 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3472 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3473 * message SHOULD NOT be sent. This is implemented elsewhere.
3475 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3476 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3477 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3478 * speaker that receives the message SHOULD ignore this attribute.
3480 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3481 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3482 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3483 ret
= BGP_ATTR_PARSE_ERROR
;
3488 /* Check all mandatory well-known attributes are present */
3489 ret
= bgp_attr_check(peer
, attr
);
3494 * At this place we can see whether we got AS4_PATH and/or
3495 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3496 * We can not do this before we've read all attributes because
3497 * the as4 handling does not say whether AS4_PATH has to be sent
3498 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3499 * in relationship to AGGREGATOR.
3500 * So, to be defensive, we are not relying on any order and read
3501 * all attributes first, including these 32bit ones, and now,
3502 * afterwards, we look what and if something is to be done for as4.
3504 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3507 /* actually... this doesn't ever return failure currently, but
3508 * better safe than sorry */
3509 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3510 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3511 &as4_aggregator_addr
)) {
3512 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3513 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3514 ret
= BGP_ATTR_PARSE_ERROR
;
3519 * Finally do the checks on the aspath we did not do yet
3520 * because we waited for a potentially synthesized aspath.
3522 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3523 ret
= bgp_attr_aspath_check(peer
, attr
);
3524 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3528 ret
= BGP_ATTR_PARSE_PROCEED
;
3532 * At this stage, we have done all fiddling with as4, and the
3533 * resulting info is in attr->aggregator resp. attr->aspath so
3534 * we can chuck as4_aggregator and as4_path alltogether in order
3539 * unintern - it is in the hash
3540 * The flag that we got this is still there, but that
3541 * does not do any trouble
3543 aspath_unintern(&as4_path
);
3546 transit
= bgp_attr_get_transit(attr
);
3547 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3548 /* Finally intern unknown attribute. */
3550 bgp_attr_set_transit(attr
, transit_intern(transit
));
3551 if (attr
->encap_subtlvs
)
3552 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3554 #ifdef ENABLE_BGP_VNC
3555 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3556 bgp_attr_get_vnc_subtlvs(attr
);
3559 bgp_attr_set_vnc_subtlvs(
3561 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3565 transit_free(transit
);
3566 bgp_attr_set_transit(attr
, NULL
);
3569 bgp_attr_flush_encap(attr
);
3573 transit
= bgp_attr_get_transit(attr
);
3575 assert(transit
->refcnt
> 0);
3576 if (attr
->encap_subtlvs
)
3577 assert(attr
->encap_subtlvs
->refcnt
> 0);
3578 #ifdef ENABLE_BGP_VNC
3579 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3580 bgp_attr_get_vnc_subtlvs(attr
);
3583 assert(vnc_subtlvs
->refcnt
> 0);
3590 * Extract the tunnel type from extended community
3592 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3593 bgp_encap_types
*tunnel_type
)
3595 struct ecommunity
*ecom
;
3601 ecom
= bgp_attr_get_ecommunity(attr
);
3602 if (!ecom
|| !ecom
->size
)
3605 for (i
= 0; i
< ecom
->size
; i
++) {
3607 uint8_t type
, sub_type
;
3609 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3612 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3613 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3615 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3622 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3623 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3628 iana_safi_t pkt_safi
;
3631 /* Set extended bit always to encode the attribute length as 2 bytes */
3632 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3633 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3634 sizep
= stream_get_endp(s
);
3635 stream_putw(s
, 0); /* Marker: Attribute length. */
3638 /* Convert AFI, SAFI to values for packet. */
3639 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3641 stream_putw(s
, pkt_afi
); /* AFI */
3642 stream_putc(s
, pkt_safi
); /* SAFI */
3646 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3647 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3648 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3649 else if (safi
== SAFI_FLOWSPEC
)
3652 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3655 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3660 case SAFI_MULTICAST
:
3661 case SAFI_LABELED_UNICAST
:
3663 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3667 stream_putl(s
, 0); /* RD = 0, per RFC */
3669 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3674 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3677 if (attr
->mp_nexthop_len
== 0)
3678 stream_putc(s
, 0); /* no nexthop for flowspec */
3680 stream_putc(s
, attr
->mp_nexthop_len
);
3681 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3690 case SAFI_MULTICAST
:
3691 case SAFI_LABELED_UNICAST
:
3693 if (attr
->mp_nexthop_len
3694 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3696 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3697 stream_put(s
, &attr
->mp_nexthop_global
,
3699 stream_put(s
, &attr
->mp_nexthop_local
,
3702 stream_putc(s
, IPV6_MAX_BYTELEN
);
3703 stream_put(s
, &attr
->mp_nexthop_global
,
3707 case SAFI_MPLS_VPN
: {
3708 if (attr
->mp_nexthop_len
3709 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3711 stream_putl(s
, 0); /* RD = 0, per RFC */
3713 stream_put(s
, &attr
->mp_nexthop_global
,
3715 } else if (attr
->mp_nexthop_len
3716 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3718 stream_putl(s
, 0); /* RD = 0, per RFC */
3720 stream_put(s
, &attr
->mp_nexthop_global
,
3722 stream_putl(s
, 0); /* RD = 0, per RFC */
3724 stream_put(s
, &attr
->mp_nexthop_local
,
3729 stream_putc(s
, IPV6_MAX_BYTELEN
);
3730 stream_put(s
, &attr
->mp_nexthop_global
,
3734 stream_putc(s
, 0); /* no nexthop for flowspec */
3740 if (safi
!= SAFI_FLOWSPEC
)
3742 EC_BGP_ATTR_NH_SEND_LEN
,
3743 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3744 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3753 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3754 const struct prefix
*p
,
3755 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3756 uint32_t num_labels
, bool addpath_capable
,
3757 uint32_t addpath_tx_id
, struct attr
*attr
)
3759 if (safi
== SAFI_MPLS_VPN
) {
3760 if (addpath_capable
)
3761 stream_putl(s
, addpath_tx_id
);
3762 /* Label, RD, Prefix write. */
3763 stream_putc(s
, p
->prefixlen
+ 88);
3764 stream_put(s
, label
, BGP_LABEL_BYTES
);
3765 stream_put(s
, prd
->val
, 8);
3766 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3767 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3768 /* EVPN prefix - contents depend on type */
3769 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3770 addpath_capable
, addpath_tx_id
);
3771 } else if (safi
== SAFI_LABELED_UNICAST
) {
3772 /* Prefix write with label. */
3773 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3775 } else if (safi
== SAFI_FLOWSPEC
) {
3776 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3777 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3778 p
->u
.prefix_flowspec
.prefixlen
);
3780 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
3783 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3784 const struct prefix
*p
)
3786 int size
= PSIZE(p
->prefixlen
);
3787 if (safi
== SAFI_MPLS_VPN
)
3789 else if (safi
== SAFI_LABELED_UNICAST
)
3790 size
+= BGP_LABEL_BYTES
;
3791 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3792 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3798 * Encodes the tunnel encapsulation attribute,
3799 * and with ENABLE_BGP_VNC the VNC attribute which uses
3800 * almost the same TLV format
3802 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3803 struct stream
*s
, struct attr
*attr
,
3806 unsigned int attrlenfield
= 0;
3807 unsigned int attrhdrlen
= 0;
3808 struct bgp_attr_encap_subtlv
*subtlvs
;
3809 struct bgp_attr_encap_subtlv
*st
;
3810 const char *attrname
;
3812 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3813 && (!attr
->encap_tunneltype
3814 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3818 case BGP_ATTR_ENCAP
:
3819 attrname
= "Tunnel Encap";
3820 subtlvs
= attr
->encap_subtlvs
;
3821 if (subtlvs
== NULL
) /* nothing to do */
3824 * The tunnel encap attr has an "outer" tlv.
3826 * L = total length of subtlvs,
3827 * V = concatenated subtlvs.
3829 attrlenfield
= 2 + 2; /* T + L */
3830 attrhdrlen
= 1 + 1; /* subTLV T + L */
3833 #ifdef ENABLE_BGP_VNC_ATTR
3836 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3837 if (subtlvs
== NULL
) /* nothing to do */
3839 attrlenfield
= 0; /* no outer T + L */
3840 attrhdrlen
= 2 + 2; /* subTLV T + L */
3848 /* compute attr length */
3849 for (st
= subtlvs
; st
; st
= st
->next
) {
3850 attrlenfield
+= (attrhdrlen
+ st
->length
);
3853 if (attrlenfield
> 0xffff) {
3854 zlog_info("%s attribute is too long (length=%d), can't send it",
3855 attrname
, attrlenfield
);
3859 if (attrlenfield
> 0xff) {
3860 /* 2-octet length field */
3862 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3863 | BGP_ATTR_FLAG_EXTLEN
);
3864 stream_putc(s
, attrtype
);
3865 stream_putw(s
, attrlenfield
& 0xffff);
3867 /* 1-octet length field */
3868 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3869 stream_putc(s
, attrtype
);
3870 stream_putc(s
, attrlenfield
& 0xff);
3873 if (attrtype
== BGP_ATTR_ENCAP
) {
3874 /* write outer T+L */
3875 stream_putw(s
, attr
->encap_tunneltype
);
3876 stream_putw(s
, attrlenfield
- 4);
3879 /* write each sub-tlv */
3880 for (st
= subtlvs
; st
; st
= st
->next
) {
3881 if (attrtype
== BGP_ATTR_ENCAP
) {
3882 stream_putc(s
, st
->type
);
3883 stream_putc(s
, st
->length
);
3884 #ifdef ENABLE_BGP_VNC
3886 stream_putw(s
, st
->type
);
3887 stream_putw(s
, st
->length
);
3890 stream_put(s
, st
->value
, st
->length
);
3894 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3896 /* Set MP attribute length. Don't count the (2) bytes used to encode
3898 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3901 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3903 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3904 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3905 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3906 PEER_FLAG_REMOVE_PRIVATE_AS
)
3907 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3908 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3909 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3910 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3911 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3912 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3917 /* Make attribute packet. */
3918 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3919 struct stream
*s
, struct attr
*attr
,
3920 struct bpacket_attr_vec_arr
*vecarr
,
3921 struct prefix
*p
, afi_t afi
, safi_t safi
,
3922 struct peer
*from
, struct prefix_rd
*prd
,
3923 mpls_label_t
*label
, uint32_t num_labels
,
3924 bool addpath_capable
, uint32_t addpath_tx_id
)
3927 size_t aspath_sizep
;
3928 struct aspath
*aspath
;
3929 int send_as4_path
= 0;
3930 int send_as4_aggregator
= 0;
3931 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
3932 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
3937 /* Remember current pointer. */
3938 cp
= stream_get_endp(s
);
3941 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3942 && !peer_cap_enhe(peer
, afi
, safi
))) {
3943 size_t mpattrlen_pos
= 0;
3945 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3947 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3948 num_labels
, addpath_capable
,
3949 addpath_tx_id
, attr
);
3950 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3953 /* Origin attribute. */
3954 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3955 stream_putc(s
, BGP_ATTR_ORIGIN
);
3957 stream_putc(s
, attr
->origin
);
3959 /* AS path attribute. */
3961 /* If remote-peer is EBGP */
3962 if (peer
->sort
== BGP_PEER_EBGP
3963 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3964 PEER_FLAG_AS_PATH_UNCHANGED
)
3965 || attr
->aspath
->segments
== NULL
)
3966 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3967 PEER_FLAG_RSERVER_CLIENT
))) {
3968 aspath
= aspath_dup(attr
->aspath
);
3970 /* Even though we may not be configured for confederations we
3972 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3973 aspath
= aspath_delete_confed_seq(aspath
);
3975 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3976 /* Stuff our path CONFED_ID on the front */
3977 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3979 if (peer
->change_local_as
) {
3980 /* If replace-as is specified, we only use the
3981 change_local_as when
3982 advertising routes. */
3983 if (!CHECK_FLAG(peer
->flags
,
3984 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3985 if (bgp_append_local_as(peer
, afi
,
3987 aspath
= aspath_add_seq(
3988 aspath
, peer
->local_as
);
3989 aspath
= aspath_add_seq(aspath
,
3990 peer
->change_local_as
);
3992 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3995 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3996 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3998 aspath
= aspath_dup(attr
->aspath
);
3999 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
4001 aspath
= attr
->aspath
;
4003 /* If peer is not AS4 capable, then:
4004 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4005 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4007 * types are in it (i.e. exclude them if they are there)
4008 * AND do this only if there is at least one asnum > 65535 in the
4010 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4012 * all ASnums > 65535 to BGP_AS_TRANS
4015 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4016 stream_putc(s
, BGP_ATTR_AS_PATH
);
4017 aspath_sizep
= stream_get_endp(s
);
4019 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4021 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4024 if (!use32bit
&& aspath_has_as4(aspath
))
4026 1; /* we'll do this later, at the correct place */
4028 /* Nexthop attribute. */
4029 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4030 && !peer_cap_enhe(peer
, afi
, safi
)) {
4031 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4033 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4034 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4035 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4036 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4039 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4040 } else if (peer_cap_enhe(from
, afi
, safi
)
4041 || (nh_afi
== AFI_IP6
)) {
4043 * Likely this is the case when an IPv4 prefix was
4044 * received with Extended Next-hop capability in this
4045 * or another vrf and is now being advertised to
4046 * non-ENHE peers. Since peer_cap_enhe only checks
4047 * peers in this vrf, also check the nh_afi to catch
4048 * the case where the originator was in another vrf.
4049 * Setting the mandatory (ipv4) next-hop attribute here
4050 * to enable implicit next-hop self with correct A-F
4051 * (ipv4 address family).
4053 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4054 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4055 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4058 stream_put_ipv4(s
, 0);
4062 /* MED attribute. */
4063 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4064 || bgp
->maxmed_active
) {
4065 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4066 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4068 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4072 /* Local preference. */
4073 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4074 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4075 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4077 stream_putl(s
, attr
->local_pref
);
4080 /* Atomic aggregate. */
4081 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4082 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4083 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4088 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4089 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4090 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4091 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4094 /* AS4 capable peer */
4096 stream_putl(s
, attr
->aggregator_as
);
4098 /* 2-byte AS peer */
4101 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4103 if (attr
->aggregator_as
> UINT16_MAX
) {
4104 stream_putw(s
, BGP_AS_TRANS
);
4106 /* we have to send AS4_AGGREGATOR, too.
4107 * we'll do that later in order to send
4108 * attributes in ascending
4111 send_as4_aggregator
= 1;
4113 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4115 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4118 /* Community attribute. */
4119 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4120 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4121 if (attr
->community
->size
* 4 > 255) {
4123 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4124 | BGP_ATTR_FLAG_EXTLEN
);
4125 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4126 stream_putw(s
, attr
->community
->size
* 4);
4129 BGP_ATTR_FLAG_OPTIONAL
4130 | BGP_ATTR_FLAG_TRANS
);
4131 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4132 stream_putc(s
, attr
->community
->size
* 4);
4134 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4138 * Large Community attribute.
4140 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4141 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4142 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4143 if (lcom_length(attr
->lcommunity
) > 255) {
4145 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4146 | BGP_ATTR_FLAG_EXTLEN
);
4147 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4148 stream_putw(s
, lcom_length(attr
->lcommunity
));
4151 BGP_ATTR_FLAG_OPTIONAL
4152 | BGP_ATTR_FLAG_TRANS
);
4153 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4154 stream_putc(s
, lcom_length(attr
->lcommunity
));
4156 stream_put(s
, attr
->lcommunity
->val
,
4157 lcom_length(attr
->lcommunity
));
4160 /* Route Reflector. */
4161 if (peer
->sort
== BGP_PEER_IBGP
&& from
4162 && from
->sort
== BGP_PEER_IBGP
) {
4163 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4165 /* Originator ID. */
4166 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4167 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4170 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4171 stream_put_in_addr(s
, &attr
->originator_id
);
4173 stream_put_in_addr(s
, &from
->remote_id
);
4176 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4177 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4180 stream_putc(s
, cluster
->length
+ 4);
4181 /* If this peer configuration's parent BGP has
4183 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4184 stream_put_in_addr(s
, &bgp
->cluster_id
);
4186 stream_put_in_addr(s
, &bgp
->router_id
);
4187 stream_put(s
, cluster
->list
, cluster
->length
);
4190 /* If this peer configuration's parent BGP has
4192 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4193 stream_put_in_addr(s
, &bgp
->cluster_id
);
4195 stream_put_in_addr(s
, &bgp
->router_id
);
4199 /* Extended Communities attribute. */
4200 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4201 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4202 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4204 if (peer
->sort
== BGP_PEER_IBGP
4205 || peer
->sort
== BGP_PEER_CONFED
) {
4206 if (ecomm
->size
* 8 > 255) {
4208 BGP_ATTR_FLAG_OPTIONAL
4209 | BGP_ATTR_FLAG_TRANS
4210 | BGP_ATTR_FLAG_EXTLEN
);
4211 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4212 stream_putw(s
, ecomm
->size
* 8);
4215 BGP_ATTR_FLAG_OPTIONAL
4216 | BGP_ATTR_FLAG_TRANS
);
4217 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4218 stream_putc(s
, ecomm
->size
* 8);
4220 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4224 int ecom_tr_size
= 0;
4227 for (i
= 0; i
< ecomm
->size
; i
++) {
4228 pnt
= ecomm
->val
+ (i
* 8);
4231 if (CHECK_FLAG(tbit
,
4232 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4239 if (ecom_tr_size
* 8 > 255) {
4242 BGP_ATTR_FLAG_OPTIONAL
4243 | BGP_ATTR_FLAG_TRANS
4244 | BGP_ATTR_FLAG_EXTLEN
);
4246 BGP_ATTR_EXT_COMMUNITIES
);
4247 stream_putw(s
, ecom_tr_size
* 8);
4251 BGP_ATTR_FLAG_OPTIONAL
4252 | BGP_ATTR_FLAG_TRANS
);
4254 BGP_ATTR_EXT_COMMUNITIES
);
4255 stream_putc(s
, ecom_tr_size
* 8);
4258 for (i
= 0; i
< ecomm
->size
; i
++) {
4259 pnt
= ecomm
->val
+ (i
* 8);
4264 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4267 stream_put(s
, pnt
, 8);
4273 /* Label index attribute. */
4274 if (safi
== SAFI_LABELED_UNICAST
) {
4275 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4276 uint32_t label_index
;
4278 label_index
= attr
->label_index
;
4280 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4282 BGP_ATTR_FLAG_OPTIONAL
4283 | BGP_ATTR_FLAG_TRANS
);
4284 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4286 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4288 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4289 stream_putc(s
, 0); // reserved
4290 stream_putw(s
, 0); // flags
4291 stream_putl(s
, label_index
);
4296 /* SRv6 Service Information Attribute. */
4297 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4298 if (attr
->srv6_l3vpn
) {
4299 uint8_t subtlv_len
=
4300 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4302 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4303 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4304 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4305 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4306 | BGP_ATTR_FLAG_TRANS
);
4307 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4308 stream_putc(s
, attr_len
);
4309 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4310 stream_putw(s
, tlv_len
);
4311 stream_putc(s
, 0); /* reserved */
4312 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4313 stream_putw(s
, subtlv_len
);
4314 stream_putc(s
, 0); /* reserved */
4315 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4316 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4317 stream_putc(s
, 0); /* sid_flags */
4318 stream_putw(s
, 0xffff); /* endpoint */
4319 stream_putc(s
, 0); /* reserved */
4322 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4325 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4326 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4327 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4328 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4329 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4330 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4331 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4332 } else if (attr
->srv6_vpn
) {
4333 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4334 | BGP_ATTR_FLAG_TRANS
);
4335 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4336 stream_putc(s
, 22); /* tlv len */
4337 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4338 stream_putw(s
, 0x13); /* tlv len */
4339 stream_putc(s
, 0x00); /* reserved */
4340 stream_putc(s
, 0x01); /* sid_type */
4341 stream_putc(s
, 0x00); /* sif_flags */
4342 stream_put(s
, &attr
->srv6_vpn
->sid
,
4343 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4347 if (send_as4_path
) {
4348 /* If the peer is NOT As4 capable, AND */
4349 /* there are ASnums > 65535 in path THEN
4350 * give out AS4_PATH */
4352 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4354 * Hm, I wonder... confederation things *should* only be at
4355 * the beginning of an aspath, right? Then we should use
4356 * aspath_delete_confed_seq for this, because it is already
4358 * Folks, talk to me: what is reasonable here!?
4360 aspath
= aspath_delete_confed_seq(aspath
);
4363 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4364 | BGP_ATTR_FLAG_EXTLEN
);
4365 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4366 aspath_sizep
= stream_get_endp(s
);
4368 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4371 if (aspath
!= attr
->aspath
)
4372 aspath_free(aspath
);
4374 if (send_as4_aggregator
) {
4375 /* send AS4_AGGREGATOR, at this place */
4376 /* this section of code moved here in order to ensure the
4378 * *ascending* order of attributes
4380 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4381 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4383 stream_putl(s
, attr
->aggregator_as
);
4384 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4387 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4388 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4389 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4390 /* Tunnel Encap attribute */
4391 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4393 #ifdef ENABLE_BGP_VNC_ATTR
4395 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4400 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4401 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4402 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4403 stream_putc(s
, 9); // Length
4404 stream_putc(s
, 0); // Flags
4405 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4406 stream_put(s
, &(attr
->label
),
4407 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4408 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4409 // Unicast tunnel endpoint IP address
4412 /* Unknown transit attribute. */
4413 struct transit
*transit
= bgp_attr_get_transit(attr
);
4416 stream_put(s
, transit
->val
, transit
->length
);
4418 /* Return total size of attribute. */
4419 return stream_get_endp(s
) - cp
;
4422 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4424 unsigned long attrlen_pnt
;
4426 iana_safi_t pkt_safi
;
4428 /* Set extended bit always to encode the attribute length as 2 bytes */
4429 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4430 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4432 attrlen_pnt
= stream_get_endp(s
);
4433 stream_putw(s
, 0); /* Length of this attribute. */
4435 /* Convert AFI, SAFI to values for packet. */
4436 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4438 stream_putw(s
, pkt_afi
);
4439 stream_putc(s
, pkt_safi
);
4444 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4445 afi_t afi
, safi_t safi
,
4446 const struct prefix_rd
*prd
,
4447 mpls_label_t
*label
, uint32_t num_labels
,
4448 bool addpath_capable
, uint32_t addpath_tx_id
,
4451 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4453 if (safi
== SAFI_LABELED_UNICAST
) {
4454 label
= (mpls_label_t
*)wlabel
;
4458 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4459 addpath_capable
, addpath_tx_id
, attr
);
4462 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4464 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4467 /* Initialization of attribute. */
4468 void bgp_attr_init(void)
4481 void bgp_attr_finish(void)
4486 ecommunity_finish();
4487 lcommunity_finish();
4494 /* Make attribute packet. */
4495 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4496 const struct prefix
*prefix
)
4501 struct aspath
*aspath
;
4502 bool addpath_capable
= false;
4503 uint32_t addpath_tx_id
= 0;
4505 /* Remember current pointer. */
4506 cp
= stream_get_endp(s
);
4508 /* Place holder of length. */
4511 /* Origin attribute. */
4512 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4513 stream_putc(s
, BGP_ATTR_ORIGIN
);
4515 stream_putc(s
, attr
->origin
);
4517 aspath
= attr
->aspath
;
4519 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4520 stream_putc(s
, BGP_ATTR_AS_PATH
);
4521 aspath_lenp
= stream_get_endp(s
);
4524 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4526 /* Nexthop attribute. */
4527 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4528 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4529 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4530 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4532 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4535 /* MED attribute. */
4536 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4537 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4538 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4540 stream_putl(s
, attr
->med
);
4543 /* Local preference. */
4544 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4545 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4546 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4548 stream_putl(s
, attr
->local_pref
);
4551 /* Atomic aggregate. */
4552 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4553 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4554 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4559 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4560 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4561 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4563 stream_putl(s
, attr
->aggregator_as
);
4564 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4567 /* Community attribute. */
4568 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4569 if (attr
->community
->size
* 4 > 255) {
4571 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4572 | BGP_ATTR_FLAG_EXTLEN
);
4573 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4574 stream_putw(s
, attr
->community
->size
* 4);
4577 BGP_ATTR_FLAG_OPTIONAL
4578 | BGP_ATTR_FLAG_TRANS
);
4579 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4580 stream_putc(s
, attr
->community
->size
* 4);
4582 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4585 /* Large Community attribute. */
4586 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4587 if (lcom_length(attr
->lcommunity
) > 255) {
4589 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4590 | BGP_ATTR_FLAG_EXTLEN
);
4591 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4592 stream_putw(s
, lcom_length(attr
->lcommunity
));
4595 BGP_ATTR_FLAG_OPTIONAL
4596 | BGP_ATTR_FLAG_TRANS
);
4597 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4598 stream_putc(s
, lcom_length(attr
->lcommunity
));
4601 stream_put(s
, attr
->lcommunity
->val
,
4602 lcom_length(attr
->lcommunity
));
4605 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4606 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4607 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4608 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4611 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4612 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4613 sizep
= stream_get_endp(s
);
4616 stream_putc(s
, 0); /* Marker: Attribute length. */
4617 stream_putw(s
, AFI_IP6
); /* AFI */
4618 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4621 stream_putc(s
, attr
->mp_nexthop_len
);
4622 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4623 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4624 stream_put(s
, &attr
->mp_nexthop_local
,
4631 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4634 /* Set MP attribute length. */
4635 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4639 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4640 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4642 BGP_ATTR_FLAG_OPTIONAL
4643 | BGP_ATTR_FLAG_TRANS
);
4644 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4646 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4647 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4648 stream_putc(s
, 0); // reserved
4649 stream_putw(s
, 0); // flags
4650 stream_putl(s
, attr
->label_index
);
4654 /* Return total size of attribute. */
4655 len
= stream_get_endp(s
) - cp
- 2;
4656 stream_putw_at(s
, cp
, len
);