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
);
1152 /* Free bgp attribute and aspath. */
1153 void bgp_attr_unintern(struct attr
**pattr
)
1155 struct attr
*attr
= *pattr
;
1159 /* Decrement attribute reference. */
1164 /* If reference becomes zero then free attribute object. */
1165 if (attr
->refcnt
== 0) {
1166 ret
= hash_release(attrhash
, attr
);
1167 assert(ret
!= NULL
);
1168 XFREE(MTYPE_ATTR
, attr
);
1172 bgp_attr_unintern_sub(&tmp
);
1175 void bgp_attr_flush(struct attr
*attr
)
1177 struct ecommunity
*ecomm
;
1178 struct ecommunity
*ipv6_ecomm
;
1179 struct cluster_list
*cluster
;
1181 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1182 aspath_free(attr
->aspath
);
1183 attr
->aspath
= NULL
;
1185 if (attr
->community
&& !attr
->community
->refcnt
)
1186 community_free(&attr
->community
);
1187 ecomm
= bgp_attr_get_ecommunity(attr
);
1188 if (ecomm
&& !ecomm
->refcnt
)
1189 ecommunity_free(&ecomm
);
1190 bgp_attr_set_ecommunity(attr
, NULL
);
1191 ipv6_ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1192 if (ipv6_ecomm
&& !ipv6_ecomm
->refcnt
)
1193 ecommunity_free(&ipv6_ecomm
);
1194 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1195 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
1196 lcommunity_free(&attr
->lcommunity
);
1198 cluster
= bgp_attr_get_cluster(attr
);
1199 if (cluster
&& !cluster
->refcnt
) {
1200 cluster_free(cluster
);
1201 bgp_attr_set_cluster(attr
, NULL
);
1204 struct transit
*transit
= bgp_attr_get_transit(attr
);
1206 if (transit
&& !transit
->refcnt
) {
1207 transit_free(transit
);
1208 bgp_attr_set_transit(attr
, NULL
);
1210 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1211 encap_free(attr
->encap_subtlvs
);
1212 attr
->encap_subtlvs
= NULL
;
1214 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1215 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1216 attr
->srv6_l3vpn
= NULL
;
1218 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1219 srv6_vpn_free(attr
->srv6_vpn
);
1220 attr
->srv6_vpn
= NULL
;
1222 #ifdef ENABLE_BGP_VNC
1223 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1224 bgp_attr_get_vnc_subtlvs(attr
);
1226 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1227 encap_free(vnc_subtlvs
);
1228 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1231 bgp_attr_extra_free(attr
);
1234 /* Implement draft-scudder-idr-optional-transitive behaviour and
1235 * avoid resetting sessions for malformed attributes which are
1236 * are partial/optional and hence where the error likely was not
1237 * introduced by the sending neighbour.
1239 static bgp_attr_parse_ret_t
1240 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1243 struct peer
*const peer
= args
->peer
;
1244 struct attr
*const attr
= args
->attr
;
1245 const uint8_t flags
= args
->flags
;
1246 /* startp and length must be special-cased, as whether or not to
1247 * send the attribute data with the NOTIFY depends on the error,
1248 * the caller therefore signals this with the seperate length argument
1250 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1252 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1253 char attr_str
[BUFSIZ
] = {0};
1255 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1257 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1260 /* Only relax error handling for eBGP peers */
1261 if (peer
->sort
!= BGP_PEER_EBGP
) {
1262 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1263 notify_datap
, length
);
1264 return BGP_ATTR_PARSE_ERROR
;
1267 /* Adjust the stream getp to the end of the attribute, in case we can
1268 * still proceed but the caller hasn't read all the attribute.
1270 stream_set_getp(BGP_INPUT(peer
),
1271 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1274 switch (args
->type
) {
1275 /* where an attribute is relatively inconsequential, e.g. it does not
1276 * affect route selection, and can be safely ignored, then any such
1277 * attributes which are malformed should just be ignored and the route
1278 * processed as normal.
1280 case BGP_ATTR_AS4_AGGREGATOR
:
1281 case BGP_ATTR_AGGREGATOR
:
1282 case BGP_ATTR_ATOMIC_AGGREGATE
:
1283 return BGP_ATTR_PARSE_PROCEED
;
1285 /* Core attributes, particularly ones which may influence route
1286 * selection, should be treat-as-withdraw.
1288 case BGP_ATTR_ORIGIN
:
1289 case BGP_ATTR_AS_PATH
:
1290 case BGP_ATTR_NEXT_HOP
:
1291 case BGP_ATTR_MULTI_EXIT_DISC
:
1292 case BGP_ATTR_LOCAL_PREF
:
1293 case BGP_ATTR_COMMUNITIES
:
1294 case BGP_ATTR_EXT_COMMUNITIES
:
1295 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1296 case BGP_ATTR_LARGE_COMMUNITIES
:
1297 case BGP_ATTR_ORIGINATOR_ID
:
1298 case BGP_ATTR_CLUSTER_LIST
:
1299 return BGP_ATTR_PARSE_WITHDRAW
;
1300 case BGP_ATTR_MP_REACH_NLRI
:
1301 case BGP_ATTR_MP_UNREACH_NLRI
:
1302 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1303 notify_datap
, length
);
1304 return BGP_ATTR_PARSE_ERROR
;
1307 /* Partial optional attributes that are malformed should not cause
1308 * the whole session to be reset. Instead treat it as a withdrawal
1309 * of the routes, if possible.
1311 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1312 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1313 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1314 return BGP_ATTR_PARSE_WITHDRAW
;
1316 /* default to reset */
1317 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1320 /* Find out what is wrong with the path attribute flag bits and log the error.
1321 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1322 Extended Length. Checking O/T/P bits at once implies, that the attribute
1323 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1324 non-transitive" attribute. */
1326 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1327 uint8_t desired_flags
/* how RFC says it must be */
1330 uint8_t seen
= 0, i
;
1331 uint8_t real_flags
= args
->flags
;
1332 const uint8_t attr_code
= args
->type
;
1334 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1335 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1336 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1337 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1338 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1339 flog_err(EC_BGP_ATTR_FLAG
,
1340 "%s attribute must%s be flagged as \"%s\"",
1341 lookup_msg(attr_str
, attr_code
, NULL
),
1342 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1345 attr_flag_str
[i
].str
);
1350 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1351 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1352 real_flags
, desired_flags
);
1356 /* Required flags for attributes. EXTLEN will be masked off when testing,
1357 * as will PARTIAL for optional+transitive attributes.
1359 const uint8_t attr_flags_values
[] = {
1360 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1361 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1362 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1363 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1364 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1365 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1366 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1367 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1368 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1369 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1370 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1371 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1372 [BGP_ATTR_EXT_COMMUNITIES
] =
1373 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1374 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1375 [BGP_ATTR_AS4_AGGREGATOR
] =
1376 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1377 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1378 [BGP_ATTR_LARGE_COMMUNITIES
] =
1379 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1380 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1381 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1382 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1384 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1386 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1388 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1389 const uint8_t flags
= args
->flags
;
1390 const uint8_t attr_code
= args
->type
;
1392 /* there may be attributes we don't know about */
1393 if (attr_code
> attr_flags_values_max
)
1395 if (attr_flags_values
[attr_code
] == 0)
1398 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1402 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1403 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1406 "%s well-known attributes must have transitive flag set (%x)",
1407 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1411 /* "For well-known attributes and for optional non-transitive
1413 * the Partial bit MUST be set to 0."
1415 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1416 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1417 flog_err(EC_BGP_ATTR_FLAG
,
1418 "%s well-known attribute must NOT have the partial flag set (%x)",
1419 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1422 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1423 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1424 flog_err(EC_BGP_ATTR_FLAG
,
1425 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1426 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1431 /* Optional transitive attributes may go through speakers that don't
1432 * reocgnise them and set the Partial bit.
1434 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1435 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1436 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1438 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1441 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1445 /* Get origin attribute of the update message. */
1446 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1448 struct peer
*const peer
= args
->peer
;
1449 struct attr
*const attr
= args
->attr
;
1450 const bgp_size_t length
= args
->length
;
1452 /* If any recognized attribute has Attribute Length that conflicts
1453 with the expected length (based on the attribute type code), then
1454 the Error Subcode is set to Attribute Length Error. The Data
1455 field contains the erroneous attribute (type, length and
1458 flog_err(EC_BGP_ATTR_LEN
,
1459 "Origin attribute length is not one %d", length
);
1460 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1464 /* Fetch origin attribute. */
1465 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1467 /* If the ORIGIN attribute has an undefined value, then the Error
1468 Subcode is set to Invalid Origin Attribute. The Data field
1469 contains the unrecognized attribute (type, length and value). */
1470 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1471 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1472 flog_err(EC_BGP_ATTR_ORIGIN
,
1473 "Origin attribute value is invalid %d", attr
->origin
);
1474 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1478 /* Set oring attribute flag. */
1479 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1484 /* Parse AS path information. This function is wrapper of
1486 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1488 struct attr
*const attr
= args
->attr
;
1489 struct peer
*const peer
= args
->peer
;
1490 const bgp_size_t length
= args
->length
;
1493 * peer with AS4 => will get 4Byte ASnums
1494 * otherwise, will get 16 Bit
1496 attr
->aspath
= aspath_parse(
1498 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1499 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1501 /* In case of IBGP, length will be zero. */
1502 if (!attr
->aspath
) {
1503 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1504 "Malformed AS path from %s, length is %d", peer
->host
,
1506 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1510 /* Set aspath attribute flag. */
1511 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1513 return BGP_ATTR_PARSE_PROCEED
;
1516 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1517 struct attr
*const attr
)
1519 /* These checks were part of bgp_attr_aspath, but with
1520 * as4 we should to check aspath things when
1521 * aspath synthesizing with as4_path has already taken place.
1522 * Otherwise we check ASPATH and use the synthesized thing, and that is
1524 * So do the checks later, i.e. here
1526 struct aspath
*aspath
;
1528 /* Confederation sanity check. */
1529 if ((peer
->sort
== BGP_PEER_CONFED
1530 && !aspath_left_confed_check(attr
->aspath
))
1531 || (peer
->sort
== BGP_PEER_EBGP
1532 && aspath_confed_check(attr
->aspath
))) {
1533 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1535 return BGP_ATTR_PARSE_WITHDRAW
;
1538 /* First AS check for EBGP. */
1539 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1540 if (peer
->sort
== BGP_PEER_EBGP
1541 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1542 flog_err(EC_BGP_ATTR_FIRST_AS
,
1543 "%s incorrect first AS (must be %u)",
1544 peer
->host
, peer
->as
);
1545 return BGP_ATTR_PARSE_WITHDRAW
;
1549 /* Codification of AS 0 Processing */
1550 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1552 EC_BGP_ATTR_MAL_AS_PATH
,
1553 "Malformed AS path, AS number is 0 in the path from %s",
1555 return BGP_ATTR_PARSE_WITHDRAW
;
1558 /* local-as prepend */
1559 if (peer
->change_local_as
1560 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1561 aspath
= aspath_dup(attr
->aspath
);
1562 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1563 aspath_unintern(&attr
->aspath
);
1564 attr
->aspath
= aspath_intern(aspath
);
1567 return BGP_ATTR_PARSE_PROCEED
;
1570 /* Parse AS4 path information. This function is another wrapper of
1572 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1573 struct aspath
**as4_path
)
1575 struct peer
*const peer
= args
->peer
;
1576 struct attr
*const attr
= args
->attr
;
1577 const bgp_size_t length
= args
->length
;
1579 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1581 /* In case of IBGP, length will be zero. */
1583 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1584 "Malformed AS4 path from %s, length is %d", peer
->host
,
1586 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1590 /* Set aspath attribute flag. */
1591 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1593 return BGP_ATTR_PARSE_PROCEED
;
1597 * Check that the nexthop attribute is valid.
1599 bgp_attr_parse_ret_t
1600 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1602 in_addr_t nexthop_h
;
1604 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1605 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1606 || IPV4_CLASS_DE(nexthop_h
))
1607 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1608 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1609 char buf
[INET_ADDRSTRLEN
];
1611 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1613 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1615 data
[0] = BGP_ATTR_FLAG_TRANS
;
1616 data
[1] = BGP_ATTR_NEXT_HOP
;
1617 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1618 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1619 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1620 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1622 return BGP_ATTR_PARSE_ERROR
;
1625 return BGP_ATTR_PARSE_PROCEED
;
1628 /* Nexthop attribute. */
1629 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1631 struct peer
*const peer
= args
->peer
;
1632 struct attr
*const attr
= args
->attr
;
1633 const bgp_size_t length
= args
->length
;
1635 /* Check nexthop attribute length. */
1637 flog_err(EC_BGP_ATTR_LEN
,
1638 "Nexthop attribute length isn't four [%d]", length
);
1640 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1644 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1645 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1647 return BGP_ATTR_PARSE_PROCEED
;
1650 /* MED atrribute. */
1651 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1653 struct peer
*const peer
= args
->peer
;
1654 struct attr
*const attr
= args
->attr
;
1655 const bgp_size_t length
= args
->length
;
1659 flog_err(EC_BGP_ATTR_LEN
,
1660 "MED attribute length isn't four [%d]", length
);
1662 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1666 attr
->med
= stream_getl(peer
->curr
);
1668 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1670 return BGP_ATTR_PARSE_PROCEED
;
1673 /* Local preference attribute. */
1674 static bgp_attr_parse_ret_t
1675 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1677 struct peer
*const peer
= args
->peer
;
1678 struct attr
*const attr
= args
->attr
;
1679 const bgp_size_t length
= args
->length
;
1681 /* if received from an internal neighbor, it SHALL be considered
1682 * malformed if its length is not equal to 4. If malformed, the
1683 * UPDATE message SHALL be handled using the approach of "treat-as-
1686 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1687 flog_err(EC_BGP_ATTR_LEN
,
1688 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1689 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1693 /* If it is contained in an UPDATE message that is received from an
1694 external peer, then this attribute MUST be ignored by the
1695 receiving speaker. */
1696 if (peer
->sort
== BGP_PEER_EBGP
) {
1697 STREAM_FORWARD_GETP(peer
->curr
, length
);
1698 return BGP_ATTR_PARSE_PROCEED
;
1701 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1703 /* Set the local-pref flag. */
1704 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1706 return BGP_ATTR_PARSE_PROCEED
;
1709 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1713 /* Atomic aggregate. */
1714 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1716 struct attr
*const attr
= args
->attr
;
1717 const bgp_size_t length
= args
->length
;
1721 flog_err(EC_BGP_ATTR_LEN
,
1722 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1724 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1728 /* Set atomic aggregate flag. */
1729 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1731 return BGP_ATTR_PARSE_PROCEED
;
1734 /* Aggregator attribute */
1735 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1737 struct peer
*const peer
= args
->peer
;
1738 struct attr
*const attr
= args
->attr
;
1739 const bgp_size_t length
= args
->length
;
1744 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1745 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1746 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1749 if (length
!= wantedlen
) {
1750 flog_err(EC_BGP_ATTR_LEN
,
1751 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1753 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1757 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1758 aggregator_as
= stream_getl(peer
->curr
);
1760 aggregator_as
= stream_getw(peer
->curr
);
1762 attr
->aggregator_as
= aggregator_as
;
1763 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1765 /* Codification of AS 0 Processing */
1766 if (aggregator_as
== BGP_AS_ZERO
) {
1767 flog_err(EC_BGP_ATTR_LEN
,
1768 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1769 peer
->host
, aspath_print(attr
->aspath
));
1771 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1772 char attr_str
[BUFSIZ
] = {0};
1774 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1776 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1779 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1782 return BGP_ATTR_PARSE_PROCEED
;
1785 /* New Aggregator attribute */
1786 static bgp_attr_parse_ret_t
1787 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1788 as_t
*as4_aggregator_as
,
1789 struct in_addr
*as4_aggregator_addr
)
1791 struct peer
*const peer
= args
->peer
;
1792 struct attr
*const attr
= args
->attr
;
1793 const bgp_size_t length
= args
->length
;
1797 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1799 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1803 aggregator_as
= stream_getl(peer
->curr
);
1805 *as4_aggregator_as
= aggregator_as
;
1806 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1808 /* Codification of AS 0 Processing */
1809 if (aggregator_as
== BGP_AS_ZERO
) {
1810 flog_err(EC_BGP_ATTR_LEN
,
1811 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1812 peer
->host
, aspath_print(attr
->aspath
));
1814 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1815 char attr_str
[BUFSIZ
] = {0};
1817 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1819 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1822 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1825 return BGP_ATTR_PARSE_PROCEED
;
1828 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1830 static bgp_attr_parse_ret_t
1831 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1832 struct aspath
*as4_path
, as_t as4_aggregator
,
1833 struct in_addr
*as4_aggregator_addr
)
1835 int ignore_as4_path
= 0;
1836 struct aspath
*newpath
;
1838 if (!attr
->aspath
) {
1839 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1841 * checked that all well-known, mandatory attributes were
1844 * Can only be a problem with peer itself - hard error
1846 return BGP_ATTR_PARSE_ERROR
;
1849 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1850 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1852 * It is worth a warning though, because the peer really
1853 * should not send them
1855 if (BGP_DEBUG(as4
, AS4
)) {
1856 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1857 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1858 "AS4 capable peer, yet it sent");
1861 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1862 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1864 "AS4 capable peer, yet it sent");
1867 return BGP_ATTR_PARSE_PROCEED
;
1870 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1871 * because that may override AS4_PATH
1873 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1874 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1876 * if the as_number in aggregator is not AS_TRANS,
1877 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1878 * and the Aggregator shall be taken as
1879 * info on the aggregating node, and the AS_PATH
1880 * shall be taken as the AS_PATH
1882 * the Aggregator shall be ignored and the
1883 * AS4_AGGREGATOR shall be taken as the
1884 * Aggregating node and the AS_PATH is to be
1885 * constructed "as in all other cases"
1887 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1889 if (BGP_DEBUG(as4
, AS4
))
1891 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1893 ignore_as4_path
= 1;
1895 /* "New_aggregator shall be taken as aggregator"
1897 attr
->aggregator_as
= as4_aggregator
;
1898 attr
->aggregator_addr
.s_addr
=
1899 as4_aggregator_addr
->s_addr
;
1902 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1903 * That is bogus - but reading the conditions
1904 * we have to handle AS4_AGGREGATOR as if it were
1905 * AGGREGATOR in that case
1907 if (BGP_DEBUG(as4
, AS4
))
1909 "[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",
1911 attr
->aggregator_as
= as4_aggregator
;
1912 /* sweep it under the carpet and simulate a "good"
1914 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1918 /* need to reconcile NEW_AS_PATH and AS_PATH */
1919 if (!ignore_as4_path
1920 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1921 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1923 return BGP_ATTR_PARSE_ERROR
;
1925 aspath_unintern(&attr
->aspath
);
1926 attr
->aspath
= aspath_intern(newpath
);
1928 return BGP_ATTR_PARSE_PROCEED
;
1931 /* Community attribute. */
1932 static bgp_attr_parse_ret_t
1933 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1935 struct peer
*const peer
= args
->peer
;
1936 struct attr
*const attr
= args
->attr
;
1937 const bgp_size_t length
= args
->length
;
1940 attr
->community
= NULL
;
1941 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1946 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1948 /* XXX: fix community_parse to use stream API and remove this */
1949 stream_forward_getp(peer
->curr
, length
);
1951 /* The Community attribute SHALL be considered malformed if its
1952 * length is not a non-zero multiple of 4.
1954 if (!attr
->community
)
1955 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1958 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1960 return BGP_ATTR_PARSE_PROCEED
;
1963 /* Originator ID attribute. */
1964 static bgp_attr_parse_ret_t
1965 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1967 struct peer
*const peer
= args
->peer
;
1968 struct attr
*const attr
= args
->attr
;
1969 const bgp_size_t length
= args
->length
;
1971 /* if received from an internal neighbor, it SHALL be considered
1972 * malformed if its length is not equal to 4. If malformed, the
1973 * UPDATE message SHALL be handled using the approach of "treat-as-
1977 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1980 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1984 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1986 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1988 return BGP_ATTR_PARSE_PROCEED
;
1991 /* Cluster list attribute. */
1992 static bgp_attr_parse_ret_t
1993 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1995 struct peer
*const peer
= args
->peer
;
1996 struct attr
*const attr
= args
->attr
;
1997 const bgp_size_t length
= args
->length
;
1999 /* if received from an internal neighbor, it SHALL be considered
2000 * malformed if its length is not a non-zero multiple of 4. If
2001 * malformed, the UPDATE message SHALL be handled using the approach
2002 * of "treat-as-withdraw".
2004 if (length
== 0 || length
% 4) {
2005 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2007 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2011 bgp_attr_set_cluster(
2012 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2015 /* XXX: Fix cluster_parse to use stream API and then remove this */
2016 stream_forward_getp(peer
->curr
, length
);
2018 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2020 return BGP_ATTR_PARSE_PROCEED
;
2023 /* Multiprotocol reachability information parse. */
2024 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2025 struct bgp_nlri
*mp_update
)
2029 iana_safi_t pkt_safi
;
2031 bgp_size_t nlri_len
;
2034 struct peer
*const peer
= args
->peer
;
2035 struct attr
*const attr
= args
->attr
;
2036 const bgp_size_t length
= args
->length
;
2038 /* Set end of packet. */
2039 s
= BGP_INPUT(peer
);
2040 start
= stream_get_getp(s
);
2042 /* safe to read statically sized header? */
2043 #define BGP_MP_REACH_MIN_SIZE 5
2044 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2045 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2046 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2047 __func__
, peer
->host
, (unsigned long)length
);
2048 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2051 /* Load AFI, SAFI. */
2052 pkt_afi
= stream_getw(s
);
2053 pkt_safi
= stream_getc(s
);
2055 /* Convert AFI, SAFI to internal values, check. */
2056 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2057 /* Log if AFI or SAFI is unrecognized. This is not an error
2059 * the attribute is otherwise malformed.
2061 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2063 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2064 peer
->host
, iana_afi2str(pkt_afi
),
2065 iana_safi2str(pkt_safi
));
2066 return BGP_ATTR_PARSE_ERROR
;
2069 /* Get nexthop length. */
2070 attr
->mp_nexthop_len
= stream_getc(s
);
2072 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2074 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2075 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2076 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2079 /* Nexthop length check. */
2080 switch (attr
->mp_nexthop_len
) {
2082 if (safi
!= SAFI_FLOWSPEC
) {
2083 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2084 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2085 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2088 case BGP_ATTR_NHLEN_VPNV4
:
2089 stream_getl(s
); /* RD high */
2090 stream_getl(s
); /* RD low */
2092 * NOTE: intentional fall through
2093 * - for consistency in rx processing
2095 * The following comment is to signal GCC this intention
2096 * and suppress the warning
2099 case BGP_ATTR_NHLEN_IPV4
:
2100 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2101 /* Probably needed for RFC 2283 */
2102 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2103 memcpy(&attr
->nexthop
.s_addr
,
2104 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2106 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2107 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2108 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2109 stream_getl(s
); /* RD high */
2110 stream_getl(s
); /* RD low */
2112 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2113 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2114 if (!peer
->nexthop
.ifp
) {
2115 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2117 return BGP_ATTR_PARSE_WITHDRAW
;
2119 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2122 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2123 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2124 if (attr
->mp_nexthop_len
2125 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2126 stream_getl(s
); /* RD high */
2127 stream_getl(s
); /* RD low */
2129 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2130 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2131 if (!peer
->nexthop
.ifp
) {
2132 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",
2134 return BGP_ATTR_PARSE_WITHDRAW
;
2136 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2138 if (attr
->mp_nexthop_len
2139 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2140 stream_getl(s
); /* RD high */
2141 stream_getl(s
); /* RD low */
2143 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2144 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2145 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2147 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2148 peer
->host
, &attr
->mp_nexthop_global
,
2149 &attr
->mp_nexthop_local
);
2151 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2153 if (!peer
->nexthop
.ifp
) {
2154 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2156 return BGP_ATTR_PARSE_WITHDRAW
;
2158 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2161 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2162 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2163 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2167 zlog_info("%s: %s sent SNPA which couldn't be read",
2168 __func__
, peer
->host
);
2169 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2174 if ((val
= stream_getc(s
)))
2176 EC_BGP_DEFUNCT_SNPA_LEN
,
2177 "%s sent non-zero value, %u, for defunct SNPA-length field",
2181 /* must have nrli_len, what is left of the attribute */
2182 nlri_len
= LEN_LEFT
;
2183 if (nlri_len
> STREAM_READABLE(s
)) {
2184 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2185 __func__
, peer
->host
);
2186 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2190 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2191 __func__
, peer
->host
);
2193 mp_update
->afi
= afi
;
2194 mp_update
->safi
= safi
;
2195 return BGP_ATTR_PARSE_EOR
;
2198 mp_update
->afi
= afi
;
2199 mp_update
->safi
= safi
;
2200 mp_update
->nlri
= stream_pnt(s
);
2201 mp_update
->length
= nlri_len
;
2203 stream_forward_getp(s
, nlri_len
);
2205 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2207 return BGP_ATTR_PARSE_PROCEED
;
2211 /* Multiprotocol unreachable parse */
2212 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2213 struct bgp_nlri
*mp_withdraw
)
2218 iana_safi_t pkt_safi
;
2220 uint16_t withdraw_len
;
2221 struct peer
*const peer
= args
->peer
;
2222 struct attr
*const attr
= args
->attr
;
2223 const bgp_size_t length
= args
->length
;
2227 #define BGP_MP_UNREACH_MIN_SIZE 3
2228 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2229 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2231 pkt_afi
= stream_getw(s
);
2232 pkt_safi
= stream_getc(s
);
2234 /* Convert AFI, SAFI to internal values, check. */
2235 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2236 /* Log if AFI or SAFI is unrecognized. This is not an error
2238 * the attribute is otherwise malformed.
2240 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2242 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2243 peer
->host
, iana_afi2str(pkt_afi
),
2244 iana_safi2str(pkt_safi
));
2245 return BGP_ATTR_PARSE_ERROR
;
2248 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2250 mp_withdraw
->afi
= afi
;
2251 mp_withdraw
->safi
= safi
;
2252 mp_withdraw
->nlri
= stream_pnt(s
);
2253 mp_withdraw
->length
= withdraw_len
;
2255 stream_forward_getp(s
, withdraw_len
);
2257 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2259 return BGP_ATTR_PARSE_PROCEED
;
2262 /* Large Community attribute. */
2263 static bgp_attr_parse_ret_t
2264 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2266 struct peer
*const peer
= args
->peer
;
2267 struct attr
*const attr
= args
->attr
;
2268 const bgp_size_t length
= args
->length
;
2271 * Large community follows new attribute format.
2274 attr
->lcommunity
= NULL
;
2275 /* Empty extcomm doesn't seem to be invalid per se */
2276 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2280 attr
->lcommunity
= lcommunity_parse(stream_pnt(peer
->curr
), length
);
2281 /* XXX: fix ecommunity_parse to use stream API */
2282 stream_forward_getp(peer
->curr
, length
);
2284 if (!attr
->lcommunity
)
2285 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2288 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2290 return BGP_ATTR_PARSE_PROCEED
;
2293 /* Extended Community attribute. */
2294 static bgp_attr_parse_ret_t
2295 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2297 struct peer
*const peer
= args
->peer
;
2298 struct attr
*const attr
= args
->attr
;
2299 const bgp_size_t length
= args
->length
;
2302 struct ecommunity
*ecomm
;
2305 bgp_attr_set_ecommunity(attr
, NULL
);
2306 /* Empty extcomm doesn't seem to be invalid per se */
2307 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2311 ecomm
= ecommunity_parse(
2312 stream_pnt(peer
->curr
), length
,
2313 CHECK_FLAG(peer
->flags
,
2314 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2315 bgp_attr_set_ecommunity(attr
, ecomm
);
2316 /* XXX: fix ecommunity_parse to use stream API */
2317 stream_forward_getp(peer
->curr
, length
);
2319 /* The Extended Community attribute SHALL be considered malformed if
2320 * its length is not a non-zero multiple of 8.
2322 if (!bgp_attr_get_ecommunity(attr
))
2323 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2326 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2328 /* Extract DF election preference and mobility sequence number */
2329 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2331 /* Extract MAC mobility sequence number, if any. */
2332 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2333 attr
->sticky
= sticky
;
2335 /* Check if this is a Gateway MAC-IP advertisement */
2336 attr
->default_gw
= bgp_attr_default_gw(attr
);
2338 /* Handle scenario where router flag ecommunity is not
2339 * set but default gw ext community is present.
2340 * Use default gateway, set and propogate R-bit.
2342 if (attr
->default_gw
)
2343 attr
->router_flag
= 1;
2345 /* Check EVPN Neighbor advertisement flags, R-bit */
2346 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2348 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2350 /* Extract the Rmac, if any */
2351 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2352 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2353 && bgp_mac_exist(&attr
->rmac
))
2354 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2358 /* Get the tunnel type from encap extended community */
2359 bgp_attr_extcom_tunnel_type(attr
,
2360 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2362 /* Extract link bandwidth, if any. */
2363 (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr
),
2366 return BGP_ATTR_PARSE_PROCEED
;
2369 /* IPv6 Extended Community attribute. */
2370 static bgp_attr_parse_ret_t
2371 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2373 struct peer
*const peer
= args
->peer
;
2374 struct attr
*const attr
= args
->attr
;
2375 const bgp_size_t length
= args
->length
;
2376 struct ecommunity
*ipv6_ecomm
= NULL
;
2379 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2380 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2384 ipv6_ecomm
= ecommunity_parse_ipv6(
2385 stream_pnt(peer
->curr
), length
,
2386 CHECK_FLAG(peer
->flags
,
2387 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2388 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2390 /* XXX: fix ecommunity_parse to use stream API */
2391 stream_forward_getp(peer
->curr
, length
);
2394 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2397 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
);
2399 return BGP_ATTR_PARSE_PROCEED
;
2402 /* Parse Tunnel Encap attribute in an UPDATE */
2403 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2404 bgp_size_t length
, /* IN: attr's length field */
2405 struct attr
*attr
, /* IN: caller already allocated */
2406 uint8_t flag
, /* IN: attr's flags field */
2410 uint16_t tunneltype
= 0;
2412 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2414 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2415 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2417 "Tunnel Encap attribute flag isn't optional and transitive %d",
2419 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2420 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2425 if (BGP_ATTR_ENCAP
== type
) {
2426 /* read outer TLV type and length */
2427 uint16_t tlv_length
;
2431 "Tunnel Encap attribute not long enough to contain outer T,L");
2432 bgp_notify_send_with_data(
2433 peer
, BGP_NOTIFY_UPDATE_ERR
,
2434 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2437 tunneltype
= stream_getw(BGP_INPUT(peer
));
2438 tlv_length
= stream_getw(BGP_INPUT(peer
));
2441 if (tlv_length
!= length
) {
2442 zlog_info("%s: tlv_length(%d) != length(%d)",
2443 __func__
, tlv_length
, length
);
2447 while (length
>= 4) {
2448 uint16_t subtype
= 0;
2449 uint16_t sublength
= 0;
2450 struct bgp_attr_encap_subtlv
*tlv
;
2452 if (BGP_ATTR_ENCAP
== type
) {
2453 subtype
= stream_getc(BGP_INPUT(peer
));
2454 sublength
= stream_getc(BGP_INPUT(peer
));
2456 #ifdef ENABLE_BGP_VNC
2458 subtype
= stream_getw(BGP_INPUT(peer
));
2459 sublength
= stream_getw(BGP_INPUT(peer
));
2464 if (sublength
> length
) {
2466 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2468 bgp_notify_send_with_data(
2469 peer
, BGP_NOTIFY_UPDATE_ERR
,
2470 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2474 /* alloc and copy sub-tlv */
2475 /* TBD make sure these are freed when attributes are released */
2476 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2477 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2478 tlv
->type
= subtype
;
2479 tlv
->length
= sublength
;
2480 stream_get(tlv
->value
, peer
->curr
, sublength
);
2481 length
-= sublength
;
2483 /* attach tlv to encap chain */
2484 if (BGP_ATTR_ENCAP
== type
) {
2485 struct bgp_attr_encap_subtlv
*stlv_last
;
2486 for (stlv_last
= attr
->encap_subtlvs
;
2487 stlv_last
&& stlv_last
->next
;
2488 stlv_last
= stlv_last
->next
)
2491 stlv_last
->next
= tlv
;
2493 attr
->encap_subtlvs
= tlv
;
2495 #ifdef ENABLE_BGP_VNC
2497 struct bgp_attr_encap_subtlv
*stlv_last
;
2498 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2499 bgp_attr_get_vnc_subtlvs(attr
);
2501 for (stlv_last
= vnc_subtlvs
;
2502 stlv_last
&& stlv_last
->next
;
2503 stlv_last
= stlv_last
->next
)
2506 stlv_last
->next
= tlv
;
2508 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2513 if (BGP_ATTR_ENCAP
== type
) {
2514 attr
->encap_tunneltype
= tunneltype
;
2518 /* spurious leftover data */
2520 "Tunnel Encap attribute length is bad: %d leftover octets",
2522 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2523 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2532 /* SRv6 Service Data Sub-Sub-TLV attribute
2533 * draft-ietf-bess-srv6-services-07
2535 static bgp_attr_parse_ret_t
2536 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2538 struct peer
*const peer
= args
->peer
;
2539 struct attr
*const attr
= args
->attr
;
2540 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2541 transposition_len
, transposition_offset
;
2543 size_t headersz
= sizeof(type
) + sizeof(length
);
2545 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2548 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2549 headersz
, STREAM_READABLE(peer
->curr
));
2550 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2554 type
= stream_getc(peer
->curr
);
2555 length
= stream_getw(peer
->curr
);
2557 if (STREAM_READABLE(peer
->curr
) < length
) {
2560 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2561 length
, STREAM_READABLE(peer
->curr
));
2562 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2566 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2567 loc_block_len
= stream_getc(peer
->curr
);
2568 loc_node_len
= stream_getc(peer
->curr
);
2569 func_len
= stream_getc(peer
->curr
);
2570 arg_len
= stream_getc(peer
->curr
);
2571 transposition_len
= stream_getc(peer
->curr
);
2572 transposition_offset
= stream_getc(peer
->curr
);
2574 /* Log SRv6 Service Data Sub-Sub-TLV */
2575 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2577 "%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",
2578 __func__
, loc_block_len
, loc_node_len
, func_len
,
2579 arg_len
, transposition_len
,
2580 transposition_offset
);
2583 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2584 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2585 attr
->srv6_l3vpn
->func_len
= func_len
;
2586 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2587 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2588 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2592 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2594 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2597 stream_forward_getp(peer
->curr
, length
);
2600 return BGP_ATTR_PARSE_PROCEED
;
2603 /* SRv6 Service Sub-TLV attribute
2604 * draft-ietf-bess-srv6-services-07
2606 static bgp_attr_parse_ret_t
2607 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2609 struct peer
*const peer
= args
->peer
;
2610 struct attr
*const attr
= args
->attr
;
2611 struct in6_addr ipv6_sid
;
2612 uint8_t type
, sid_flags
;
2613 uint16_t length
, endpoint_behavior
;
2614 size_t headersz
= sizeof(type
) + sizeof(length
);
2615 bgp_attr_parse_ret_t err
;
2618 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2621 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2622 headersz
, STREAM_READABLE(peer
->curr
));
2623 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2627 type
= stream_getc(peer
->curr
);
2628 length
= stream_getw(peer
->curr
);
2630 if (STREAM_READABLE(peer
->curr
) < length
) {
2633 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2634 length
, STREAM_READABLE(peer
->curr
));
2635 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2639 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2640 stream_getc(peer
->curr
);
2641 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2642 sid_flags
= stream_getc(peer
->curr
);
2643 endpoint_behavior
= stream_getw(peer
->curr
);
2644 stream_getc(peer
->curr
);
2646 /* Log SRv6 Service Sub-TLV */
2647 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2648 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2650 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2651 __func__
, buf
, sid_flags
, endpoint_behavior
);
2654 /* Configure from Info */
2655 if (attr
->srv6_l3vpn
) {
2656 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2657 "Prefix SID SRv6 L3VPN field repeated");
2658 return bgp_attr_malformed(
2659 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2661 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2662 sizeof(struct bgp_attr_srv6_l3vpn
));
2663 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2664 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2665 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2666 attr
->srv6_l3vpn
->loc_block_len
= 0;
2667 attr
->srv6_l3vpn
->loc_node_len
= 0;
2668 attr
->srv6_l3vpn
->func_len
= 0;
2669 attr
->srv6_l3vpn
->arg_len
= 0;
2670 attr
->srv6_l3vpn
->transposition_len
= 0;
2671 attr
->srv6_l3vpn
->transposition_offset
= 0;
2673 // Sub-Sub-TLV found
2674 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2675 err
= bgp_attr_srv6_service_data(args
);
2677 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2681 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2684 /* Placeholder code for unsupported type */
2686 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2688 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2691 stream_forward_getp(peer
->curr
, length
);
2694 return BGP_ATTR_PARSE_PROCEED
;
2698 * Read an individual SID value returning how much data we have read
2699 * Returns 0 if there was an error that needs to be passed up the stack
2701 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2702 struct bgp_attr_parser_args
*args
)
2704 struct peer
*const peer
= args
->peer
;
2705 struct attr
*const attr
= args
->attr
;
2706 uint32_t label_index
;
2707 struct in6_addr ipv6_sid
;
2709 uint32_t srgb_range
;
2711 uint8_t sid_type
, sid_flags
;
2714 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2715 if (STREAM_READABLE(peer
->curr
) < length
2716 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2717 flog_err(EC_BGP_ATTR_LEN
,
2718 "Prefix SID label index length is %hu instead of %u",
2719 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2720 return bgp_attr_malformed(args
,
2721 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2725 /* Ignore flags and reserved */
2726 stream_getc(peer
->curr
);
2727 stream_getw(peer
->curr
);
2729 /* Fetch the label index and see if it is valid. */
2730 label_index
= stream_getl(peer
->curr
);
2731 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2732 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2735 /* Store label index; subsequently, we'll check on
2737 attr
->label_index
= label_index
;
2740 /* Placeholder code for the IPv6 SID type */
2741 else if (type
== BGP_PREFIX_SID_IPV6
) {
2742 if (STREAM_READABLE(peer
->curr
) < length
2743 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2744 flog_err(EC_BGP_ATTR_LEN
,
2745 "Prefix SID IPv6 length is %hu instead of %u",
2746 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2747 return bgp_attr_malformed(args
,
2748 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2752 /* Ignore reserved */
2753 stream_getc(peer
->curr
);
2754 stream_getw(peer
->curr
);
2756 stream_get(&ipv6_sid
, peer
->curr
, 16);
2759 /* Placeholder code for the Originator SRGB type */
2760 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2762 * ietf-idr-bgp-prefix-sid-05:
2763 * Length is the total length of the value portion of the
2764 * TLV: 2 + multiple of 6.
2766 * peer->curr stream readp should be at the beginning of the 16
2767 * bit flag field at this point in the code.
2771 * Check that the TLV length field is sane: at least 2 bytes of
2772 * flag, and at least 1 SRGB (these are 6 bytes each)
2774 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2777 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2779 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2780 return bgp_attr_malformed(
2781 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2786 * Check that we actually have at least as much data as
2787 * specified by the length field
2789 if (STREAM_READABLE(peer
->curr
) < length
) {
2790 flog_err(EC_BGP_ATTR_LEN
,
2791 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2792 length
, STREAM_READABLE(peer
->curr
));
2793 return bgp_attr_malformed(
2794 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2799 * Check that the portion of the TLV containing the sequence of
2800 * SRGBs corresponds to a multiple of the SRGB size; to get
2801 * that length, we skip the 16 bit flags field
2803 stream_getw(peer
->curr
);
2805 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2808 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2809 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2810 return bgp_attr_malformed(
2811 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2815 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2817 for (int i
= 0; i
< srgb_count
; i
++) {
2818 stream_get(&srgb_base
, peer
->curr
, 3);
2819 stream_get(&srgb_range
, peer
->curr
, 3);
2823 /* Placeholder code for the VPN-SID Service type */
2824 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2825 if (STREAM_READABLE(peer
->curr
) < length
2826 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2827 flog_err(EC_BGP_ATTR_LEN
,
2828 "Prefix SID VPN SID length is %hu instead of %u",
2829 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2830 return bgp_attr_malformed(args
,
2831 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2835 /* Parse VPN-SID Sub-TLV */
2836 stream_getc(peer
->curr
); /* reserved */
2837 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2838 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2839 stream_get(&ipv6_sid
, peer
->curr
,
2840 sizeof(ipv6_sid
)); /* sid_value */
2842 /* Log VPN-SID Sub-TLV */
2843 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2844 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2846 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2847 __func__
, buf
, sid_type
, sid_flags
);
2850 /* Configure from Info */
2851 if (attr
->srv6_vpn
) {
2852 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2853 "Prefix SID SRv6 VPN field repeated");
2854 return bgp_attr_malformed(
2855 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2857 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2858 sizeof(struct bgp_attr_srv6_vpn
));
2859 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2860 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2861 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2864 /* Placeholder code for the SRv6 L3 Service type */
2865 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2866 if (STREAM_READABLE(peer
->curr
) < length
) {
2869 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
2870 length
, STREAM_READABLE(peer
->curr
));
2871 return bgp_attr_malformed(args
,
2872 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2876 /* ignore reserved */
2877 stream_getc(peer
->curr
);
2879 return bgp_attr_srv6_service(args
);
2882 /* Placeholder code for Unsupported TLV */
2885 if (STREAM_READABLE(peer
->curr
) < length
) {
2888 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2889 length
, STREAM_READABLE(peer
->curr
));
2890 return bgp_attr_malformed(
2891 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2895 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2897 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2900 stream_forward_getp(peer
->curr
, length
);
2903 return BGP_ATTR_PARSE_PROCEED
;
2906 /* Prefix SID attribute
2907 * draft-ietf-idr-bgp-prefix-sid-05
2909 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2911 struct peer
*const peer
= args
->peer
;
2912 struct attr
*const attr
= args
->attr
;
2913 bgp_attr_parse_ret_t ret
;
2915 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2919 size_t headersz
= sizeof(type
) + sizeof(length
);
2920 size_t psid_parsed_length
= 0;
2922 while (STREAM_READABLE(peer
->curr
) > 0
2923 && psid_parsed_length
< args
->length
) {
2925 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2928 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2929 headersz
, STREAM_READABLE(peer
->curr
));
2930 return bgp_attr_malformed(
2931 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2935 type
= stream_getc(peer
->curr
);
2936 length
= stream_getw(peer
->curr
);
2938 if (STREAM_READABLE(peer
->curr
) < length
) {
2941 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2942 length
, STREAM_READABLE(peer
->curr
));
2943 return bgp_attr_malformed(args
,
2944 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2948 ret
= bgp_attr_psid_sub(type
, length
, args
);
2950 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2953 psid_parsed_length
+= length
+ headersz
;
2955 if (psid_parsed_length
> args
->length
) {
2958 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2959 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2960 return bgp_attr_malformed(
2961 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2966 return BGP_ATTR_PARSE_PROCEED
;
2969 /* PMSI tunnel attribute (RFC 6514)
2970 * Basic validation checks done here.
2972 static bgp_attr_parse_ret_t
2973 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2975 struct peer
*const peer
= args
->peer
;
2976 struct attr
*const attr
= args
->attr
;
2977 const bgp_size_t length
= args
->length
;
2979 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2981 /* Verify that the receiver is expecting "ingress replication" as we
2982 * can only support that.
2984 if (length
< attr_parse_len
) {
2985 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2987 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2990 stream_getc(peer
->curr
); /* Flags */
2991 tnl_type
= stream_getc(peer
->curr
);
2992 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2993 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2994 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2995 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2998 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3000 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3001 "Bad PMSI tunnel attribute length %d for IR",
3003 return bgp_attr_malformed(
3004 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3009 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3010 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3011 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3013 /* Forward read pointer of input stream. */
3014 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3016 return BGP_ATTR_PARSE_PROCEED
;
3019 /* BGP unknown attribute treatment. */
3020 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3022 bgp_size_t total
= args
->total
;
3023 struct transit
*transit
;
3024 struct peer
*const peer
= args
->peer
;
3025 struct attr
*const attr
= args
->attr
;
3026 uint8_t *const startp
= args
->startp
;
3027 const uint8_t type
= args
->type
;
3028 const uint8_t flag
= args
->flags
;
3029 const bgp_size_t length
= args
->length
;
3031 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3033 "%s Unknown attribute is received (type %d, length %d)",
3034 peer
->host
, type
, length
);
3036 /* Forward read pointer of input stream. */
3037 stream_forward_getp(peer
->curr
, length
);
3039 /* If any of the mandatory well-known attributes are not recognized,
3040 then the Error Subcode is set to Unrecognized Well-known
3041 Attribute. The Data field contains the unrecognized attribute
3042 (type, length and value). */
3043 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3044 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3048 /* Unrecognized non-transitive optional attributes must be quietly
3049 ignored and not passed along to other BGP peers. */
3050 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3051 return BGP_ATTR_PARSE_PROCEED
;
3053 /* If a path with recognized transitive optional attribute is
3054 accepted and passed along to other BGP peers and the Partial bit
3055 in the Attribute Flags octet is set to 1 by some previous AS, it
3056 is not set back to 0 by the current AS. */
3057 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3059 /* Store transitive attribute to the end of attr->transit. */
3060 transit
= bgp_attr_get_transit(attr
);
3062 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3064 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3065 transit
->length
+ total
);
3067 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3068 transit
->length
+= total
;
3069 bgp_attr_set_transit(attr
, transit
);
3071 return BGP_ATTR_PARSE_PROCEED
;
3074 /* Well-known attribute check. */
3075 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3079 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3081 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3082 return BGP_ATTR_PARSE_PROCEED
;
3084 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3085 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3086 are present, it should. Check for any other attribute being present
3089 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3090 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3091 return BGP_ATTR_PARSE_PROCEED
;
3093 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3094 type
= BGP_ATTR_ORIGIN
;
3096 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3097 type
= BGP_ATTR_AS_PATH
;
3099 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3101 * NLRI is empty. We can't easily check NLRI empty here though.
3103 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3104 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3105 type
= BGP_ATTR_NEXT_HOP
;
3107 if (peer
->sort
== BGP_PEER_IBGP
3108 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3109 type
= BGP_ATTR_LOCAL_PREF
;
3111 /* If any of the well-known mandatory attributes are not present
3112 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3115 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3116 "%s Missing well-known attribute %s.", peer
->host
,
3117 lookup_msg(attr_str
, type
, NULL
));
3118 return BGP_ATTR_PARSE_WITHDRAW
;
3120 return BGP_ATTR_PARSE_PROCEED
;
3123 /* Read attribute of update packet. This function is called from
3124 bgp_update_receive() in bgp_packet.c. */
3125 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3126 bgp_size_t size
, struct bgp_nlri
*mp_update
,
3127 struct bgp_nlri
*mp_withdraw
)
3129 bgp_attr_parse_ret_t ret
;
3133 uint8_t *startp
, *endp
;
3135 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3136 /* we need the as4_path only until we have synthesized the as_path with
3138 /* same goes for as4_aggregator */
3139 struct aspath
*as4_path
= NULL
;
3140 as_t as4_aggregator
= 0;
3141 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3142 struct transit
*transit
;
3144 /* Initialize bitmap. */
3145 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3147 /* End pointer of BGP attribute. */
3148 endp
= BGP_INPUT_PNT(peer
) + size
;
3150 /* Get attributes to the end of attribute length. */
3151 while (BGP_INPUT_PNT(peer
) < endp
) {
3152 /* Check remaining length check.*/
3153 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3154 /* XXX warning: long int format, int arg (arg 5) */
3156 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3157 "%s: error BGP attribute length %lu is smaller than min len",
3159 (unsigned long)(endp
3160 - stream_pnt(BGP_INPUT(peer
))));
3162 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3163 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3164 ret
= BGP_ATTR_PARSE_ERROR
;
3168 /* Fetch attribute flag and type. */
3169 startp
= BGP_INPUT_PNT(peer
);
3170 /* "The lower-order four bits of the Attribute Flags octet are
3171 unused. They MUST be zero when sent and MUST be ignored when
3173 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3174 type
= stream_getc(BGP_INPUT(peer
));
3176 /* Check whether Extended-Length applies and is in bounds */
3177 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3178 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3180 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3181 "%s: Extended length set, but just %lu bytes of attr header",
3183 (unsigned long)(endp
3184 - stream_pnt(BGP_INPUT(peer
))));
3186 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3187 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3188 ret
= BGP_ATTR_PARSE_ERROR
;
3192 /* Check extended attribue length bit. */
3193 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3194 length
= stream_getw(BGP_INPUT(peer
));
3196 length
= stream_getc(BGP_INPUT(peer
));
3198 /* If any attribute appears more than once in the UPDATE
3199 message, then the Error Subcode is set to Malformed Attribute
3202 if (CHECK_BITMAP(seen
, type
)) {
3204 EC_BGP_ATTRIBUTE_REPEATED
,
3205 "%s: error BGP attribute type %d appears twice in a message",
3208 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3209 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3210 ret
= BGP_ATTR_PARSE_ERROR
;
3214 /* Set type to bitmap to check duplicate attribute. `type' is
3215 unsigned char so it never overflow bitmap range. */
3217 SET_BITMAP(seen
, type
);
3219 /* Overflow check. */
3220 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3222 if (attr_endp
> endp
) {
3224 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3225 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3226 peer
->host
, type
, length
, size
, attr_endp
,
3230 * If any recognized attribute has an Attribute
3231 * Length that conflicts with the expected length
3232 * (based on the attribute type code), then the
3233 * Error Subcode MUST be set to Attribute Length
3234 * Error. The Data field MUST contain the erroneous
3235 * attribute (type, length, and value).
3237 * We do not currently have a good way to determine the
3238 * length of the attribute independent of the length
3239 * received in the message. Instead we send the
3240 * minimum between the amount of data we have and the
3241 * amount specified by the attribute length field.
3243 * Instead of directly passing in the packet buffer and
3244 * offset we use the stream_get* functions to read into
3245 * a stack buffer, since they perform bounds checking
3246 * and we are working with untrusted data.
3248 unsigned char ndata
[peer
->max_packet_size
];
3249 memset(ndata
, 0x00, sizeof(ndata
));
3251 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3252 /* Rewind to end of flag field */
3253 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3255 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3257 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3259 size_t atl
= attr_endp
- startp
;
3260 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3261 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3263 bgp_notify_send_with_data(
3264 peer
, BGP_NOTIFY_UPDATE_ERR
,
3265 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3268 ret
= BGP_ATTR_PARSE_ERROR
;
3272 struct bgp_attr_parser_args attr_args
= {
3279 .total
= attr_endp
- startp
,
3283 /* If any recognized attribute has Attribute Flags that conflict
3284 with the Attribute Type Code, then the Error Subcode is set
3286 Attribute Flags Error. The Data field contains the erroneous
3287 attribute (type, length and value). */
3288 if (bgp_attr_flag_invalid(&attr_args
)) {
3289 ret
= bgp_attr_malformed(
3290 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3292 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3297 /* OK check attribute and store it's value. */
3299 case BGP_ATTR_ORIGIN
:
3300 ret
= bgp_attr_origin(&attr_args
);
3302 case BGP_ATTR_AS_PATH
:
3303 ret
= bgp_attr_aspath(&attr_args
);
3305 case BGP_ATTR_AS4_PATH
:
3306 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3308 case BGP_ATTR_NEXT_HOP
:
3309 ret
= bgp_attr_nexthop(&attr_args
);
3311 case BGP_ATTR_MULTI_EXIT_DISC
:
3312 ret
= bgp_attr_med(&attr_args
);
3314 case BGP_ATTR_LOCAL_PREF
:
3315 ret
= bgp_attr_local_pref(&attr_args
);
3317 case BGP_ATTR_ATOMIC_AGGREGATE
:
3318 ret
= bgp_attr_atomic(&attr_args
);
3320 case BGP_ATTR_AGGREGATOR
:
3321 ret
= bgp_attr_aggregator(&attr_args
);
3323 case BGP_ATTR_AS4_AGGREGATOR
:
3324 ret
= bgp_attr_as4_aggregator(&attr_args
,
3326 &as4_aggregator_addr
);
3328 case BGP_ATTR_COMMUNITIES
:
3329 ret
= bgp_attr_community(&attr_args
);
3331 case BGP_ATTR_LARGE_COMMUNITIES
:
3332 ret
= bgp_attr_large_community(&attr_args
);
3334 case BGP_ATTR_ORIGINATOR_ID
:
3335 ret
= bgp_attr_originator_id(&attr_args
);
3337 case BGP_ATTR_CLUSTER_LIST
:
3338 ret
= bgp_attr_cluster_list(&attr_args
);
3340 case BGP_ATTR_MP_REACH_NLRI
:
3341 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3343 case BGP_ATTR_MP_UNREACH_NLRI
:
3344 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3346 case BGP_ATTR_EXT_COMMUNITIES
:
3347 ret
= bgp_attr_ext_communities(&attr_args
);
3349 #ifdef ENABLE_BGP_VNC_ATTR
3352 case BGP_ATTR_ENCAP
:
3353 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3356 case BGP_ATTR_PREFIX_SID
:
3357 ret
= bgp_attr_prefix_sid(&attr_args
);
3359 case BGP_ATTR_PMSI_TUNNEL
:
3360 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3362 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3363 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3366 ret
= bgp_attr_unknown(&attr_args
);
3370 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3371 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3372 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3373 ret
= BGP_ATTR_PARSE_ERROR
;
3377 if (ret
== BGP_ATTR_PARSE_EOR
) {
3381 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3382 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3383 "%s: Attribute %s, parse error", peer
->host
,
3384 lookup_msg(attr_str
, type
, NULL
));
3387 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3389 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3390 "%s: Attribute %s, parse error - treating as withdrawal",
3391 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3395 /* Check the fetched length. */
3396 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3397 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3398 "%s: BGP attribute %s, fetch error",
3399 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3400 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3401 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3402 ret
= BGP_ATTR_PARSE_ERROR
;
3408 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3409 * About Prefix-SID path attribute,
3410 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3411 * may only appear in a BGP Prefix-SID attribute attached to
3412 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3413 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3415 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3416 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3418 /* Check final read pointer is same as end pointer. */
3419 if (BGP_INPUT_PNT(peer
) != endp
) {
3420 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3421 "%s: BGP attribute %s, length mismatch", peer
->host
,
3422 lookup_msg(attr_str
, type
, NULL
));
3423 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3424 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3426 ret
= BGP_ATTR_PARSE_ERROR
;
3431 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3432 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3433 * This is implemented below and will result in a NOTIFICATION. If the
3434 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3435 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3436 * message SHOULD NOT be sent. This is implemented elsewhere.
3438 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3439 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3440 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3441 * speaker that receives the message SHOULD ignore this attribute.
3443 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3444 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3445 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3446 ret
= BGP_ATTR_PARSE_ERROR
;
3451 /* Check all mandatory well-known attributes are present */
3452 ret
= bgp_attr_check(peer
, attr
);
3457 * At this place we can see whether we got AS4_PATH and/or
3458 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3459 * We can not do this before we've read all attributes because
3460 * the as4 handling does not say whether AS4_PATH has to be sent
3461 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3462 * in relationship to AGGREGATOR.
3463 * So, to be defensive, we are not relying on any order and read
3464 * all attributes first, including these 32bit ones, and now,
3465 * afterwards, we look what and if something is to be done for as4.
3467 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3470 /* actually... this doesn't ever return failure currently, but
3471 * better safe than sorry */
3472 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3473 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3474 &as4_aggregator_addr
)) {
3475 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3476 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3477 ret
= BGP_ATTR_PARSE_ERROR
;
3482 * Finally do the checks on the aspath we did not do yet
3483 * because we waited for a potentially synthesized aspath.
3485 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3486 ret
= bgp_attr_aspath_check(peer
, attr
);
3487 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3491 ret
= BGP_ATTR_PARSE_PROCEED
;
3495 * At this stage, we have done all fiddling with as4, and the
3496 * resulting info is in attr->aggregator resp. attr->aspath so
3497 * we can chuck as4_aggregator and as4_path alltogether in order
3502 * unintern - it is in the hash
3503 * The flag that we got this is still there, but that
3504 * does not do any trouble
3506 aspath_unintern(&as4_path
);
3509 transit
= bgp_attr_get_transit(attr
);
3510 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3511 /* Finally intern unknown attribute. */
3513 bgp_attr_set_transit(attr
, transit_intern(transit
));
3514 if (attr
->encap_subtlvs
)
3515 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3517 #ifdef ENABLE_BGP_VNC
3518 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3519 bgp_attr_get_vnc_subtlvs(attr
);
3522 bgp_attr_set_vnc_subtlvs(
3524 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3528 transit_free(transit
);
3529 bgp_attr_set_transit(attr
, NULL
);
3532 bgp_attr_flush_encap(attr
);
3536 transit
= bgp_attr_get_transit(attr
);
3538 assert(transit
->refcnt
> 0);
3539 if (attr
->encap_subtlvs
)
3540 assert(attr
->encap_subtlvs
->refcnt
> 0);
3541 #ifdef ENABLE_BGP_VNC
3542 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3543 bgp_attr_get_vnc_subtlvs(attr
);
3546 assert(vnc_subtlvs
->refcnt
> 0);
3553 * Extract the tunnel type from extended community
3555 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3556 bgp_encap_types
*tunnel_type
)
3558 struct ecommunity
*ecom
;
3564 ecom
= bgp_attr_get_ecommunity(attr
);
3565 if (!ecom
|| !ecom
->size
)
3568 for (i
= 0; i
< ecom
->size
; i
++) {
3570 uint8_t type
, sub_type
;
3572 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3575 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3576 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3578 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3585 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3586 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3591 iana_safi_t pkt_safi
;
3594 /* Set extended bit always to encode the attribute length as 2 bytes */
3595 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3596 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3597 sizep
= stream_get_endp(s
);
3598 stream_putw(s
, 0); /* Marker: Attribute length. */
3601 /* Convert AFI, SAFI to values for packet. */
3602 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3604 stream_putw(s
, pkt_afi
); /* AFI */
3605 stream_putc(s
, pkt_safi
); /* SAFI */
3609 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3610 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3611 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3612 else if (safi
== SAFI_FLOWSPEC
)
3615 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3618 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3623 case SAFI_MULTICAST
:
3624 case SAFI_LABELED_UNICAST
:
3626 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3630 stream_putl(s
, 0); /* RD = 0, per RFC */
3632 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3637 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3640 if (attr
->mp_nexthop_len
== 0)
3641 stream_putc(s
, 0); /* no nexthop for flowspec */
3643 stream_putc(s
, attr
->mp_nexthop_len
);
3644 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3653 case SAFI_MULTICAST
:
3654 case SAFI_LABELED_UNICAST
:
3656 if (attr
->mp_nexthop_len
3657 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3659 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3660 stream_put(s
, &attr
->mp_nexthop_global
,
3662 stream_put(s
, &attr
->mp_nexthop_local
,
3665 stream_putc(s
, IPV6_MAX_BYTELEN
);
3666 stream_put(s
, &attr
->mp_nexthop_global
,
3670 case SAFI_MPLS_VPN
: {
3671 if (attr
->mp_nexthop_len
3672 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3674 stream_putl(s
, 0); /* RD = 0, per RFC */
3676 stream_put(s
, &attr
->mp_nexthop_global
,
3678 } else if (attr
->mp_nexthop_len
3679 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3681 stream_putl(s
, 0); /* RD = 0, per RFC */
3683 stream_put(s
, &attr
->mp_nexthop_global
,
3685 stream_putl(s
, 0); /* RD = 0, per RFC */
3687 stream_put(s
, &attr
->mp_nexthop_local
,
3692 stream_putc(s
, IPV6_MAX_BYTELEN
);
3693 stream_put(s
, &attr
->mp_nexthop_global
,
3697 stream_putc(s
, 0); /* no nexthop for flowspec */
3703 if (safi
!= SAFI_FLOWSPEC
)
3705 EC_BGP_ATTR_NH_SEND_LEN
,
3706 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3707 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3716 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3717 const struct prefix
*p
,
3718 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3719 uint32_t num_labels
, bool addpath_capable
,
3720 uint32_t addpath_tx_id
, struct attr
*attr
)
3722 if (safi
== SAFI_MPLS_VPN
) {
3723 if (addpath_capable
)
3724 stream_putl(s
, addpath_tx_id
);
3725 /* Label, RD, Prefix write. */
3726 stream_putc(s
, p
->prefixlen
+ 88);
3727 stream_put(s
, label
, BGP_LABEL_BYTES
);
3728 stream_put(s
, prd
->val
, 8);
3729 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3730 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3731 /* EVPN prefix - contents depend on type */
3732 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3733 addpath_capable
, addpath_tx_id
);
3734 } else if (safi
== SAFI_LABELED_UNICAST
) {
3735 /* Prefix write with label. */
3736 stream_put_labeled_prefix(s
, p
, label
, addpath_capable
,
3738 } else if (safi
== SAFI_FLOWSPEC
) {
3739 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3740 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3741 p
->u
.prefix_flowspec
.prefixlen
);
3743 stream_put_prefix_addpath(s
, p
, addpath_capable
, addpath_tx_id
);
3746 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3747 const struct prefix
*p
)
3749 int size
= PSIZE(p
->prefixlen
);
3750 if (safi
== SAFI_MPLS_VPN
)
3752 else if (safi
== SAFI_LABELED_UNICAST
)
3753 size
+= BGP_LABEL_BYTES
;
3754 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3755 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3761 * Encodes the tunnel encapsulation attribute,
3762 * and with ENABLE_BGP_VNC the VNC attribute which uses
3763 * almost the same TLV format
3765 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3766 struct stream
*s
, struct attr
*attr
,
3769 unsigned int attrlenfield
= 0;
3770 unsigned int attrhdrlen
= 0;
3771 struct bgp_attr_encap_subtlv
*subtlvs
;
3772 struct bgp_attr_encap_subtlv
*st
;
3773 const char *attrname
;
3775 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3776 && (!attr
->encap_tunneltype
3777 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3781 case BGP_ATTR_ENCAP
:
3782 attrname
= "Tunnel Encap";
3783 subtlvs
= attr
->encap_subtlvs
;
3784 if (subtlvs
== NULL
) /* nothing to do */
3787 * The tunnel encap attr has an "outer" tlv.
3789 * L = total length of subtlvs,
3790 * V = concatenated subtlvs.
3792 attrlenfield
= 2 + 2; /* T + L */
3793 attrhdrlen
= 1 + 1; /* subTLV T + L */
3796 #ifdef ENABLE_BGP_VNC_ATTR
3799 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3800 if (subtlvs
== NULL
) /* nothing to do */
3802 attrlenfield
= 0; /* no outer T + L */
3803 attrhdrlen
= 2 + 2; /* subTLV T + L */
3811 /* compute attr length */
3812 for (st
= subtlvs
; st
; st
= st
->next
) {
3813 attrlenfield
+= (attrhdrlen
+ st
->length
);
3816 if (attrlenfield
> 0xffff) {
3817 zlog_info("%s attribute is too long (length=%d), can't send it",
3818 attrname
, attrlenfield
);
3822 if (attrlenfield
> 0xff) {
3823 /* 2-octet length field */
3825 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3826 | BGP_ATTR_FLAG_EXTLEN
);
3827 stream_putc(s
, attrtype
);
3828 stream_putw(s
, attrlenfield
& 0xffff);
3830 /* 1-octet length field */
3831 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3832 stream_putc(s
, attrtype
);
3833 stream_putc(s
, attrlenfield
& 0xff);
3836 if (attrtype
== BGP_ATTR_ENCAP
) {
3837 /* write outer T+L */
3838 stream_putw(s
, attr
->encap_tunneltype
);
3839 stream_putw(s
, attrlenfield
- 4);
3842 /* write each sub-tlv */
3843 for (st
= subtlvs
; st
; st
= st
->next
) {
3844 if (attrtype
== BGP_ATTR_ENCAP
) {
3845 stream_putc(s
, st
->type
);
3846 stream_putc(s
, st
->length
);
3847 #ifdef ENABLE_BGP_VNC
3849 stream_putw(s
, st
->type
);
3850 stream_putw(s
, st
->length
);
3853 stream_put(s
, st
->value
, st
->length
);
3857 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3859 /* Set MP attribute length. Don't count the (2) bytes used to encode
3861 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3864 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3866 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3867 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3868 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3869 PEER_FLAG_REMOVE_PRIVATE_AS
)
3870 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3871 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3872 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3873 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3874 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3875 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3880 /* Make attribute packet. */
3881 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3882 struct stream
*s
, struct attr
*attr
,
3883 struct bpacket_attr_vec_arr
*vecarr
,
3884 struct prefix
*p
, afi_t afi
, safi_t safi
,
3885 struct peer
*from
, struct prefix_rd
*prd
,
3886 mpls_label_t
*label
, uint32_t num_labels
,
3887 bool addpath_capable
, uint32_t addpath_tx_id
)
3890 size_t aspath_sizep
;
3891 struct aspath
*aspath
;
3892 int send_as4_path
= 0;
3893 int send_as4_aggregator
= 0;
3894 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
3895 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
3900 /* Remember current pointer. */
3901 cp
= stream_get_endp(s
);
3904 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3905 && !peer_cap_enhe(peer
, afi
, safi
))) {
3906 size_t mpattrlen_pos
= 0;
3908 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3910 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3911 num_labels
, addpath_capable
,
3912 addpath_tx_id
, attr
);
3913 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3916 /* Origin attribute. */
3917 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3918 stream_putc(s
, BGP_ATTR_ORIGIN
);
3920 stream_putc(s
, attr
->origin
);
3922 /* AS path attribute. */
3924 /* If remote-peer is EBGP */
3925 if (peer
->sort
== BGP_PEER_EBGP
3926 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3927 PEER_FLAG_AS_PATH_UNCHANGED
)
3928 || attr
->aspath
->segments
== NULL
)
3929 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3930 PEER_FLAG_RSERVER_CLIENT
))) {
3931 aspath
= aspath_dup(attr
->aspath
);
3933 /* Even though we may not be configured for confederations we
3935 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3936 aspath
= aspath_delete_confed_seq(aspath
);
3938 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3939 /* Stuff our path CONFED_ID on the front */
3940 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3942 if (peer
->change_local_as
) {
3943 /* If replace-as is specified, we only use the
3944 change_local_as when
3945 advertising routes. */
3946 if (!CHECK_FLAG(peer
->flags
,
3947 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3948 if (bgp_append_local_as(peer
, afi
,
3950 aspath
= aspath_add_seq(
3951 aspath
, peer
->local_as
);
3952 aspath
= aspath_add_seq(aspath
,
3953 peer
->change_local_as
);
3955 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3958 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3959 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3961 aspath
= aspath_dup(attr
->aspath
);
3962 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3964 aspath
= attr
->aspath
;
3966 /* If peer is not AS4 capable, then:
3967 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3968 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3970 * types are in it (i.e. exclude them if they are there)
3971 * AND do this only if there is at least one asnum > 65535 in the
3973 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3975 * all ASnums > 65535 to BGP_AS_TRANS
3978 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3979 stream_putc(s
, BGP_ATTR_AS_PATH
);
3980 aspath_sizep
= stream_get_endp(s
);
3982 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3984 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3987 if (!use32bit
&& aspath_has_as4(aspath
))
3989 1; /* we'll do this later, at the correct place */
3991 /* Nexthop attribute. */
3992 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3993 && !peer_cap_enhe(peer
, afi
, safi
)) {
3994 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3996 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3997 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3998 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3999 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4002 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4003 } else if (peer_cap_enhe(from
, afi
, safi
)
4004 || (nh_afi
== AFI_IP6
)) {
4006 * Likely this is the case when an IPv4 prefix was
4007 * received with Extended Next-hop capability in this
4008 * or another vrf and is now being advertised to
4009 * non-ENHE peers. Since peer_cap_enhe only checks
4010 * peers in this vrf, also check the nh_afi to catch
4011 * the case where the originator was in another vrf.
4012 * Setting the mandatory (ipv4) next-hop attribute here
4013 * to enable implicit next-hop self with correct A-F
4014 * (ipv4 address family).
4016 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4017 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4018 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4021 stream_put_ipv4(s
, 0);
4025 /* MED attribute. */
4026 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4027 || bgp
->maxmed_active
) {
4028 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4029 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4031 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4035 /* Local preference. */
4036 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4037 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4038 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4040 stream_putl(s
, attr
->local_pref
);
4043 /* Atomic aggregate. */
4044 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4045 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4046 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4051 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4052 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4053 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4054 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4057 /* AS4 capable peer */
4059 stream_putl(s
, attr
->aggregator_as
);
4061 /* 2-byte AS peer */
4064 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4066 if (attr
->aggregator_as
> UINT16_MAX
) {
4067 stream_putw(s
, BGP_AS_TRANS
);
4069 /* we have to send AS4_AGGREGATOR, too.
4070 * we'll do that later in order to send
4071 * attributes in ascending
4074 send_as4_aggregator
= 1;
4076 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4078 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4081 /* Community attribute. */
4082 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4083 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4084 if (attr
->community
->size
* 4 > 255) {
4086 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4087 | BGP_ATTR_FLAG_EXTLEN
);
4088 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4089 stream_putw(s
, attr
->community
->size
* 4);
4092 BGP_ATTR_FLAG_OPTIONAL
4093 | BGP_ATTR_FLAG_TRANS
);
4094 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4095 stream_putc(s
, attr
->community
->size
* 4);
4097 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4101 * Large Community attribute.
4103 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4104 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4105 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4106 if (lcom_length(attr
->lcommunity
) > 255) {
4108 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4109 | BGP_ATTR_FLAG_EXTLEN
);
4110 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4111 stream_putw(s
, lcom_length(attr
->lcommunity
));
4114 BGP_ATTR_FLAG_OPTIONAL
4115 | BGP_ATTR_FLAG_TRANS
);
4116 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4117 stream_putc(s
, lcom_length(attr
->lcommunity
));
4119 stream_put(s
, attr
->lcommunity
->val
,
4120 lcom_length(attr
->lcommunity
));
4123 /* Route Reflector. */
4124 if (peer
->sort
== BGP_PEER_IBGP
&& from
4125 && from
->sort
== BGP_PEER_IBGP
) {
4126 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4128 /* Originator ID. */
4129 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4130 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4133 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4134 stream_put_in_addr(s
, &attr
->originator_id
);
4136 stream_put_in_addr(s
, &from
->remote_id
);
4139 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4140 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4143 stream_putc(s
, cluster
->length
+ 4);
4144 /* If this peer configuration's parent BGP has
4146 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4147 stream_put_in_addr(s
, &bgp
->cluster_id
);
4149 stream_put_in_addr(s
, &bgp
->router_id
);
4150 stream_put(s
, cluster
->list
, cluster
->length
);
4153 /* If this peer configuration's parent BGP has
4155 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4156 stream_put_in_addr(s
, &bgp
->cluster_id
);
4158 stream_put_in_addr(s
, &bgp
->router_id
);
4162 /* Extended Communities attribute. */
4163 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4164 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4165 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
4167 if (peer
->sort
== BGP_PEER_IBGP
4168 || peer
->sort
== BGP_PEER_CONFED
) {
4169 if (ecomm
->size
* 8 > 255) {
4171 BGP_ATTR_FLAG_OPTIONAL
4172 | BGP_ATTR_FLAG_TRANS
4173 | BGP_ATTR_FLAG_EXTLEN
);
4174 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4175 stream_putw(s
, ecomm
->size
* 8);
4178 BGP_ATTR_FLAG_OPTIONAL
4179 | BGP_ATTR_FLAG_TRANS
);
4180 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4181 stream_putc(s
, ecomm
->size
* 8);
4183 stream_put(s
, ecomm
->val
, ecomm
->size
* 8);
4187 int ecom_tr_size
= 0;
4190 for (i
= 0; i
< ecomm
->size
; i
++) {
4191 pnt
= ecomm
->val
+ (i
* 8);
4194 if (CHECK_FLAG(tbit
,
4195 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4202 if (ecom_tr_size
* 8 > 255) {
4205 BGP_ATTR_FLAG_OPTIONAL
4206 | BGP_ATTR_FLAG_TRANS
4207 | BGP_ATTR_FLAG_EXTLEN
);
4209 BGP_ATTR_EXT_COMMUNITIES
);
4210 stream_putw(s
, ecom_tr_size
* 8);
4214 BGP_ATTR_FLAG_OPTIONAL
4215 | BGP_ATTR_FLAG_TRANS
);
4217 BGP_ATTR_EXT_COMMUNITIES
);
4218 stream_putc(s
, ecom_tr_size
* 8);
4221 for (i
= 0; i
< ecomm
->size
; i
++) {
4222 pnt
= ecomm
->val
+ (i
* 8);
4227 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4230 stream_put(s
, pnt
, 8);
4236 /* Label index attribute. */
4237 if (safi
== SAFI_LABELED_UNICAST
) {
4238 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4239 uint32_t label_index
;
4241 label_index
= attr
->label_index
;
4243 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4245 BGP_ATTR_FLAG_OPTIONAL
4246 | BGP_ATTR_FLAG_TRANS
);
4247 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4249 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4251 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4252 stream_putc(s
, 0); // reserved
4253 stream_putw(s
, 0); // flags
4254 stream_putl(s
, label_index
);
4259 /* SRv6 Service Information Attribute. */
4260 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4261 if (attr
->srv6_l3vpn
) {
4262 uint8_t subtlv_len
=
4263 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4265 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4266 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4267 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4268 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4269 | BGP_ATTR_FLAG_TRANS
);
4270 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4271 stream_putc(s
, attr_len
);
4272 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4273 stream_putw(s
, tlv_len
);
4274 stream_putc(s
, 0); /* reserved */
4275 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4276 stream_putw(s
, subtlv_len
);
4277 stream_putc(s
, 0); /* reserved */
4278 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4279 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4280 stream_putc(s
, 0); /* sid_flags */
4281 stream_putw(s
, 0xffff); /* endpoint */
4282 stream_putc(s
, 0); /* reserved */
4285 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4288 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4289 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4290 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4291 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4292 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4293 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4294 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4295 } else if (attr
->srv6_vpn
) {
4296 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4297 | BGP_ATTR_FLAG_TRANS
);
4298 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4299 stream_putc(s
, 22); /* tlv len */
4300 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4301 stream_putw(s
, 0x13); /* tlv len */
4302 stream_putc(s
, 0x00); /* reserved */
4303 stream_putc(s
, 0x01); /* sid_type */
4304 stream_putc(s
, 0x00); /* sif_flags */
4305 stream_put(s
, &attr
->srv6_vpn
->sid
,
4306 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4310 if (send_as4_path
) {
4311 /* If the peer is NOT As4 capable, AND */
4312 /* there are ASnums > 65535 in path THEN
4313 * give out AS4_PATH */
4315 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4317 * Hm, I wonder... confederation things *should* only be at
4318 * the beginning of an aspath, right? Then we should use
4319 * aspath_delete_confed_seq for this, because it is already
4321 * Folks, talk to me: what is reasonable here!?
4323 aspath
= aspath_delete_confed_seq(aspath
);
4326 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4327 | BGP_ATTR_FLAG_EXTLEN
);
4328 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4329 aspath_sizep
= stream_get_endp(s
);
4331 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4334 if (aspath
!= attr
->aspath
)
4335 aspath_free(aspath
);
4337 if (send_as4_aggregator
) {
4338 /* send AS4_AGGREGATOR, at this place */
4339 /* this section of code moved here in order to ensure the
4341 * *ascending* order of attributes
4343 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4344 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4346 stream_putl(s
, attr
->aggregator_as
);
4347 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4350 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4351 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4352 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4353 /* Tunnel Encap attribute */
4354 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4356 #ifdef ENABLE_BGP_VNC_ATTR
4358 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4363 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4364 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4365 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4366 stream_putc(s
, 9); // Length
4367 stream_putc(s
, 0); // Flags
4368 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4369 stream_put(s
, &(attr
->label
),
4370 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4371 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4372 // Unicast tunnel endpoint IP address
4375 /* Unknown transit attribute. */
4376 struct transit
*transit
= bgp_attr_get_transit(attr
);
4379 stream_put(s
, transit
->val
, transit
->length
);
4381 /* Return total size of attribute. */
4382 return stream_get_endp(s
) - cp
;
4385 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4387 unsigned long attrlen_pnt
;
4389 iana_safi_t pkt_safi
;
4391 /* Set extended bit always to encode the attribute length as 2 bytes */
4392 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4393 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4395 attrlen_pnt
= stream_get_endp(s
);
4396 stream_putw(s
, 0); /* Length of this attribute. */
4398 /* Convert AFI, SAFI to values for packet. */
4399 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4401 stream_putw(s
, pkt_afi
);
4402 stream_putc(s
, pkt_safi
);
4407 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4408 afi_t afi
, safi_t safi
,
4409 const struct prefix_rd
*prd
,
4410 mpls_label_t
*label
, uint32_t num_labels
,
4411 bool addpath_capable
, uint32_t addpath_tx_id
,
4414 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4416 if (safi
== SAFI_LABELED_UNICAST
) {
4417 label
= (mpls_label_t
*)wlabel
;
4421 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4422 addpath_capable
, addpath_tx_id
, attr
);
4425 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4427 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4430 /* Initialization of attribute. */
4431 void bgp_attr_init(void)
4444 void bgp_attr_finish(void)
4449 ecommunity_finish();
4450 lcommunity_finish();
4457 /* Make attribute packet. */
4458 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4459 const struct prefix
*prefix
)
4464 struct aspath
*aspath
;
4465 bool addpath_capable
= false;
4466 uint32_t addpath_tx_id
= 0;
4468 /* Remember current pointer. */
4469 cp
= stream_get_endp(s
);
4471 /* Place holder of length. */
4474 /* Origin attribute. */
4475 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4476 stream_putc(s
, BGP_ATTR_ORIGIN
);
4478 stream_putc(s
, attr
->origin
);
4480 aspath
= attr
->aspath
;
4482 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4483 stream_putc(s
, BGP_ATTR_AS_PATH
);
4484 aspath_lenp
= stream_get_endp(s
);
4487 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4489 /* Nexthop attribute. */
4490 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4491 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4492 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4493 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4495 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4498 /* MED attribute. */
4499 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4500 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4501 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4503 stream_putl(s
, attr
->med
);
4506 /* Local preference. */
4507 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4508 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4509 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4511 stream_putl(s
, attr
->local_pref
);
4514 /* Atomic aggregate. */
4515 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4516 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4517 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4522 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4523 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4524 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4526 stream_putl(s
, attr
->aggregator_as
);
4527 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4530 /* Community attribute. */
4531 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4532 if (attr
->community
->size
* 4 > 255) {
4534 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4535 | BGP_ATTR_FLAG_EXTLEN
);
4536 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4537 stream_putw(s
, attr
->community
->size
* 4);
4540 BGP_ATTR_FLAG_OPTIONAL
4541 | BGP_ATTR_FLAG_TRANS
);
4542 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4543 stream_putc(s
, attr
->community
->size
* 4);
4545 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4548 /* Large Community attribute. */
4549 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4550 if (lcom_length(attr
->lcommunity
) > 255) {
4552 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4553 | BGP_ATTR_FLAG_EXTLEN
);
4554 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4555 stream_putw(s
, lcom_length(attr
->lcommunity
));
4558 BGP_ATTR_FLAG_OPTIONAL
4559 | BGP_ATTR_FLAG_TRANS
);
4560 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4561 stream_putc(s
, lcom_length(attr
->lcommunity
));
4564 stream_put(s
, attr
->lcommunity
->val
,
4565 lcom_length(attr
->lcommunity
));
4568 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4569 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4570 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4571 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4574 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4575 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4576 sizep
= stream_get_endp(s
);
4579 stream_putc(s
, 0); /* Marker: Attribute length. */
4580 stream_putw(s
, AFI_IP6
); /* AFI */
4581 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4584 stream_putc(s
, attr
->mp_nexthop_len
);
4585 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4586 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4587 stream_put(s
, &attr
->mp_nexthop_local
,
4594 stream_put_prefix_addpath(s
, prefix
, addpath_capable
,
4597 /* Set MP attribute length. */
4598 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4602 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4603 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4605 BGP_ATTR_FLAG_OPTIONAL
4606 | BGP_ATTR_FLAG_TRANS
);
4607 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4609 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4610 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4611 stream_putc(s
, 0); // reserved
4612 stream_putw(s
, 0); // flags
4613 stream_putl(s
, attr
->label_index
);
4617 /* Return total size of attribute. */
4618 len
= stream_get_endp(s
) - cp
- 2;
4619 stream_putw_at(s
, cp
, len
);