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_DPA
, "DPA"},
72 {BGP_ATTR_ADVERTISER
, "ADVERTISER"},
73 {BGP_ATTR_RCID_PATH
, "RCID_PATH"},
74 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
75 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
76 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
77 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
78 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
79 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
80 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
81 {BGP_ATTR_ENCAP
, "ENCAP"},
82 #ifdef ENABLE_BGP_VNC_ATTR
83 {BGP_ATTR_VNC
, "VNC"},
85 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
86 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
87 {BGP_ATTR_IPV6_EXT_COMMUNITIES
, "IPV6_EXT_COMMUNITIES"},
90 static const struct message attr_flag_str
[] = {
91 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
92 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
93 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
94 /* bgp_attr_flags_diagnose() relies on this bit being last in
96 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
99 static struct hash
*cluster_hash
;
101 static void *cluster_hash_alloc(void *p
)
103 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
104 struct cluster_list
*cluster
;
106 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
107 cluster
->length
= val
->length
;
109 if (cluster
->length
) {
110 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
111 memcpy(cluster
->list
, val
->list
, val
->length
);
113 cluster
->list
= NULL
;
120 /* Cluster list related functions. */
121 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
123 struct cluster_list tmp
= {};
124 struct cluster_list
*cluster
;
127 tmp
.list
= length
== 0 ? NULL
: pnt
;
129 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
134 bool cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
138 for (i
= 0; i
< cluster
->length
/ 4; i
++)
139 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
144 static unsigned int cluster_hash_key_make(const void *p
)
146 const struct cluster_list
*cluster
= p
;
148 return jhash(cluster
->list
, cluster
->length
, 0);
151 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
153 const struct cluster_list
*cluster1
= p1
;
154 const struct cluster_list
*cluster2
= p2
;
156 if (cluster1
->list
== cluster2
->list
)
159 if (!cluster1
->list
|| !cluster2
->list
)
162 if (cluster1
->length
!= cluster2
->length
)
165 return (memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
) == 0);
168 static void cluster_free(struct cluster_list
*cluster
)
170 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
171 XFREE(MTYPE_CLUSTER
, cluster
);
174 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
176 struct cluster_list
*find
;
178 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
184 static void cluster_unintern(struct cluster_list
**cluster
)
186 if ((*cluster
)->refcnt
)
187 (*cluster
)->refcnt
--;
189 if ((*cluster
)->refcnt
== 0) {
190 void *p
= hash_release(cluster_hash
, *cluster
);
191 assert(p
== *cluster
);
192 cluster_free(*cluster
);
197 static void cluster_init(void)
199 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
203 static void cluster_finish(void)
205 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
206 hash_free(cluster_hash
);
210 static struct hash
*encap_hash
= NULL
;
211 #ifdef ENABLE_BGP_VNC
212 static struct hash
*vnc_hash
= NULL
;
214 static struct hash
*srv6_l3vpn_hash
;
215 static struct hash
*srv6_vpn_hash
;
217 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
219 struct bgp_attr_encap_subtlv
*new;
220 struct bgp_attr_encap_subtlv
*tail
;
221 struct bgp_attr_encap_subtlv
*p
;
223 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
224 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
226 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
229 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
232 memcpy(tail
, p
, size
);
239 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
241 struct bgp_attr_encap_subtlv
*next
;
245 XFREE(MTYPE_ENCAP_TLV
, p
);
250 void bgp_attr_flush_encap(struct attr
*attr
)
255 if (attr
->encap_subtlvs
) {
256 encap_free(attr
->encap_subtlvs
);
257 attr
->encap_subtlvs
= NULL
;
259 #ifdef ENABLE_BGP_VNC
260 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
261 bgp_attr_get_vnc_subtlvs(attr
);
264 encap_free(vnc_subtlvs
);
265 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
271 * Compare encap sub-tlv chains
276 * This algorithm could be made faster if needed
278 static bool encap_same(const struct bgp_attr_encap_subtlv
*h1
,
279 const struct bgp_attr_encap_subtlv
*h2
)
281 const struct bgp_attr_encap_subtlv
*p
;
282 const struct bgp_attr_encap_subtlv
*q
;
286 if (h1
== NULL
|| h2
== NULL
)
289 for (p
= h1
; p
; p
= p
->next
) {
290 for (q
= h2
; q
; q
= q
->next
) {
291 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
292 && !memcmp(p
->value
, q
->value
, p
->length
)) {
301 for (p
= h2
; p
; p
= p
->next
) {
302 for (q
= h1
; q
; q
= q
->next
) {
303 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
304 && !memcmp(p
->value
, q
->value
, p
->length
)) {
316 static void *encap_hash_alloc(void *p
)
318 /* Encap structure is already allocated. */
324 #ifdef ENABLE_BGP_VNC
329 static struct bgp_attr_encap_subtlv
*
330 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
332 struct bgp_attr_encap_subtlv
*find
;
333 struct hash
*hash
= encap_hash
;
334 #ifdef ENABLE_BGP_VNC
335 if (type
== VNC_SUBTLV_TYPE
)
339 find
= hash_get(hash
, encap
, encap_hash_alloc
);
347 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
348 encap_subtlv_type type
)
350 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
354 if (encap
->refcnt
== 0) {
355 struct hash
*hash
= encap_hash
;
356 #ifdef ENABLE_BGP_VNC
357 if (type
== VNC_SUBTLV_TYPE
)
360 hash_release(hash
, encap
);
366 static unsigned int encap_hash_key_make(const void *p
)
368 const struct bgp_attr_encap_subtlv
*encap
= p
;
370 return jhash(encap
->value
, encap
->length
, 0);
373 static bool encap_hash_cmp(const void *p1
, const void *p2
)
375 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
376 (const struct bgp_attr_encap_subtlv
*)p2
);
379 static void encap_init(void)
381 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
383 #ifdef ENABLE_BGP_VNC
384 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
389 static void encap_finish(void)
391 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
392 hash_free(encap_hash
);
394 #ifdef ENABLE_BGP_VNC
395 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
401 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
410 return !memcmp(bgp_attr_get_evpn_overlay(a1
),
411 bgp_attr_get_evpn_overlay(a2
),
412 sizeof(struct bgp_route_evpn
));
415 /* Unknown transit attribute. */
416 static struct hash
*transit_hash
;
418 static void transit_free(struct transit
*transit
)
420 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
421 XFREE(MTYPE_TRANSIT
, transit
);
424 static void *transit_hash_alloc(void *p
)
426 /* Transit structure is already allocated. */
430 static struct transit
*transit_intern(struct transit
*transit
)
432 struct transit
*find
;
434 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
436 transit_free(transit
);
442 static void transit_unintern(struct transit
**transit
)
444 if ((*transit
)->refcnt
)
445 (*transit
)->refcnt
--;
447 if ((*transit
)->refcnt
== 0) {
448 hash_release(transit_hash
, *transit
);
449 transit_free(*transit
);
454 static void *srv6_l3vpn_hash_alloc(void *p
)
459 static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn
*l3vpn
)
461 XFREE(MTYPE_BGP_SRV6_L3VPN
, l3vpn
);
464 static struct bgp_attr_srv6_l3vpn
*
465 srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn
*l3vpn
)
467 struct bgp_attr_srv6_l3vpn
*find
;
469 find
= hash_get(srv6_l3vpn_hash
, l3vpn
, srv6_l3vpn_hash_alloc
);
471 srv6_l3vpn_free(l3vpn
);
476 static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn
**l3vpnp
)
478 struct bgp_attr_srv6_l3vpn
*l3vpn
= *l3vpnp
;
483 if (l3vpn
->refcnt
== 0) {
484 hash_release(srv6_l3vpn_hash
, l3vpn
);
485 srv6_l3vpn_free(l3vpn
);
490 static void *srv6_vpn_hash_alloc(void *p
)
495 static void srv6_vpn_free(struct bgp_attr_srv6_vpn
*vpn
)
497 XFREE(MTYPE_BGP_SRV6_VPN
, vpn
);
500 static struct bgp_attr_srv6_vpn
*srv6_vpn_intern(struct bgp_attr_srv6_vpn
*vpn
)
502 struct bgp_attr_srv6_vpn
*find
;
504 find
= hash_get(srv6_vpn_hash
, vpn
, srv6_vpn_hash_alloc
);
511 static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn
**vpnp
)
513 struct bgp_attr_srv6_vpn
*vpn
= *vpnp
;
518 if (vpn
->refcnt
== 0) {
519 hash_release(srv6_vpn_hash
, vpn
);
525 static uint32_t srv6_l3vpn_hash_key_make(const void *p
)
527 const struct bgp_attr_srv6_l3vpn
*l3vpn
= p
;
530 key
= jhash(&l3vpn
->sid
, 16, key
);
531 key
= jhash_1word(l3vpn
->sid_flags
, key
);
532 key
= jhash_1word(l3vpn
->endpoint_behavior
, key
);
533 key
= jhash_1word(l3vpn
->loc_block_len
, key
);
534 key
= jhash_1word(l3vpn
->loc_node_len
, key
);
535 key
= jhash_1word(l3vpn
->func_len
, key
);
536 key
= jhash_1word(l3vpn
->arg_len
, key
);
537 key
= jhash_1word(l3vpn
->transposition_len
, key
);
538 key
= jhash_1word(l3vpn
->transposition_offset
, key
);
542 static bool srv6_l3vpn_hash_cmp(const void *p1
, const void *p2
)
544 const struct bgp_attr_srv6_l3vpn
*l3vpn1
= p1
;
545 const struct bgp_attr_srv6_l3vpn
*l3vpn2
= p2
;
547 return sid_same(&l3vpn1
->sid
, &l3vpn2
->sid
)
548 && l3vpn1
->sid_flags
== l3vpn2
->sid_flags
549 && l3vpn1
->endpoint_behavior
== l3vpn2
->endpoint_behavior
550 && l3vpn1
->loc_block_len
== l3vpn2
->loc_block_len
551 && l3vpn1
->loc_node_len
== l3vpn2
->loc_node_len
552 && l3vpn1
->func_len
== l3vpn2
->func_len
553 && l3vpn1
->arg_len
== l3vpn2
->arg_len
554 && l3vpn1
->transposition_len
== l3vpn2
->transposition_len
555 && l3vpn1
->transposition_offset
== l3vpn2
->transposition_offset
;
558 static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn
*h1
,
559 const struct bgp_attr_srv6_l3vpn
*h2
)
563 else if (h1
== NULL
|| h2
== NULL
)
566 return srv6_l3vpn_hash_cmp((const void *)h1
, (const void *)h2
);
569 static unsigned int srv6_vpn_hash_key_make(const void *p
)
571 const struct bgp_attr_srv6_vpn
*vpn
= p
;
574 key
= jhash(&vpn
->sid
, 16, key
);
575 key
= jhash_1word(vpn
->sid_flags
, key
);
579 static bool srv6_vpn_hash_cmp(const void *p1
, const void *p2
)
581 const struct bgp_attr_srv6_vpn
*vpn1
= p1
;
582 const struct bgp_attr_srv6_vpn
*vpn2
= p2
;
584 return sid_same(&vpn1
->sid
, &vpn2
->sid
)
585 && vpn1
->sid_flags
== vpn2
->sid_flags
;
588 static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn
*h1
,
589 const struct bgp_attr_srv6_vpn
*h2
)
593 else if (h1
== NULL
|| h2
== NULL
)
596 return srv6_vpn_hash_cmp((const void *)h1
, (const void *)h2
);
599 static void srv6_init(void)
602 hash_create(srv6_l3vpn_hash_key_make
, srv6_l3vpn_hash_cmp
,
603 "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
604 srv6_vpn_hash
= hash_create(srv6_vpn_hash_key_make
, srv6_vpn_hash_cmp
,
605 "BGP Prefix-SID SRv6-VPN-Service-TLV");
608 static void srv6_finish(void)
610 hash_clean(srv6_l3vpn_hash
, (void (*)(void *))srv6_l3vpn_free
);
611 hash_free(srv6_l3vpn_hash
);
612 srv6_l3vpn_hash
= NULL
;
613 hash_clean(srv6_vpn_hash
, (void (*)(void *))srv6_vpn_free
);
614 hash_free(srv6_vpn_hash
);
615 srv6_vpn_hash
= NULL
;
618 static unsigned int transit_hash_key_make(const void *p
)
620 const struct transit
*transit
= p
;
622 return jhash(transit
->val
, transit
->length
, 0);
625 static bool transit_hash_cmp(const void *p1
, const void *p2
)
627 const struct transit
*transit1
= p1
;
628 const struct transit
*transit2
= p2
;
630 return (transit1
->length
== transit2
->length
631 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
634 static void transit_init(void)
636 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
640 static void transit_finish(void)
642 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
643 hash_free(transit_hash
);
647 /* Attribute hash routines. */
648 static struct hash
*attrhash
;
650 unsigned long int attr_count(void)
652 return attrhash
->count
;
655 unsigned long int attr_unknown_count(void)
657 return transit_hash
->count
;
660 unsigned int attrhash_key_make(const void *p
)
662 const struct attr
*attr
= (struct attr
*)p
;
664 #define MIX(val) key = jhash_1word(val, key)
665 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
667 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
668 MIX3(attr
->local_pref
, attr
->aggregator_as
,
669 attr
->aggregator_addr
.s_addr
);
670 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
671 attr
->originator_id
.s_addr
);
672 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
675 MIX(aspath_key_make(attr
->aspath
));
677 MIX(community_hash_make(attr
->community
));
679 if (attr
->lcommunity
)
680 MIX(lcommunity_hash_make(attr
->lcommunity
));
681 if (attr
->ecommunity
)
682 MIX(ecommunity_hash_make(attr
->ecommunity
));
683 if (bgp_attr_get_ipv6_ecommunity(attr
))
684 MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr
)));
685 if (bgp_attr_get_cluster(attr
))
686 MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr
)));
687 if (bgp_attr_get_transit(attr
))
688 MIX(transit_hash_key_make(bgp_attr_get_transit(attr
)));
689 if (attr
->encap_subtlvs
)
690 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
691 if (attr
->srv6_l3vpn
)
692 MIX(srv6_l3vpn_hash_key_make(attr
->srv6_l3vpn
));
694 MIX(srv6_vpn_hash_key_make(attr
->srv6_vpn
));
695 #ifdef ENABLE_BGP_VNC
696 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
697 bgp_attr_get_vnc_subtlvs(attr
);
699 MIX(encap_hash_key_make(vnc_subtlvs
));
701 MIX(attr
->mp_nexthop_len
);
702 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
703 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
704 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
705 MIX(attr
->rmap_table_id
);
712 bool attrhash_cmp(const void *p1
, const void *p2
)
714 const struct attr
*attr1
= p1
;
715 const struct attr
*attr2
= p2
;
717 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
718 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
719 && attr1
->aspath
== attr2
->aspath
720 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
721 && attr1
->local_pref
== attr2
->local_pref
722 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
723 if (attr1
->aggregator_as
== attr2
->aggregator_as
724 && attr1
->aggregator_addr
.s_addr
725 == attr2
->aggregator_addr
.s_addr
726 && attr1
->weight
== attr2
->weight
727 && attr1
->tag
== attr2
->tag
728 && attr1
->label_index
== attr2
->label_index
729 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
730 && attr1
->ecommunity
== attr2
->ecommunity
731 && bgp_attr_get_ipv6_ecommunity(attr1
)
732 == bgp_attr_get_ipv6_ecommunity(attr2
)
733 && attr1
->lcommunity
== attr2
->lcommunity
734 && bgp_attr_get_cluster(attr1
)
735 == bgp_attr_get_cluster(attr2
)
736 && bgp_attr_get_transit(attr1
)
737 == bgp_attr_get_transit(attr2
)
738 && attr1
->rmap_table_id
== attr2
->rmap_table_id
739 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
740 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
741 #ifdef ENABLE_BGP_VNC
742 && encap_same(bgp_attr_get_vnc_subtlvs(attr1
),
743 bgp_attr_get_vnc_subtlvs(attr2
))
745 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
746 &attr2
->mp_nexthop_global
)
747 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
748 &attr2
->mp_nexthop_local
)
749 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
750 &attr2
->mp_nexthop_global_in
)
751 && IPV4_ADDR_SAME(&attr1
->originator_id
,
752 &attr2
->originator_id
)
753 && overlay_index_same(attr1
, attr2
)
754 && !memcmp(&attr1
->esi
, &attr2
->esi
, sizeof(esi_t
))
755 && attr1
->es_flags
== attr2
->es_flags
756 && attr1
->mm_sync_seqnum
== attr2
->mm_sync_seqnum
757 && attr1
->df_pref
== attr2
->df_pref
758 && attr1
->df_alg
== attr2
->df_alg
759 && attr1
->nh_ifindex
== attr2
->nh_ifindex
760 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
761 && attr1
->distance
== attr2
->distance
762 && srv6_l3vpn_same(attr1
->srv6_l3vpn
, attr2
->srv6_l3vpn
)
763 && srv6_vpn_same(attr1
->srv6_vpn
, attr2
->srv6_vpn
)
764 && attr1
->srte_color
== attr2
->srte_color
765 && attr1
->nh_type
== attr2
->nh_type
766 && attr1
->bh_type
== attr2
->bh_type
)
773 static void attrhash_init(void)
776 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
780 * special for hash_clean below
782 static void attr_vfree(void *attr
)
784 XFREE(MTYPE_ATTR
, attr
);
787 static void attrhash_finish(void)
789 hash_clean(attrhash
, attr_vfree
);
794 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
796 struct attr
*attr
= bucket
->data
;
797 char sid_str
[BUFSIZ
];
799 vty_out(vty
, "attr[%ld] nexthop %pI4\n", attr
->refcnt
, &attr
->nexthop
);
802 if (attr
->srv6_l3vpn
)
803 inet_ntop(AF_INET6
, &attr
->srv6_l3vpn
->sid
, sid_str
, BUFSIZ
);
804 else if (attr
->srv6_vpn
)
805 inet_ntop(AF_INET6
, &attr
->srv6_vpn
->sid
, sid_str
, BUFSIZ
);
808 "\tflags: %" PRIu64
" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
809 attr
->flag
, attr
->distance
, attr
->med
, attr
->local_pref
,
810 attr
->origin
, attr
->weight
, attr
->label
, sid_str
);
813 void attr_show_all(struct vty
*vty
)
815 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
816 void *))attr_show_all_iterator
,
820 static void *bgp_attr_hash_alloc(void *p
)
822 struct attr
*val
= (struct attr
*)p
;
825 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
827 if (val
->encap_subtlvs
) {
828 val
->encap_subtlvs
= NULL
;
830 #ifdef ENABLE_BGP_VNC
831 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
832 bgp_attr_get_vnc_subtlvs(val
);
835 bgp_attr_set_vnc_subtlvs(val
, NULL
);
838 val
->srv6_l3vpn
= NULL
;
840 val
->srv6_vpn
= NULL
;
846 /* Internet argument attribute. */
847 struct attr
*bgp_attr_intern(struct attr
*attr
)
850 struct ecommunity
*ecomm
;
852 /* Intern referenced strucutre. */
854 if (!attr
->aspath
->refcnt
)
855 attr
->aspath
= aspath_intern(attr
->aspath
);
857 attr
->aspath
->refcnt
++;
859 if (attr
->community
) {
860 if (!attr
->community
->refcnt
)
861 attr
->community
= community_intern(attr
->community
);
863 attr
->community
->refcnt
++;
866 if (attr
->ecommunity
) {
867 if (!attr
->ecommunity
->refcnt
)
868 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
870 attr
->ecommunity
->refcnt
++;
873 ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
876 bgp_attr_set_ipv6_ecommunity(attr
,
877 ecommunity_intern(ecomm
));
882 if (attr
->lcommunity
) {
883 if (!attr
->lcommunity
->refcnt
)
884 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
886 attr
->lcommunity
->refcnt
++;
889 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
892 if (!cluster
->refcnt
)
893 bgp_attr_set_cluster(attr
, cluster_intern(cluster
));
898 struct transit
*transit
= bgp_attr_get_transit(attr
);
901 if (!transit
->refcnt
)
902 bgp_attr_set_transit(attr
, transit_intern(transit
));
906 if (attr
->encap_subtlvs
) {
907 if (!attr
->encap_subtlvs
->refcnt
)
908 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
911 attr
->encap_subtlvs
->refcnt
++;
913 if (attr
->srv6_l3vpn
) {
914 if (!attr
->srv6_l3vpn
->refcnt
)
915 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
917 attr
->srv6_l3vpn
->refcnt
++;
919 if (attr
->srv6_vpn
) {
920 if (!attr
->srv6_vpn
->refcnt
)
921 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
923 attr
->srv6_vpn
->refcnt
++;
925 #ifdef ENABLE_BGP_VNC
926 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
927 bgp_attr_get_vnc_subtlvs(attr
);
930 if (!vnc_subtlvs
->refcnt
)
931 bgp_attr_set_vnc_subtlvs(
933 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
935 vnc_subtlvs
->refcnt
++;
939 /* At this point, attr only contains intern'd pointers. that means
940 * if we find it in attrhash, it has all the same pointers and we
941 * correctly updated the refcounts on these.
942 * If we don't find it, we need to allocate a one because in all
943 * cases this returns a new reference to a hashed attr, but the input
945 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
951 /* Make network statement's attribute. */
952 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
954 memset(attr
, 0, sizeof(struct attr
));
956 attr
->origin
= origin
;
957 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
958 attr
->aspath
= aspath_empty();
959 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
960 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
962 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
963 attr
->label
= MPLS_INVALID_LABEL
;
964 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
965 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
970 /* Create the attributes for an aggregate */
971 struct attr
*bgp_attr_aggregate_intern(
972 struct bgp
*bgp
, uint8_t origin
, struct aspath
*aspath
,
973 struct community
*community
, struct ecommunity
*ecommunity
,
974 struct lcommunity
*lcommunity
, struct bgp_aggregate
*aggregate
,
975 uint8_t atomic_aggregate
, const struct prefix
*p
)
981 memset(&attr
, 0, sizeof(struct attr
));
983 /* Origin attribute. */
984 attr
.origin
= origin
;
985 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
987 /* AS path attribute. */
989 attr
.aspath
= aspath_intern(aspath
);
991 attr
.aspath
= aspath_empty();
992 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
994 /* Next hop attribute. */
995 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
998 uint32_t gshut
= COMMUNITY_GSHUT
;
1000 /* If we are not shutting down ourselves and we are
1001 * aggregating a route that contains the GSHUT community we
1002 * need to remove that community when creating the aggregate */
1003 if (!bgp_in_graceful_shutdown(bgp
)
1004 && community_include(community
, gshut
)) {
1005 community_del_val(community
, &gshut
);
1008 attr
.community
= community
;
1009 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1013 attr
.ecommunity
= ecommunity
;
1014 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1018 attr
.lcommunity
= lcommunity
;
1019 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1022 if (bgp_in_graceful_shutdown(bgp
))
1023 bgp_attr_add_gshut_community(&attr
);
1025 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1026 attr
.label
= MPLS_INVALID_LABEL
;
1027 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
1028 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1029 if (!aggregate
->as_set
|| atomic_aggregate
)
1030 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1031 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1032 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
1033 attr
.aggregator_as
= bgp
->confed_id
;
1035 attr
.aggregator_as
= bgp
->as
;
1036 attr
.aggregator_addr
= bgp
->router_id
;
1037 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
1038 attr
.label
= MPLS_INVALID_LABEL
;
1040 /* Apply route-map */
1041 if (aggregate
->rmap
.name
) {
1042 struct attr attr_tmp
= attr
;
1043 struct bgp_path_info rmap_path
;
1045 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1046 rmap_path
.peer
= bgp
->peer_self
;
1047 rmap_path
.attr
= &attr_tmp
;
1049 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
1051 ret
= route_map_apply(aggregate
->rmap
.map
, p
, &rmap_path
);
1053 bgp
->peer_self
->rmap_type
= 0;
1055 if (ret
== RMAP_DENYMATCH
) {
1056 /* Free uninterned attribute. */
1057 bgp_attr_flush(&attr_tmp
);
1059 /* Unintern original. */
1060 aspath_unintern(&attr
.aspath
);
1064 if (bgp_in_graceful_shutdown(bgp
))
1065 bgp_attr_add_gshut_community(&attr_tmp
);
1067 new = bgp_attr_intern(&attr_tmp
);
1070 if (bgp_in_graceful_shutdown(bgp
))
1071 bgp_attr_add_gshut_community(&attr
);
1073 new = bgp_attr_intern(&attr
);
1076 aspath_unintern(&new->aspath
);
1080 /* Unintern just the sub-components of the attr, but not the attr */
1081 void bgp_attr_unintern_sub(struct attr
*attr
)
1083 struct ecommunity
*ecomm
;
1084 struct cluster_list
*cluster
;
1086 /* aspath refcount shoud be decrement. */
1088 aspath_unintern(&attr
->aspath
);
1089 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
1091 if (attr
->community
)
1092 community_unintern(&attr
->community
);
1093 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1095 ecommunity_unintern(&attr
->ecommunity
);
1096 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
1098 ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1099 ecommunity_unintern(&ecomm
);
1100 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
));
1101 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1103 if (attr
->lcommunity
)
1104 lcommunity_unintern(&attr
->lcommunity
);
1105 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1107 cluster
= bgp_attr_get_cluster(attr
);
1109 cluster_unintern(&cluster
);
1110 bgp_attr_set_cluster(attr
, cluster
);
1112 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
1114 struct transit
*transit
= bgp_attr_get_transit(attr
);
1117 transit_unintern(&transit
);
1118 bgp_attr_set_transit(attr
, transit
);
1121 if (attr
->encap_subtlvs
)
1122 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
1124 #ifdef ENABLE_BGP_VNC
1125 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1126 bgp_attr_get_vnc_subtlvs(attr
);
1129 encap_unintern(&vnc_subtlvs
, VNC_SUBTLV_TYPE
);
1130 bgp_attr_set_vnc_subtlvs(attr
, vnc_subtlvs
);
1134 if (attr
->srv6_l3vpn
)
1135 srv6_l3vpn_unintern(&attr
->srv6_l3vpn
);
1138 srv6_vpn_unintern(&attr
->srv6_vpn
);
1142 * We have some show commands that let you experimentally
1143 * apply a route-map. When we apply the route-map
1144 * we are reseting values but not saving them for
1145 * posterity via intern'ing( because route-maps don't
1146 * do that) but at this point in time we need
1147 * to compare the new attr to the old and if the
1148 * routemap has changed it we need to, as Snoop Dog says,
1149 * Drop it like it's hot
1151 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
1153 if (new->aspath
!= old
->aspath
)
1154 aspath_free(new->aspath
);
1156 if (new->community
!= old
->community
)
1157 community_free(&new->community
);
1159 if (new->ecommunity
!= old
->ecommunity
)
1160 ecommunity_free(&new->ecommunity
);
1162 if (new->lcommunity
!= old
->lcommunity
)
1163 lcommunity_free(&new->lcommunity
);
1165 if (new->srv6_l3vpn
!= old
->srv6_l3vpn
) {
1166 srv6_l3vpn_free(new->srv6_l3vpn
);
1167 new->srv6_l3vpn
= NULL
;
1170 if (new->srv6_vpn
!= old
->srv6_vpn
) {
1171 srv6_vpn_free(new->srv6_vpn
);
1172 new->srv6_vpn
= NULL
;
1176 /* Free bgp attribute and aspath. */
1177 void bgp_attr_unintern(struct attr
**pattr
)
1179 struct attr
*attr
= *pattr
;
1183 /* Decrement attribute reference. */
1188 /* If reference becomes zero then free attribute object. */
1189 if (attr
->refcnt
== 0) {
1190 ret
= hash_release(attrhash
, attr
);
1191 assert(ret
!= NULL
);
1192 XFREE(MTYPE_ATTR
, attr
);
1196 bgp_attr_unintern_sub(&tmp
);
1199 void bgp_attr_flush(struct attr
*attr
)
1201 struct ecommunity
*ecomm
;
1202 struct cluster_list
*cluster
;
1204 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
1205 aspath_free(attr
->aspath
);
1206 attr
->aspath
= NULL
;
1208 if (attr
->community
&& !attr
->community
->refcnt
)
1209 community_free(&attr
->community
);
1210 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
1211 ecommunity_free(&attr
->ecommunity
);
1212 ecomm
= bgp_attr_get_ipv6_ecommunity(attr
);
1213 if (ecomm
&& !ecomm
->refcnt
)
1214 ecommunity_free(&ecomm
);
1215 bgp_attr_set_ipv6_ecommunity(attr
, NULL
);
1216 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
1217 lcommunity_free(&attr
->lcommunity
);
1219 cluster
= bgp_attr_get_cluster(attr
);
1220 if (cluster
&& !cluster
->refcnt
) {
1221 cluster_free(cluster
);
1222 bgp_attr_set_cluster(attr
, NULL
);
1225 struct transit
*transit
= bgp_attr_get_transit(attr
);
1227 if (transit
&& !transit
->refcnt
) {
1228 transit_free(transit
);
1229 bgp_attr_set_transit(attr
, NULL
);
1231 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
1232 encap_free(attr
->encap_subtlvs
);
1233 attr
->encap_subtlvs
= NULL
;
1235 if (attr
->srv6_l3vpn
&& !attr
->srv6_l3vpn
->refcnt
) {
1236 srv6_l3vpn_free(attr
->srv6_l3vpn
);
1237 attr
->srv6_l3vpn
= NULL
;
1239 if (attr
->srv6_vpn
&& !attr
->srv6_vpn
->refcnt
) {
1240 srv6_vpn_free(attr
->srv6_vpn
);
1241 attr
->srv6_vpn
= NULL
;
1243 #ifdef ENABLE_BGP_VNC
1244 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
1245 bgp_attr_get_vnc_subtlvs(attr
);
1247 if (vnc_subtlvs
&& !vnc_subtlvs
->refcnt
) {
1248 encap_free(vnc_subtlvs
);
1249 bgp_attr_set_vnc_subtlvs(attr
, NULL
);
1254 /* Implement draft-scudder-idr-optional-transitive behaviour and
1255 * avoid resetting sessions for malformed attributes which are
1256 * are partial/optional and hence where the error likely was not
1257 * introduced by the sending neighbour.
1259 static bgp_attr_parse_ret_t
1260 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
1263 struct peer
*const peer
= args
->peer
;
1264 struct attr
*const attr
= args
->attr
;
1265 const uint8_t flags
= args
->flags
;
1266 /* startp and length must be special-cased, as whether or not to
1267 * send the attribute data with the NOTIFY depends on the error,
1268 * the caller therefore signals this with the seperate length argument
1270 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
1272 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1273 char attr_str
[BUFSIZ
] = {0};
1275 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1277 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1280 /* Only relax error handling for eBGP peers */
1281 if (peer
->sort
!= BGP_PEER_EBGP
) {
1282 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1283 notify_datap
, length
);
1284 return BGP_ATTR_PARSE_ERROR
;
1287 /* Adjust the stream getp to the end of the attribute, in case we can
1288 * still proceed but the caller hasn't read all the attribute.
1290 stream_set_getp(BGP_INPUT(peer
),
1291 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
1294 switch (args
->type
) {
1295 /* where an attribute is relatively inconsequential, e.g. it does not
1296 * affect route selection, and can be safely ignored, then any such
1297 * attributes which are malformed should just be ignored and the route
1298 * processed as normal.
1300 case BGP_ATTR_AS4_AGGREGATOR
:
1301 case BGP_ATTR_AGGREGATOR
:
1302 case BGP_ATTR_ATOMIC_AGGREGATE
:
1303 return BGP_ATTR_PARSE_PROCEED
;
1305 /* Core attributes, particularly ones which may influence route
1306 * selection, should be treat-as-withdraw.
1308 case BGP_ATTR_ORIGIN
:
1309 case BGP_ATTR_AS_PATH
:
1310 case BGP_ATTR_NEXT_HOP
:
1311 case BGP_ATTR_MULTI_EXIT_DISC
:
1312 case BGP_ATTR_LOCAL_PREF
:
1313 case BGP_ATTR_COMMUNITIES
:
1314 case BGP_ATTR_EXT_COMMUNITIES
:
1315 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
1316 case BGP_ATTR_LARGE_COMMUNITIES
:
1317 case BGP_ATTR_ORIGINATOR_ID
:
1318 case BGP_ATTR_CLUSTER_LIST
:
1319 return BGP_ATTR_PARSE_WITHDRAW
;
1320 case BGP_ATTR_MP_REACH_NLRI
:
1321 case BGP_ATTR_MP_UNREACH_NLRI
:
1322 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1323 notify_datap
, length
);
1324 return BGP_ATTR_PARSE_ERROR
;
1327 /* Partial optional attributes that are malformed should not cause
1328 * the whole session to be reset. Instead treat it as a withdrawal
1329 * of the routes, if possible.
1331 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1332 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1333 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1334 return BGP_ATTR_PARSE_WITHDRAW
;
1336 /* default to reset */
1337 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1340 /* Find out what is wrong with the path attribute flag bits and log the error.
1341 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1342 Extended Length. Checking O/T/P bits at once implies, that the attribute
1343 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1344 non-transitive" attribute. */
1346 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1347 uint8_t desired_flags
/* how RFC says it must be */
1350 uint8_t seen
= 0, i
;
1351 uint8_t real_flags
= args
->flags
;
1352 const uint8_t attr_code
= args
->type
;
1354 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1355 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1356 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1357 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1358 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1359 flog_err(EC_BGP_ATTR_FLAG
,
1360 "%s attribute must%s be flagged as \"%s\"",
1361 lookup_msg(attr_str
, attr_code
, NULL
),
1362 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1365 attr_flag_str
[i
].str
);
1370 "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1371 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1372 real_flags
, desired_flags
);
1376 /* Required flags for attributes. EXTLEN will be masked off when testing,
1377 * as will PARTIAL for optional+transitive attributes.
1379 const uint8_t attr_flags_values
[] = {
1380 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1381 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1382 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1383 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1384 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1385 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1386 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1387 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1388 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1389 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1390 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1391 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1392 [BGP_ATTR_EXT_COMMUNITIES
] =
1393 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1394 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1395 [BGP_ATTR_AS4_AGGREGATOR
] =
1396 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1397 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1398 [BGP_ATTR_LARGE_COMMUNITIES
] =
1399 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1400 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1401 [BGP_ATTR_IPV6_EXT_COMMUNITIES
] =
1402 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1404 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1406 static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1408 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1409 const uint8_t flags
= args
->flags
;
1410 const uint8_t attr_code
= args
->type
;
1412 /* there may be attributes we don't know about */
1413 if (attr_code
> attr_flags_values_max
)
1415 if (attr_flags_values
[attr_code
] == 0)
1418 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1422 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1423 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1426 "%s well-known attributes must have transitive flag set (%x)",
1427 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1431 /* "For well-known attributes and for optional non-transitive
1433 * the Partial bit MUST be set to 0."
1435 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1436 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1437 flog_err(EC_BGP_ATTR_FLAG
,
1438 "%s well-known attribute must NOT have the partial flag set (%x)",
1439 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1442 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1443 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1444 flog_err(EC_BGP_ATTR_FLAG
,
1445 "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1446 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1451 /* Optional transitive attributes may go through speakers that don't
1452 * reocgnise them and set the Partial bit.
1454 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1455 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1456 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1458 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1461 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1465 /* Get origin attribute of the update message. */
1466 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1468 struct peer
*const peer
= args
->peer
;
1469 struct attr
*const attr
= args
->attr
;
1470 const bgp_size_t length
= args
->length
;
1472 /* If any recognized attribute has Attribute Length that conflicts
1473 with the expected length (based on the attribute type code), then
1474 the Error Subcode is set to Attribute Length Error. The Data
1475 field contains the erroneous attribute (type, length and
1478 flog_err(EC_BGP_ATTR_LEN
,
1479 "Origin attribute length is not one %d", length
);
1480 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1484 /* Fetch origin attribute. */
1485 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1487 /* If the ORIGIN attribute has an undefined value, then the Error
1488 Subcode is set to Invalid Origin Attribute. The Data field
1489 contains the unrecognized attribute (type, length and value). */
1490 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1491 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1492 flog_err(EC_BGP_ATTR_ORIGIN
,
1493 "Origin attribute value is invalid %d", attr
->origin
);
1494 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1498 /* Set oring attribute flag. */
1499 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1504 /* Parse AS path information. This function is wrapper of
1506 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1508 struct attr
*const attr
= args
->attr
;
1509 struct peer
*const peer
= args
->peer
;
1510 const bgp_size_t length
= args
->length
;
1513 * peer with AS4 => will get 4Byte ASnums
1514 * otherwise, will get 16 Bit
1516 attr
->aspath
= aspath_parse(
1518 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1519 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
));
1521 /* In case of IBGP, length will be zero. */
1522 if (!attr
->aspath
) {
1523 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1524 "Malformed AS path from %s, length is %d", peer
->host
,
1526 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1530 /* Set aspath attribute flag. */
1531 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1533 return BGP_ATTR_PARSE_PROCEED
;
1536 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1537 struct attr
*const attr
)
1539 /* These checks were part of bgp_attr_aspath, but with
1540 * as4 we should to check aspath things when
1541 * aspath synthesizing with as4_path has already taken place.
1542 * Otherwise we check ASPATH and use the synthesized thing, and that is
1544 * So do the checks later, i.e. here
1546 struct aspath
*aspath
;
1548 /* Confederation sanity check. */
1549 if ((peer
->sort
== BGP_PEER_CONFED
1550 && !aspath_left_confed_check(attr
->aspath
))
1551 || (peer
->sort
== BGP_PEER_EBGP
1552 && aspath_confed_check(attr
->aspath
))) {
1553 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1555 return BGP_ATTR_PARSE_WITHDRAW
;
1558 /* First AS check for EBGP. */
1559 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1560 if (peer
->sort
== BGP_PEER_EBGP
1561 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1562 flog_err(EC_BGP_ATTR_FIRST_AS
,
1563 "%s incorrect first AS (must be %u)",
1564 peer
->host
, peer
->as
);
1565 return BGP_ATTR_PARSE_WITHDRAW
;
1569 /* Codification of AS 0 Processing */
1570 if (peer
->sort
== BGP_PEER_EBGP
&& aspath_check_as_zero(attr
->aspath
)) {
1572 EC_BGP_ATTR_MAL_AS_PATH
,
1573 "Malformed AS path, AS number is 0 in the path from %s",
1575 return BGP_ATTR_PARSE_WITHDRAW
;
1578 /* local-as prepend */
1579 if (peer
->change_local_as
1580 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1581 aspath
= aspath_dup(attr
->aspath
);
1582 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1583 aspath_unintern(&attr
->aspath
);
1584 attr
->aspath
= aspath_intern(aspath
);
1587 return BGP_ATTR_PARSE_PROCEED
;
1590 /* Parse AS4 path information. This function is another wrapper of
1592 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1593 struct aspath
**as4_path
)
1595 struct peer
*const peer
= args
->peer
;
1596 struct attr
*const attr
= args
->attr
;
1597 const bgp_size_t length
= args
->length
;
1599 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1601 /* In case of IBGP, length will be zero. */
1603 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1604 "Malformed AS4 path from %s, length is %d", peer
->host
,
1606 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1610 /* Set aspath attribute flag. */
1611 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1613 return BGP_ATTR_PARSE_PROCEED
;
1617 * Check that the nexthop attribute is valid.
1619 bgp_attr_parse_ret_t
1620 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1622 in_addr_t nexthop_h
;
1624 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1625 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1626 || IPV4_CLASS_DE(nexthop_h
))
1627 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1628 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1629 char buf
[INET_ADDRSTRLEN
];
1631 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1633 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1635 data
[0] = BGP_ATTR_FLAG_TRANS
;
1636 data
[1] = BGP_ATTR_NEXT_HOP
;
1637 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1638 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1639 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1640 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1642 return BGP_ATTR_PARSE_ERROR
;
1645 return BGP_ATTR_PARSE_PROCEED
;
1648 /* Nexthop attribute. */
1649 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1651 struct peer
*const peer
= args
->peer
;
1652 struct attr
*const attr
= args
->attr
;
1653 const bgp_size_t length
= args
->length
;
1655 /* Check nexthop attribute length. */
1657 flog_err(EC_BGP_ATTR_LEN
,
1658 "Nexthop attribute length isn't four [%d]", length
);
1660 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1664 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1665 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1667 return BGP_ATTR_PARSE_PROCEED
;
1670 /* MED atrribute. */
1671 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1673 struct peer
*const peer
= args
->peer
;
1674 struct attr
*const attr
= args
->attr
;
1675 const bgp_size_t length
= args
->length
;
1679 flog_err(EC_BGP_ATTR_LEN
,
1680 "MED attribute length isn't four [%d]", length
);
1682 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1686 attr
->med
= stream_getl(peer
->curr
);
1688 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1690 return BGP_ATTR_PARSE_PROCEED
;
1693 /* Local preference attribute. */
1694 static bgp_attr_parse_ret_t
1695 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1697 struct peer
*const peer
= args
->peer
;
1698 struct attr
*const attr
= args
->attr
;
1699 const bgp_size_t length
= args
->length
;
1701 /* if received from an internal neighbor, it SHALL be considered
1702 * malformed if its length is not equal to 4. If malformed, the
1703 * UPDATE message SHALL be handled using the approach of "treat-as-
1706 if (peer
->sort
== BGP_PEER_IBGP
&& length
!= 4) {
1707 flog_err(EC_BGP_ATTR_LEN
,
1708 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1709 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1713 /* If it is contained in an UPDATE message that is received from an
1714 external peer, then this attribute MUST be ignored by the
1715 receiving speaker. */
1716 if (peer
->sort
== BGP_PEER_EBGP
) {
1717 STREAM_FORWARD_GETP(peer
->curr
, length
);
1718 return BGP_ATTR_PARSE_PROCEED
;
1721 STREAM_GETL(peer
->curr
, attr
->local_pref
);
1723 /* Set the local-pref flag. */
1724 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1726 return BGP_ATTR_PARSE_PROCEED
;
1729 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1733 /* Atomic aggregate. */
1734 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1736 struct attr
*const attr
= args
->attr
;
1737 const bgp_size_t length
= args
->length
;
1741 flog_err(EC_BGP_ATTR_LEN
,
1742 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1744 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1748 /* Set atomic aggregate flag. */
1749 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1751 return BGP_ATTR_PARSE_PROCEED
;
1754 /* Aggregator attribute */
1755 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1757 struct peer
*const peer
= args
->peer
;
1758 struct attr
*const attr
= args
->attr
;
1759 const bgp_size_t length
= args
->length
;
1764 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1765 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
1766 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
))
1769 if (length
!= wantedlen
) {
1770 flog_err(EC_BGP_ATTR_LEN
,
1771 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1773 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1777 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1778 aggregator_as
= stream_getl(peer
->curr
);
1780 aggregator_as
= stream_getw(peer
->curr
);
1782 attr
->aggregator_as
= aggregator_as
;
1783 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1785 /* Codification of AS 0 Processing */
1786 if (aggregator_as
== BGP_AS_ZERO
) {
1787 flog_err(EC_BGP_ATTR_LEN
,
1788 "%s: AGGREGATOR AS number is 0 for aspath: %s",
1789 peer
->host
, aspath_print(attr
->aspath
));
1791 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1792 char attr_str
[BUFSIZ
] = {0};
1794 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1796 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1799 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1802 return BGP_ATTR_PARSE_PROCEED
;
1805 /* New Aggregator attribute */
1806 static bgp_attr_parse_ret_t
1807 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1808 as_t
*as4_aggregator_as
,
1809 struct in_addr
*as4_aggregator_addr
)
1811 struct peer
*const peer
= args
->peer
;
1812 struct attr
*const attr
= args
->attr
;
1813 const bgp_size_t length
= args
->length
;
1817 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1819 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1823 aggregator_as
= stream_getl(peer
->curr
);
1825 *as4_aggregator_as
= aggregator_as
;
1826 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1828 /* Codification of AS 0 Processing */
1829 if (aggregator_as
== BGP_AS_ZERO
) {
1830 flog_err(EC_BGP_ATTR_LEN
,
1831 "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1832 peer
->host
, aspath_print(attr
->aspath
));
1834 if (bgp_debug_update(peer
, NULL
, NULL
, 1)) {
1835 char attr_str
[BUFSIZ
] = {0};
1837 bgp_dump_attr(attr
, attr_str
, sizeof(attr_str
));
1839 zlog_debug("%s: attributes: %s", __func__
, attr_str
);
1842 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1845 return BGP_ATTR_PARSE_PROCEED
;
1848 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1850 static bgp_attr_parse_ret_t
1851 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1852 struct aspath
*as4_path
, as_t as4_aggregator
,
1853 struct in_addr
*as4_aggregator_addr
)
1855 int ignore_as4_path
= 0;
1856 struct aspath
*newpath
;
1858 if (!attr
->aspath
) {
1859 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1861 * checked that all well-known, mandatory attributes were
1864 * Can only be a problem with peer itself - hard error
1866 return BGP_ATTR_PARSE_ERROR
;
1869 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1870 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1872 * It is worth a warning though, because the peer really
1873 * should not send them
1875 if (BGP_DEBUG(as4
, AS4
)) {
1876 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1877 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1878 "AS4 capable peer, yet it sent");
1881 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1882 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1884 "AS4 capable peer, yet it sent");
1887 return BGP_ATTR_PARSE_PROCEED
;
1890 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1891 * because that may override AS4_PATH
1893 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1894 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1896 * if the as_number in aggregator is not AS_TRANS,
1897 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1898 * and the Aggregator shall be taken as
1899 * info on the aggregating node, and the AS_PATH
1900 * shall be taken as the AS_PATH
1902 * the Aggregator shall be ignored and the
1903 * AS4_AGGREGATOR shall be taken as the
1904 * Aggregating node and the AS_PATH is to be
1905 * constructed "as in all other cases"
1907 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1909 if (BGP_DEBUG(as4
, AS4
))
1911 "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
1913 ignore_as4_path
= 1;
1915 /* "New_aggregator shall be taken as aggregator"
1917 attr
->aggregator_as
= as4_aggregator
;
1918 attr
->aggregator_addr
.s_addr
=
1919 as4_aggregator_addr
->s_addr
;
1922 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1923 * That is bogus - but reading the conditions
1924 * we have to handle AS4_AGGREGATOR as if it were
1925 * AGGREGATOR in that case
1927 if (BGP_DEBUG(as4
, AS4
))
1929 "[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",
1931 attr
->aggregator_as
= as4_aggregator
;
1932 /* sweep it under the carpet and simulate a "good"
1934 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1938 /* need to reconcile NEW_AS_PATH and AS_PATH */
1939 if (!ignore_as4_path
1940 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1941 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1943 return BGP_ATTR_PARSE_ERROR
;
1945 aspath_unintern(&attr
->aspath
);
1946 attr
->aspath
= aspath_intern(newpath
);
1948 return BGP_ATTR_PARSE_PROCEED
;
1951 /* Community attribute. */
1952 static bgp_attr_parse_ret_t
1953 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1955 struct peer
*const peer
= args
->peer
;
1956 struct attr
*const attr
= args
->attr
;
1957 const bgp_size_t length
= args
->length
;
1960 attr
->community
= NULL
;
1961 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1966 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1968 /* XXX: fix community_parse to use stream API and remove this */
1969 stream_forward_getp(peer
->curr
, length
);
1971 /* The Community attribute SHALL be considered malformed if its
1972 * length is not a non-zero multiple of 4.
1974 if (!attr
->community
)
1975 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1978 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1980 return BGP_ATTR_PARSE_PROCEED
;
1983 /* Originator ID attribute. */
1984 static bgp_attr_parse_ret_t
1985 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1987 struct peer
*const peer
= args
->peer
;
1988 struct attr
*const attr
= args
->attr
;
1989 const bgp_size_t length
= args
->length
;
1991 /* if received from an internal neighbor, it SHALL be considered
1992 * malformed if its length is not equal to 4. If malformed, the
1993 * UPDATE message SHALL be handled using the approach of "treat-as-
1997 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
2000 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2004 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
2006 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2008 return BGP_ATTR_PARSE_PROCEED
;
2011 /* Cluster list attribute. */
2012 static bgp_attr_parse_ret_t
2013 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
2015 struct peer
*const peer
= args
->peer
;
2016 struct attr
*const attr
= args
->attr
;
2017 const bgp_size_t length
= args
->length
;
2019 /* if received from an internal neighbor, it SHALL be considered
2020 * malformed if its length is not a non-zero multiple of 4. If
2021 * malformed, the UPDATE message SHALL be handled using the approach
2022 * of "treat-as-withdraw".
2024 if (length
== 0 || length
% 4) {
2025 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
2027 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2031 bgp_attr_set_cluster(
2032 attr
, cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
),
2035 /* XXX: Fix cluster_parse to use stream API and then remove this */
2036 stream_forward_getp(peer
->curr
, length
);
2038 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
2040 return BGP_ATTR_PARSE_PROCEED
;
2043 /* Multiprotocol reachability information parse. */
2044 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
2045 struct bgp_nlri
*mp_update
)
2049 iana_safi_t pkt_safi
;
2051 bgp_size_t nlri_len
;
2054 struct peer
*const peer
= args
->peer
;
2055 struct attr
*const attr
= args
->attr
;
2056 const bgp_size_t length
= args
->length
;
2058 /* Set end of packet. */
2059 s
= BGP_INPUT(peer
);
2060 start
= stream_get_getp(s
);
2062 /* safe to read statically sized header? */
2063 #define BGP_MP_REACH_MIN_SIZE 5
2064 #define LEN_LEFT (length - (stream_get_getp(s) - start))
2065 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
2066 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2067 __func__
, peer
->host
, (unsigned long)length
);
2068 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2071 /* Load AFI, SAFI. */
2072 pkt_afi
= stream_getw(s
);
2073 pkt_safi
= stream_getc(s
);
2075 /* Convert AFI, SAFI to internal values, check. */
2076 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2077 /* Log if AFI or SAFI is unrecognized. This is not an error
2079 * the attribute is otherwise malformed.
2081 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2083 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2084 peer
->host
, iana_afi2str(pkt_afi
),
2085 iana_safi2str(pkt_safi
));
2086 return BGP_ATTR_PARSE_ERROR
;
2089 /* Get nexthop length. */
2090 attr
->mp_nexthop_len
= stream_getc(s
);
2092 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
2094 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2095 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2096 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2099 /* Nexthop length check. */
2100 switch (attr
->mp_nexthop_len
) {
2102 if (safi
!= SAFI_FLOWSPEC
) {
2103 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2104 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2105 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2108 case BGP_ATTR_NHLEN_VPNV4
:
2109 stream_getl(s
); /* RD high */
2110 stream_getl(s
); /* RD low */
2112 * NOTE: intentional fall through
2113 * - for consistency in rx processing
2115 * The following comment is to signal GCC this intention
2116 * and suppress the warning
2119 case BGP_ATTR_NHLEN_IPV4
:
2120 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
2121 /* Probably needed for RFC 2283 */
2122 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
2123 memcpy(&attr
->nexthop
.s_addr
,
2124 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
2126 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2127 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2128 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
2129 stream_getl(s
); /* RD high */
2130 stream_getl(s
); /* RD low */
2132 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2133 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2134 if (!peer
->nexthop
.ifp
) {
2135 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2137 return BGP_ATTR_PARSE_WITHDRAW
;
2139 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2142 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2143 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
2144 if (attr
->mp_nexthop_len
2145 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2146 stream_getl(s
); /* RD high */
2147 stream_getl(s
); /* RD low */
2149 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
2150 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2151 if (!peer
->nexthop
.ifp
) {
2152 zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2154 return BGP_ATTR_PARSE_WITHDRAW
;
2156 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2158 if (attr
->mp_nexthop_len
2159 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
2160 stream_getl(s
); /* RD high */
2161 stream_getl(s
); /* RD low */
2163 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
2164 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
2165 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2167 "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2168 peer
->host
, &attr
->mp_nexthop_global
,
2169 &attr
->mp_nexthop_local
);
2171 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
2173 if (!peer
->nexthop
.ifp
) {
2174 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2176 return BGP_ATTR_PARSE_WITHDRAW
;
2178 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
2181 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2182 __func__
, peer
->host
, attr
->mp_nexthop_len
);
2183 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2187 zlog_info("%s: %s sent SNPA which couldn't be read",
2188 __func__
, peer
->host
);
2189 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2194 if ((val
= stream_getc(s
)))
2196 EC_BGP_DEFUNCT_SNPA_LEN
,
2197 "%s sent non-zero value, %u, for defunct SNPA-length field",
2201 /* must have nrli_len, what is left of the attribute */
2202 nlri_len
= LEN_LEFT
;
2203 if (nlri_len
> STREAM_READABLE(s
)) {
2204 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2205 __func__
, peer
->host
);
2206 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2210 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2211 __func__
, peer
->host
);
2213 mp_update
->afi
= afi
;
2214 mp_update
->safi
= safi
;
2215 return BGP_ATTR_PARSE_EOR
;
2218 mp_update
->afi
= afi
;
2219 mp_update
->safi
= safi
;
2220 mp_update
->nlri
= stream_pnt(s
);
2221 mp_update
->length
= nlri_len
;
2223 stream_forward_getp(s
, nlri_len
);
2225 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
2227 return BGP_ATTR_PARSE_PROCEED
;
2231 /* Multiprotocol unreachable parse */
2232 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
2233 struct bgp_nlri
*mp_withdraw
)
2238 iana_safi_t pkt_safi
;
2240 uint16_t withdraw_len
;
2241 struct peer
*const peer
= args
->peer
;
2242 struct attr
*const attr
= args
->attr
;
2243 const bgp_size_t length
= args
->length
;
2247 #define BGP_MP_UNREACH_MIN_SIZE 3
2248 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
2249 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
2251 pkt_afi
= stream_getw(s
);
2252 pkt_safi
= stream_getc(s
);
2254 /* Convert AFI, SAFI to internal values, check. */
2255 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
2256 /* Log if AFI or SAFI is unrecognized. This is not an error
2258 * the attribute is otherwise malformed.
2260 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
2262 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2263 peer
->host
, iana_afi2str(pkt_afi
),
2264 iana_safi2str(pkt_safi
));
2265 return BGP_ATTR_PARSE_ERROR
;
2268 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
2270 mp_withdraw
->afi
= afi
;
2271 mp_withdraw
->safi
= safi
;
2272 mp_withdraw
->nlri
= stream_pnt(s
);
2273 mp_withdraw
->length
= withdraw_len
;
2275 stream_forward_getp(s
, withdraw_len
);
2277 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
2279 return BGP_ATTR_PARSE_PROCEED
;
2282 /* Large Community attribute. */
2283 static bgp_attr_parse_ret_t
2284 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
2286 struct peer
*const peer
= args
->peer
;
2287 struct attr
*const attr
= args
->attr
;
2288 const bgp_size_t length
= args
->length
;
2291 * Large community follows new attribute format.
2294 attr
->lcommunity
= NULL
;
2295 /* Empty extcomm doesn't seem to be invalid per se */
2296 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2300 attr
->lcommunity
= lcommunity_parse(stream_pnt(peer
->curr
), length
);
2301 /* XXX: fix ecommunity_parse to use stream API */
2302 stream_forward_getp(peer
->curr
, length
);
2304 if (!attr
->lcommunity
)
2305 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2308 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
2310 return BGP_ATTR_PARSE_PROCEED
;
2313 /* Extended Community attribute. */
2314 static bgp_attr_parse_ret_t
2315 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
2317 struct peer
*const peer
= args
->peer
;
2318 struct attr
*const attr
= args
->attr
;
2319 const bgp_size_t length
= args
->length
;
2324 attr
->ecommunity
= NULL
;
2325 /* Empty extcomm doesn't seem to be invalid per se */
2326 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2330 attr
->ecommunity
= ecommunity_parse(
2331 stream_pnt(peer
->curr
), length
,
2332 CHECK_FLAG(peer
->flags
,
2333 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2334 /* XXX: fix ecommunity_parse to use stream API */
2335 stream_forward_getp(peer
->curr
, length
);
2337 /* The Extended Community attribute SHALL be considered malformed if
2338 * its length is not a non-zero multiple of 8.
2340 if (!attr
->ecommunity
)
2341 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2344 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2346 /* Extract DF election preference and mobility sequence number */
2347 attr
->df_pref
= bgp_attr_df_pref_from_ec(attr
, &attr
->df_alg
);
2349 /* Extract MAC mobility sequence number, if any. */
2350 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
2351 attr
->sticky
= sticky
;
2353 /* Check if this is a Gateway MAC-IP advertisement */
2354 attr
->default_gw
= bgp_attr_default_gw(attr
);
2356 /* Handle scenario where router flag ecommunity is not
2357 * set but default gw ext community is present.
2358 * Use default gateway, set and propogate R-bit.
2360 if (attr
->default_gw
)
2361 attr
->router_flag
= 1;
2363 /* Check EVPN Neighbor advertisement flags, R-bit */
2364 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
, &proxy
);
2366 attr
->es_flags
|= ATTR_ES_PROXY_ADVERT
;
2368 /* Extract the Rmac, if any */
2369 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
2370 if (bgp_debug_update(peer
, NULL
, NULL
, 1)
2371 && bgp_mac_exist(&attr
->rmac
))
2372 zlog_debug("%s: router mac %pEA is self mac", __func__
,
2376 /* Get the tunnel type from encap extended community */
2377 bgp_attr_extcom_tunnel_type(attr
,
2378 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2380 /* Extract link bandwidth, if any. */
2381 (void)ecommunity_linkbw_present(attr
->ecommunity
, &attr
->link_bw
);
2383 return BGP_ATTR_PARSE_PROCEED
;
2386 /* IPv6 Extended Community attribute. */
2387 static bgp_attr_parse_ret_t
2388 bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args
*args
)
2390 struct peer
*const peer
= args
->peer
;
2391 struct attr
*const attr
= args
->attr
;
2392 const bgp_size_t length
= args
->length
;
2393 struct ecommunity
*ipv6_ecomm
= NULL
;
2396 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2397 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2401 ipv6_ecomm
= ecommunity_parse_ipv6(
2402 stream_pnt(peer
->curr
), length
,
2403 CHECK_FLAG(peer
->flags
,
2404 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE
));
2405 bgp_attr_set_ipv6_ecommunity(attr
, ipv6_ecomm
);
2407 /* XXX: fix ecommunity_parse to use stream API */
2408 stream_forward_getp(peer
->curr
, length
);
2411 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2414 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES
);
2416 return BGP_ATTR_PARSE_PROCEED
;
2419 /* Parse Tunnel Encap attribute in an UPDATE */
2420 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2421 bgp_size_t length
, /* IN: attr's length field */
2422 struct attr
*attr
, /* IN: caller already allocated */
2423 uint8_t flag
, /* IN: attr's flags field */
2427 uint16_t tunneltype
= 0;
2429 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2431 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2432 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2434 "Tunnel Encap attribute flag isn't optional and transitive %d",
2436 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2437 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2442 if (BGP_ATTR_ENCAP
== type
) {
2443 /* read outer TLV type and length */
2444 uint16_t tlv_length
;
2448 "Tunnel Encap attribute not long enough to contain outer T,L");
2449 bgp_notify_send_with_data(
2450 peer
, BGP_NOTIFY_UPDATE_ERR
,
2451 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2454 tunneltype
= stream_getw(BGP_INPUT(peer
));
2455 tlv_length
= stream_getw(BGP_INPUT(peer
));
2458 if (tlv_length
!= length
) {
2459 zlog_info("%s: tlv_length(%d) != length(%d)",
2460 __func__
, tlv_length
, length
);
2464 while (length
>= 4) {
2465 uint16_t subtype
= 0;
2466 uint16_t sublength
= 0;
2467 struct bgp_attr_encap_subtlv
*tlv
;
2469 if (BGP_ATTR_ENCAP
== type
) {
2470 subtype
= stream_getc(BGP_INPUT(peer
));
2471 sublength
= stream_getc(BGP_INPUT(peer
));
2473 #ifdef ENABLE_BGP_VNC
2475 subtype
= stream_getw(BGP_INPUT(peer
));
2476 sublength
= stream_getw(BGP_INPUT(peer
));
2481 if (sublength
> length
) {
2483 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2485 bgp_notify_send_with_data(
2486 peer
, BGP_NOTIFY_UPDATE_ERR
,
2487 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2491 /* alloc and copy sub-tlv */
2492 /* TBD make sure these are freed when attributes are released */
2493 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2494 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2495 tlv
->type
= subtype
;
2496 tlv
->length
= sublength
;
2497 stream_get(tlv
->value
, peer
->curr
, sublength
);
2498 length
-= sublength
;
2500 /* attach tlv to encap chain */
2501 if (BGP_ATTR_ENCAP
== type
) {
2502 struct bgp_attr_encap_subtlv
*stlv_last
;
2503 for (stlv_last
= attr
->encap_subtlvs
;
2504 stlv_last
&& stlv_last
->next
;
2505 stlv_last
= stlv_last
->next
)
2508 stlv_last
->next
= tlv
;
2510 attr
->encap_subtlvs
= tlv
;
2512 #ifdef ENABLE_BGP_VNC
2514 struct bgp_attr_encap_subtlv
*stlv_last
;
2515 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
2516 bgp_attr_get_vnc_subtlvs(attr
);
2518 for (stlv_last
= vnc_subtlvs
;
2519 stlv_last
&& stlv_last
->next
;
2520 stlv_last
= stlv_last
->next
)
2523 stlv_last
->next
= tlv
;
2525 bgp_attr_set_vnc_subtlvs(attr
, tlv
);
2530 if (BGP_ATTR_ENCAP
== type
) {
2531 attr
->encap_tunneltype
= tunneltype
;
2535 /* spurious leftover data */
2537 "Tunnel Encap attribute length is bad: %d leftover octets",
2539 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2540 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2549 /* SRv6 Service Data Sub-Sub-TLV attribute
2550 * draft-ietf-bess-srv6-services-07
2552 static bgp_attr_parse_ret_t
2553 bgp_attr_srv6_service_data(struct bgp_attr_parser_args
*args
)
2555 struct peer
*const peer
= args
->peer
;
2556 struct attr
*const attr
= args
->attr
;
2557 uint8_t type
, loc_block_len
, loc_node_len
, func_len
, arg_len
,
2558 transposition_len
, transposition_offset
;
2560 size_t headersz
= sizeof(type
) + sizeof(length
);
2562 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2565 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2566 headersz
, STREAM_READABLE(peer
->curr
));
2567 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2571 type
= stream_getc(peer
->curr
);
2572 length
= stream_getw(peer
->curr
);
2574 if (STREAM_READABLE(peer
->curr
) < length
) {
2577 "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2578 length
, STREAM_READABLE(peer
->curr
));
2579 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2583 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
) {
2584 loc_block_len
= stream_getc(peer
->curr
);
2585 loc_node_len
= stream_getc(peer
->curr
);
2586 func_len
= stream_getc(peer
->curr
);
2587 arg_len
= stream_getc(peer
->curr
);
2588 transposition_len
= stream_getc(peer
->curr
);
2589 transposition_offset
= stream_getc(peer
->curr
);
2591 /* Log SRv6 Service Data Sub-Sub-TLV */
2592 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2594 "%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",
2595 __func__
, loc_block_len
, loc_node_len
, func_len
,
2596 arg_len
, transposition_len
,
2597 transposition_offset
);
2600 attr
->srv6_l3vpn
->loc_block_len
= loc_block_len
;
2601 attr
->srv6_l3vpn
->loc_node_len
= loc_node_len
;
2602 attr
->srv6_l3vpn
->func_len
= func_len
;
2603 attr
->srv6_l3vpn
->arg_len
= arg_len
;
2604 attr
->srv6_l3vpn
->transposition_len
= transposition_len
;
2605 attr
->srv6_l3vpn
->transposition_offset
= transposition_offset
;
2609 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2611 "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2614 stream_forward_getp(peer
->curr
, length
);
2617 return BGP_ATTR_PARSE_PROCEED
;
2620 /* SRv6 Service Sub-TLV attribute
2621 * draft-ietf-bess-srv6-services-07
2623 static bgp_attr_parse_ret_t
2624 bgp_attr_srv6_service(struct bgp_attr_parser_args
*args
)
2626 struct peer
*const peer
= args
->peer
;
2627 struct attr
*const attr
= args
->attr
;
2628 struct in6_addr ipv6_sid
;
2629 uint8_t type
, sid_flags
;
2630 uint16_t length
, endpoint_behavior
;
2631 size_t headersz
= sizeof(type
) + sizeof(length
);
2632 bgp_attr_parse_ret_t err
;
2635 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2638 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2639 headersz
, STREAM_READABLE(peer
->curr
));
2640 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2644 type
= stream_getc(peer
->curr
);
2645 length
= stream_getw(peer
->curr
);
2647 if (STREAM_READABLE(peer
->curr
) < length
) {
2650 "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2651 length
, STREAM_READABLE(peer
->curr
));
2652 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2656 if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
) {
2657 stream_getc(peer
->curr
);
2658 stream_get(&ipv6_sid
, peer
->curr
, sizeof(ipv6_sid
));
2659 sid_flags
= stream_getc(peer
->curr
);
2660 endpoint_behavior
= stream_getw(peer
->curr
);
2661 stream_getc(peer
->curr
);
2663 /* Log SRv6 Service Sub-TLV */
2664 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2665 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2667 "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
2668 __func__
, buf
, sid_flags
, endpoint_behavior
);
2671 /* Configure from Info */
2672 if (attr
->srv6_l3vpn
) {
2673 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2674 "Prefix SID SRv6 L3VPN field repeated");
2675 return bgp_attr_malformed(
2676 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2678 attr
->srv6_l3vpn
= XCALLOC(MTYPE_BGP_SRV6_L3VPN
,
2679 sizeof(struct bgp_attr_srv6_l3vpn
));
2680 sid_copy(&attr
->srv6_l3vpn
->sid
, &ipv6_sid
);
2681 attr
->srv6_l3vpn
->sid_flags
= sid_flags
;
2682 attr
->srv6_l3vpn
->endpoint_behavior
= endpoint_behavior
;
2683 attr
->srv6_l3vpn
->loc_block_len
= 0;
2684 attr
->srv6_l3vpn
->loc_node_len
= 0;
2685 attr
->srv6_l3vpn
->func_len
= 0;
2686 attr
->srv6_l3vpn
->arg_len
= 0;
2687 attr
->srv6_l3vpn
->transposition_len
= 0;
2688 attr
->srv6_l3vpn
->transposition_offset
= 0;
2690 // Sub-Sub-TLV found
2691 if (length
> BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
) {
2692 err
= bgp_attr_srv6_service_data(args
);
2694 if (err
!= BGP_ATTR_PARSE_PROCEED
)
2698 attr
->srv6_l3vpn
= srv6_l3vpn_intern(attr
->srv6_l3vpn
);
2701 /* Placeholder code for unsupported type */
2703 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2705 "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2708 stream_forward_getp(peer
->curr
, length
);
2711 return BGP_ATTR_PARSE_PROCEED
;
2715 * Read an individual SID value returning how much data we have read
2716 * Returns 0 if there was an error that needs to be passed up the stack
2718 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(uint8_t type
, uint16_t length
,
2719 struct bgp_attr_parser_args
*args
)
2721 struct peer
*const peer
= args
->peer
;
2722 struct attr
*const attr
= args
->attr
;
2723 uint32_t label_index
;
2724 struct in6_addr ipv6_sid
;
2726 uint32_t srgb_range
;
2728 uint8_t sid_type
, sid_flags
;
2731 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2732 if (STREAM_READABLE(peer
->curr
) < length
2733 || length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2734 flog_err(EC_BGP_ATTR_LEN
,
2735 "Prefix SID label index length is %hu instead of %u",
2736 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2737 return bgp_attr_malformed(args
,
2738 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2742 /* Ignore flags and reserved */
2743 stream_getc(peer
->curr
);
2744 stream_getw(peer
->curr
);
2746 /* Fetch the label index and see if it is valid. */
2747 label_index
= stream_getl(peer
->curr
);
2748 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2749 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2752 /* Store label index; subsequently, we'll check on
2754 attr
->label_index
= label_index
;
2757 /* Placeholder code for the IPv6 SID type */
2758 else if (type
== BGP_PREFIX_SID_IPV6
) {
2759 if (STREAM_READABLE(peer
->curr
) < length
2760 || length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2761 flog_err(EC_BGP_ATTR_LEN
,
2762 "Prefix SID IPv6 length is %hu instead of %u",
2763 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2764 return bgp_attr_malformed(args
,
2765 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2769 /* Ignore reserved */
2770 stream_getc(peer
->curr
);
2771 stream_getw(peer
->curr
);
2773 stream_get(&ipv6_sid
, peer
->curr
, 16);
2776 /* Placeholder code for the Originator SRGB type */
2777 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2779 * ietf-idr-bgp-prefix-sid-05:
2780 * Length is the total length of the value portion of the
2781 * TLV: 2 + multiple of 6.
2783 * peer->curr stream readp should be at the beginning of the 16
2784 * bit flag field at this point in the code.
2788 * Check that the TLV length field is sane: at least 2 bytes of
2789 * flag, and at least 1 SRGB (these are 6 bytes each)
2791 if (length
< (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
)) {
2794 "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
2796 2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2797 return bgp_attr_malformed(
2798 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2803 * Check that we actually have at least as much data as
2804 * specified by the length field
2806 if (STREAM_READABLE(peer
->curr
) < length
) {
2807 flog_err(EC_BGP_ATTR_LEN
,
2808 "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
2809 length
, STREAM_READABLE(peer
->curr
));
2810 return bgp_attr_malformed(
2811 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2816 * Check that the portion of the TLV containing the sequence of
2817 * SRGBs corresponds to a multiple of the SRGB size; to get
2818 * that length, we skip the 16 bit flags field
2820 stream_getw(peer
->curr
);
2822 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2825 "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
2826 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2827 return bgp_attr_malformed(
2828 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2832 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2834 for (int i
= 0; i
< srgb_count
; i
++) {
2835 stream_get(&srgb_base
, peer
->curr
, 3);
2836 stream_get(&srgb_range
, peer
->curr
, 3);
2840 /* Placeholder code for the VPN-SID Service type */
2841 else if (type
== BGP_PREFIX_SID_VPN_SID
) {
2842 if (STREAM_READABLE(peer
->curr
) < length
2843 || length
!= BGP_PREFIX_SID_VPN_SID_LENGTH
) {
2844 flog_err(EC_BGP_ATTR_LEN
,
2845 "Prefix SID VPN SID length is %hu instead of %u",
2846 length
, BGP_PREFIX_SID_VPN_SID_LENGTH
);
2847 return bgp_attr_malformed(args
,
2848 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2852 /* Parse VPN-SID Sub-TLV */
2853 stream_getc(peer
->curr
); /* reserved */
2854 sid_type
= stream_getc(peer
->curr
); /* sid_type */
2855 sid_flags
= stream_getc(peer
->curr
); /* sid_flags */
2856 stream_get(&ipv6_sid
, peer
->curr
,
2857 sizeof(ipv6_sid
)); /* sid_value */
2859 /* Log VPN-SID Sub-TLV */
2860 if (BGP_DEBUG(vpn
, VPN_LEAK_LABEL
)) {
2861 inet_ntop(AF_INET6
, &ipv6_sid
, buf
, sizeof(buf
));
2863 "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
2864 __func__
, buf
, sid_type
, sid_flags
);
2867 /* Configure from Info */
2868 if (attr
->srv6_vpn
) {
2869 flog_err(EC_BGP_ATTRIBUTE_REPEATED
,
2870 "Prefix SID SRv6 VPN field repeated");
2871 return bgp_attr_malformed(
2872 args
, BGP_NOTIFY_UPDATE_MAL_ATTR
, args
->total
);
2874 attr
->srv6_vpn
= XCALLOC(MTYPE_BGP_SRV6_VPN
,
2875 sizeof(struct bgp_attr_srv6_vpn
));
2876 attr
->srv6_vpn
->sid_flags
= sid_flags
;
2877 sid_copy(&attr
->srv6_vpn
->sid
, &ipv6_sid
);
2878 attr
->srv6_vpn
= srv6_vpn_intern(attr
->srv6_vpn
);
2881 /* Placeholder code for the SRv6 L3 Service type */
2882 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
) {
2883 if (STREAM_READABLE(peer
->curr
) < length
) {
2886 "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
2887 length
, STREAM_READABLE(peer
->curr
));
2888 return bgp_attr_malformed(args
,
2889 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2893 /* ignore reserved */
2894 stream_getc(peer
->curr
);
2896 return bgp_attr_srv6_service(args
);
2899 /* Placeholder code for Unsupported TLV */
2902 if (STREAM_READABLE(peer
->curr
) < length
) {
2905 "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
2906 length
, STREAM_READABLE(peer
->curr
));
2907 return bgp_attr_malformed(
2908 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2912 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2914 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2917 stream_forward_getp(peer
->curr
, length
);
2920 return BGP_ATTR_PARSE_PROCEED
;
2923 /* Prefix SID attribute
2924 * draft-ietf-idr-bgp-prefix-sid-05
2926 bgp_attr_parse_ret_t
bgp_attr_prefix_sid(struct bgp_attr_parser_args
*args
)
2928 struct peer
*const peer
= args
->peer
;
2929 struct attr
*const attr
= args
->attr
;
2930 bgp_attr_parse_ret_t ret
;
2932 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2936 size_t headersz
= sizeof(type
) + sizeof(length
);
2937 size_t psid_parsed_length
= 0;
2939 while (STREAM_READABLE(peer
->curr
) > 0
2940 && psid_parsed_length
< args
->length
) {
2942 if (STREAM_READABLE(peer
->curr
) < headersz
) {
2945 "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2946 headersz
, STREAM_READABLE(peer
->curr
));
2947 return bgp_attr_malformed(
2948 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2952 type
= stream_getc(peer
->curr
);
2953 length
= stream_getw(peer
->curr
);
2955 if (STREAM_READABLE(peer
->curr
) < length
) {
2958 "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
2959 length
, STREAM_READABLE(peer
->curr
));
2960 return bgp_attr_malformed(args
,
2961 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2965 ret
= bgp_attr_psid_sub(type
, length
, args
);
2967 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2970 psid_parsed_length
+= length
+ headersz
;
2972 if (psid_parsed_length
> args
->length
) {
2975 "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
2976 length
+ headersz
, psid_parsed_length
- (length
+ headersz
));
2977 return bgp_attr_malformed(
2978 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2983 return BGP_ATTR_PARSE_PROCEED
;
2986 /* PMSI tunnel attribute (RFC 6514)
2987 * Basic validation checks done here.
2989 static bgp_attr_parse_ret_t
2990 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2992 struct peer
*const peer
= args
->peer
;
2993 struct attr
*const attr
= args
->attr
;
2994 const bgp_size_t length
= args
->length
;
2996 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2998 /* Verify that the receiver is expecting "ingress replication" as we
2999 * can only support that.
3001 if (length
< attr_parse_len
) {
3002 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
3004 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3007 stream_getc(peer
->curr
); /* Flags */
3008 tnl_type
= stream_getc(peer
->curr
);
3009 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
3010 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
3011 "Invalid PMSI tunnel attribute type %d", tnl_type
);
3012 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
3015 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
3017 flog_err(EC_BGP_ATTR_PMSI_LEN
,
3018 "Bad PMSI tunnel attribute length %d for IR",
3020 return bgp_attr_malformed(
3021 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
3026 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
3027 bgp_attr_set_pmsi_tnl_type(attr
, tnl_type
);
3028 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
3030 /* Forward read pointer of input stream. */
3031 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
3033 return BGP_ATTR_PARSE_PROCEED
;
3036 /* BGP unknown attribute treatment. */
3037 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
3039 bgp_size_t total
= args
->total
;
3040 struct transit
*transit
;
3041 struct peer
*const peer
= args
->peer
;
3042 struct attr
*const attr
= args
->attr
;
3043 uint8_t *const startp
= args
->startp
;
3044 const uint8_t type
= args
->type
;
3045 const uint8_t flag
= args
->flags
;
3046 const bgp_size_t length
= args
->length
;
3048 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3050 "%s Unknown attribute is received (type %d, length %d)",
3051 peer
->host
, type
, length
);
3053 /* Forward read pointer of input stream. */
3054 stream_forward_getp(peer
->curr
, length
);
3056 /* If any of the mandatory well-known attributes are not recognized,
3057 then the Error Subcode is set to Unrecognized Well-known
3058 Attribute. The Data field contains the unrecognized attribute
3059 (type, length and value). */
3060 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
3061 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
3065 /* Unrecognized non-transitive optional attributes must be quietly
3066 ignored and not passed along to other BGP peers. */
3067 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
3068 return BGP_ATTR_PARSE_PROCEED
;
3070 /* If a path with recognized transitive optional attribute is
3071 accepted and passed along to other BGP peers and the Partial bit
3072 in the Attribute Flags octet is set to 1 by some previous AS, it
3073 is not set back to 0 by the current AS. */
3074 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
3076 /* Store transitive attribute to the end of attr->transit. */
3077 transit
= bgp_attr_get_transit(attr
);
3079 transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
3081 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
3082 transit
->length
+ total
);
3084 memcpy(transit
->val
+ transit
->length
, startp
, total
);
3085 transit
->length
+= total
;
3086 bgp_attr_set_transit(attr
, transit
);
3088 return BGP_ATTR_PARSE_PROCEED
;
3091 /* Well-known attribute check. */
3092 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
3096 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3098 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
3099 return BGP_ATTR_PARSE_PROCEED
;
3101 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3102 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3103 are present, it should. Check for any other attribute being present
3106 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
3107 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
3108 return BGP_ATTR_PARSE_PROCEED
;
3110 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
3111 type
= BGP_ATTR_ORIGIN
;
3113 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
3114 type
= BGP_ATTR_AS_PATH
;
3116 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3118 * NLRI is empty. We can't easily check NLRI empty here though.
3120 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3121 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
3122 type
= BGP_ATTR_NEXT_HOP
;
3124 if (peer
->sort
== BGP_PEER_IBGP
3125 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
3126 type
= BGP_ATTR_LOCAL_PREF
;
3128 /* If any of the well-known mandatory attributes are not present
3129 * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3132 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
3133 "%s Missing well-known attribute %s.", peer
->host
,
3134 lookup_msg(attr_str
, type
, NULL
));
3135 return BGP_ATTR_PARSE_WITHDRAW
;
3137 return BGP_ATTR_PARSE_PROCEED
;
3140 /* Read attribute of update packet. This function is called from
3141 bgp_update_receive() in bgp_packet.c. */
3142 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
3143 bgp_size_t size
, struct bgp_nlri
*mp_update
,
3144 struct bgp_nlri
*mp_withdraw
)
3146 bgp_attr_parse_ret_t ret
;
3150 uint8_t *startp
, *endp
;
3152 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
3153 /* we need the as4_path only until we have synthesized the as_path with
3155 /* same goes for as4_aggregator */
3156 struct aspath
*as4_path
= NULL
;
3157 as_t as4_aggregator
= 0;
3158 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
3159 struct transit
*transit
;
3161 /* Initialize bitmap. */
3162 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
3164 /* End pointer of BGP attribute. */
3165 endp
= BGP_INPUT_PNT(peer
) + size
;
3167 /* Get attributes to the end of attribute length. */
3168 while (BGP_INPUT_PNT(peer
) < endp
) {
3169 /* Check remaining length check.*/
3170 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
3171 /* XXX warning: long int format, int arg (arg 5) */
3173 EC_BGP_ATTRIBUTE_TOO_SMALL
,
3174 "%s: error BGP attribute length %lu is smaller than min len",
3176 (unsigned long)(endp
3177 - stream_pnt(BGP_INPUT(peer
))));
3179 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3180 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3181 ret
= BGP_ATTR_PARSE_ERROR
;
3185 /* Fetch attribute flag and type. */
3186 startp
= BGP_INPUT_PNT(peer
);
3187 /* "The lower-order four bits of the Attribute Flags octet are
3188 unused. They MUST be zero when sent and MUST be ignored when
3190 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
3191 type
= stream_getc(BGP_INPUT(peer
));
3193 /* Check whether Extended-Length applies and is in bounds */
3194 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
3195 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
3197 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
3198 "%s: Extended length set, but just %lu bytes of attr header",
3200 (unsigned long)(endp
3201 - stream_pnt(BGP_INPUT(peer
))));
3203 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3204 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3205 ret
= BGP_ATTR_PARSE_ERROR
;
3209 /* Check extended attribue length bit. */
3210 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
3211 length
= stream_getw(BGP_INPUT(peer
));
3213 length
= stream_getc(BGP_INPUT(peer
));
3215 /* If any attribute appears more than once in the UPDATE
3216 message, then the Error Subcode is set to Malformed Attribute
3219 if (CHECK_BITMAP(seen
, type
)) {
3221 EC_BGP_ATTRIBUTE_REPEATED
,
3222 "%s: error BGP attribute type %d appears twice in a message",
3225 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3226 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3227 ret
= BGP_ATTR_PARSE_ERROR
;
3231 /* Set type to bitmap to check duplicate attribute. `type' is
3232 unsigned char so it never overflow bitmap range. */
3234 SET_BITMAP(seen
, type
);
3236 /* Overflow check. */
3237 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
3239 if (attr_endp
> endp
) {
3241 EC_BGP_ATTRIBUTE_TOO_LARGE
,
3242 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
3243 peer
->host
, type
, length
, size
, attr_endp
,
3247 * If any recognized attribute has an Attribute
3248 * Length that conflicts with the expected length
3249 * (based on the attribute type code), then the
3250 * Error Subcode MUST be set to Attribute Length
3251 * Error. The Data field MUST contain the erroneous
3252 * attribute (type, length, and value).
3254 * We do not currently have a good way to determine the
3255 * length of the attribute independent of the length
3256 * received in the message. Instead we send the
3257 * minimum between the amount of data we have and the
3258 * amount specified by the attribute length field.
3260 * Instead of directly passing in the packet buffer and
3261 * offset we use the stream_get* functions to read into
3262 * a stack buffer, since they perform bounds checking
3263 * and we are working with untrusted data.
3265 unsigned char ndata
[peer
->max_packet_size
];
3266 memset(ndata
, 0x00, sizeof(ndata
));
3268 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
3269 /* Rewind to end of flag field */
3270 stream_rewind_getp(BGP_INPUT(peer
), (1 + lfl
));
3272 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
3274 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
3276 size_t atl
= attr_endp
- startp
;
3277 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
3278 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
3280 bgp_notify_send_with_data(
3281 peer
, BGP_NOTIFY_UPDATE_ERR
,
3282 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
3285 ret
= BGP_ATTR_PARSE_ERROR
;
3289 struct bgp_attr_parser_args attr_args
= {
3296 .total
= attr_endp
- startp
,
3300 /* If any recognized attribute has Attribute Flags that conflict
3301 with the Attribute Type Code, then the Error Subcode is set
3303 Attribute Flags Error. The Data field contains the erroneous
3304 attribute (type, length and value). */
3305 if (bgp_attr_flag_invalid(&attr_args
)) {
3306 ret
= bgp_attr_malformed(
3307 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
3309 if (ret
== BGP_ATTR_PARSE_PROCEED
)
3314 /* OK check attribute and store it's value. */
3316 case BGP_ATTR_ORIGIN
:
3317 ret
= bgp_attr_origin(&attr_args
);
3319 case BGP_ATTR_AS_PATH
:
3320 ret
= bgp_attr_aspath(&attr_args
);
3322 case BGP_ATTR_AS4_PATH
:
3323 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
3325 case BGP_ATTR_NEXT_HOP
:
3326 ret
= bgp_attr_nexthop(&attr_args
);
3328 case BGP_ATTR_MULTI_EXIT_DISC
:
3329 ret
= bgp_attr_med(&attr_args
);
3331 case BGP_ATTR_LOCAL_PREF
:
3332 ret
= bgp_attr_local_pref(&attr_args
);
3334 case BGP_ATTR_ATOMIC_AGGREGATE
:
3335 ret
= bgp_attr_atomic(&attr_args
);
3337 case BGP_ATTR_AGGREGATOR
:
3338 ret
= bgp_attr_aggregator(&attr_args
);
3340 case BGP_ATTR_AS4_AGGREGATOR
:
3341 ret
= bgp_attr_as4_aggregator(&attr_args
,
3343 &as4_aggregator_addr
);
3345 case BGP_ATTR_COMMUNITIES
:
3346 ret
= bgp_attr_community(&attr_args
);
3348 case BGP_ATTR_LARGE_COMMUNITIES
:
3349 ret
= bgp_attr_large_community(&attr_args
);
3351 case BGP_ATTR_ORIGINATOR_ID
:
3352 ret
= bgp_attr_originator_id(&attr_args
);
3354 case BGP_ATTR_CLUSTER_LIST
:
3355 ret
= bgp_attr_cluster_list(&attr_args
);
3357 case BGP_ATTR_MP_REACH_NLRI
:
3358 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
3360 case BGP_ATTR_MP_UNREACH_NLRI
:
3361 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
3363 case BGP_ATTR_EXT_COMMUNITIES
:
3364 ret
= bgp_attr_ext_communities(&attr_args
);
3366 #ifdef ENABLE_BGP_VNC_ATTR
3369 case BGP_ATTR_ENCAP
:
3370 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
3373 case BGP_ATTR_PREFIX_SID
:
3374 ret
= bgp_attr_prefix_sid(&attr_args
);
3376 case BGP_ATTR_PMSI_TUNNEL
:
3377 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
3379 case BGP_ATTR_IPV6_EXT_COMMUNITIES
:
3380 ret
= bgp_attr_ipv6_ext_communities(&attr_args
);
3383 ret
= bgp_attr_unknown(&attr_args
);
3387 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
3388 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3389 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3390 ret
= BGP_ATTR_PARSE_ERROR
;
3394 if (ret
== BGP_ATTR_PARSE_EOR
) {
3398 if (ret
== BGP_ATTR_PARSE_ERROR
) {
3399 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
3400 "%s: Attribute %s, parse error", peer
->host
,
3401 lookup_msg(attr_str
, type
, NULL
));
3404 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
3406 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
3407 "%s: Attribute %s, parse error - treating as withdrawal",
3408 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3412 /* Check the fetched length. */
3413 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
3414 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
3415 "%s: BGP attribute %s, fetch error",
3416 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
3417 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3418 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3419 ret
= BGP_ATTR_PARSE_ERROR
;
3425 * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3426 * About Prefix-SID path attribute,
3427 * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3428 * may only appear in a BGP Prefix-SID attribute attached to
3429 * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3430 * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3432 if (!attr
->mp_nexthop_len
|| mp_update
->safi
!= SAFI_LABELED_UNICAST
)
3433 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
3435 /* Check final read pointer is same as end pointer. */
3436 if (BGP_INPUT_PNT(peer
) != endp
) {
3437 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
3438 "%s: BGP attribute %s, length mismatch", peer
->host
,
3439 lookup_msg(attr_str
, type
, NULL
));
3440 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3441 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
3443 ret
= BGP_ATTR_PARSE_ERROR
;
3448 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3449 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3450 * This is implemented below and will result in a NOTIFICATION. If the
3451 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3452 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3453 * message SHOULD NOT be sent. This is implemented elsewhere.
3455 * RFC4760: An UPDATE message that carries no NLRI, other than the one
3456 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3457 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3458 * speaker that receives the message SHOULD ignore this attribute.
3460 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
3461 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
3462 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
3463 ret
= BGP_ATTR_PARSE_ERROR
;
3468 /* Check all mandatory well-known attributes are present */
3469 ret
= bgp_attr_check(peer
, attr
);
3474 * At this place we can see whether we got AS4_PATH and/or
3475 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3476 * We can not do this before we've read all attributes because
3477 * the as4 handling does not say whether AS4_PATH has to be sent
3478 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3479 * in relationship to AGGREGATOR.
3480 * So, to be defensive, we are not relying on any order and read
3481 * all attributes first, including these 32bit ones, and now,
3482 * afterwards, we look what and if something is to be done for as4.
3484 * It is possible to not have AS_PATH, e.g. GR EoR and sole
3487 /* actually... this doesn't ever return failure currently, but
3488 * better safe than sorry */
3489 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
3490 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
3491 &as4_aggregator_addr
)) {
3492 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
3493 BGP_NOTIFY_UPDATE_MAL_ATTR
);
3494 ret
= BGP_ATTR_PARSE_ERROR
;
3499 * Finally do the checks on the aspath we did not do yet
3500 * because we waited for a potentially synthesized aspath.
3502 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
3503 ret
= bgp_attr_aspath_check(peer
, attr
);
3504 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
3508 ret
= BGP_ATTR_PARSE_PROCEED
;
3512 * At this stage, we have done all fiddling with as4, and the
3513 * resulting info is in attr->aggregator resp. attr->aspath so
3514 * we can chuck as4_aggregator and as4_path alltogether in order
3519 * unintern - it is in the hash
3520 * The flag that we got this is still there, but that
3521 * does not do any trouble
3523 aspath_unintern(&as4_path
);
3526 transit
= bgp_attr_get_transit(attr
);
3527 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
3528 /* Finally intern unknown attribute. */
3530 bgp_attr_set_transit(attr
, transit_intern(transit
));
3531 if (attr
->encap_subtlvs
)
3532 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
3534 #ifdef ENABLE_BGP_VNC
3535 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3536 bgp_attr_get_vnc_subtlvs(attr
);
3539 bgp_attr_set_vnc_subtlvs(
3541 encap_intern(vnc_subtlvs
, VNC_SUBTLV_TYPE
));
3545 transit_free(transit
);
3546 bgp_attr_set_transit(attr
, NULL
);
3549 bgp_attr_flush_encap(attr
);
3553 transit
= bgp_attr_get_transit(attr
);
3555 assert(transit
->refcnt
> 0);
3556 if (attr
->encap_subtlvs
)
3557 assert(attr
->encap_subtlvs
->refcnt
> 0);
3558 #ifdef ENABLE_BGP_VNC
3559 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
3560 bgp_attr_get_vnc_subtlvs(attr
);
3563 assert(vnc_subtlvs
->refcnt
> 0);
3570 * Extract the tunnel type from extended community
3572 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
3573 bgp_encap_types
*tunnel_type
)
3575 struct ecommunity
*ecom
;
3581 ecom
= attr
->ecommunity
;
3582 if (!ecom
|| !ecom
->size
)
3585 for (i
= 0; i
< ecom
->size
; i
++) {
3587 uint8_t type
, sub_type
;
3589 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
3592 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
3593 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
3595 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
3602 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
3603 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
3608 iana_safi_t pkt_safi
;
3611 /* Set extended bit always to encode the attribute length as 2 bytes */
3612 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3613 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3614 sizep
= stream_get_endp(s
);
3615 stream_putw(s
, 0); /* Marker: Attribute length. */
3618 /* Convert AFI, SAFI to values for packet. */
3619 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3621 stream_putw(s
, pkt_afi
); /* AFI */
3622 stream_putc(s
, pkt_safi
); /* SAFI */
3626 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
3627 || safi
== SAFI_MPLS_VPN
|| safi
== SAFI_MULTICAST
))
3628 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
3629 else if (safi
== SAFI_FLOWSPEC
)
3632 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3635 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
3640 case SAFI_MULTICAST
:
3641 case SAFI_LABELED_UNICAST
:
3643 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3647 stream_putl(s
, 0); /* RD = 0, per RFC */
3649 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3654 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
3657 if (attr
->mp_nexthop_len
== 0)
3658 stream_putc(s
, 0); /* no nexthop for flowspec */
3660 stream_putc(s
, attr
->mp_nexthop_len
);
3661 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3670 case SAFI_MULTICAST
:
3671 case SAFI_LABELED_UNICAST
:
3673 if (attr
->mp_nexthop_len
3674 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3676 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
3677 stream_put(s
, &attr
->mp_nexthop_global
,
3679 stream_put(s
, &attr
->mp_nexthop_local
,
3682 stream_putc(s
, IPV6_MAX_BYTELEN
);
3683 stream_put(s
, &attr
->mp_nexthop_global
,
3687 case SAFI_MPLS_VPN
: {
3688 if (attr
->mp_nexthop_len
3689 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
3691 stream_putl(s
, 0); /* RD = 0, per RFC */
3693 stream_put(s
, &attr
->mp_nexthop_global
,
3695 } else if (attr
->mp_nexthop_len
3696 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
3698 stream_putl(s
, 0); /* RD = 0, per RFC */
3700 stream_put(s
, &attr
->mp_nexthop_global
,
3702 stream_putl(s
, 0); /* RD = 0, per RFC */
3704 stream_put(s
, &attr
->mp_nexthop_local
,
3709 stream_putc(s
, IPV6_MAX_BYTELEN
);
3710 stream_put(s
, &attr
->mp_nexthop_global
,
3714 stream_putc(s
, 0); /* no nexthop for flowspec */
3720 if (safi
!= SAFI_FLOWSPEC
)
3722 EC_BGP_ATTR_NH_SEND_LEN
,
3723 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3724 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3733 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3734 const struct prefix
*p
,
3735 const struct prefix_rd
*prd
, mpls_label_t
*label
,
3736 uint32_t num_labels
, int addpath_encode
,
3737 uint32_t addpath_tx_id
, struct attr
*attr
)
3739 if (safi
== SAFI_MPLS_VPN
) {
3741 stream_putl(s
, addpath_tx_id
);
3742 /* Label, RD, Prefix write. */
3743 stream_putc(s
, p
->prefixlen
+ 88);
3744 stream_put(s
, label
, BGP_LABEL_BYTES
);
3745 stream_put(s
, prd
->val
, 8);
3746 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3747 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3748 /* EVPN prefix - contents depend on type */
3749 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3750 addpath_encode
, addpath_tx_id
);
3751 } else if (safi
== SAFI_LABELED_UNICAST
) {
3752 /* Prefix write with label. */
3753 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3755 } else if (safi
== SAFI_FLOWSPEC
) {
3756 stream_putc(s
, p
->u
.prefix_flowspec
.prefixlen
);
3757 stream_put(s
, (const void *)p
->u
.prefix_flowspec
.ptr
,
3758 p
->u
.prefix_flowspec
.prefixlen
);
3760 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3763 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
,
3764 const struct prefix
*p
)
3766 int size
= PSIZE(p
->prefixlen
);
3767 if (safi
== SAFI_MPLS_VPN
)
3769 else if (safi
== SAFI_LABELED_UNICAST
)
3770 size
+= BGP_LABEL_BYTES
;
3771 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3772 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3778 * Encodes the tunnel encapsulation attribute,
3779 * and with ENABLE_BGP_VNC the VNC attribute which uses
3780 * almost the same TLV format
3782 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3783 struct stream
*s
, struct attr
*attr
,
3786 unsigned int attrlenfield
= 0;
3787 unsigned int attrhdrlen
= 0;
3788 struct bgp_attr_encap_subtlv
*subtlvs
;
3789 struct bgp_attr_encap_subtlv
*st
;
3790 const char *attrname
;
3792 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3793 && (!attr
->encap_tunneltype
3794 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3798 case BGP_ATTR_ENCAP
:
3799 attrname
= "Tunnel Encap";
3800 subtlvs
= attr
->encap_subtlvs
;
3801 if (subtlvs
== NULL
) /* nothing to do */
3804 * The tunnel encap attr has an "outer" tlv.
3806 * L = total length of subtlvs,
3807 * V = concatenated subtlvs.
3809 attrlenfield
= 2 + 2; /* T + L */
3810 attrhdrlen
= 1 + 1; /* subTLV T + L */
3813 #ifdef ENABLE_BGP_VNC_ATTR
3816 subtlvs
= bgp_attr_get_vnc_subtlvs(attr
);
3817 if (subtlvs
== NULL
) /* nothing to do */
3819 attrlenfield
= 0; /* no outer T + L */
3820 attrhdrlen
= 2 + 2; /* subTLV T + L */
3828 /* compute attr length */
3829 for (st
= subtlvs
; st
; st
= st
->next
) {
3830 attrlenfield
+= (attrhdrlen
+ st
->length
);
3833 if (attrlenfield
> 0xffff) {
3834 zlog_info("%s attribute is too long (length=%d), can't send it",
3835 attrname
, attrlenfield
);
3839 if (attrlenfield
> 0xff) {
3840 /* 2-octet length field */
3842 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3843 | BGP_ATTR_FLAG_EXTLEN
);
3844 stream_putc(s
, attrtype
);
3845 stream_putw(s
, attrlenfield
& 0xffff);
3847 /* 1-octet length field */
3848 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3849 stream_putc(s
, attrtype
);
3850 stream_putc(s
, attrlenfield
& 0xff);
3853 if (attrtype
== BGP_ATTR_ENCAP
) {
3854 /* write outer T+L */
3855 stream_putw(s
, attr
->encap_tunneltype
);
3856 stream_putw(s
, attrlenfield
- 4);
3859 /* write each sub-tlv */
3860 for (st
= subtlvs
; st
; st
= st
->next
) {
3861 if (attrtype
== BGP_ATTR_ENCAP
) {
3862 stream_putc(s
, st
->type
);
3863 stream_putc(s
, st
->length
);
3864 #ifdef ENABLE_BGP_VNC
3866 stream_putw(s
, st
->type
);
3867 stream_putw(s
, st
->length
);
3870 stream_put(s
, st
->value
, st
->length
);
3874 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3876 /* Set MP attribute length. Don't count the (2) bytes used to encode
3878 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3881 static bool bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3883 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3884 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3885 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3886 PEER_FLAG_REMOVE_PRIVATE_AS
)
3887 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3888 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3889 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3890 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3891 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3892 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3897 /* Make attribute packet. */
3898 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3899 struct stream
*s
, struct attr
*attr
,
3900 struct bpacket_attr_vec_arr
*vecarr
,
3901 struct prefix
*p
, afi_t afi
, safi_t safi
,
3902 struct peer
*from
, struct prefix_rd
*prd
,
3903 mpls_label_t
*label
, uint32_t num_labels
,
3904 int addpath_encode
, uint32_t addpath_tx_id
)
3907 size_t aspath_sizep
;
3908 struct aspath
*aspath
;
3909 int send_as4_path
= 0;
3910 int send_as4_aggregator
= 0;
3911 bool use32bit
= CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)
3912 && CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_ADV
);
3917 /* Remember current pointer. */
3918 cp
= stream_get_endp(s
);
3921 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3922 && !peer_cap_enhe(peer
, afi
, safi
))) {
3923 size_t mpattrlen_pos
= 0;
3925 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3927 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3928 num_labels
, addpath_encode
,
3929 addpath_tx_id
, attr
);
3930 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3933 /* Origin attribute. */
3934 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3935 stream_putc(s
, BGP_ATTR_ORIGIN
);
3937 stream_putc(s
, attr
->origin
);
3939 /* AS path attribute. */
3941 /* If remote-peer is EBGP */
3942 if (peer
->sort
== BGP_PEER_EBGP
3943 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3944 PEER_FLAG_AS_PATH_UNCHANGED
)
3945 || attr
->aspath
->segments
== NULL
)
3946 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3947 PEER_FLAG_RSERVER_CLIENT
))) {
3948 aspath
= aspath_dup(attr
->aspath
);
3950 /* Even though we may not be configured for confederations we
3952 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3953 aspath
= aspath_delete_confed_seq(aspath
);
3955 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3956 /* Stuff our path CONFED_ID on the front */
3957 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3959 if (peer
->change_local_as
) {
3960 /* If replace-as is specified, we only use the
3961 change_local_as when
3962 advertising routes. */
3963 if (!CHECK_FLAG(peer
->flags
,
3964 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3965 if (bgp_append_local_as(peer
, afi
,
3967 aspath
= aspath_add_seq(
3968 aspath
, peer
->local_as
);
3969 aspath
= aspath_add_seq(aspath
,
3970 peer
->change_local_as
);
3972 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3975 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3976 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3978 aspath
= aspath_dup(attr
->aspath
);
3979 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3981 aspath
= attr
->aspath
;
3983 /* If peer is not AS4 capable, then:
3984 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3985 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3987 * types are in it (i.e. exclude them if they are there)
3988 * AND do this only if there is at least one asnum > 65535 in the
3990 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3992 * all ASnums > 65535 to BGP_AS_TRANS
3995 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3996 stream_putc(s
, BGP_ATTR_AS_PATH
);
3997 aspath_sizep
= stream_get_endp(s
);
3999 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
4001 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4004 if (!use32bit
&& aspath_has_as4(aspath
))
4006 1; /* we'll do this later, at the correct place */
4008 /* Nexthop attribute. */
4009 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
4010 && !peer_cap_enhe(peer
, afi
, safi
)) {
4011 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
4013 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
4014 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4015 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4016 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4019 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4020 } else if (peer_cap_enhe(from
, afi
, safi
)
4021 || (nh_afi
== AFI_IP6
)) {
4023 * Likely this is the case when an IPv4 prefix was
4024 * received with Extended Next-hop capability in this
4025 * or another vrf and is now being advertised to
4026 * non-ENHE peers. Since peer_cap_enhe only checks
4027 * peers in this vrf, also check the nh_afi to catch
4028 * the case where the originator was in another vrf.
4029 * Setting the mandatory (ipv4) next-hop attribute here
4030 * to enable implicit next-hop self with correct A-F
4031 * (ipv4 address family).
4033 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4034 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4035 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
4038 stream_put_ipv4(s
, 0);
4042 /* MED attribute. */
4043 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
4044 || bgp
->maxmed_active
) {
4045 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4046 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4048 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
4052 /* Local preference. */
4053 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
4054 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4055 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4057 stream_putl(s
, attr
->local_pref
);
4060 /* Atomic aggregate. */
4061 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4062 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4063 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4068 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4069 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4070 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4071 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4074 /* AS4 capable peer */
4076 stream_putl(s
, attr
->aggregator_as
);
4078 /* 2-byte AS peer */
4081 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4083 if (attr
->aggregator_as
> UINT16_MAX
) {
4084 stream_putw(s
, BGP_AS_TRANS
);
4086 /* we have to send AS4_AGGREGATOR, too.
4087 * we'll do that later in order to send
4088 * attributes in ascending
4091 send_as4_aggregator
= 1;
4093 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
4095 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4098 /* Community attribute. */
4099 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
4100 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
4101 if (attr
->community
->size
* 4 > 255) {
4103 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4104 | BGP_ATTR_FLAG_EXTLEN
);
4105 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4106 stream_putw(s
, attr
->community
->size
* 4);
4109 BGP_ATTR_FLAG_OPTIONAL
4110 | BGP_ATTR_FLAG_TRANS
);
4111 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4112 stream_putc(s
, attr
->community
->size
* 4);
4114 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4118 * Large Community attribute.
4120 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
4121 PEER_FLAG_SEND_LARGE_COMMUNITY
)
4122 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
4123 if (lcom_length(attr
->lcommunity
) > 255) {
4125 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4126 | BGP_ATTR_FLAG_EXTLEN
);
4127 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4128 stream_putw(s
, lcom_length(attr
->lcommunity
));
4131 BGP_ATTR_FLAG_OPTIONAL
4132 | BGP_ATTR_FLAG_TRANS
);
4133 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4134 stream_putc(s
, lcom_length(attr
->lcommunity
));
4136 stream_put(s
, attr
->lcommunity
->val
,
4137 lcom_length(attr
->lcommunity
));
4140 /* Route Reflector. */
4141 if (peer
->sort
== BGP_PEER_IBGP
&& from
4142 && from
->sort
== BGP_PEER_IBGP
) {
4143 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
4145 /* Originator ID. */
4146 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4147 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
4150 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
4151 stream_put_in_addr(s
, &attr
->originator_id
);
4153 stream_put_in_addr(s
, &from
->remote_id
);
4156 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4157 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
4160 stream_putc(s
, cluster
->length
+ 4);
4161 /* If this peer configuration's parent BGP has
4163 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4164 stream_put_in_addr(s
, &bgp
->cluster_id
);
4166 stream_put_in_addr(s
, &bgp
->router_id
);
4167 stream_put(s
, cluster
->list
, cluster
->length
);
4170 /* If this peer configuration's parent BGP has
4172 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
4173 stream_put_in_addr(s
, &bgp
->cluster_id
);
4175 stream_put_in_addr(s
, &bgp
->router_id
);
4179 /* Extended Communities attribute. */
4180 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
4181 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
4182 if (peer
->sort
== BGP_PEER_IBGP
4183 || peer
->sort
== BGP_PEER_CONFED
) {
4184 if (attr
->ecommunity
->size
* 8 > 255) {
4186 BGP_ATTR_FLAG_OPTIONAL
4187 | BGP_ATTR_FLAG_TRANS
4188 | BGP_ATTR_FLAG_EXTLEN
);
4189 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4190 stream_putw(s
, attr
->ecommunity
->size
* 8);
4193 BGP_ATTR_FLAG_OPTIONAL
4194 | BGP_ATTR_FLAG_TRANS
);
4195 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
4196 stream_putc(s
, attr
->ecommunity
->size
* 8);
4198 stream_put(s
, attr
->ecommunity
->val
,
4199 attr
->ecommunity
->size
* 8);
4203 int ecom_tr_size
= 0;
4206 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
4207 pnt
= attr
->ecommunity
->val
+ (i
* 8);
4210 if (CHECK_FLAG(tbit
,
4211 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4218 if (ecom_tr_size
* 8 > 255) {
4221 BGP_ATTR_FLAG_OPTIONAL
4222 | BGP_ATTR_FLAG_TRANS
4223 | BGP_ATTR_FLAG_EXTLEN
);
4225 BGP_ATTR_EXT_COMMUNITIES
);
4226 stream_putw(s
, ecom_tr_size
* 8);
4230 BGP_ATTR_FLAG_OPTIONAL
4231 | BGP_ATTR_FLAG_TRANS
);
4233 BGP_ATTR_EXT_COMMUNITIES
);
4234 stream_putc(s
, ecom_tr_size
* 8);
4237 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
4238 pnt
= attr
->ecommunity
->val
+ (i
* 8);
4243 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
4246 stream_put(s
, pnt
, 8);
4252 /* Label index attribute. */
4253 if (safi
== SAFI_LABELED_UNICAST
) {
4254 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4255 uint32_t label_index
;
4257 label_index
= attr
->label_index
;
4259 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
4261 BGP_ATTR_FLAG_OPTIONAL
4262 | BGP_ATTR_FLAG_TRANS
);
4263 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4265 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4267 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4268 stream_putc(s
, 0); // reserved
4269 stream_putw(s
, 0); // flags
4270 stream_putl(s
, label_index
);
4275 /* SRv6 Service Information Attribute. */
4276 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && safi
== SAFI_MPLS_VPN
) {
4277 if (attr
->srv6_l3vpn
) {
4278 uint8_t subtlv_len
=
4279 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4281 + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH
;
4282 uint8_t tlv_len
= subtlv_len
+ BGP_ATTR_MIN_LEN
+ 1;
4283 uint8_t attr_len
= tlv_len
+ BGP_ATTR_MIN_LEN
;
4284 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4285 | BGP_ATTR_FLAG_TRANS
);
4286 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4287 stream_putc(s
, attr_len
);
4288 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE
);
4289 stream_putw(s
, tlv_len
);
4290 stream_putc(s
, 0); /* reserved */
4291 stream_putc(s
, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO
);
4292 stream_putw(s
, subtlv_len
);
4293 stream_putc(s
, 0); /* reserved */
4294 stream_put(s
, &attr
->srv6_l3vpn
->sid
,
4295 sizeof(attr
->srv6_l3vpn
->sid
)); /* sid */
4296 stream_putc(s
, 0); /* sid_flags */
4297 stream_putw(s
, 0xffff); /* endpoint */
4298 stream_putc(s
, 0); /* reserved */
4301 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE
);
4304 BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
);
4305 stream_putc(s
, attr
->srv6_l3vpn
->loc_block_len
);
4306 stream_putc(s
, attr
->srv6_l3vpn
->loc_node_len
);
4307 stream_putc(s
, attr
->srv6_l3vpn
->func_len
);
4308 stream_putc(s
, attr
->srv6_l3vpn
->arg_len
);
4309 stream_putc(s
, attr
->srv6_l3vpn
->transposition_len
);
4310 stream_putc(s
, attr
->srv6_l3vpn
->transposition_offset
);
4311 } else if (attr
->srv6_vpn
) {
4312 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
4313 | BGP_ATTR_FLAG_TRANS
);
4314 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4315 stream_putc(s
, 22); /* tlv len */
4316 stream_putc(s
, BGP_PREFIX_SID_VPN_SID
);
4317 stream_putw(s
, 0x13); /* tlv len */
4318 stream_putc(s
, 0x00); /* reserved */
4319 stream_putc(s
, 0x01); /* sid_type */
4320 stream_putc(s
, 0x00); /* sif_flags */
4321 stream_put(s
, &attr
->srv6_vpn
->sid
,
4322 sizeof(attr
->srv6_vpn
->sid
)); /* sid */
4326 if (send_as4_path
) {
4327 /* If the peer is NOT As4 capable, AND */
4328 /* there are ASnums > 65535 in path THEN
4329 * give out AS4_PATH */
4331 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4333 * Hm, I wonder... confederation things *should* only be at
4334 * the beginning of an aspath, right? Then we should use
4335 * aspath_delete_confed_seq for this, because it is already
4337 * Folks, talk to me: what is reasonable here!?
4339 aspath
= aspath_delete_confed_seq(aspath
);
4342 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
4343 | BGP_ATTR_FLAG_EXTLEN
);
4344 stream_putc(s
, BGP_ATTR_AS4_PATH
);
4345 aspath_sizep
= stream_get_endp(s
);
4347 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
4350 if (aspath
!= attr
->aspath
)
4351 aspath_free(aspath
);
4353 if (send_as4_aggregator
) {
4354 /* send AS4_AGGREGATOR, at this place */
4355 /* this section of code moved here in order to ensure the
4357 * *ascending* order of attributes
4359 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4360 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
4362 stream_putl(s
, attr
->aggregator_as
);
4363 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4366 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4367 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
4368 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
4369 /* Tunnel Encap attribute */
4370 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
4372 #ifdef ENABLE_BGP_VNC_ATTR
4374 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
4379 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
4380 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4381 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
4382 stream_putc(s
, 9); // Length
4383 stream_putc(s
, 0); // Flags
4384 stream_putc(s
, bgp_attr_get_pmsi_tnl_type(attr
));
4385 stream_put(s
, &(attr
->label
),
4386 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
4387 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4388 // Unicast tunnel endpoint IP address
4391 /* Unknown transit attribute. */
4392 struct transit
*transit
= bgp_attr_get_transit(attr
);
4395 stream_put(s
, transit
->val
, transit
->length
);
4397 /* Return total size of attribute. */
4398 return stream_get_endp(s
) - cp
;
4401 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
4403 unsigned long attrlen_pnt
;
4405 iana_safi_t pkt_safi
;
4407 /* Set extended bit always to encode the attribute length as 2 bytes */
4408 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
4409 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
4411 attrlen_pnt
= stream_get_endp(s
);
4412 stream_putw(s
, 0); /* Length of this attribute. */
4414 /* Convert AFI, SAFI to values for packet. */
4415 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
4417 stream_putw(s
, pkt_afi
);
4418 stream_putc(s
, pkt_safi
);
4423 void bgp_packet_mpunreach_prefix(struct stream
*s
, const struct prefix
*p
,
4424 afi_t afi
, safi_t safi
,
4425 const struct prefix_rd
*prd
,
4426 mpls_label_t
*label
, uint32_t num_labels
,
4427 int addpath_encode
, uint32_t addpath_tx_id
,
4430 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
4432 if (safi
== SAFI_LABELED_UNICAST
) {
4433 label
= (mpls_label_t
*)wlabel
;
4437 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
4438 addpath_encode
, addpath_tx_id
, attr
);
4441 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
4443 bgp_packet_mpattr_end(s
, attrlen_pnt
);
4446 /* Initialization of attribute. */
4447 void bgp_attr_init(void)
4460 void bgp_attr_finish(void)
4465 ecommunity_finish();
4466 lcommunity_finish();
4473 /* Make attribute packet. */
4474 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
4475 const struct prefix
*prefix
)
4480 struct aspath
*aspath
;
4481 int addpath_encode
= 0;
4482 uint32_t addpath_tx_id
= 0;
4484 /* Remember current pointer. */
4485 cp
= stream_get_endp(s
);
4487 /* Place holder of length. */
4490 /* Origin attribute. */
4491 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4492 stream_putc(s
, BGP_ATTR_ORIGIN
);
4494 stream_putc(s
, attr
->origin
);
4496 aspath
= attr
->aspath
;
4498 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
4499 stream_putc(s
, BGP_ATTR_AS_PATH
);
4500 aspath_lenp
= stream_get_endp(s
);
4503 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
4505 /* Nexthop attribute. */
4506 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4507 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
4508 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4509 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
4511 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
4514 /* MED attribute. */
4515 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
4516 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4517 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
4519 stream_putl(s
, attr
->med
);
4522 /* Local preference. */
4523 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
4524 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4525 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
4527 stream_putl(s
, attr
->local_pref
);
4530 /* Atomic aggregate. */
4531 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
4532 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
4533 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
4538 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
4539 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
4540 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
4542 stream_putl(s
, attr
->aggregator_as
);
4543 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
4546 /* Community attribute. */
4547 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
4548 if (attr
->community
->size
* 4 > 255) {
4550 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4551 | BGP_ATTR_FLAG_EXTLEN
);
4552 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4553 stream_putw(s
, attr
->community
->size
* 4);
4556 BGP_ATTR_FLAG_OPTIONAL
4557 | BGP_ATTR_FLAG_TRANS
);
4558 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
4559 stream_putc(s
, attr
->community
->size
* 4);
4561 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
4564 /* Large Community attribute. */
4565 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
4566 if (lcom_length(attr
->lcommunity
) > 255) {
4568 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
4569 | BGP_ATTR_FLAG_EXTLEN
);
4570 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4571 stream_putw(s
, lcom_length(attr
->lcommunity
));
4574 BGP_ATTR_FLAG_OPTIONAL
4575 | BGP_ATTR_FLAG_TRANS
);
4576 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
4577 stream_putc(s
, lcom_length(attr
->lcommunity
));
4580 stream_put(s
, attr
->lcommunity
->val
,
4581 lcom_length(attr
->lcommunity
));
4584 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4585 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
4586 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
4587 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
4590 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
4591 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
4592 sizep
= stream_get_endp(s
);
4595 stream_putc(s
, 0); /* Marker: Attribute length. */
4596 stream_putw(s
, AFI_IP6
); /* AFI */
4597 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
4600 stream_putc(s
, attr
->mp_nexthop_len
);
4601 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
4602 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
4603 stream_put(s
, &attr
->mp_nexthop_local
,
4610 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
4613 /* Set MP attribute length. */
4614 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
4618 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
4619 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4621 BGP_ATTR_FLAG_OPTIONAL
4622 | BGP_ATTR_FLAG_TRANS
);
4623 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
4625 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
4626 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
4627 stream_putc(s
, 0); // reserved
4628 stream_putw(s
, 0); // flags
4629 stream_putl(s
, attr
->label_index
);
4633 /* Return total size of attribute. */
4634 len
= stream_get_endp(s
) - cp
- 2;
4635 stream_putw_at(s
, cp
, len
);