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
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_aspath.h"
40 #include "bgpd/bgp_community.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_errors.h"
43 #include "bgpd/bgp_label.h"
44 #include "bgpd/bgp_packet.h"
45 #include "bgpd/bgp_ecommunity.h"
46 #include "bgpd/bgp_lcommunity.h"
47 #include "bgpd/bgp_updgrp.h"
48 #include "bgpd/bgp_encap_types.h"
50 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
51 #include "bgp_encap_types.h"
52 #include "bgp_vnc_types.h"
55 #include "bgp_flowspec_private.h"
58 /* Attribute strings for logging. */
59 static const struct message attr_str
[] = {
60 {BGP_ATTR_ORIGIN
, "ORIGIN"},
61 {BGP_ATTR_AS_PATH
, "AS_PATH"},
62 {BGP_ATTR_NEXT_HOP
, "NEXT_HOP"},
63 {BGP_ATTR_MULTI_EXIT_DISC
, "MULTI_EXIT_DISC"},
64 {BGP_ATTR_LOCAL_PREF
, "LOCAL_PREF"},
65 {BGP_ATTR_ATOMIC_AGGREGATE
, "ATOMIC_AGGREGATE"},
66 {BGP_ATTR_AGGREGATOR
, "AGGREGATOR"},
67 {BGP_ATTR_COMMUNITIES
, "COMMUNITY"},
68 {BGP_ATTR_ORIGINATOR_ID
, "ORIGINATOR_ID"},
69 {BGP_ATTR_CLUSTER_LIST
, "CLUSTER_LIST"},
70 {BGP_ATTR_DPA
, "DPA"},
71 {BGP_ATTR_ADVERTISER
, "ADVERTISER"},
72 {BGP_ATTR_RCID_PATH
, "RCID_PATH"},
73 {BGP_ATTR_MP_REACH_NLRI
, "MP_REACH_NLRI"},
74 {BGP_ATTR_MP_UNREACH_NLRI
, "MP_UNREACH_NLRI"},
75 {BGP_ATTR_EXT_COMMUNITIES
, "EXT_COMMUNITIES"},
76 {BGP_ATTR_AS4_PATH
, "AS4_PATH"},
77 {BGP_ATTR_AS4_AGGREGATOR
, "AS4_AGGREGATOR"},
78 {BGP_ATTR_AS_PATHLIMIT
, "AS_PATHLIMIT"},
79 {BGP_ATTR_PMSI_TUNNEL
, "PMSI_TUNNEL_ATTRIBUTE"},
80 {BGP_ATTR_ENCAP
, "ENCAP"},
81 #if ENABLE_BGP_VNC_ATTR
82 {BGP_ATTR_VNC
, "VNC"},
84 {BGP_ATTR_LARGE_COMMUNITIES
, "LARGE_COMMUNITY"},
85 {BGP_ATTR_PREFIX_SID
, "PREFIX_SID"},
88 static const struct message attr_flag_str
[] = {
89 {BGP_ATTR_FLAG_OPTIONAL
, "Optional"},
90 {BGP_ATTR_FLAG_TRANS
, "Transitive"},
91 {BGP_ATTR_FLAG_PARTIAL
, "Partial"},
92 /* bgp_attr_flags_diagnose() relies on this bit being last in
94 {BGP_ATTR_FLAG_EXTLEN
, "Extended Length"},
97 static struct hash
*cluster_hash
;
99 static void *cluster_hash_alloc(void *p
)
101 const struct cluster_list
*val
= (const struct cluster_list
*)p
;
102 struct cluster_list
*cluster
;
104 cluster
= XMALLOC(MTYPE_CLUSTER
, sizeof(struct cluster_list
));
105 cluster
->length
= val
->length
;
107 if (cluster
->length
) {
108 cluster
->list
= XMALLOC(MTYPE_CLUSTER_VAL
, val
->length
);
109 memcpy(cluster
->list
, val
->list
, val
->length
);
111 cluster
->list
= NULL
;
118 /* Cluster list related functions. */
119 static struct cluster_list
*cluster_parse(struct in_addr
*pnt
, int length
)
121 struct cluster_list tmp
;
122 struct cluster_list
*cluster
;
127 cluster
= hash_get(cluster_hash
, &tmp
, cluster_hash_alloc
);
132 int cluster_loop_check(struct cluster_list
*cluster
, struct in_addr originator
)
136 for (i
= 0; i
< cluster
->length
/ 4; i
++)
137 if (cluster
->list
[i
].s_addr
== originator
.s_addr
)
142 static unsigned int cluster_hash_key_make(const void *p
)
144 const struct cluster_list
*cluster
= p
;
146 return jhash(cluster
->list
, cluster
->length
, 0);
149 static bool cluster_hash_cmp(const void *p1
, const void *p2
)
151 const struct cluster_list
*cluster1
= p1
;
152 const struct cluster_list
*cluster2
= p2
;
154 return (cluster1
->length
== cluster2
->length
155 && memcmp(cluster1
->list
, cluster2
->list
, cluster1
->length
)
159 static void cluster_free(struct cluster_list
*cluster
)
161 XFREE(MTYPE_CLUSTER_VAL
, cluster
->list
);
162 XFREE(MTYPE_CLUSTER
, cluster
);
165 static struct cluster_list
*cluster_intern(struct cluster_list
*cluster
)
167 struct cluster_list
*find
;
169 find
= hash_get(cluster_hash
, cluster
, cluster_hash_alloc
);
175 void cluster_unintern(struct cluster_list
*cluster
)
180 if (cluster
->refcnt
== 0) {
181 hash_release(cluster_hash
, cluster
);
182 cluster_free(cluster
);
186 static void cluster_init(void)
188 cluster_hash
= hash_create(cluster_hash_key_make
, cluster_hash_cmp
,
192 static void cluster_finish(void)
194 hash_clean(cluster_hash
, (void (*)(void *))cluster_free
);
195 hash_free(cluster_hash
);
199 static struct hash
*encap_hash
= NULL
;
201 static struct hash
*vnc_hash
= NULL
;
204 struct bgp_attr_encap_subtlv
*encap_tlv_dup(struct bgp_attr_encap_subtlv
*orig
)
206 struct bgp_attr_encap_subtlv
*new;
207 struct bgp_attr_encap_subtlv
*tail
;
208 struct bgp_attr_encap_subtlv
*p
;
210 for (p
= orig
, tail
= new = NULL
; p
; p
= p
->next
) {
211 int size
= sizeof(struct bgp_attr_encap_subtlv
) + p
->length
;
213 tail
->next
= XCALLOC(MTYPE_ENCAP_TLV
, size
);
216 tail
= new = XCALLOC(MTYPE_ENCAP_TLV
, size
);
219 memcpy(tail
, p
, size
);
226 static void encap_free(struct bgp_attr_encap_subtlv
*p
)
228 struct bgp_attr_encap_subtlv
*next
;
232 XFREE(MTYPE_ENCAP_TLV
, p
);
237 void bgp_attr_flush_encap(struct attr
*attr
)
242 if (attr
->encap_subtlvs
) {
243 encap_free(attr
->encap_subtlvs
);
244 attr
->encap_subtlvs
= NULL
;
247 if (attr
->vnc_subtlvs
) {
248 encap_free(attr
->vnc_subtlvs
);
249 attr
->vnc_subtlvs
= NULL
;
255 * Compare encap sub-tlv chains
260 * This algorithm could be made faster if needed
262 static int encap_same(const struct bgp_attr_encap_subtlv
*h1
,
263 const struct bgp_attr_encap_subtlv
*h2
)
265 const struct bgp_attr_encap_subtlv
*p
;
266 const struct bgp_attr_encap_subtlv
*q
;
270 if (h1
== NULL
|| h2
== NULL
)
273 for (p
= h1
; p
; p
= p
->next
) {
274 for (q
= h2
; q
; q
= q
->next
) {
275 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
276 && !memcmp(p
->value
, q
->value
, p
->length
)) {
285 for (p
= h2
; p
; p
= p
->next
) {
286 for (q
= h1
; q
; q
= q
->next
) {
287 if ((p
->type
== q
->type
) && (p
->length
== q
->length
)
288 && !memcmp(p
->value
, q
->value
, p
->length
)) {
300 static void *encap_hash_alloc(void *p
)
302 /* Encap structure is already allocated. */
313 static struct bgp_attr_encap_subtlv
*
314 encap_intern(struct bgp_attr_encap_subtlv
*encap
, encap_subtlv_type type
)
316 struct bgp_attr_encap_subtlv
*find
;
317 struct hash
*hash
= encap_hash
;
319 if (type
== VNC_SUBTLV_TYPE
)
323 find
= hash_get(hash
, encap
, encap_hash_alloc
);
331 static void encap_unintern(struct bgp_attr_encap_subtlv
**encapp
,
332 encap_subtlv_type type
)
334 struct bgp_attr_encap_subtlv
*encap
= *encapp
;
338 if (encap
->refcnt
== 0) {
339 struct hash
*hash
= encap_hash
;
341 if (type
== VNC_SUBTLV_TYPE
)
344 hash_release(hash
, encap
);
350 static unsigned int encap_hash_key_make(const void *p
)
352 const struct bgp_attr_encap_subtlv
*encap
= p
;
354 return jhash(encap
->value
, encap
->length
, 0);
357 static bool encap_hash_cmp(const void *p1
, const void *p2
)
359 return encap_same((const struct bgp_attr_encap_subtlv
*)p1
,
360 (const struct bgp_attr_encap_subtlv
*)p2
);
363 static void encap_init(void)
365 encap_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
368 vnc_hash
= hash_create(encap_hash_key_make
, encap_hash_cmp
,
373 static void encap_finish(void)
375 hash_clean(encap_hash
, (void (*)(void *))encap_free
);
376 hash_free(encap_hash
);
379 hash_clean(vnc_hash
, (void (*)(void *))encap_free
);
385 static bool overlay_index_same(const struct attr
*a1
, const struct attr
*a2
)
393 return !memcmp(&(a1
->evpn_overlay
), &(a2
->evpn_overlay
),
394 sizeof(struct bgp_route_evpn
));
397 /* Unknown transit attribute. */
398 static struct hash
*transit_hash
;
400 static void transit_free(struct transit
*transit
)
402 XFREE(MTYPE_TRANSIT_VAL
, transit
->val
);
403 XFREE(MTYPE_TRANSIT
, transit
);
406 static void *transit_hash_alloc(void *p
)
408 /* Transit structure is already allocated. */
412 static struct transit
*transit_intern(struct transit
*transit
)
414 struct transit
*find
;
416 find
= hash_get(transit_hash
, transit
, transit_hash_alloc
);
418 transit_free(transit
);
424 void transit_unintern(struct transit
*transit
)
429 if (transit
->refcnt
== 0) {
430 hash_release(transit_hash
, transit
);
431 transit_free(transit
);
435 static unsigned int transit_hash_key_make(const void *p
)
437 const struct transit
*transit
= p
;
439 return jhash(transit
->val
, transit
->length
, 0);
442 static bool transit_hash_cmp(const void *p1
, const void *p2
)
444 const struct transit
*transit1
= p1
;
445 const struct transit
*transit2
= p2
;
447 return (transit1
->length
== transit2
->length
448 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
451 static void transit_init(void)
453 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
457 static void transit_finish(void)
459 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
460 hash_free(transit_hash
);
464 /* Attribute hash routines. */
465 static struct hash
*attrhash
;
467 /* Shallow copy of an attribute
468 * Though, not so shallow that it doesn't copy the contents
469 * of the attr_extra pointed to by 'extra'
471 void bgp_attr_dup(struct attr
*new, struct attr
*orig
)
476 unsigned long int attr_count(void)
478 return attrhash
->count
;
481 unsigned long int attr_unknown_count(void)
483 return transit_hash
->count
;
486 unsigned int attrhash_key_make(const void *p
)
488 const struct attr
*attr
= (struct attr
*)p
;
490 #define MIX(val) key = jhash_1word(val, key)
491 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
493 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
494 MIX3(attr
->local_pref
, attr
->aggregator_as
,
495 attr
->aggregator_addr
.s_addr
);
496 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
497 attr
->originator_id
.s_addr
);
498 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
501 MIX(aspath_key_make(attr
->aspath
));
503 MIX(community_hash_make(attr
->community
));
505 if (attr
->lcommunity
)
506 MIX(lcommunity_hash_make(attr
->lcommunity
));
507 if (attr
->ecommunity
)
508 MIX(ecommunity_hash_make(attr
->ecommunity
));
510 MIX(cluster_hash_key_make(attr
->cluster
));
512 MIX(transit_hash_key_make(attr
->transit
));
513 if (attr
->encap_subtlvs
)
514 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
516 if (attr
->vnc_subtlvs
)
517 MIX(encap_hash_key_make(attr
->vnc_subtlvs
));
519 MIX(attr
->mp_nexthop_len
);
520 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
521 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
522 MIX(attr
->nh_ifindex
);
523 MIX(attr
->nh_lla_ifindex
);
528 bool attrhash_cmp(const void *p1
, const void *p2
)
530 const struct attr
*attr1
= p1
;
531 const struct attr
*attr2
= p2
;
533 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
534 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
535 && attr1
->aspath
== attr2
->aspath
536 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
537 && attr1
->local_pref
== attr2
->local_pref
538 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
539 if (attr1
->aggregator_as
== attr2
->aggregator_as
540 && attr1
->aggregator_addr
.s_addr
541 == attr2
->aggregator_addr
.s_addr
542 && attr1
->weight
== attr2
->weight
543 && attr1
->tag
== attr2
->tag
544 && attr1
->label_index
== attr2
->label_index
545 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
546 && attr1
->ecommunity
== attr2
->ecommunity
547 && attr1
->lcommunity
== attr2
->lcommunity
548 && attr1
->cluster
== attr2
->cluster
549 && attr1
->transit
== attr2
->transit
550 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
551 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
553 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
555 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
556 &attr2
->mp_nexthop_global
)
557 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
558 &attr2
->mp_nexthop_local
)
559 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
560 &attr2
->mp_nexthop_global_in
)
561 && IPV4_ADDR_SAME(&attr1
->originator_id
,
562 &attr2
->originator_id
)
563 && overlay_index_same(attr1
, attr2
)
564 && attr1
->nh_ifindex
== attr2
->nh_ifindex
565 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
)
572 static void attrhash_init(void)
575 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
579 * special for hash_clean below
581 static void attr_vfree(void *attr
)
583 XFREE(MTYPE_ATTR
, attr
);
586 static void attrhash_finish(void)
588 hash_clean(attrhash
, attr_vfree
);
593 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
595 struct attr
*attr
= bucket
->data
;
597 vty_out(vty
, "attr[%ld] nexthop %s\n", attr
->refcnt
,
598 inet_ntoa(attr
->nexthop
));
599 vty_out(vty
, "\tflags: %" PRIu64
" med: %u local_pref: %u origin: %u weight: %u label: %u\n",
600 attr
->flag
, attr
->med
, attr
->local_pref
, attr
->origin
,
601 attr
->weight
, attr
->label
);
604 void attr_show_all(struct vty
*vty
)
606 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
607 void *))attr_show_all_iterator
,
611 static void *bgp_attr_hash_alloc(void *p
)
613 struct attr
*val
= (struct attr
*)p
;
616 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
618 if (val
->encap_subtlvs
) {
619 val
->encap_subtlvs
= NULL
;
622 if (val
->vnc_subtlvs
) {
623 val
->vnc_subtlvs
= NULL
;
630 /* Internet argument attribute. */
631 struct attr
*bgp_attr_intern(struct attr
*attr
)
635 /* Intern referenced strucutre. */
637 if (!attr
->aspath
->refcnt
)
638 attr
->aspath
= aspath_intern(attr
->aspath
);
640 attr
->aspath
->refcnt
++;
642 if (attr
->community
) {
643 if (!attr
->community
->refcnt
)
644 attr
->community
= community_intern(attr
->community
);
646 attr
->community
->refcnt
++;
649 if (attr
->ecommunity
) {
650 if (!attr
->ecommunity
->refcnt
)
651 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
653 attr
->ecommunity
->refcnt
++;
655 if (attr
->lcommunity
) {
656 if (!attr
->lcommunity
->refcnt
)
657 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
659 attr
->lcommunity
->refcnt
++;
662 if (!attr
->cluster
->refcnt
)
663 attr
->cluster
= cluster_intern(attr
->cluster
);
665 attr
->cluster
->refcnt
++;
668 if (!attr
->transit
->refcnt
)
669 attr
->transit
= transit_intern(attr
->transit
);
671 attr
->transit
->refcnt
++;
673 if (attr
->encap_subtlvs
) {
674 if (!attr
->encap_subtlvs
->refcnt
)
675 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
678 attr
->encap_subtlvs
->refcnt
++;
681 if (attr
->vnc_subtlvs
) {
682 if (!attr
->vnc_subtlvs
->refcnt
)
683 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
686 attr
->vnc_subtlvs
->refcnt
++;
690 /* At this point, attr only contains intern'd pointers. that means
691 * if we find it in attrhash, it has all the same pointers and we
692 * correctly updated the refcounts on these.
693 * If we don't find it, we need to allocate a one because in all
694 * cases this returns a new reference to a hashed attr, but the input
696 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
702 /* Make network statement's attribute. */
703 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
705 memset(attr
, 0, sizeof(struct attr
));
707 attr
->origin
= origin
;
708 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
709 attr
->aspath
= aspath_empty();
710 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
711 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
713 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
714 attr
->label
= MPLS_INVALID_LABEL
;
715 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
716 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
721 /* Create the attributes for an aggregate */
722 struct attr
*bgp_attr_aggregate_intern(struct bgp
*bgp
, uint8_t origin
,
723 struct aspath
*aspath
,
724 struct community
*community
,
725 struct ecommunity
*ecommunity
,
726 struct lcommunity
*lcommunity
,
727 struct bgp_aggregate
*aggregate
,
728 uint8_t atomic_aggregate
,
735 memset(&attr
, 0, sizeof(struct attr
));
737 /* Origin attribute. */
738 attr
.origin
= origin
;
739 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
741 /* AS path attribute. */
743 attr
.aspath
= aspath_intern(aspath
);
745 attr
.aspath
= aspath_empty();
746 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
748 /* Next hop attribute. */
749 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
752 uint32_t gshut
= COMMUNITY_GSHUT
;
754 /* If we are not shutting down ourselves and we are
755 * aggregating a route that contains the GSHUT community we
756 * need to remove that community when creating the aggregate */
757 if (!bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)
758 && community_include(community
, gshut
)) {
759 community_del_val(community
, &gshut
);
762 attr
.community
= community
;
763 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
767 attr
.ecommunity
= ecommunity
;
768 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
772 attr
.lcommunity
= lcommunity
;
773 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
776 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
777 bgp_attr_add_gshut_community(&attr
);
780 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
781 attr
.label
= MPLS_INVALID_LABEL
;
782 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
783 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
784 if (!aggregate
->as_set
|| atomic_aggregate
)
785 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
786 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
787 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
788 attr
.aggregator_as
= bgp
->confed_id
;
790 attr
.aggregator_as
= bgp
->as
;
791 attr
.aggregator_addr
= bgp
->router_id
;
792 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
793 attr
.label
= MPLS_INVALID_LABEL
;
795 /* Apply route-map */
796 if (aggregate
->rmap
.name
) {
797 struct attr attr_tmp
= attr
;
798 struct bgp_path_info rmap_path
;
800 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
801 rmap_path
.peer
= bgp
->peer_self
;
802 rmap_path
.attr
= &attr_tmp
;
804 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
806 ret
= route_map_apply(aggregate
->rmap
.map
, p
, RMAP_BGP
,
809 bgp
->peer_self
->rmap_type
= 0;
811 if (ret
== RMAP_DENYMATCH
) {
812 /* Free uninterned attribute. */
813 bgp_attr_flush(&attr_tmp
);
815 /* Unintern original. */
816 aspath_unintern(&attr
.aspath
);
820 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
821 bgp_attr_add_gshut_community(&attr_tmp
);
823 new = bgp_attr_intern(&attr_tmp
);
826 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
827 bgp_attr_add_gshut_community(&attr
);
829 new = bgp_attr_intern(&attr
);
832 aspath_unintern(&new->aspath
);
836 /* Unintern just the sub-components of the attr, but not the attr */
837 void bgp_attr_unintern_sub(struct attr
*attr
)
839 /* aspath refcount shoud be decrement. */
841 aspath_unintern(&attr
->aspath
);
842 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
845 community_unintern(&attr
->community
);
846 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
848 if (attr
->ecommunity
)
849 ecommunity_unintern(&attr
->ecommunity
);
850 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
852 if (attr
->lcommunity
)
853 lcommunity_unintern(&attr
->lcommunity
);
854 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
857 cluster_unintern(attr
->cluster
);
858 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
861 transit_unintern(attr
->transit
);
863 if (attr
->encap_subtlvs
)
864 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
867 if (attr
->vnc_subtlvs
)
868 encap_unintern(&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
873 * We have some show commands that let you experimentally
874 * apply a route-map. When we apply the route-map
875 * we are reseting values but not saving them for
876 * posterity via intern'ing( because route-maps don't
877 * do that) but at this point in time we need
878 * to compare the new attr to the old and if the
879 * routemap has changed it we need to, as Snoop Dog says,
880 * Drop it like it's hot
882 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
884 if (new->aspath
!= old
->aspath
)
885 aspath_free(new->aspath
);
887 if (new->community
!= old
->community
)
888 community_free(&new->community
);
890 if (new->ecommunity
!= old
->ecommunity
)
891 ecommunity_free(&new->ecommunity
);
893 if (new->lcommunity
!= old
->lcommunity
)
894 lcommunity_free(&new->lcommunity
);
897 /* Free bgp attribute and aspath. */
898 void bgp_attr_unintern(struct attr
**pattr
)
900 struct attr
*attr
= *pattr
;
904 /* Decrement attribute reference. */
909 /* If reference becomes zero then free attribute object. */
910 if (attr
->refcnt
== 0) {
911 ret
= hash_release(attrhash
, attr
);
913 XFREE(MTYPE_ATTR
, attr
);
917 bgp_attr_unintern_sub(&tmp
);
920 void bgp_attr_flush(struct attr
*attr
)
922 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
923 aspath_free(attr
->aspath
);
926 if (attr
->community
&& !attr
->community
->refcnt
)
927 community_free(&attr
->community
);
928 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
929 ecommunity_free(&attr
->ecommunity
);
930 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
931 lcommunity_free(&attr
->lcommunity
);
932 if (attr
->cluster
&& !attr
->cluster
->refcnt
) {
933 cluster_free(attr
->cluster
);
934 attr
->cluster
= NULL
;
936 if (attr
->transit
&& !attr
->transit
->refcnt
) {
937 transit_free(attr
->transit
);
938 attr
->transit
= NULL
;
940 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
941 encap_free(attr
->encap_subtlvs
);
942 attr
->encap_subtlvs
= NULL
;
945 if (attr
->vnc_subtlvs
&& !attr
->vnc_subtlvs
->refcnt
) {
946 encap_free(attr
->vnc_subtlvs
);
947 attr
->vnc_subtlvs
= NULL
;
952 /* Implement draft-scudder-idr-optional-transitive behaviour and
953 * avoid resetting sessions for malformed attributes which are
954 * are partial/optional and hence where the error likely was not
955 * introduced by the sending neighbour.
957 static bgp_attr_parse_ret_t
958 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
961 struct peer
*const peer
= args
->peer
;
962 const uint8_t flags
= args
->flags
;
963 /* startp and length must be special-cased, as whether or not to
964 * send the attribute data with the NOTIFY depends on the error,
965 * the caller therefore signals this with the seperate length argument
967 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
969 /* Only relax error handling for eBGP peers */
970 if (peer
->sort
!= BGP_PEER_EBGP
) {
971 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
972 notify_datap
, length
);
973 return BGP_ATTR_PARSE_ERROR
;
976 /* Adjust the stream getp to the end of the attribute, in case we can
977 * still proceed but the caller hasn't read all the attribute.
979 stream_set_getp(BGP_INPUT(peer
),
980 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
983 switch (args
->type
) {
984 /* where an attribute is relatively inconsequential, e.g. it does not
985 * affect route selection, and can be safely ignored, then any such
986 * attributes which are malformed should just be ignored and the route
987 * processed as normal.
989 case BGP_ATTR_AS4_AGGREGATOR
:
990 case BGP_ATTR_AGGREGATOR
:
991 case BGP_ATTR_ATOMIC_AGGREGATE
:
992 return BGP_ATTR_PARSE_PROCEED
;
994 /* Core attributes, particularly ones which may influence route
995 * selection, should always cause session resets
997 case BGP_ATTR_ORIGIN
:
998 case BGP_ATTR_AS_PATH
:
999 case BGP_ATTR_NEXT_HOP
:
1000 case BGP_ATTR_MULTI_EXIT_DISC
:
1001 case BGP_ATTR_LOCAL_PREF
:
1002 case BGP_ATTR_COMMUNITIES
:
1003 case BGP_ATTR_ORIGINATOR_ID
:
1004 case BGP_ATTR_CLUSTER_LIST
:
1005 case BGP_ATTR_MP_REACH_NLRI
:
1006 case BGP_ATTR_MP_UNREACH_NLRI
:
1007 case BGP_ATTR_EXT_COMMUNITIES
:
1008 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1009 notify_datap
, length
);
1010 return BGP_ATTR_PARSE_ERROR
;
1013 /* Partial optional attributes that are malformed should not cause
1014 * the whole session to be reset. Instead treat it as a withdrawal
1015 * of the routes, if possible.
1017 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1018 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1019 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1020 return BGP_ATTR_PARSE_WITHDRAW
;
1022 /* default to reset */
1023 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1026 /* Find out what is wrong with the path attribute flag bits and log the error.
1027 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1028 Extended Length. Checking O/T/P bits at once implies, that the attribute
1029 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1030 non-transitive" attribute. */
1032 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1033 uint8_t desired_flags
/* how RFC says it must be */
1036 uint8_t seen
= 0, i
;
1037 uint8_t real_flags
= args
->flags
;
1038 const uint8_t attr_code
= args
->type
;
1040 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1041 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1042 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1043 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1044 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1045 flog_err(EC_BGP_ATTR_FLAG
,
1046 "%s attribute must%s be flagged as \"%s\"",
1047 lookup_msg(attr_str
, attr_code
, NULL
),
1048 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1051 attr_flag_str
[i
].str
);
1056 "Strange, %s called for attr %s, but no problem found with flags"
1057 " (real flags 0x%x, desired 0x%x)",
1058 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1059 real_flags
, desired_flags
);
1063 /* Required flags for attributes. EXTLEN will be masked off when testing,
1064 * as will PARTIAL for optional+transitive attributes.
1066 const uint8_t attr_flags_values
[] = {
1067 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1068 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1069 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1070 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1071 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1072 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1073 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1074 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1075 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1076 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1077 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1078 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1079 [BGP_ATTR_EXT_COMMUNITIES
] =
1080 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1081 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1082 [BGP_ATTR_AS4_AGGREGATOR
] =
1083 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1084 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1085 [BGP_ATTR_LARGE_COMMUNITIES
] =
1086 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1087 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1089 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1091 static int bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1093 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1094 const uint8_t flags
= args
->flags
;
1095 const uint8_t attr_code
= args
->type
;
1097 /* there may be attributes we don't know about */
1098 if (attr_code
> attr_flags_values_max
)
1100 if (attr_flags_values
[attr_code
] == 0)
1103 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1107 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1108 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1111 "%s well-known attributes must have transitive flag set (%x)",
1112 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1116 /* "For well-known attributes and for optional non-transitive
1118 * the Partial bit MUST be set to 0."
1120 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1121 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1122 flog_err(EC_BGP_ATTR_FLAG
,
1123 "%s well-known attribute "
1124 "must NOT have the partial flag set (%x)",
1125 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1128 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1129 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1130 flog_err(EC_BGP_ATTR_FLAG
,
1131 "%s optional + transitive attribute "
1132 "must NOT have the partial flag set (%x)",
1133 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1138 /* Optional transitive attributes may go through speakers that don't
1139 * reocgnise them and set the Partial bit.
1141 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1142 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1143 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1145 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1148 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1152 /* Get origin attribute of the update message. */
1153 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1155 struct peer
*const peer
= args
->peer
;
1156 struct attr
*const attr
= args
->attr
;
1157 const bgp_size_t length
= args
->length
;
1159 /* If any recognized attribute has Attribute Length that conflicts
1160 with the expected length (based on the attribute type code), then
1161 the Error Subcode is set to Attribute Length Error. The Data
1162 field contains the erroneous attribute (type, length and
1165 flog_err(EC_BGP_ATTR_LEN
,
1166 "Origin attribute length is not one %d", length
);
1167 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1171 /* Fetch origin attribute. */
1172 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1174 /* If the ORIGIN attribute has an undefined value, then the Error
1175 Subcode is set to Invalid Origin Attribute. The Data field
1176 contains the unrecognized attribute (type, length and value). */
1177 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1178 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1179 flog_err(EC_BGP_ATTR_ORIGIN
,
1180 "Origin attribute value is invalid %d", attr
->origin
);
1181 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1185 /* Set oring attribute flag. */
1186 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1191 /* Parse AS path information. This function is wrapper of
1193 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1195 struct attr
*const attr
= args
->attr
;
1196 struct peer
*const peer
= args
->peer
;
1197 const bgp_size_t length
= args
->length
;
1200 * peer with AS4 => will get 4Byte ASnums
1201 * otherwise, will get 16 Bit
1203 attr
->aspath
= aspath_parse(peer
->curr
, length
,
1204 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1206 /* In case of IBGP, length will be zero. */
1207 if (!attr
->aspath
) {
1208 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1209 "Malformed AS path from %s, length is %d", peer
->host
,
1211 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1215 /* Set aspath attribute flag. */
1216 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1218 return BGP_ATTR_PARSE_PROCEED
;
1221 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1222 struct attr
*const attr
)
1224 /* These checks were part of bgp_attr_aspath, but with
1225 * as4 we should to check aspath things when
1226 * aspath synthesizing with as4_path has already taken place.
1227 * Otherwise we check ASPATH and use the synthesized thing, and that is
1229 * So do the checks later, i.e. here
1231 struct aspath
*aspath
;
1233 /* Confederation sanity check. */
1234 if ((peer
->sort
== BGP_PEER_CONFED
1235 && !aspath_left_confed_check(attr
->aspath
))
1236 || (peer
->sort
== BGP_PEER_EBGP
1237 && aspath_confed_check(attr
->aspath
))) {
1238 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1240 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1241 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1242 return BGP_ATTR_PARSE_ERROR
;
1245 /* First AS check for EBGP. */
1246 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1247 if (peer
->sort
== BGP_PEER_EBGP
1248 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1249 flog_err(EC_BGP_ATTR_FIRST_AS
,
1250 "%s incorrect first AS (must be %u)",
1251 peer
->host
, peer
->as
);
1252 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1253 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1254 return BGP_ATTR_PARSE_ERROR
;
1258 /* local-as prepend */
1259 if (peer
->change_local_as
1260 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1261 aspath
= aspath_dup(attr
->aspath
);
1262 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1263 aspath_unintern(&attr
->aspath
);
1264 attr
->aspath
= aspath_intern(aspath
);
1267 return BGP_ATTR_PARSE_PROCEED
;
1270 /* Parse AS4 path information. This function is another wrapper of
1272 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1273 struct aspath
**as4_path
)
1275 struct peer
*const peer
= args
->peer
;
1276 struct attr
*const attr
= args
->attr
;
1277 const bgp_size_t length
= args
->length
;
1279 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1281 /* In case of IBGP, length will be zero. */
1283 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1284 "Malformed AS4 path from %s, length is %d", peer
->host
,
1286 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1290 /* Set aspath attribute flag. */
1291 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1293 return BGP_ATTR_PARSE_PROCEED
;
1297 * Check that the nexthop attribute is valid.
1299 bgp_attr_parse_ret_t
1300 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1302 in_addr_t nexthop_h
;
1304 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1305 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1306 || IPV4_CLASS_DE(nexthop_h
))
1307 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1308 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1309 char buf
[INET_ADDRSTRLEN
];
1311 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1313 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1315 data
[0] = BGP_ATTR_FLAG_TRANS
;
1316 data
[1] = BGP_ATTR_NEXT_HOP
;
1317 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1318 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1319 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1320 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1322 return BGP_ATTR_PARSE_ERROR
;
1325 return BGP_ATTR_PARSE_PROCEED
;
1328 /* Nexthop attribute. */
1329 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1331 struct peer
*const peer
= args
->peer
;
1332 struct attr
*const attr
= args
->attr
;
1333 const bgp_size_t length
= args
->length
;
1335 /* Check nexthop attribute length. */
1337 flog_err(EC_BGP_ATTR_LEN
,
1338 "Nexthop attribute length isn't four [%d]", length
);
1340 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1344 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1345 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1347 return BGP_ATTR_PARSE_PROCEED
;
1350 /* MED atrribute. */
1351 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1353 struct peer
*const peer
= args
->peer
;
1354 struct attr
*const attr
= args
->attr
;
1355 const bgp_size_t length
= args
->length
;
1359 flog_err(EC_BGP_ATTR_LEN
,
1360 "MED attribute length isn't four [%d]", length
);
1362 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1366 attr
->med
= stream_getl(peer
->curr
);
1368 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1370 return BGP_ATTR_PARSE_PROCEED
;
1373 /* Local preference attribute. */
1374 static bgp_attr_parse_ret_t
1375 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1377 struct peer
*const peer
= args
->peer
;
1378 struct attr
*const attr
= args
->attr
;
1379 const bgp_size_t length
= args
->length
;
1383 flog_err(EC_BGP_ATTR_LEN
,
1384 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1385 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1389 /* If it is contained in an UPDATE message that is received from an
1390 external peer, then this attribute MUST be ignored by the
1391 receiving speaker. */
1392 if (peer
->sort
== BGP_PEER_EBGP
) {
1393 stream_forward_getp(peer
->curr
, length
);
1394 return BGP_ATTR_PARSE_PROCEED
;
1397 attr
->local_pref
= stream_getl(peer
->curr
);
1399 /* Set the local-pref flag. */
1400 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1402 return BGP_ATTR_PARSE_PROCEED
;
1405 /* Atomic aggregate. */
1406 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1408 struct attr
*const attr
= args
->attr
;
1409 const bgp_size_t length
= args
->length
;
1413 flog_err(EC_BGP_ATTR_LEN
,
1414 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1416 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1420 /* Set atomic aggregate flag. */
1421 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1423 return BGP_ATTR_PARSE_PROCEED
;
1426 /* Aggregator attribute */
1427 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1429 struct peer
*const peer
= args
->peer
;
1430 struct attr
*const attr
= args
->attr
;
1431 const bgp_size_t length
= args
->length
;
1435 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1436 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1439 if (length
!= wantedlen
) {
1440 flog_err(EC_BGP_ATTR_LEN
,
1441 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1443 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1447 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1448 attr
->aggregator_as
= stream_getl(peer
->curr
);
1450 attr
->aggregator_as
= stream_getw(peer
->curr
);
1451 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1453 /* Set atomic aggregate flag. */
1454 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1456 return BGP_ATTR_PARSE_PROCEED
;
1459 /* New Aggregator attribute */
1460 static bgp_attr_parse_ret_t
1461 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1462 as_t
*as4_aggregator_as
,
1463 struct in_addr
*as4_aggregator_addr
)
1465 struct peer
*const peer
= args
->peer
;
1466 struct attr
*const attr
= args
->attr
;
1467 const bgp_size_t length
= args
->length
;
1470 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1472 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1476 *as4_aggregator_as
= stream_getl(peer
->curr
);
1477 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1479 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1481 return BGP_ATTR_PARSE_PROCEED
;
1484 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1486 static bgp_attr_parse_ret_t
1487 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1488 struct aspath
*as4_path
, as_t as4_aggregator
,
1489 struct in_addr
*as4_aggregator_addr
)
1491 int ignore_as4_path
= 0;
1492 struct aspath
*newpath
;
1494 if (!attr
->aspath
) {
1495 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1497 * checked that all well-known, mandatory attributes were
1500 * Can only be a problem with peer itself - hard error
1502 return BGP_ATTR_PARSE_ERROR
;
1505 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1506 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1508 * It is worth a warning though, because the peer really
1509 * should not send them
1511 if (BGP_DEBUG(as4
, AS4
)) {
1512 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1513 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1514 "AS4 capable peer, yet it sent");
1517 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1518 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1520 "AS4 capable peer, yet it sent");
1523 return BGP_ATTR_PARSE_PROCEED
;
1526 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1527 * because that may override AS4_PATH
1529 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1530 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1532 * if the as_number in aggregator is not AS_TRANS,
1533 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1534 * and the Aggregator shall be taken as
1535 * info on the aggregating node, and the AS_PATH
1536 * shall be taken as the AS_PATH
1538 * the Aggregator shall be ignored and the
1539 * AS4_AGGREGATOR shall be taken as the
1540 * Aggregating node and the AS_PATH is to be
1541 * constructed "as in all other cases"
1543 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1545 if (BGP_DEBUG(as4
, AS4
))
1547 "[AS4] %s BGP not AS4 capable peer"
1548 " send AGGREGATOR != AS_TRANS and"
1549 " AS4_AGGREGATOR, so ignore"
1550 " AS4_AGGREGATOR and AS4_PATH",
1552 ignore_as4_path
= 1;
1554 /* "New_aggregator shall be taken as aggregator"
1556 attr
->aggregator_as
= as4_aggregator
;
1557 attr
->aggregator_addr
.s_addr
=
1558 as4_aggregator_addr
->s_addr
;
1561 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1562 * That is bogus - but reading the conditions
1563 * we have to handle AS4_AGGREGATOR as if it were
1564 * AGGREGATOR in that case
1566 if (BGP_DEBUG(as4
, AS4
))
1568 "[AS4] %s BGP not AS4 capable peer send"
1569 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1570 " it as if AGGREGATOR with AS_TRANS had been there",
1572 attr
->aggregator_as
= as4_aggregator
;
1573 /* sweep it under the carpet and simulate a "good"
1575 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1579 /* need to reconcile NEW_AS_PATH and AS_PATH */
1580 if (!ignore_as4_path
1581 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1582 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1584 return BGP_ATTR_PARSE_ERROR
;
1586 aspath_unintern(&attr
->aspath
);
1587 attr
->aspath
= aspath_intern(newpath
);
1589 return BGP_ATTR_PARSE_PROCEED
;
1592 /* Community attribute. */
1593 static bgp_attr_parse_ret_t
1594 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1596 struct peer
*const peer
= args
->peer
;
1597 struct attr
*const attr
= args
->attr
;
1598 const bgp_size_t length
= args
->length
;
1601 attr
->community
= NULL
;
1602 return BGP_ATTR_PARSE_PROCEED
;
1606 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1608 /* XXX: fix community_parse to use stream API and remove this */
1609 stream_forward_getp(peer
->curr
, length
);
1611 if (!attr
->community
)
1612 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1615 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1617 return BGP_ATTR_PARSE_PROCEED
;
1620 /* Originator ID attribute. */
1621 static bgp_attr_parse_ret_t
1622 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1624 struct peer
*const peer
= args
->peer
;
1625 struct attr
*const attr
= args
->attr
;
1626 const bgp_size_t length
= args
->length
;
1630 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1633 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1637 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1639 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1641 return BGP_ATTR_PARSE_PROCEED
;
1644 /* Cluster list attribute. */
1645 static bgp_attr_parse_ret_t
1646 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1648 struct peer
*const peer
= args
->peer
;
1649 struct attr
*const attr
= args
->attr
;
1650 const bgp_size_t length
= args
->length
;
1654 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
1656 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1661 cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
), length
);
1663 /* XXX: Fix cluster_parse to use stream API and then remove this */
1664 stream_forward_getp(peer
->curr
, length
);
1666 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1668 return BGP_ATTR_PARSE_PROCEED
;
1671 /* Multiprotocol reachability information parse. */
1672 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1673 struct bgp_nlri
*mp_update
)
1677 iana_safi_t pkt_safi
;
1679 bgp_size_t nlri_len
;
1682 struct peer
*const peer
= args
->peer
;
1683 struct attr
*const attr
= args
->attr
;
1684 const bgp_size_t length
= args
->length
;
1686 /* Set end of packet. */
1687 s
= BGP_INPUT(peer
);
1688 start
= stream_get_getp(s
);
1690 /* safe to read statically sized header? */
1691 #define BGP_MP_REACH_MIN_SIZE 5
1692 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1693 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1694 zlog_info("%s: %s sent invalid length, %lu", __func__
,
1695 peer
->host
, (unsigned long)length
);
1696 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1699 /* Load AFI, SAFI. */
1700 pkt_afi
= stream_getw(s
);
1701 pkt_safi
= stream_getc(s
);
1703 /* Convert AFI, SAFI to internal values, check. */
1704 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1705 /* Log if AFI or SAFI is unrecognized. This is not an error
1707 * the attribute is otherwise malformed.
1709 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1711 "%s: MP_REACH received AFI %s or SAFI %s is unrecognized",
1712 peer
->host
, iana_afi2str(pkt_afi
),
1713 iana_safi2str(pkt_safi
));
1714 return BGP_ATTR_PARSE_ERROR
;
1717 /* Get nexthop length. */
1718 attr
->mp_nexthop_len
= stream_getc(s
);
1720 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
1722 "%s: %s, MP nexthop length, %u, goes past end of attribute",
1723 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1724 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1727 /* Nexthop length check. */
1728 switch (attr
->mp_nexthop_len
) {
1730 if (safi
!= SAFI_FLOWSPEC
) {
1731 zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d",
1732 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1733 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1736 case BGP_ATTR_NHLEN_VPNV4
:
1737 stream_getl(s
); /* RD high */
1738 stream_getl(s
); /* RD low */
1740 * NOTE: intentional fall through
1741 * - for consistency in rx processing
1743 * The following comment is to signal GCC this intention
1744 * and suppress the warning
1747 case BGP_ATTR_NHLEN_IPV4
:
1748 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1749 /* Probably needed for RFC 2283 */
1750 if (attr
->nexthop
.s_addr
== 0)
1751 memcpy(&attr
->nexthop
.s_addr
,
1752 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1754 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1755 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1756 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
1757 stream_getl(s
); /* RD high */
1758 stream_getl(s
); /* RD low */
1760 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1761 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1762 if (!peer
->nexthop
.ifp
) {
1763 zlog_warn("%s: Received a V6/VPNV6 Global attribute but address is a V6 LL and we have no peer interface information, withdrawing",
1765 return BGP_ATTR_PARSE_WITHDRAW
;
1767 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1770 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1771 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1772 if (attr
->mp_nexthop_len
1773 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1774 stream_getl(s
); /* RD high */
1775 stream_getl(s
); /* RD low */
1777 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1778 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1779 if (!peer
->nexthop
.ifp
) {
1780 zlog_warn("%s: Received V6/VPNV6 Global and LL attribute but global address is a V6 LL and we have no peer interface information, withdrawing",
1782 return BGP_ATTR_PARSE_WITHDRAW
;
1784 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1786 if (attr
->mp_nexthop_len
1787 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1788 stream_getl(s
); /* RD high */
1789 stream_getl(s
); /* RD low */
1791 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1792 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
1793 char buf1
[INET6_ADDRSTRLEN
];
1794 char buf2
[INET6_ADDRSTRLEN
];
1796 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1798 "%s rcvd nexthops %s, %s -- ignoring non-LL value",
1801 &attr
->mp_nexthop_global
,
1802 buf1
, INET6_ADDRSTRLEN
),
1804 &attr
->mp_nexthop_local
, buf2
,
1807 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1809 if (!peer
->nexthop
.ifp
) {
1810 zlog_warn("%s: Received a V6 LL nexthop and we have no peer interface information, withdrawing",
1812 return BGP_ATTR_PARSE_WITHDRAW
;
1814 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1817 zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d",
1818 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1819 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1823 zlog_info("%s: (%s) Failed to read SNPA and NLRI(s)", __func__
,
1825 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1830 if ((val
= stream_getc(s
)))
1832 EC_BGP_DEFUNCT_SNPA_LEN
,
1833 "%s sent non-zero value, %u, for defunct SNPA-length field",
1837 /* must have nrli_len, what is left of the attribute */
1838 nlri_len
= LEN_LEFT
;
1839 if (nlri_len
> STREAM_READABLE(s
)) {
1840 zlog_info("%s: (%s) Failed to read NLRI", __func__
, peer
->host
);
1841 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1845 zlog_info("%s: (%s) No Reachability, Treating as a EOR marker",
1846 __func__
, peer
->host
);
1848 mp_update
->afi
= afi
;
1849 mp_update
->safi
= safi
;
1850 return BGP_ATTR_PARSE_EOR
;
1853 mp_update
->afi
= afi
;
1854 mp_update
->safi
= safi
;
1855 mp_update
->nlri
= stream_pnt(s
);
1856 mp_update
->length
= nlri_len
;
1858 stream_forward_getp(s
, nlri_len
);
1860 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
1862 return BGP_ATTR_PARSE_PROCEED
;
1866 /* Multiprotocol unreachable parse */
1867 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
1868 struct bgp_nlri
*mp_withdraw
)
1873 iana_safi_t pkt_safi
;
1875 uint16_t withdraw_len
;
1876 struct peer
*const peer
= args
->peer
;
1877 struct attr
*const attr
= args
->attr
;
1878 const bgp_size_t length
= args
->length
;
1882 #define BGP_MP_UNREACH_MIN_SIZE 3
1883 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1884 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1886 pkt_afi
= stream_getw(s
);
1887 pkt_safi
= stream_getc(s
);
1889 /* Convert AFI, SAFI to internal values, check. */
1890 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1891 /* Log if AFI or SAFI is unrecognized. This is not an error
1893 * the attribute is otherwise malformed.
1895 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1897 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
1898 peer
->host
, iana_afi2str(pkt_afi
),
1899 iana_safi2str(pkt_safi
));
1900 return BGP_ATTR_PARSE_ERROR
;
1903 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1905 mp_withdraw
->afi
= afi
;
1906 mp_withdraw
->safi
= safi
;
1907 mp_withdraw
->nlri
= stream_pnt(s
);
1908 mp_withdraw
->length
= withdraw_len
;
1910 stream_forward_getp(s
, withdraw_len
);
1912 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
1914 return BGP_ATTR_PARSE_PROCEED
;
1917 /* Large Community attribute. */
1918 static bgp_attr_parse_ret_t
1919 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
1921 struct peer
*const peer
= args
->peer
;
1922 struct attr
*const attr
= args
->attr
;
1923 const bgp_size_t length
= args
->length
;
1926 * Large community follows new attribute format.
1929 attr
->lcommunity
= NULL
;
1930 /* Empty extcomm doesn't seem to be invalid per se */
1931 return BGP_ATTR_PARSE_PROCEED
;
1935 lcommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1936 /* XXX: fix ecommunity_parse to use stream API */
1937 stream_forward_getp(peer
->curr
, length
);
1939 if (!attr
->lcommunity
)
1940 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1943 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1945 return BGP_ATTR_PARSE_PROCEED
;
1948 /* Extended Community attribute. */
1949 static bgp_attr_parse_ret_t
1950 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
1952 struct peer
*const peer
= args
->peer
;
1953 struct attr
*const attr
= args
->attr
;
1954 const bgp_size_t length
= args
->length
;
1958 attr
->ecommunity
= NULL
;
1959 /* Empty extcomm doesn't seem to be invalid per se */
1960 return BGP_ATTR_PARSE_PROCEED
;
1964 ecommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1965 /* XXX: fix ecommunity_parse to use stream API */
1966 stream_forward_getp(peer
->curr
, length
);
1968 if (!attr
->ecommunity
)
1969 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1972 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1974 /* Extract MAC mobility sequence number, if any. */
1975 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
1976 attr
->sticky
= sticky
;
1978 /* Check if this is a Gateway MAC-IP advertisement */
1979 attr
->default_gw
= bgp_attr_default_gw(attr
);
1981 /* Handle scenario where router flag ecommunity is not
1982 * set but default gw ext community is present.
1983 * Use default gateway, set and propogate R-bit.
1985 if (attr
->default_gw
)
1986 attr
->router_flag
= 1;
1988 /* Check EVPN Neighbor advertisement flags, R-bit */
1989 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
);
1991 /* Extract the Rmac, if any */
1992 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
1993 if (bgp_debug_update(peer
, NULL
, NULL
, 1) &&
1994 bgp_mac_exist(&attr
->rmac
)) {
1995 char buf1
[ETHER_ADDR_STRLEN
];
1997 zlog_debug("%s: router mac %s is self mac",
1999 prefix_mac2str(&attr
->rmac
, buf1
,
2005 /* Get the tunnel type from encap extended community */
2006 bgp_attr_extcom_tunnel_type(attr
,
2007 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2009 return BGP_ATTR_PARSE_PROCEED
;
2012 /* Parse Tunnel Encap attribute in an UPDATE */
2013 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2014 bgp_size_t length
, /* IN: attr's length field */
2015 struct attr
*attr
, /* IN: caller already allocated */
2016 uint8_t flag
, /* IN: attr's flags field */
2020 uint16_t tunneltype
= 0;
2022 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2024 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2025 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2027 "Tunnel Encap attribute flag isn't optional and transitive %d",
2029 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2030 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2035 if (BGP_ATTR_ENCAP
== type
) {
2036 /* read outer TLV type and length */
2037 uint16_t tlv_length
;
2041 "Tunnel Encap attribute not long enough to contain outer T,L");
2042 bgp_notify_send_with_data(
2043 peer
, BGP_NOTIFY_UPDATE_ERR
,
2044 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2047 tunneltype
= stream_getw(BGP_INPUT(peer
));
2048 tlv_length
= stream_getw(BGP_INPUT(peer
));
2051 if (tlv_length
!= length
) {
2052 zlog_info("%s: tlv_length(%d) != length(%d)", __func__
,
2053 tlv_length
, length
);
2057 while (length
>= 4) {
2058 uint16_t subtype
= 0;
2059 uint16_t sublength
= 0;
2060 struct bgp_attr_encap_subtlv
*tlv
;
2062 if (BGP_ATTR_ENCAP
== type
) {
2063 subtype
= stream_getc(BGP_INPUT(peer
));
2064 sublength
= stream_getc(BGP_INPUT(peer
));
2068 subtype
= stream_getw(BGP_INPUT(peer
));
2069 sublength
= stream_getw(BGP_INPUT(peer
));
2074 if (sublength
> length
) {
2076 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2078 bgp_notify_send_with_data(
2079 peer
, BGP_NOTIFY_UPDATE_ERR
,
2080 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2084 /* alloc and copy sub-tlv */
2085 /* TBD make sure these are freed when attributes are released */
2086 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2087 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2088 tlv
->type
= subtype
;
2089 tlv
->length
= sublength
;
2090 stream_get(tlv
->value
, peer
->curr
, sublength
);
2091 length
-= sublength
;
2093 /* attach tlv to encap chain */
2094 if (BGP_ATTR_ENCAP
== type
) {
2095 struct bgp_attr_encap_subtlv
*stlv_last
;
2096 for (stlv_last
= attr
->encap_subtlvs
;
2097 stlv_last
&& stlv_last
->next
;
2098 stlv_last
= stlv_last
->next
)
2101 stlv_last
->next
= tlv
;
2103 attr
->encap_subtlvs
= tlv
;
2107 struct bgp_attr_encap_subtlv
*stlv_last
;
2108 for (stlv_last
= attr
->vnc_subtlvs
;
2109 stlv_last
&& stlv_last
->next
;
2110 stlv_last
= stlv_last
->next
)
2113 stlv_last
->next
= tlv
;
2115 attr
->vnc_subtlvs
= tlv
;
2121 if (BGP_ATTR_ENCAP
== type
) {
2122 attr
->encap_tunneltype
= tunneltype
;
2126 /* spurious leftover data */
2128 "Tunnel Encap attribute length is bad: %d leftover octets",
2130 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2131 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2140 * Read an individual SID value returning how much data we have read
2141 * Returns 0 if there was an error that needs to be passed up the stack
2143 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(int32_t type
,
2145 struct bgp_attr_parser_args
*args
,
2146 struct bgp_nlri
*mp_update
)
2148 struct peer
*const peer
= args
->peer
;
2149 struct attr
*const attr
= args
->attr
;
2150 uint32_t label_index
;
2151 struct in6_addr ipv6_sid
;
2153 uint32_t srgb_range
;
2156 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2157 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2160 "Prefix SID label index length is %d instead of %d",
2161 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2162 return bgp_attr_malformed(args
,
2163 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2167 /* Ignore flags and reserved */
2168 stream_getc(peer
->curr
);
2169 stream_getw(peer
->curr
);
2171 /* Fetch the label index and see if it is valid. */
2172 label_index
= stream_getl(peer
->curr
);
2173 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2174 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2177 /* Store label index; subsequently, we'll check on
2179 attr
->label_index
= label_index
;
2182 * Ignore the Label index attribute unless received for
2186 if (!mp_update
->length
2187 || mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2188 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
2191 /* Placeholder code for the IPv6 SID type */
2192 else if (type
== BGP_PREFIX_SID_IPV6
) {
2193 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2194 flog_err(EC_BGP_ATTR_LEN
,
2195 "Prefix SID IPv6 length is %d instead of %d",
2196 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2197 return bgp_attr_malformed(args
,
2198 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2202 /* Ignore reserved */
2203 stream_getc(peer
->curr
);
2204 stream_getw(peer
->curr
);
2206 stream_get(&ipv6_sid
, peer
->curr
, 16);
2209 /* Placeholder code for the Originator SRGB type */
2210 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2212 stream_getw(peer
->curr
);
2216 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2219 "Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2220 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2221 return bgp_attr_malformed(
2222 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2226 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2228 for (int i
= 0; i
< srgb_count
; i
++) {
2229 stream_get(&srgb_base
, peer
->curr
, 3);
2230 stream_get(&srgb_range
, peer
->curr
, 3);
2234 return BGP_ATTR_PARSE_PROCEED
;
2237 /* Prefix SID attribute
2238 * draft-ietf-idr-bgp-prefix-sid-05
2240 bgp_attr_parse_ret_t
2241 bgp_attr_prefix_sid(int32_t tlength
, struct bgp_attr_parser_args
*args
,
2242 struct bgp_nlri
*mp_update
)
2244 struct peer
*const peer
= args
->peer
;
2245 struct attr
*const attr
= args
->attr
;
2246 bgp_attr_parse_ret_t ret
;
2248 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2251 int32_t type
, length
;
2253 type
= stream_getc(peer
->curr
);
2254 length
= stream_getw(peer
->curr
);
2256 ret
= bgp_attr_psid_sub(type
, length
, args
, mp_update
);
2258 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2261 * Subtract length + the T and the L
2262 * since length is the Vector portion
2264 tlength
-= length
+ 3;
2269 "Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
2271 return bgp_attr_malformed(args
,
2272 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2277 return BGP_ATTR_PARSE_PROCEED
;
2280 /* PMSI tunnel attribute (RFC 6514)
2281 * Basic validation checks done here.
2283 static bgp_attr_parse_ret_t
2284 bgp_attr_pmsi_tunnel(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
;
2290 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2292 /* Verify that the receiver is expecting "ingress replication" as we
2293 * can only support that.
2295 if (length
< attr_parse_len
) {
2296 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2298 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2301 stream_getc(peer
->curr
); /* Flags */
2302 tnl_type
= stream_getc(peer
->curr
);
2303 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2304 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2305 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2306 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2309 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2311 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2312 "Bad PMSI tunnel attribute length %d for IR",
2314 return bgp_attr_malformed(
2315 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2320 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2321 attr
->pmsi_tnl_type
= tnl_type
;
2322 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2324 /* Forward read pointer of input stream. */
2325 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2327 return BGP_ATTR_PARSE_PROCEED
;
2330 /* BGP unknown attribute treatment. */
2331 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2333 bgp_size_t total
= args
->total
;
2334 struct transit
*transit
;
2335 struct peer
*const peer
= args
->peer
;
2336 struct attr
*const attr
= args
->attr
;
2337 uint8_t *const startp
= args
->startp
;
2338 const uint8_t type
= args
->type
;
2339 const uint8_t flag
= args
->flags
;
2340 const bgp_size_t length
= args
->length
;
2342 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2344 "%s Unknown attribute is received (type %d, length %d)",
2345 peer
->host
, type
, length
);
2347 /* Forward read pointer of input stream. */
2348 stream_forward_getp(peer
->curr
, length
);
2350 /* If any of the mandatory well-known attributes are not recognized,
2351 then the Error Subcode is set to Unrecognized Well-known
2352 Attribute. The Data field contains the unrecognized attribute
2353 (type, length and value). */
2354 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2355 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2359 /* Unrecognized non-transitive optional attributes must be quietly
2360 ignored and not passed along to other BGP peers. */
2361 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2362 return BGP_ATTR_PARSE_PROCEED
;
2364 /* If a path with recognized transitive optional attribute is
2365 accepted and passed along to other BGP peers and the Partial bit
2366 in the Attribute Flags octet is set to 1 by some previous AS, it
2367 is not set back to 0 by the current AS. */
2368 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2370 /* Store transitive attribute to the end of attr->transit. */
2372 attr
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2374 transit
= attr
->transit
;
2377 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2378 transit
->length
+ total
);
2380 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2382 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2383 transit
->length
+= total
;
2385 return BGP_ATTR_PARSE_PROCEED
;
2388 /* Well-known attribute check. */
2389 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2393 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2395 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2396 return BGP_ATTR_PARSE_PROCEED
;
2398 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2399 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2400 are present, it should. Check for any other attribute being present
2403 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2404 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2405 return BGP_ATTR_PARSE_PROCEED
;
2407 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2408 type
= BGP_ATTR_ORIGIN
;
2410 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2411 type
= BGP_ATTR_AS_PATH
;
2413 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2415 * NLRI is empty. We can't easily check NLRI empty here though.
2417 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2418 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2419 type
= BGP_ATTR_NEXT_HOP
;
2421 if (peer
->sort
== BGP_PEER_IBGP
2422 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2423 type
= BGP_ATTR_LOCAL_PREF
;
2426 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2427 "%s Missing well-known attribute %s.", peer
->host
,
2428 lookup_msg(attr_str
, type
, NULL
));
2429 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2430 BGP_NOTIFY_UPDATE_MISS_ATTR
, &type
,
2432 return BGP_ATTR_PARSE_ERROR
;
2434 return BGP_ATTR_PARSE_PROCEED
;
2437 /* Read attribute of update packet. This function is called from
2438 bgp_update_receive() in bgp_packet.c. */
2439 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2440 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2441 struct bgp_nlri
*mp_withdraw
)
2443 bgp_attr_parse_ret_t ret
;
2447 uint8_t *startp
, *endp
;
2449 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2450 /* we need the as4_path only until we have synthesized the as_path with
2452 /* same goes for as4_aggregator */
2453 struct aspath
*as4_path
= NULL
;
2454 as_t as4_aggregator
= 0;
2455 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2457 /* Initialize bitmap. */
2458 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2460 /* End pointer of BGP attribute. */
2461 endp
= BGP_INPUT_PNT(peer
) + size
;
2463 /* Get attributes to the end of attribute length. */
2464 while (BGP_INPUT_PNT(peer
) < endp
) {
2465 /* Check remaining length check.*/
2466 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2467 /* XXX warning: long int format, int arg (arg 5) */
2469 EC_BGP_ATTRIBUTE_TOO_SMALL
,
2470 "%s: error BGP attribute length %lu is smaller than min len",
2472 (unsigned long)(endp
2473 - stream_pnt(BGP_INPUT(peer
))));
2475 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2476 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2477 return BGP_ATTR_PARSE_ERROR
;
2480 /* Fetch attribute flag and type. */
2481 startp
= BGP_INPUT_PNT(peer
);
2482 /* "The lower-order four bits of the Attribute Flags octet are
2483 unused. They MUST be zero when sent and MUST be ignored when
2485 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2486 type
= stream_getc(BGP_INPUT(peer
));
2488 /* Check whether Extended-Length applies and is in bounds */
2489 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2490 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2492 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
2493 "%s: Extended length set, but just %lu bytes of attr header",
2495 (unsigned long)(endp
2496 - stream_pnt(BGP_INPUT(peer
))));
2498 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2499 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2500 return BGP_ATTR_PARSE_ERROR
;
2503 /* Check extended attribue length bit. */
2504 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2505 length
= stream_getw(BGP_INPUT(peer
));
2507 length
= stream_getc(BGP_INPUT(peer
));
2509 /* If any attribute appears more than once in the UPDATE
2510 message, then the Error Subcode is set to Malformed Attribute
2513 if (CHECK_BITMAP(seen
, type
)) {
2515 EC_BGP_ATTRIBUTE_REPEATED
,
2516 "%s: error BGP attribute type %d appears twice in a message",
2519 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2520 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2521 return BGP_ATTR_PARSE_ERROR
;
2524 /* Set type to bitmap to check duplicate attribute. `type' is
2525 unsigned char so it never overflow bitmap range. */
2527 SET_BITMAP(seen
, type
);
2529 /* Overflow check. */
2530 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2532 if (attr_endp
> endp
) {
2534 EC_BGP_ATTRIBUTE_TOO_LARGE
,
2535 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
2536 peer
->host
, type
, length
, size
, attr_endp
,
2540 * If any recognized attribute has an Attribute
2541 * Length that conflicts with the expected length
2542 * (based on the attribute type code), then the
2543 * Error Subcode MUST be set to Attribute Length
2544 * Error. The Data field MUST contain the erroneous
2545 * attribute (type, length, and value).
2547 * We do not currently have a good way to determine the
2548 * length of the attribute independent of the length
2549 * received in the message. Instead we send the
2550 * minimum between the amount of data we have and the
2551 * amount specified by the attribute length field.
2553 * Instead of directly passing in the packet buffer and
2554 * offset we use the stream_get* functions to read into
2555 * a stack buffer, since they perform bounds checking
2556 * and we are working with untrusted data.
2558 unsigned char ndata
[BGP_MAX_PACKET_SIZE
];
2559 memset(ndata
, 0x00, sizeof(ndata
));
2561 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
2562 /* Rewind to end of flag field */
2563 stream_forward_getp(BGP_INPUT(peer
), -(1 + lfl
));
2565 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
2567 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
2569 size_t atl
= attr_endp
- startp
;
2570 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
2571 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
2573 bgp_notify_send_with_data(
2574 peer
, BGP_NOTIFY_UPDATE_ERR
,
2575 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
2578 return BGP_ATTR_PARSE_ERROR
;
2581 struct bgp_attr_parser_args attr_args
= {
2588 .total
= attr_endp
- startp
,
2592 /* If any recognized attribute has Attribute Flags that conflict
2593 with the Attribute Type Code, then the Error Subcode is set
2595 Attribute Flags Error. The Data field contains the erroneous
2596 attribute (type, length and value). */
2597 if (bgp_attr_flag_invalid(&attr_args
)) {
2598 ret
= bgp_attr_malformed(
2599 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2601 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2606 /* OK check attribute and store it's value. */
2608 case BGP_ATTR_ORIGIN
:
2609 ret
= bgp_attr_origin(&attr_args
);
2611 case BGP_ATTR_AS_PATH
:
2612 ret
= bgp_attr_aspath(&attr_args
);
2614 case BGP_ATTR_AS4_PATH
:
2615 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
2617 case BGP_ATTR_NEXT_HOP
:
2618 ret
= bgp_attr_nexthop(&attr_args
);
2620 case BGP_ATTR_MULTI_EXIT_DISC
:
2621 ret
= bgp_attr_med(&attr_args
);
2623 case BGP_ATTR_LOCAL_PREF
:
2624 ret
= bgp_attr_local_pref(&attr_args
);
2626 case BGP_ATTR_ATOMIC_AGGREGATE
:
2627 ret
= bgp_attr_atomic(&attr_args
);
2629 case BGP_ATTR_AGGREGATOR
:
2630 ret
= bgp_attr_aggregator(&attr_args
);
2632 case BGP_ATTR_AS4_AGGREGATOR
:
2633 ret
= bgp_attr_as4_aggregator(&attr_args
,
2635 &as4_aggregator_addr
);
2637 case BGP_ATTR_COMMUNITIES
:
2638 ret
= bgp_attr_community(&attr_args
);
2640 case BGP_ATTR_LARGE_COMMUNITIES
:
2641 ret
= bgp_attr_large_community(&attr_args
);
2643 case BGP_ATTR_ORIGINATOR_ID
:
2644 ret
= bgp_attr_originator_id(&attr_args
);
2646 case BGP_ATTR_CLUSTER_LIST
:
2647 ret
= bgp_attr_cluster_list(&attr_args
);
2649 case BGP_ATTR_MP_REACH_NLRI
:
2650 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
2652 case BGP_ATTR_MP_UNREACH_NLRI
:
2653 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
2655 case BGP_ATTR_EXT_COMMUNITIES
:
2656 ret
= bgp_attr_ext_communities(&attr_args
);
2658 #if ENABLE_BGP_VNC_ATTR
2661 case BGP_ATTR_ENCAP
:
2662 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
2665 case BGP_ATTR_PREFIX_SID
:
2666 ret
= bgp_attr_prefix_sid(length
,
2667 &attr_args
, mp_update
);
2669 case BGP_ATTR_PMSI_TUNNEL
:
2670 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
2673 ret
= bgp_attr_unknown(&attr_args
);
2677 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
2678 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2679 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2680 ret
= BGP_ATTR_PARSE_ERROR
;
2683 if (ret
== BGP_ATTR_PARSE_EOR
) {
2685 aspath_unintern(&as4_path
);
2689 /* If hard error occurred immediately return to the caller. */
2690 if (ret
== BGP_ATTR_PARSE_ERROR
) {
2691 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
2692 "%s: Attribute %s, parse error", peer
->host
,
2693 lookup_msg(attr_str
, type
, NULL
));
2695 aspath_unintern(&as4_path
);
2698 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
2701 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
2702 "%s: Attribute %s, parse error - treating as withdrawal",
2703 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2705 aspath_unintern(&as4_path
);
2709 /* Check the fetched length. */
2710 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
2711 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
2712 "%s: BGP attribute %s, fetch error",
2713 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2714 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2715 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2717 aspath_unintern(&as4_path
);
2718 return BGP_ATTR_PARSE_ERROR
;
2722 /* Check final read pointer is same as end pointer. */
2723 if (BGP_INPUT_PNT(peer
) != endp
) {
2724 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
2725 "%s: BGP attribute %s, length mismatch", peer
->host
,
2726 lookup_msg(attr_str
, type
, NULL
));
2727 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2728 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2730 aspath_unintern(&as4_path
);
2731 return BGP_ATTR_PARSE_ERROR
;
2735 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
2736 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
2737 * This is implemented below and will result in a NOTIFICATION. If the
2738 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
2739 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
2740 * message SHOULD NOT be sent. This is implemented elsewhere.
2742 * RFC4760: An UPDATE message that carries no NLRI, other than the one
2743 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
2744 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
2745 * speaker that receives the message SHOULD ignore this attribute.
2747 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2748 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
2749 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
2750 return BGP_ATTR_PARSE_ERROR
;
2754 /* Check all mandatory well-known attributes are present */
2755 if ((ret
= bgp_attr_check(peer
, attr
)) < 0) {
2757 aspath_unintern(&as4_path
);
2762 * At this place we can see whether we got AS4_PATH and/or
2763 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2764 * We can not do this before we've read all attributes because
2765 * the as4 handling does not say whether AS4_PATH has to be sent
2766 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2767 * in relationship to AGGREGATOR.
2768 * So, to be defensive, we are not relying on any order and read
2769 * all attributes first, including these 32bit ones, and now,
2770 * afterwards, we look what and if something is to be done for as4.
2772 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2775 /* actually... this doesn't ever return failure currently, but
2776 * better safe than sorry */
2777 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
2778 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
2779 &as4_aggregator_addr
)) {
2780 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2781 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2783 aspath_unintern(&as4_path
);
2784 return BGP_ATTR_PARSE_ERROR
;
2787 /* At this stage, we have done all fiddling with as4, and the
2788 * resulting info is in attr->aggregator resp. attr->aspath
2789 * so we can chuck as4_aggregator and as4_path alltogether in
2790 * order to save memory
2793 aspath_unintern(&as4_path
); /* unintern - it is in the hash */
2794 /* The flag that we got this is still there, but that does not
2799 * The "rest" of the code does nothing with as4_aggregator.
2800 * there is no memory attached specifically which is not part
2802 * so ignoring just means do nothing.
2805 * Finally do the checks on the aspath we did not do yet
2806 * because we waited for a potentially synthesized aspath.
2808 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
2809 ret
= bgp_attr_aspath_check(peer
, attr
);
2810 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2813 /* Finally intern unknown attribute. */
2815 attr
->transit
= transit_intern(attr
->transit
);
2816 if (attr
->encap_subtlvs
)
2817 attr
->encap_subtlvs
=
2818 encap_intern(attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2820 if (attr
->vnc_subtlvs
)
2822 encap_intern(attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2825 return BGP_ATTR_PARSE_PROCEED
;
2829 * Extract the tunnel type from extended community
2831 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
2832 bgp_encap_types
*tunnel_type
)
2834 struct ecommunity
*ecom
;
2839 ecom
= attr
->ecommunity
;
2840 if (!ecom
|| !ecom
->size
)
2843 for (i
= 0; i
< ecom
->size
; i
++) {
2845 uint8_t type
, sub_type
;
2847 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
2850 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
2851 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
2853 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
2860 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
2861 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
2866 iana_safi_t pkt_safi
;
2869 /* Set extended bit always to encode the attribute length as 2 bytes */
2870 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
2871 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
2872 sizep
= stream_get_endp(s
);
2873 stream_putw(s
, 0); /* Marker: Attribute length. */
2876 /* Convert AFI, SAFI to values for packet. */
2877 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
2879 stream_putw(s
, pkt_afi
); /* AFI */
2880 stream_putc(s
, pkt_safi
); /* SAFI */
2884 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
2885 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
2887 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
2890 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2895 case SAFI_MULTICAST
:
2896 case SAFI_LABELED_UNICAST
:
2898 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
2902 stream_putl(s
, 0); /* RD = 0, per RFC */
2904 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2909 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2912 stream_putc(s
, 0); /* no nexthop for flowspec */
2920 case SAFI_MULTICAST
:
2921 case SAFI_LABELED_UNICAST
:
2923 if (attr
->mp_nexthop_len
2924 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2926 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2927 stream_put(s
, &attr
->mp_nexthop_global
,
2929 stream_put(s
, &attr
->mp_nexthop_local
,
2932 stream_putc(s
, IPV6_MAX_BYTELEN
);
2933 stream_put(s
, &attr
->mp_nexthop_global
,
2937 case SAFI_MPLS_VPN
: {
2938 if (attr
->mp_nexthop_len
2939 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2941 stream_putl(s
, 0); /* RD = 0, per RFC */
2943 stream_put(s
, &attr
->mp_nexthop_global
,
2945 } else if (attr
->mp_nexthop_len
2946 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2948 stream_putl(s
, 0); /* RD = 0, per RFC */
2950 stream_put(s
, &attr
->mp_nexthop_global
,
2952 stream_putl(s
, 0); /* RD = 0, per RFC */
2954 stream_put(s
, &attr
->mp_nexthop_local
,
2959 stream_putc(s
, IPV6_MAX_BYTELEN
);
2960 stream_put(s
, &attr
->mp_nexthop_global
,
2964 stream_putc(s
, 0); /* no nexthop for flowspec */
2970 if (safi
!= SAFI_FLOWSPEC
)
2972 EC_BGP_ATTR_NH_SEND_LEN
,
2973 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
2974 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
2983 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
2984 struct prefix
*p
, struct prefix_rd
*prd
,
2985 mpls_label_t
*label
, uint32_t num_labels
,
2986 int addpath_encode
, uint32_t addpath_tx_id
,
2989 if (safi
== SAFI_MPLS_VPN
) {
2991 stream_putl(s
, addpath_tx_id
);
2992 /* Label, RD, Prefix write. */
2993 stream_putc(s
, p
->prefixlen
+ 88);
2994 stream_put(s
, label
, BGP_LABEL_BYTES
);
2995 stream_put(s
, prd
->val
, 8);
2996 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
2997 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
2998 /* EVPN prefix - contents depend on type */
2999 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3000 addpath_encode
, addpath_tx_id
);
3001 } else if (safi
== SAFI_LABELED_UNICAST
) {
3002 /* Prefix write with label. */
3003 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3005 } else if (safi
== SAFI_FLOWSPEC
) {
3006 if (PSIZE (p
->prefixlen
)+2 < FLOWSPEC_NLRI_SIZELIMIT
)
3007 stream_putc(s
, PSIZE (p
->prefixlen
)+2);
3009 stream_putw(s
, (PSIZE (p
->prefixlen
)+2)|(0xf<<12));
3010 stream_putc(s
, 2);/* Filter type */
3011 stream_putc(s
, p
->prefixlen
);/* Prefix length */
3012 stream_put(s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
3014 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3017 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
, struct prefix
*p
)
3019 int size
= PSIZE(p
->prefixlen
);
3020 if (safi
== SAFI_MPLS_VPN
)
3022 else if (safi
== SAFI_LABELED_UNICAST
)
3023 size
+= BGP_LABEL_BYTES
;
3024 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3025 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3031 * Encodes the tunnel encapsulation attribute,
3032 * and with ENABLE_BGP_VNC the VNC attribute which uses
3033 * almost the same TLV format
3035 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3036 struct stream
*s
, struct attr
*attr
,
3039 unsigned int attrlenfield
= 0;
3040 unsigned int attrhdrlen
= 0;
3041 struct bgp_attr_encap_subtlv
*subtlvs
;
3042 struct bgp_attr_encap_subtlv
*st
;
3043 const char *attrname
;
3045 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3046 && (!attr
->encap_tunneltype
3047 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3051 case BGP_ATTR_ENCAP
:
3052 attrname
= "Tunnel Encap";
3053 subtlvs
= attr
->encap_subtlvs
;
3054 if (subtlvs
== NULL
) /* nothing to do */
3057 * The tunnel encap attr has an "outer" tlv.
3059 * L = total length of subtlvs,
3060 * V = concatenated subtlvs.
3062 attrlenfield
= 2 + 2; /* T + L */
3063 attrhdrlen
= 1 + 1; /* subTLV T + L */
3066 #if ENABLE_BGP_VNC_ATTR
3069 subtlvs
= attr
->vnc_subtlvs
;
3070 if (subtlvs
== NULL
) /* nothing to do */
3072 attrlenfield
= 0; /* no outer T + L */
3073 attrhdrlen
= 2 + 2; /* subTLV T + L */
3081 /* compute attr length */
3082 for (st
= subtlvs
; st
; st
= st
->next
) {
3083 attrlenfield
+= (attrhdrlen
+ st
->length
);
3086 if (attrlenfield
> 0xffff) {
3087 zlog_info("%s attribute is too long (length=%d), can't send it",
3088 attrname
, attrlenfield
);
3092 if (attrlenfield
> 0xff) {
3093 /* 2-octet length field */
3095 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3096 | BGP_ATTR_FLAG_EXTLEN
);
3097 stream_putc(s
, attrtype
);
3098 stream_putw(s
, attrlenfield
& 0xffff);
3100 /* 1-octet length field */
3101 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3102 stream_putc(s
, attrtype
);
3103 stream_putc(s
, attrlenfield
& 0xff);
3106 if (attrtype
== BGP_ATTR_ENCAP
) {
3107 /* write outer T+L */
3108 stream_putw(s
, attr
->encap_tunneltype
);
3109 stream_putw(s
, attrlenfield
- 4);
3112 /* write each sub-tlv */
3113 for (st
= subtlvs
; st
; st
= st
->next
) {
3114 if (attrtype
== BGP_ATTR_ENCAP
) {
3115 stream_putc(s
, st
->type
);
3116 stream_putc(s
, st
->length
);
3119 stream_putw(s
, st
->type
);
3120 stream_putw(s
, st
->length
);
3123 stream_put(s
, st
->value
, st
->length
);
3127 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3129 /* Set MP attribute length. Don't count the (2) bytes used to encode
3131 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3134 static int bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3136 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3137 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3138 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3139 PEER_FLAG_REMOVE_PRIVATE_AS
)
3140 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3141 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3142 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3143 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3144 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3145 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3150 /* Make attribute packet. */
3151 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3152 struct stream
*s
, struct attr
*attr
,
3153 struct bpacket_attr_vec_arr
*vecarr
,
3154 struct prefix
*p
, afi_t afi
, safi_t safi
,
3155 struct peer
*from
, struct prefix_rd
*prd
,
3156 mpls_label_t
*label
, uint32_t num_labels
,
3157 int addpath_encode
, uint32_t addpath_tx_id
)
3160 size_t aspath_sizep
;
3161 struct aspath
*aspath
;
3162 int send_as4_path
= 0;
3163 int send_as4_aggregator
= 0;
3164 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3169 /* Remember current pointer. */
3170 cp
= stream_get_endp(s
);
3173 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3174 && !peer_cap_enhe(peer
, afi
, safi
))) {
3175 size_t mpattrlen_pos
= 0;
3177 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3179 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3180 num_labels
, addpath_encode
,
3181 addpath_tx_id
, attr
);
3182 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3185 /* Origin attribute. */
3186 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3187 stream_putc(s
, BGP_ATTR_ORIGIN
);
3189 stream_putc(s
, attr
->origin
);
3191 /* AS path attribute. */
3193 /* If remote-peer is EBGP */
3194 if (peer
->sort
== BGP_PEER_EBGP
3195 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3196 PEER_FLAG_AS_PATH_UNCHANGED
)
3197 || attr
->aspath
->segments
== NULL
)
3198 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3199 PEER_FLAG_RSERVER_CLIENT
))) {
3200 aspath
= aspath_dup(attr
->aspath
);
3202 /* Even though we may not be configured for confederations we
3204 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3205 aspath
= aspath_delete_confed_seq(aspath
);
3207 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3208 /* Stuff our path CONFED_ID on the front */
3209 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3211 if (peer
->change_local_as
) {
3212 /* If replace-as is specified, we only use the
3213 change_local_as when
3214 advertising routes. */
3215 if (!CHECK_FLAG(peer
->flags
,
3216 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3217 if (bgp_append_local_as(peer
, afi
,
3219 aspath
= aspath_add_seq(
3220 aspath
, peer
->local_as
);
3221 aspath
= aspath_add_seq(aspath
,
3222 peer
->change_local_as
);
3224 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3227 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3228 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3230 aspath
= aspath_dup(attr
->aspath
);
3231 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3233 aspath
= attr
->aspath
;
3235 /* If peer is not AS4 capable, then:
3236 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3237 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3239 * types are in it (i.e. exclude them if they are there)
3240 * AND do this only if there is at least one asnum > 65535 in the
3242 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3244 * all ASnums > 65535 to BGP_AS_TRANS
3247 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3248 stream_putc(s
, BGP_ATTR_AS_PATH
);
3249 aspath_sizep
= stream_get_endp(s
);
3251 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3253 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3256 if (!use32bit
&& aspath_has_as4(aspath
))
3258 1; /* we'll do this later, at the correct place */
3260 /* Nexthop attribute. */
3261 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3262 && !peer_cap_enhe(peer
, afi
, safi
)) {
3263 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3265 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3266 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3267 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3268 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3271 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3272 } else if (peer_cap_enhe(from
, afi
, safi
)
3273 || (nh_afi
== AFI_IP6
)) {
3275 * Likely this is the case when an IPv4 prefix was
3276 * received with Extended Next-hop capability in this
3277 * or another vrf and is now being advertised to
3278 * non-ENHE peers. Since peer_cap_enhe only checks
3279 * peers in this vrf, also check the nh_afi to catch
3280 * the case where the originator was in another vrf.
3281 * Setting the mandatory (ipv4) next-hop attribute here
3282 * to enable implicit next-hop self with correct A-F
3283 * (ipv4 address family).
3285 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3286 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3287 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3290 stream_put_ipv4(s
, 0);
3294 /* MED attribute. */
3295 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3296 || bgp
->maxmed_active
) {
3297 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3298 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3300 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3304 /* Local preference. */
3305 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3306 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3307 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3309 stream_putl(s
, attr
->local_pref
);
3312 /* Atomic aggregate. */
3313 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3314 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3315 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3320 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3321 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3322 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3323 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3326 /* AS4 capable peer */
3328 stream_putl(s
, attr
->aggregator_as
);
3330 /* 2-byte AS peer */
3333 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3335 if (attr
->aggregator_as
> 65535) {
3336 stream_putw(s
, BGP_AS_TRANS
);
3338 /* we have to send AS4_AGGREGATOR, too.
3339 * we'll do that later in order to send
3340 * attributes in ascending
3343 send_as4_aggregator
= 1;
3345 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3347 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3350 /* Community attribute. */
3351 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3352 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3353 if (attr
->community
->size
* 4 > 255) {
3355 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3356 | BGP_ATTR_FLAG_EXTLEN
);
3357 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3358 stream_putw(s
, attr
->community
->size
* 4);
3361 BGP_ATTR_FLAG_OPTIONAL
3362 | BGP_ATTR_FLAG_TRANS
);
3363 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3364 stream_putc(s
, attr
->community
->size
* 4);
3366 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3370 * Large Community attribute.
3372 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3373 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3374 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3375 if (lcom_length(attr
->lcommunity
) > 255) {
3377 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3378 | BGP_ATTR_FLAG_EXTLEN
);
3379 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3380 stream_putw(s
, lcom_length(attr
->lcommunity
));
3383 BGP_ATTR_FLAG_OPTIONAL
3384 | BGP_ATTR_FLAG_TRANS
);
3385 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3386 stream_putc(s
, lcom_length(attr
->lcommunity
));
3388 stream_put(s
, attr
->lcommunity
->val
,
3389 lcom_length(attr
->lcommunity
));
3392 /* Route Reflector. */
3393 if (peer
->sort
== BGP_PEER_IBGP
&& from
3394 && from
->sort
== BGP_PEER_IBGP
) {
3395 /* Originator ID. */
3396 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3397 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3400 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3401 stream_put_in_addr(s
, &attr
->originator_id
);
3403 stream_put_in_addr(s
, &from
->remote_id
);
3406 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3407 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3409 if (attr
->cluster
) {
3410 stream_putc(s
, attr
->cluster
->length
+ 4);
3411 /* If this peer configuration's parent BGP has
3413 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3414 stream_put_in_addr(s
, &bgp
->cluster_id
);
3416 stream_put_in_addr(s
, &bgp
->router_id
);
3417 stream_put(s
, attr
->cluster
->list
,
3418 attr
->cluster
->length
);
3421 /* If this peer configuration's parent BGP has
3423 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3424 stream_put_in_addr(s
, &bgp
->cluster_id
);
3426 stream_put_in_addr(s
, &bgp
->router_id
);
3430 /* Extended Communities attribute. */
3431 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3432 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3433 if (peer
->sort
== BGP_PEER_IBGP
3434 || peer
->sort
== BGP_PEER_CONFED
) {
3435 if (attr
->ecommunity
->size
* 8 > 255) {
3437 BGP_ATTR_FLAG_OPTIONAL
3438 | BGP_ATTR_FLAG_TRANS
3439 | BGP_ATTR_FLAG_EXTLEN
);
3440 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3441 stream_putw(s
, attr
->ecommunity
->size
* 8);
3444 BGP_ATTR_FLAG_OPTIONAL
3445 | BGP_ATTR_FLAG_TRANS
);
3446 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3447 stream_putc(s
, attr
->ecommunity
->size
* 8);
3449 stream_put(s
, attr
->ecommunity
->val
,
3450 attr
->ecommunity
->size
* 8);
3454 int ecom_tr_size
= 0;
3457 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3458 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3461 if (CHECK_FLAG(tbit
,
3462 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3469 if (ecom_tr_size
* 8 > 255) {
3472 BGP_ATTR_FLAG_OPTIONAL
3473 | BGP_ATTR_FLAG_TRANS
3474 | BGP_ATTR_FLAG_EXTLEN
);
3476 BGP_ATTR_EXT_COMMUNITIES
);
3477 stream_putw(s
, ecom_tr_size
* 8);
3481 BGP_ATTR_FLAG_OPTIONAL
3482 | BGP_ATTR_FLAG_TRANS
);
3484 BGP_ATTR_EXT_COMMUNITIES
);
3485 stream_putc(s
, ecom_tr_size
* 8);
3488 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3489 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3494 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3497 stream_put(s
, pnt
, 8);
3503 /* Label index attribute. */
3504 if (safi
== SAFI_LABELED_UNICAST
) {
3505 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3506 uint32_t label_index
;
3508 label_index
= attr
->label_index
;
3510 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
3512 BGP_ATTR_FLAG_OPTIONAL
3513 | BGP_ATTR_FLAG_TRANS
);
3514 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3516 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3518 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3519 stream_putc(s
, 0); // reserved
3520 stream_putw(s
, 0); // flags
3521 stream_putl(s
, label_index
);
3526 if (send_as4_path
) {
3527 /* If the peer is NOT As4 capable, AND */
3528 /* there are ASnums > 65535 in path THEN
3529 * give out AS4_PATH */
3531 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3533 * Hm, I wonder... confederation things *should* only be at
3534 * the beginning of an aspath, right? Then we should use
3535 * aspath_delete_confed_seq for this, because it is already
3537 * Folks, talk to me: what is reasonable here!?
3539 aspath
= aspath_delete_confed_seq(aspath
);
3542 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3543 | BGP_ATTR_FLAG_EXTLEN
);
3544 stream_putc(s
, BGP_ATTR_AS4_PATH
);
3545 aspath_sizep
= stream_get_endp(s
);
3547 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
3550 if (aspath
!= attr
->aspath
)
3551 aspath_free(aspath
);
3553 if (send_as4_aggregator
) {
3554 /* send AS4_AGGREGATOR, at this place */
3555 /* this section of code moved here in order to ensure the
3557 * *ascending* order of attributes
3559 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3560 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
3562 stream_putl(s
, attr
->aggregator_as
);
3563 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3566 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3567 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3568 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
3569 /* Tunnel Encap attribute */
3570 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3572 #if ENABLE_BGP_VNC_ATTR
3574 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3579 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
3580 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3581 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
3582 stream_putc(s
, 9); // Length
3583 stream_putc(s
, 0); // Flags
3584 stream_putc(s
, attr
->pmsi_tnl_type
);
3585 stream_put(s
, &(attr
->label
),
3586 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
3587 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3588 // Unicast tunnel endpoint IP address
3591 /* Unknown transit attribute. */
3593 stream_put(s
, attr
->transit
->val
, attr
->transit
->length
);
3595 /* Return total size of attribute. */
3596 return stream_get_endp(s
) - cp
;
3599 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
3601 unsigned long attrlen_pnt
;
3603 iana_safi_t pkt_safi
;
3605 /* Set extended bit always to encode the attribute length as 2 bytes */
3606 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3607 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
3609 attrlen_pnt
= stream_get_endp(s
);
3610 stream_putw(s
, 0); /* Length of this attribute. */
3612 /* Convert AFI, SAFI to values for packet. */
3613 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3615 stream_putw(s
, pkt_afi
);
3616 stream_putc(s
, pkt_safi
);
3621 void bgp_packet_mpunreach_prefix(struct stream
*s
, struct prefix
*p
, afi_t afi
,
3622 safi_t safi
, struct prefix_rd
*prd
,
3623 mpls_label_t
*label
, uint32_t num_labels
,
3624 int addpath_encode
, uint32_t addpath_tx_id
,
3627 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
3629 if (safi
== SAFI_LABELED_UNICAST
) {
3630 label
= (mpls_label_t
*)wlabel
;
3634 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
3635 addpath_encode
, addpath_tx_id
, attr
);
3638 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
3640 bgp_packet_mpattr_end(s
, attrlen_pnt
);
3643 /* Initialization of attribute. */
3644 void bgp_attr_init(void)
3656 void bgp_attr_finish(void)
3661 ecommunity_finish();
3662 lcommunity_finish();
3668 /* Make attribute packet. */
3669 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
3670 struct prefix
*prefix
)
3675 struct aspath
*aspath
;
3676 int addpath_encode
= 0;
3677 uint32_t addpath_tx_id
= 0;
3679 /* Remember current pointer. */
3680 cp
= stream_get_endp(s
);
3682 /* Place holder of length. */
3685 /* Origin attribute. */
3686 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3687 stream_putc(s
, BGP_ATTR_ORIGIN
);
3689 stream_putc(s
, attr
->origin
);
3691 aspath
= attr
->aspath
;
3693 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3694 stream_putc(s
, BGP_ATTR_AS_PATH
);
3695 aspath_lenp
= stream_get_endp(s
);
3698 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
3700 /* Nexthop attribute. */
3701 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3702 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
3703 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3704 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3706 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3709 /* MED attribute. */
3710 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
3711 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3712 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3714 stream_putl(s
, attr
->med
);
3717 /* Local preference. */
3718 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
3719 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3720 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3722 stream_putl(s
, attr
->local_pref
);
3725 /* Atomic aggregate. */
3726 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3727 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3728 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3733 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3734 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3735 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3737 stream_putl(s
, attr
->aggregator_as
);
3738 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3741 /* Community attribute. */
3742 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3743 if (attr
->community
->size
* 4 > 255) {
3745 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3746 | BGP_ATTR_FLAG_EXTLEN
);
3747 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3748 stream_putw(s
, attr
->community
->size
* 4);
3751 BGP_ATTR_FLAG_OPTIONAL
3752 | BGP_ATTR_FLAG_TRANS
);
3753 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3754 stream_putc(s
, attr
->community
->size
* 4);
3756 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3759 /* Large Community attribute. */
3760 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
3761 if (lcom_length(attr
->lcommunity
) > 255) {
3763 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3764 | BGP_ATTR_FLAG_EXTLEN
);
3765 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3766 stream_putw(s
, lcom_length(attr
->lcommunity
));
3769 BGP_ATTR_FLAG_OPTIONAL
3770 | BGP_ATTR_FLAG_TRANS
);
3771 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3772 stream_putc(s
, lcom_length(attr
->lcommunity
));
3775 stream_put(s
, attr
->lcommunity
->val
,
3776 lcom_length(attr
->lcommunity
));
3779 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3780 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
3781 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
3782 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
3785 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3786 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3787 sizep
= stream_get_endp(s
);
3790 stream_putc(s
, 0); /* Marker: Attribute length. */
3791 stream_putw(s
, AFI_IP6
); /* AFI */
3792 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3795 stream_putc(s
, attr
->mp_nexthop_len
);
3796 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3797 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3798 stream_put(s
, &attr
->mp_nexthop_local
,
3805 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
3808 /* Set MP attribute length. */
3809 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
3813 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3814 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
3816 BGP_ATTR_FLAG_OPTIONAL
3817 | BGP_ATTR_FLAG_TRANS
);
3818 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3820 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3821 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3822 stream_putc(s
, 0); // reserved
3823 stream_putw(s
, 0); // flags
3824 stream_putl(s
, attr
->label_index
);
3828 /* Return total size of attribute. */
3829 len
= stream_get_endp(s
) - cp
- 2;
3830 stream_putw_at(s
, cp
, len
);