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 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
523 MIX(attr
->rmap_table_id
);
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
->rmap_table_id
== attr2
->rmap_table_id
551 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
552 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
554 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
556 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
557 &attr2
->mp_nexthop_global
)
558 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
559 &attr2
->mp_nexthop_local
)
560 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
561 &attr2
->mp_nexthop_global_in
)
562 && IPV4_ADDR_SAME(&attr1
->originator_id
,
563 &attr2
->originator_id
)
564 && overlay_index_same(attr1
, attr2
)
565 && attr1
->nh_ifindex
== attr2
->nh_ifindex
566 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
567 && attr1
->distance
== attr2
->distance
)
574 static void attrhash_init(void)
577 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
581 * special for hash_clean below
583 static void attr_vfree(void *attr
)
585 XFREE(MTYPE_ATTR
, attr
);
588 static void attrhash_finish(void)
590 hash_clean(attrhash
, attr_vfree
);
595 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
597 struct attr
*attr
= bucket
->data
;
599 vty_out(vty
, "attr[%ld] nexthop %s\n", attr
->refcnt
,
600 inet_ntoa(attr
->nexthop
));
601 vty_out(vty
, "\tflags: %" PRIu64
" med: %u local_pref: %u origin: %u weight: %u label: %u\n",
602 attr
->flag
, attr
->med
, attr
->local_pref
, attr
->origin
,
603 attr
->weight
, attr
->label
);
606 void attr_show_all(struct vty
*vty
)
608 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
609 void *))attr_show_all_iterator
,
613 static void *bgp_attr_hash_alloc(void *p
)
615 struct attr
*val
= (struct attr
*)p
;
618 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
620 if (val
->encap_subtlvs
) {
621 val
->encap_subtlvs
= NULL
;
624 if (val
->vnc_subtlvs
) {
625 val
->vnc_subtlvs
= NULL
;
632 /* Internet argument attribute. */
633 struct attr
*bgp_attr_intern(struct attr
*attr
)
637 /* Intern referenced strucutre. */
639 if (!attr
->aspath
->refcnt
)
640 attr
->aspath
= aspath_intern(attr
->aspath
);
642 attr
->aspath
->refcnt
++;
644 if (attr
->community
) {
645 if (!attr
->community
->refcnt
)
646 attr
->community
= community_intern(attr
->community
);
648 attr
->community
->refcnt
++;
651 if (attr
->ecommunity
) {
652 if (!attr
->ecommunity
->refcnt
)
653 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
655 attr
->ecommunity
->refcnt
++;
657 if (attr
->lcommunity
) {
658 if (!attr
->lcommunity
->refcnt
)
659 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
661 attr
->lcommunity
->refcnt
++;
664 if (!attr
->cluster
->refcnt
)
665 attr
->cluster
= cluster_intern(attr
->cluster
);
667 attr
->cluster
->refcnt
++;
670 if (!attr
->transit
->refcnt
)
671 attr
->transit
= transit_intern(attr
->transit
);
673 attr
->transit
->refcnt
++;
675 if (attr
->encap_subtlvs
) {
676 if (!attr
->encap_subtlvs
->refcnt
)
677 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
680 attr
->encap_subtlvs
->refcnt
++;
683 if (attr
->vnc_subtlvs
) {
684 if (!attr
->vnc_subtlvs
->refcnt
)
685 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
688 attr
->vnc_subtlvs
->refcnt
++;
692 /* At this point, attr only contains intern'd pointers. that means
693 * if we find it in attrhash, it has all the same pointers and we
694 * correctly updated the refcounts on these.
695 * If we don't find it, we need to allocate a one because in all
696 * cases this returns a new reference to a hashed attr, but the input
698 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
704 /* Make network statement's attribute. */
705 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
707 memset(attr
, 0, sizeof(struct attr
));
709 attr
->origin
= origin
;
710 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
711 attr
->aspath
= aspath_empty();
712 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
713 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
715 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
716 attr
->label
= MPLS_INVALID_LABEL
;
717 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
718 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
723 /* Create the attributes for an aggregate */
724 struct attr
*bgp_attr_aggregate_intern(struct bgp
*bgp
, uint8_t origin
,
725 struct aspath
*aspath
,
726 struct community
*community
,
727 struct ecommunity
*ecommunity
,
728 struct lcommunity
*lcommunity
,
729 struct bgp_aggregate
*aggregate
,
730 uint8_t atomic_aggregate
,
737 memset(&attr
, 0, sizeof(struct attr
));
739 /* Origin attribute. */
740 attr
.origin
= origin
;
741 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
743 /* AS path attribute. */
745 attr
.aspath
= aspath_intern(aspath
);
747 attr
.aspath
= aspath_empty();
748 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
750 /* Next hop attribute. */
751 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
754 uint32_t gshut
= COMMUNITY_GSHUT
;
756 /* If we are not shutting down ourselves and we are
757 * aggregating a route that contains the GSHUT community we
758 * need to remove that community when creating the aggregate */
759 if (!bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)
760 && community_include(community
, gshut
)) {
761 community_del_val(community
, &gshut
);
764 attr
.community
= community
;
765 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
769 attr
.ecommunity
= ecommunity
;
770 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
774 attr
.lcommunity
= lcommunity
;
775 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
778 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
779 bgp_attr_add_gshut_community(&attr
);
782 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
783 attr
.label
= MPLS_INVALID_LABEL
;
784 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
785 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
786 if (!aggregate
->as_set
|| atomic_aggregate
)
787 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
788 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
789 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
790 attr
.aggregator_as
= bgp
->confed_id
;
792 attr
.aggregator_as
= bgp
->as
;
793 attr
.aggregator_addr
= bgp
->router_id
;
794 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
795 attr
.label
= MPLS_INVALID_LABEL
;
797 /* Apply route-map */
798 if (aggregate
->rmap
.name
) {
799 struct attr attr_tmp
= attr
;
800 struct bgp_path_info rmap_path
;
802 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
803 rmap_path
.peer
= bgp
->peer_self
;
804 rmap_path
.attr
= &attr_tmp
;
806 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
808 ret
= route_map_apply(aggregate
->rmap
.map
, p
, RMAP_BGP
,
811 bgp
->peer_self
->rmap_type
= 0;
813 if (ret
== RMAP_DENYMATCH
) {
814 /* Free uninterned attribute. */
815 bgp_attr_flush(&attr_tmp
);
817 /* Unintern original. */
818 aspath_unintern(&attr
.aspath
);
822 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
823 bgp_attr_add_gshut_community(&attr_tmp
);
825 new = bgp_attr_intern(&attr_tmp
);
828 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
829 bgp_attr_add_gshut_community(&attr
);
831 new = bgp_attr_intern(&attr
);
834 aspath_unintern(&new->aspath
);
838 /* Unintern just the sub-components of the attr, but not the attr */
839 void bgp_attr_unintern_sub(struct attr
*attr
)
841 /* aspath refcount shoud be decrement. */
843 aspath_unintern(&attr
->aspath
);
844 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
847 community_unintern(&attr
->community
);
848 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
850 if (attr
->ecommunity
)
851 ecommunity_unintern(&attr
->ecommunity
);
852 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
854 if (attr
->lcommunity
)
855 lcommunity_unintern(&attr
->lcommunity
);
856 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
859 cluster_unintern(attr
->cluster
);
860 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
863 transit_unintern(attr
->transit
);
865 if (attr
->encap_subtlvs
)
866 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
869 if (attr
->vnc_subtlvs
)
870 encap_unintern(&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
875 * We have some show commands that let you experimentally
876 * apply a route-map. When we apply the route-map
877 * we are reseting values but not saving them for
878 * posterity via intern'ing( because route-maps don't
879 * do that) but at this point in time we need
880 * to compare the new attr to the old and if the
881 * routemap has changed it we need to, as Snoop Dog says,
882 * Drop it like it's hot
884 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
886 if (new->aspath
!= old
->aspath
)
887 aspath_free(new->aspath
);
889 if (new->community
!= old
->community
)
890 community_free(&new->community
);
892 if (new->ecommunity
!= old
->ecommunity
)
893 ecommunity_free(&new->ecommunity
);
895 if (new->lcommunity
!= old
->lcommunity
)
896 lcommunity_free(&new->lcommunity
);
899 /* Free bgp attribute and aspath. */
900 void bgp_attr_unintern(struct attr
**pattr
)
902 struct attr
*attr
= *pattr
;
906 /* Decrement attribute reference. */
911 /* If reference becomes zero then free attribute object. */
912 if (attr
->refcnt
== 0) {
913 ret
= hash_release(attrhash
, attr
);
915 XFREE(MTYPE_ATTR
, attr
);
919 bgp_attr_unintern_sub(&tmp
);
922 void bgp_attr_flush(struct attr
*attr
)
924 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
925 aspath_free(attr
->aspath
);
928 if (attr
->community
&& !attr
->community
->refcnt
)
929 community_free(&attr
->community
);
930 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
931 ecommunity_free(&attr
->ecommunity
);
932 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
933 lcommunity_free(&attr
->lcommunity
);
934 if (attr
->cluster
&& !attr
->cluster
->refcnt
) {
935 cluster_free(attr
->cluster
);
936 attr
->cluster
= NULL
;
938 if (attr
->transit
&& !attr
->transit
->refcnt
) {
939 transit_free(attr
->transit
);
940 attr
->transit
= NULL
;
942 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
943 encap_free(attr
->encap_subtlvs
);
944 attr
->encap_subtlvs
= NULL
;
947 if (attr
->vnc_subtlvs
&& !attr
->vnc_subtlvs
->refcnt
) {
948 encap_free(attr
->vnc_subtlvs
);
949 attr
->vnc_subtlvs
= NULL
;
954 /* Implement draft-scudder-idr-optional-transitive behaviour and
955 * avoid resetting sessions for malformed attributes which are
956 * are partial/optional and hence where the error likely was not
957 * introduced by the sending neighbour.
959 static bgp_attr_parse_ret_t
960 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
963 struct peer
*const peer
= args
->peer
;
964 const uint8_t flags
= args
->flags
;
965 /* startp and length must be special-cased, as whether or not to
966 * send the attribute data with the NOTIFY depends on the error,
967 * the caller therefore signals this with the seperate length argument
969 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
971 /* Only relax error handling for eBGP peers */
972 if (peer
->sort
!= BGP_PEER_EBGP
) {
973 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
974 notify_datap
, length
);
975 return BGP_ATTR_PARSE_ERROR
;
978 /* Adjust the stream getp to the end of the attribute, in case we can
979 * still proceed but the caller hasn't read all the attribute.
981 stream_set_getp(BGP_INPUT(peer
),
982 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
985 switch (args
->type
) {
986 /* where an attribute is relatively inconsequential, e.g. it does not
987 * affect route selection, and can be safely ignored, then any such
988 * attributes which are malformed should just be ignored and the route
989 * processed as normal.
991 case BGP_ATTR_AS4_AGGREGATOR
:
992 case BGP_ATTR_AGGREGATOR
:
993 case BGP_ATTR_ATOMIC_AGGREGATE
:
994 return BGP_ATTR_PARSE_PROCEED
;
996 /* Core attributes, particularly ones which may influence route
997 * selection, should always cause session resets
999 case BGP_ATTR_ORIGIN
:
1000 case BGP_ATTR_AS_PATH
:
1001 case BGP_ATTR_NEXT_HOP
:
1002 case BGP_ATTR_MULTI_EXIT_DISC
:
1003 case BGP_ATTR_LOCAL_PREF
:
1004 case BGP_ATTR_COMMUNITIES
:
1005 case BGP_ATTR_ORIGINATOR_ID
:
1006 case BGP_ATTR_CLUSTER_LIST
:
1007 case BGP_ATTR_MP_REACH_NLRI
:
1008 case BGP_ATTR_MP_UNREACH_NLRI
:
1009 case BGP_ATTR_EXT_COMMUNITIES
:
1010 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1011 notify_datap
, length
);
1012 return BGP_ATTR_PARSE_ERROR
;
1015 /* Partial optional attributes that are malformed should not cause
1016 * the whole session to be reset. Instead treat it as a withdrawal
1017 * of the routes, if possible.
1019 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1020 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1021 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1022 return BGP_ATTR_PARSE_WITHDRAW
;
1024 /* default to reset */
1025 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1028 /* Find out what is wrong with the path attribute flag bits and log the error.
1029 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1030 Extended Length. Checking O/T/P bits at once implies, that the attribute
1031 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1032 non-transitive" attribute. */
1034 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1035 uint8_t desired_flags
/* how RFC says it must be */
1038 uint8_t seen
= 0, i
;
1039 uint8_t real_flags
= args
->flags
;
1040 const uint8_t attr_code
= args
->type
;
1042 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1043 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1044 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1045 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1046 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1047 flog_err(EC_BGP_ATTR_FLAG
,
1048 "%s attribute must%s be flagged as \"%s\"",
1049 lookup_msg(attr_str
, attr_code
, NULL
),
1050 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1053 attr_flag_str
[i
].str
);
1058 "Strange, %s called for attr %s, but no problem found with flags"
1059 " (real flags 0x%x, desired 0x%x)",
1060 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1061 real_flags
, desired_flags
);
1065 /* Required flags for attributes. EXTLEN will be masked off when testing,
1066 * as will PARTIAL for optional+transitive attributes.
1068 const uint8_t attr_flags_values
[] = {
1069 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1070 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1071 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1072 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1073 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1074 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1075 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1076 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1077 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1078 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1079 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1080 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1081 [BGP_ATTR_EXT_COMMUNITIES
] =
1082 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1083 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1084 [BGP_ATTR_AS4_AGGREGATOR
] =
1085 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1086 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1087 [BGP_ATTR_LARGE_COMMUNITIES
] =
1088 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1089 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1091 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1093 static int bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1095 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1096 const uint8_t flags
= args
->flags
;
1097 const uint8_t attr_code
= args
->type
;
1099 /* there may be attributes we don't know about */
1100 if (attr_code
> attr_flags_values_max
)
1102 if (attr_flags_values
[attr_code
] == 0)
1105 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1109 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1110 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1113 "%s well-known attributes must have transitive flag set (%x)",
1114 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1118 /* "For well-known attributes and for optional non-transitive
1120 * the Partial bit MUST be set to 0."
1122 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1123 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1124 flog_err(EC_BGP_ATTR_FLAG
,
1125 "%s well-known attribute "
1126 "must NOT have the partial flag set (%x)",
1127 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1130 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1131 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1132 flog_err(EC_BGP_ATTR_FLAG
,
1133 "%s optional + transitive attribute "
1134 "must NOT have the partial flag set (%x)",
1135 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1140 /* Optional transitive attributes may go through speakers that don't
1141 * reocgnise them and set the Partial bit.
1143 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1144 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1145 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1147 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1150 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1154 /* Get origin attribute of the update message. */
1155 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1157 struct peer
*const peer
= args
->peer
;
1158 struct attr
*const attr
= args
->attr
;
1159 const bgp_size_t length
= args
->length
;
1161 /* If any recognized attribute has Attribute Length that conflicts
1162 with the expected length (based on the attribute type code), then
1163 the Error Subcode is set to Attribute Length Error. The Data
1164 field contains the erroneous attribute (type, length and
1167 flog_err(EC_BGP_ATTR_LEN
,
1168 "Origin attribute length is not one %d", length
);
1169 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1173 /* Fetch origin attribute. */
1174 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1176 /* If the ORIGIN attribute has an undefined value, then the Error
1177 Subcode is set to Invalid Origin Attribute. The Data field
1178 contains the unrecognized attribute (type, length and value). */
1179 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1180 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1181 flog_err(EC_BGP_ATTR_ORIGIN
,
1182 "Origin attribute value is invalid %d", attr
->origin
);
1183 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1187 /* Set oring attribute flag. */
1188 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1193 /* Parse AS path information. This function is wrapper of
1195 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1197 struct attr
*const attr
= args
->attr
;
1198 struct peer
*const peer
= args
->peer
;
1199 const bgp_size_t length
= args
->length
;
1202 * peer with AS4 => will get 4Byte ASnums
1203 * otherwise, will get 16 Bit
1205 attr
->aspath
= aspath_parse(peer
->curr
, length
,
1206 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1208 /* In case of IBGP, length will be zero. */
1209 if (!attr
->aspath
) {
1210 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1211 "Malformed AS path from %s, length is %d", peer
->host
,
1213 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1217 /* Set aspath attribute flag. */
1218 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1220 return BGP_ATTR_PARSE_PROCEED
;
1223 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1224 struct attr
*const attr
)
1226 /* These checks were part of bgp_attr_aspath, but with
1227 * as4 we should to check aspath things when
1228 * aspath synthesizing with as4_path has already taken place.
1229 * Otherwise we check ASPATH and use the synthesized thing, and that is
1231 * So do the checks later, i.e. here
1233 struct aspath
*aspath
;
1235 /* Confederation sanity check. */
1236 if ((peer
->sort
== BGP_PEER_CONFED
1237 && !aspath_left_confed_check(attr
->aspath
))
1238 || (peer
->sort
== BGP_PEER_EBGP
1239 && aspath_confed_check(attr
->aspath
))) {
1240 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1242 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1243 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1244 return BGP_ATTR_PARSE_ERROR
;
1247 /* First AS check for EBGP. */
1248 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1249 if (peer
->sort
== BGP_PEER_EBGP
1250 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1251 flog_err(EC_BGP_ATTR_FIRST_AS
,
1252 "%s incorrect first AS (must be %u)",
1253 peer
->host
, peer
->as
);
1254 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1255 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1256 return BGP_ATTR_PARSE_ERROR
;
1260 /* local-as prepend */
1261 if (peer
->change_local_as
1262 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1263 aspath
= aspath_dup(attr
->aspath
);
1264 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1265 aspath_unintern(&attr
->aspath
);
1266 attr
->aspath
= aspath_intern(aspath
);
1269 return BGP_ATTR_PARSE_PROCEED
;
1272 /* Parse AS4 path information. This function is another wrapper of
1274 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1275 struct aspath
**as4_path
)
1277 struct peer
*const peer
= args
->peer
;
1278 struct attr
*const attr
= args
->attr
;
1279 const bgp_size_t length
= args
->length
;
1281 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1283 /* In case of IBGP, length will be zero. */
1285 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1286 "Malformed AS4 path from %s, length is %d", peer
->host
,
1288 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1292 /* Set aspath attribute flag. */
1293 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1295 return BGP_ATTR_PARSE_PROCEED
;
1299 * Check that the nexthop attribute is valid.
1301 bgp_attr_parse_ret_t
1302 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1304 in_addr_t nexthop_h
;
1306 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1307 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1308 || IPV4_CLASS_DE(nexthop_h
))
1309 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1310 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1311 char buf
[INET_ADDRSTRLEN
];
1313 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1315 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1317 data
[0] = BGP_ATTR_FLAG_TRANS
;
1318 data
[1] = BGP_ATTR_NEXT_HOP
;
1319 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1320 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1321 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1322 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1324 return BGP_ATTR_PARSE_ERROR
;
1327 return BGP_ATTR_PARSE_PROCEED
;
1330 /* Nexthop attribute. */
1331 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1333 struct peer
*const peer
= args
->peer
;
1334 struct attr
*const attr
= args
->attr
;
1335 const bgp_size_t length
= args
->length
;
1337 /* Check nexthop attribute length. */
1339 flog_err(EC_BGP_ATTR_LEN
,
1340 "Nexthop attribute length isn't four [%d]", length
);
1342 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1346 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1347 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1349 return BGP_ATTR_PARSE_PROCEED
;
1352 /* MED atrribute. */
1353 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1355 struct peer
*const peer
= args
->peer
;
1356 struct attr
*const attr
= args
->attr
;
1357 const bgp_size_t length
= args
->length
;
1361 flog_err(EC_BGP_ATTR_LEN
,
1362 "MED attribute length isn't four [%d]", length
);
1364 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1368 attr
->med
= stream_getl(peer
->curr
);
1370 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1372 return BGP_ATTR_PARSE_PROCEED
;
1375 /* Local preference attribute. */
1376 static bgp_attr_parse_ret_t
1377 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1379 struct peer
*const peer
= args
->peer
;
1380 struct attr
*const attr
= args
->attr
;
1381 const bgp_size_t length
= args
->length
;
1385 flog_err(EC_BGP_ATTR_LEN
,
1386 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1387 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1391 /* If it is contained in an UPDATE message that is received from an
1392 external peer, then this attribute MUST be ignored by the
1393 receiving speaker. */
1394 if (peer
->sort
== BGP_PEER_EBGP
) {
1395 stream_forward_getp(peer
->curr
, length
);
1396 return BGP_ATTR_PARSE_PROCEED
;
1399 attr
->local_pref
= stream_getl(peer
->curr
);
1401 /* Set the local-pref flag. */
1402 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1404 return BGP_ATTR_PARSE_PROCEED
;
1407 /* Atomic aggregate. */
1408 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1410 struct attr
*const attr
= args
->attr
;
1411 const bgp_size_t length
= args
->length
;
1415 flog_err(EC_BGP_ATTR_LEN
,
1416 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1418 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1422 /* Set atomic aggregate flag. */
1423 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1425 return BGP_ATTR_PARSE_PROCEED
;
1428 /* Aggregator attribute */
1429 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1431 struct peer
*const peer
= args
->peer
;
1432 struct attr
*const attr
= args
->attr
;
1433 const bgp_size_t length
= args
->length
;
1437 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1438 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1441 if (length
!= wantedlen
) {
1442 flog_err(EC_BGP_ATTR_LEN
,
1443 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1445 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1449 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1450 attr
->aggregator_as
= stream_getl(peer
->curr
);
1452 attr
->aggregator_as
= stream_getw(peer
->curr
);
1453 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1455 /* Set atomic aggregate flag. */
1456 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1458 return BGP_ATTR_PARSE_PROCEED
;
1461 /* New Aggregator attribute */
1462 static bgp_attr_parse_ret_t
1463 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1464 as_t
*as4_aggregator_as
,
1465 struct in_addr
*as4_aggregator_addr
)
1467 struct peer
*const peer
= args
->peer
;
1468 struct attr
*const attr
= args
->attr
;
1469 const bgp_size_t length
= args
->length
;
1472 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1474 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1478 *as4_aggregator_as
= stream_getl(peer
->curr
);
1479 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1481 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1483 return BGP_ATTR_PARSE_PROCEED
;
1486 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1488 static bgp_attr_parse_ret_t
1489 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1490 struct aspath
*as4_path
, as_t as4_aggregator
,
1491 struct in_addr
*as4_aggregator_addr
)
1493 int ignore_as4_path
= 0;
1494 struct aspath
*newpath
;
1496 if (!attr
->aspath
) {
1497 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1499 * checked that all well-known, mandatory attributes were
1502 * Can only be a problem with peer itself - hard error
1504 return BGP_ATTR_PARSE_ERROR
;
1507 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1508 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1510 * It is worth a warning though, because the peer really
1511 * should not send them
1513 if (BGP_DEBUG(as4
, AS4
)) {
1514 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1515 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1516 "AS4 capable peer, yet it sent");
1519 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1520 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1522 "AS4 capable peer, yet it sent");
1525 return BGP_ATTR_PARSE_PROCEED
;
1528 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1529 * because that may override AS4_PATH
1531 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1532 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1534 * if the as_number in aggregator is not AS_TRANS,
1535 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1536 * and the Aggregator shall be taken as
1537 * info on the aggregating node, and the AS_PATH
1538 * shall be taken as the AS_PATH
1540 * the Aggregator shall be ignored and the
1541 * AS4_AGGREGATOR shall be taken as the
1542 * Aggregating node and the AS_PATH is to be
1543 * constructed "as in all other cases"
1545 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1547 if (BGP_DEBUG(as4
, AS4
))
1549 "[AS4] %s BGP not AS4 capable peer"
1550 " send AGGREGATOR != AS_TRANS and"
1551 " AS4_AGGREGATOR, so ignore"
1552 " AS4_AGGREGATOR and AS4_PATH",
1554 ignore_as4_path
= 1;
1556 /* "New_aggregator shall be taken as aggregator"
1558 attr
->aggregator_as
= as4_aggregator
;
1559 attr
->aggregator_addr
.s_addr
=
1560 as4_aggregator_addr
->s_addr
;
1563 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1564 * That is bogus - but reading the conditions
1565 * we have to handle AS4_AGGREGATOR as if it were
1566 * AGGREGATOR in that case
1568 if (BGP_DEBUG(as4
, AS4
))
1570 "[AS4] %s BGP not AS4 capable peer send"
1571 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1572 " it as if AGGREGATOR with AS_TRANS had been there",
1574 attr
->aggregator_as
= as4_aggregator
;
1575 /* sweep it under the carpet and simulate a "good"
1577 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1581 /* need to reconcile NEW_AS_PATH and AS_PATH */
1582 if (!ignore_as4_path
1583 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1584 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1586 return BGP_ATTR_PARSE_ERROR
;
1588 aspath_unintern(&attr
->aspath
);
1589 attr
->aspath
= aspath_intern(newpath
);
1591 return BGP_ATTR_PARSE_PROCEED
;
1594 /* Community attribute. */
1595 static bgp_attr_parse_ret_t
1596 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1598 struct peer
*const peer
= args
->peer
;
1599 struct attr
*const attr
= args
->attr
;
1600 const bgp_size_t length
= args
->length
;
1603 attr
->community
= NULL
;
1604 return BGP_ATTR_PARSE_PROCEED
;
1608 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1610 /* XXX: fix community_parse to use stream API and remove this */
1611 stream_forward_getp(peer
->curr
, length
);
1613 if (!attr
->community
)
1614 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1617 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1619 return BGP_ATTR_PARSE_PROCEED
;
1622 /* Originator ID attribute. */
1623 static bgp_attr_parse_ret_t
1624 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1626 struct peer
*const peer
= args
->peer
;
1627 struct attr
*const attr
= args
->attr
;
1628 const bgp_size_t length
= args
->length
;
1632 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1635 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1639 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1641 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1643 return BGP_ATTR_PARSE_PROCEED
;
1646 /* Cluster list attribute. */
1647 static bgp_attr_parse_ret_t
1648 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1650 struct peer
*const peer
= args
->peer
;
1651 struct attr
*const attr
= args
->attr
;
1652 const bgp_size_t length
= args
->length
;
1656 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
1658 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1663 cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
), length
);
1665 /* XXX: Fix cluster_parse to use stream API and then remove this */
1666 stream_forward_getp(peer
->curr
, length
);
1668 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1670 return BGP_ATTR_PARSE_PROCEED
;
1673 /* Multiprotocol reachability information parse. */
1674 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1675 struct bgp_nlri
*mp_update
)
1679 iana_safi_t pkt_safi
;
1681 bgp_size_t nlri_len
;
1684 struct peer
*const peer
= args
->peer
;
1685 struct attr
*const attr
= args
->attr
;
1686 const bgp_size_t length
= args
->length
;
1688 /* Set end of packet. */
1689 s
= BGP_INPUT(peer
);
1690 start
= stream_get_getp(s
);
1692 /* safe to read statically sized header? */
1693 #define BGP_MP_REACH_MIN_SIZE 5
1694 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1695 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1696 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
1697 __func__
, peer
->host
, (unsigned long)length
);
1698 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1701 /* Load AFI, SAFI. */
1702 pkt_afi
= stream_getw(s
);
1703 pkt_safi
= stream_getc(s
);
1705 /* Convert AFI, SAFI to internal values, check. */
1706 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1707 /* Log if AFI or SAFI is unrecognized. This is not an error
1709 * the attribute is otherwise malformed.
1711 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1713 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
1714 peer
->host
, iana_afi2str(pkt_afi
),
1715 iana_safi2str(pkt_safi
));
1716 return BGP_ATTR_PARSE_ERROR
;
1719 /* Get nexthop length. */
1720 attr
->mp_nexthop_len
= stream_getc(s
);
1722 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
1724 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
1725 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1726 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1729 /* Nexthop length check. */
1730 switch (attr
->mp_nexthop_len
) {
1732 if (safi
!= SAFI_FLOWSPEC
) {
1733 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
1734 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1735 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1738 case BGP_ATTR_NHLEN_VPNV4
:
1739 stream_getl(s
); /* RD high */
1740 stream_getl(s
); /* RD low */
1742 * NOTE: intentional fall through
1743 * - for consistency in rx processing
1745 * The following comment is to signal GCC this intention
1746 * and suppress the warning
1749 case BGP_ATTR_NHLEN_IPV4
:
1750 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1751 /* Probably needed for RFC 2283 */
1752 if (attr
->nexthop
.s_addr
== 0)
1753 memcpy(&attr
->nexthop
.s_addr
,
1754 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1756 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1757 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1758 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
1759 stream_getl(s
); /* RD high */
1760 stream_getl(s
); /* RD low */
1762 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1763 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1764 if (!peer
->nexthop
.ifp
) {
1765 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
1767 return BGP_ATTR_PARSE_WITHDRAW
;
1769 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1772 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1773 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1774 if (attr
->mp_nexthop_len
1775 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1776 stream_getl(s
); /* RD high */
1777 stream_getl(s
); /* RD low */
1779 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1780 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1781 if (!peer
->nexthop
.ifp
) {
1782 zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
1784 return BGP_ATTR_PARSE_WITHDRAW
;
1786 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1788 if (attr
->mp_nexthop_len
1789 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1790 stream_getl(s
); /* RD high */
1791 stream_getl(s
); /* RD low */
1793 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1794 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
1795 char buf1
[INET6_ADDRSTRLEN
];
1796 char buf2
[INET6_ADDRSTRLEN
];
1798 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1800 "%s sent next-hops %s and %s. Ignoring non-LL value",
1803 &attr
->mp_nexthop_global
,
1804 buf1
, INET6_ADDRSTRLEN
),
1806 &attr
->mp_nexthop_local
, buf2
,
1809 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1811 if (!peer
->nexthop
.ifp
) {
1812 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
1814 return BGP_ATTR_PARSE_WITHDRAW
;
1816 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1819 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
1820 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1821 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1825 zlog_info("%s: %s sent SNPA which couldn't be read",
1826 __func__
, peer
->host
);
1827 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1832 if ((val
= stream_getc(s
)))
1834 EC_BGP_DEFUNCT_SNPA_LEN
,
1835 "%s sent non-zero value, %u, for defunct SNPA-length field",
1839 /* must have nrli_len, what is left of the attribute */
1840 nlri_len
= LEN_LEFT
;
1841 if (nlri_len
> STREAM_READABLE(s
)) {
1842 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
1843 __func__
, peer
->host
);
1844 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1848 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
1849 __func__
, peer
->host
);
1851 mp_update
->afi
= afi
;
1852 mp_update
->safi
= safi
;
1853 return BGP_ATTR_PARSE_EOR
;
1856 mp_update
->afi
= afi
;
1857 mp_update
->safi
= safi
;
1858 mp_update
->nlri
= stream_pnt(s
);
1859 mp_update
->length
= nlri_len
;
1861 stream_forward_getp(s
, nlri_len
);
1863 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
1865 return BGP_ATTR_PARSE_PROCEED
;
1869 /* Multiprotocol unreachable parse */
1870 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
1871 struct bgp_nlri
*mp_withdraw
)
1876 iana_safi_t pkt_safi
;
1878 uint16_t withdraw_len
;
1879 struct peer
*const peer
= args
->peer
;
1880 struct attr
*const attr
= args
->attr
;
1881 const bgp_size_t length
= args
->length
;
1885 #define BGP_MP_UNREACH_MIN_SIZE 3
1886 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1887 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1889 pkt_afi
= stream_getw(s
);
1890 pkt_safi
= stream_getc(s
);
1892 /* Convert AFI, SAFI to internal values, check. */
1893 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1894 /* Log if AFI or SAFI is unrecognized. This is not an error
1896 * the attribute is otherwise malformed.
1898 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1900 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
1901 peer
->host
, iana_afi2str(pkt_afi
),
1902 iana_safi2str(pkt_safi
));
1903 return BGP_ATTR_PARSE_ERROR
;
1906 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1908 mp_withdraw
->afi
= afi
;
1909 mp_withdraw
->safi
= safi
;
1910 mp_withdraw
->nlri
= stream_pnt(s
);
1911 mp_withdraw
->length
= withdraw_len
;
1913 stream_forward_getp(s
, withdraw_len
);
1915 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
1917 return BGP_ATTR_PARSE_PROCEED
;
1920 /* Large Community attribute. */
1921 static bgp_attr_parse_ret_t
1922 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
1924 struct peer
*const peer
= args
->peer
;
1925 struct attr
*const attr
= args
->attr
;
1926 const bgp_size_t length
= args
->length
;
1929 * Large community follows new attribute format.
1932 attr
->lcommunity
= NULL
;
1933 /* Empty extcomm doesn't seem to be invalid per se */
1934 return BGP_ATTR_PARSE_PROCEED
;
1938 lcommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1939 /* XXX: fix ecommunity_parse to use stream API */
1940 stream_forward_getp(peer
->curr
, length
);
1942 if (!attr
->lcommunity
)
1943 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1946 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1948 return BGP_ATTR_PARSE_PROCEED
;
1951 /* Extended Community attribute. */
1952 static bgp_attr_parse_ret_t
1953 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
1955 struct peer
*const peer
= args
->peer
;
1956 struct attr
*const attr
= args
->attr
;
1957 const bgp_size_t length
= args
->length
;
1961 attr
->ecommunity
= NULL
;
1962 /* Empty extcomm doesn't seem to be invalid per se */
1963 return BGP_ATTR_PARSE_PROCEED
;
1967 ecommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1968 /* XXX: fix ecommunity_parse to use stream API */
1969 stream_forward_getp(peer
->curr
, length
);
1971 if (!attr
->ecommunity
)
1972 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1975 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1977 /* Extract MAC mobility sequence number, if any. */
1978 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
1979 attr
->sticky
= sticky
;
1981 /* Check if this is a Gateway MAC-IP advertisement */
1982 attr
->default_gw
= bgp_attr_default_gw(attr
);
1984 /* Handle scenario where router flag ecommunity is not
1985 * set but default gw ext community is present.
1986 * Use default gateway, set and propogate R-bit.
1988 if (attr
->default_gw
)
1989 attr
->router_flag
= 1;
1991 /* Check EVPN Neighbor advertisement flags, R-bit */
1992 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
);
1994 /* Extract the Rmac, if any */
1995 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
1996 if (bgp_debug_update(peer
, NULL
, NULL
, 1) &&
1997 bgp_mac_exist(&attr
->rmac
)) {
1998 char buf1
[ETHER_ADDR_STRLEN
];
2000 zlog_debug("%s: router mac %s is self mac",
2002 prefix_mac2str(&attr
->rmac
, buf1
,
2008 /* Get the tunnel type from encap extended community */
2009 bgp_attr_extcom_tunnel_type(attr
,
2010 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2012 return BGP_ATTR_PARSE_PROCEED
;
2015 /* Parse Tunnel Encap attribute in an UPDATE */
2016 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2017 bgp_size_t length
, /* IN: attr's length field */
2018 struct attr
*attr
, /* IN: caller already allocated */
2019 uint8_t flag
, /* IN: attr's flags field */
2023 uint16_t tunneltype
= 0;
2025 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2027 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2028 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2030 "Tunnel Encap attribute flag isn't optional and transitive %d",
2032 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2033 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2038 if (BGP_ATTR_ENCAP
== type
) {
2039 /* read outer TLV type and length */
2040 uint16_t tlv_length
;
2044 "Tunnel Encap attribute not long enough to contain outer T,L");
2045 bgp_notify_send_with_data(
2046 peer
, BGP_NOTIFY_UPDATE_ERR
,
2047 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2050 tunneltype
= stream_getw(BGP_INPUT(peer
));
2051 tlv_length
= stream_getw(BGP_INPUT(peer
));
2054 if (tlv_length
!= length
) {
2055 zlog_info("%s: tlv_length(%d) != length(%d)",
2056 __func__
, tlv_length
, length
);
2060 while (length
>= 4) {
2061 uint16_t subtype
= 0;
2062 uint16_t sublength
= 0;
2063 struct bgp_attr_encap_subtlv
*tlv
;
2065 if (BGP_ATTR_ENCAP
== type
) {
2066 subtype
= stream_getc(BGP_INPUT(peer
));
2067 sublength
= stream_getc(BGP_INPUT(peer
));
2071 subtype
= stream_getw(BGP_INPUT(peer
));
2072 sublength
= stream_getw(BGP_INPUT(peer
));
2077 if (sublength
> length
) {
2079 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2081 bgp_notify_send_with_data(
2082 peer
, BGP_NOTIFY_UPDATE_ERR
,
2083 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2087 /* alloc and copy sub-tlv */
2088 /* TBD make sure these are freed when attributes are released */
2089 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2090 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2091 tlv
->type
= subtype
;
2092 tlv
->length
= sublength
;
2093 stream_get(tlv
->value
, peer
->curr
, sublength
);
2094 length
-= sublength
;
2096 /* attach tlv to encap chain */
2097 if (BGP_ATTR_ENCAP
== type
) {
2098 struct bgp_attr_encap_subtlv
*stlv_last
;
2099 for (stlv_last
= attr
->encap_subtlvs
;
2100 stlv_last
&& stlv_last
->next
;
2101 stlv_last
= stlv_last
->next
)
2104 stlv_last
->next
= tlv
;
2106 attr
->encap_subtlvs
= tlv
;
2110 struct bgp_attr_encap_subtlv
*stlv_last
;
2111 for (stlv_last
= attr
->vnc_subtlvs
;
2112 stlv_last
&& stlv_last
->next
;
2113 stlv_last
= stlv_last
->next
)
2116 stlv_last
->next
= tlv
;
2118 attr
->vnc_subtlvs
= tlv
;
2124 if (BGP_ATTR_ENCAP
== type
) {
2125 attr
->encap_tunneltype
= tunneltype
;
2129 /* spurious leftover data */
2131 "Tunnel Encap attribute length is bad: %d leftover octets",
2133 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2134 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2143 * Read an individual SID value returning how much data we have read
2144 * Returns 0 if there was an error that needs to be passed up the stack
2146 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(int32_t type
,
2148 struct bgp_attr_parser_args
*args
,
2149 struct bgp_nlri
*mp_update
)
2151 struct peer
*const peer
= args
->peer
;
2152 struct attr
*const attr
= args
->attr
;
2153 uint32_t label_index
;
2154 struct in6_addr ipv6_sid
;
2156 uint32_t srgb_range
;
2159 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2160 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2163 "Prefix SID label index length is %d instead of %d",
2164 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2165 return bgp_attr_malformed(args
,
2166 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2170 /* Ignore flags and reserved */
2171 stream_getc(peer
->curr
);
2172 stream_getw(peer
->curr
);
2174 /* Fetch the label index and see if it is valid. */
2175 label_index
= stream_getl(peer
->curr
);
2176 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2177 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2180 /* Store label index; subsequently, we'll check on
2182 attr
->label_index
= label_index
;
2185 * Ignore the Label index attribute unless received for
2189 if (!mp_update
->length
2190 || mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2191 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
2194 /* Placeholder code for the IPv6 SID type */
2195 else if (type
== BGP_PREFIX_SID_IPV6
) {
2196 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2197 flog_err(EC_BGP_ATTR_LEN
,
2198 "Prefix SID IPv6 length is %d instead of %d",
2199 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2200 return bgp_attr_malformed(args
,
2201 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2205 /* Ignore reserved */
2206 stream_getc(peer
->curr
);
2207 stream_getw(peer
->curr
);
2209 stream_get(&ipv6_sid
, peer
->curr
, 16);
2212 /* Placeholder code for the Originator SRGB type */
2213 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2215 stream_getw(peer
->curr
);
2219 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2222 "Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2223 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2224 return bgp_attr_malformed(
2225 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2229 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2231 for (int i
= 0; i
< srgb_count
; i
++) {
2232 stream_get(&srgb_base
, peer
->curr
, 3);
2233 stream_get(&srgb_range
, peer
->curr
, 3);
2237 return BGP_ATTR_PARSE_PROCEED
;
2240 /* Prefix SID attribute
2241 * draft-ietf-idr-bgp-prefix-sid-05
2243 bgp_attr_parse_ret_t
2244 bgp_attr_prefix_sid(int32_t tlength
, struct bgp_attr_parser_args
*args
,
2245 struct bgp_nlri
*mp_update
)
2247 struct peer
*const peer
= args
->peer
;
2248 struct attr
*const attr
= args
->attr
;
2249 bgp_attr_parse_ret_t ret
;
2251 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2254 int32_t type
, length
;
2256 type
= stream_getc(peer
->curr
);
2257 length
= stream_getw(peer
->curr
);
2259 ret
= bgp_attr_psid_sub(type
, length
, args
, mp_update
);
2261 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2264 * Subtract length + the T and the L
2265 * since length is the Vector portion
2267 tlength
-= length
+ 3;
2272 "Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
2274 return bgp_attr_malformed(args
,
2275 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2280 return BGP_ATTR_PARSE_PROCEED
;
2283 /* PMSI tunnel attribute (RFC 6514)
2284 * Basic validation checks done here.
2286 static bgp_attr_parse_ret_t
2287 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2289 struct peer
*const peer
= args
->peer
;
2290 struct attr
*const attr
= args
->attr
;
2291 const bgp_size_t length
= args
->length
;
2293 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2295 /* Verify that the receiver is expecting "ingress replication" as we
2296 * can only support that.
2298 if (length
< attr_parse_len
) {
2299 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2301 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2304 stream_getc(peer
->curr
); /* Flags */
2305 tnl_type
= stream_getc(peer
->curr
);
2306 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2307 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2308 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2309 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2312 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2314 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2315 "Bad PMSI tunnel attribute length %d for IR",
2317 return bgp_attr_malformed(
2318 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2323 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2324 attr
->pmsi_tnl_type
= tnl_type
;
2325 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2327 /* Forward read pointer of input stream. */
2328 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2330 return BGP_ATTR_PARSE_PROCEED
;
2333 /* BGP unknown attribute treatment. */
2334 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2336 bgp_size_t total
= args
->total
;
2337 struct transit
*transit
;
2338 struct peer
*const peer
= args
->peer
;
2339 struct attr
*const attr
= args
->attr
;
2340 uint8_t *const startp
= args
->startp
;
2341 const uint8_t type
= args
->type
;
2342 const uint8_t flag
= args
->flags
;
2343 const bgp_size_t length
= args
->length
;
2345 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2347 "%s Unknown attribute is received (type %d, length %d)",
2348 peer
->host
, type
, length
);
2350 /* Forward read pointer of input stream. */
2351 stream_forward_getp(peer
->curr
, length
);
2353 /* If any of the mandatory well-known attributes are not recognized,
2354 then the Error Subcode is set to Unrecognized Well-known
2355 Attribute. The Data field contains the unrecognized attribute
2356 (type, length and value). */
2357 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2358 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2362 /* Unrecognized non-transitive optional attributes must be quietly
2363 ignored and not passed along to other BGP peers. */
2364 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2365 return BGP_ATTR_PARSE_PROCEED
;
2367 /* If a path with recognized transitive optional attribute is
2368 accepted and passed along to other BGP peers and the Partial bit
2369 in the Attribute Flags octet is set to 1 by some previous AS, it
2370 is not set back to 0 by the current AS. */
2371 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2373 /* Store transitive attribute to the end of attr->transit. */
2375 attr
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2377 transit
= attr
->transit
;
2380 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2381 transit
->length
+ total
);
2383 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2385 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2386 transit
->length
+= total
;
2388 return BGP_ATTR_PARSE_PROCEED
;
2391 /* Well-known attribute check. */
2392 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2396 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2398 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2399 return BGP_ATTR_PARSE_PROCEED
;
2401 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2402 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2403 are present, it should. Check for any other attribute being present
2406 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2407 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2408 return BGP_ATTR_PARSE_PROCEED
;
2410 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2411 type
= BGP_ATTR_ORIGIN
;
2413 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2414 type
= BGP_ATTR_AS_PATH
;
2416 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2418 * NLRI is empty. We can't easily check NLRI empty here though.
2420 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2421 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2422 type
= BGP_ATTR_NEXT_HOP
;
2424 if (peer
->sort
== BGP_PEER_IBGP
2425 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2426 type
= BGP_ATTR_LOCAL_PREF
;
2429 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2430 "%s Missing well-known attribute %s.", peer
->host
,
2431 lookup_msg(attr_str
, type
, NULL
));
2432 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2433 BGP_NOTIFY_UPDATE_MISS_ATTR
, &type
,
2435 return BGP_ATTR_PARSE_ERROR
;
2437 return BGP_ATTR_PARSE_PROCEED
;
2440 /* Read attribute of update packet. This function is called from
2441 bgp_update_receive() in bgp_packet.c. */
2442 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2443 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2444 struct bgp_nlri
*mp_withdraw
)
2446 bgp_attr_parse_ret_t ret
;
2450 uint8_t *startp
, *endp
;
2452 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2453 /* we need the as4_path only until we have synthesized the as_path with
2455 /* same goes for as4_aggregator */
2456 struct aspath
*as4_path
= NULL
;
2457 as_t as4_aggregator
= 0;
2458 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2460 /* Initialize bitmap. */
2461 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2463 /* End pointer of BGP attribute. */
2464 endp
= BGP_INPUT_PNT(peer
) + size
;
2466 /* Get attributes to the end of attribute length. */
2467 while (BGP_INPUT_PNT(peer
) < endp
) {
2468 /* Check remaining length check.*/
2469 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2470 /* XXX warning: long int format, int arg (arg 5) */
2472 EC_BGP_ATTRIBUTE_TOO_SMALL
,
2473 "%s: error BGP attribute length %lu is smaller than min len",
2475 (unsigned long)(endp
2476 - stream_pnt(BGP_INPUT(peer
))));
2478 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2479 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2480 return BGP_ATTR_PARSE_ERROR
;
2483 /* Fetch attribute flag and type. */
2484 startp
= BGP_INPUT_PNT(peer
);
2485 /* "The lower-order four bits of the Attribute Flags octet are
2486 unused. They MUST be zero when sent and MUST be ignored when
2488 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2489 type
= stream_getc(BGP_INPUT(peer
));
2491 /* Check whether Extended-Length applies and is in bounds */
2492 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2493 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2495 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
2496 "%s: Extended length set, but just %lu bytes of attr header",
2498 (unsigned long)(endp
2499 - stream_pnt(BGP_INPUT(peer
))));
2501 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2502 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2503 return BGP_ATTR_PARSE_ERROR
;
2506 /* Check extended attribue length bit. */
2507 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2508 length
= stream_getw(BGP_INPUT(peer
));
2510 length
= stream_getc(BGP_INPUT(peer
));
2512 /* If any attribute appears more than once in the UPDATE
2513 message, then the Error Subcode is set to Malformed Attribute
2516 if (CHECK_BITMAP(seen
, type
)) {
2518 EC_BGP_ATTRIBUTE_REPEATED
,
2519 "%s: error BGP attribute type %d appears twice in a message",
2522 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2523 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2524 return BGP_ATTR_PARSE_ERROR
;
2527 /* Set type to bitmap to check duplicate attribute. `type' is
2528 unsigned char so it never overflow bitmap range. */
2530 SET_BITMAP(seen
, type
);
2532 /* Overflow check. */
2533 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2535 if (attr_endp
> endp
) {
2537 EC_BGP_ATTRIBUTE_TOO_LARGE
,
2538 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
2539 peer
->host
, type
, length
, size
, attr_endp
,
2543 * If any recognized attribute has an Attribute
2544 * Length that conflicts with the expected length
2545 * (based on the attribute type code), then the
2546 * Error Subcode MUST be set to Attribute Length
2547 * Error. The Data field MUST contain the erroneous
2548 * attribute (type, length, and value).
2550 * We do not currently have a good way to determine the
2551 * length of the attribute independent of the length
2552 * received in the message. Instead we send the
2553 * minimum between the amount of data we have and the
2554 * amount specified by the attribute length field.
2556 * Instead of directly passing in the packet buffer and
2557 * offset we use the stream_get* functions to read into
2558 * a stack buffer, since they perform bounds checking
2559 * and we are working with untrusted data.
2561 unsigned char ndata
[BGP_MAX_PACKET_SIZE
];
2562 memset(ndata
, 0x00, sizeof(ndata
));
2564 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
2565 /* Rewind to end of flag field */
2566 stream_forward_getp(BGP_INPUT(peer
), -(1 + lfl
));
2568 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
2570 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
2572 size_t atl
= attr_endp
- startp
;
2573 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
2574 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
2576 bgp_notify_send_with_data(
2577 peer
, BGP_NOTIFY_UPDATE_ERR
,
2578 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
2581 return BGP_ATTR_PARSE_ERROR
;
2584 struct bgp_attr_parser_args attr_args
= {
2591 .total
= attr_endp
- startp
,
2595 /* If any recognized attribute has Attribute Flags that conflict
2596 with the Attribute Type Code, then the Error Subcode is set
2598 Attribute Flags Error. The Data field contains the erroneous
2599 attribute (type, length and value). */
2600 if (bgp_attr_flag_invalid(&attr_args
)) {
2601 ret
= bgp_attr_malformed(
2602 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2604 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2609 /* OK check attribute and store it's value. */
2611 case BGP_ATTR_ORIGIN
:
2612 ret
= bgp_attr_origin(&attr_args
);
2614 case BGP_ATTR_AS_PATH
:
2615 ret
= bgp_attr_aspath(&attr_args
);
2617 case BGP_ATTR_AS4_PATH
:
2618 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
2620 case BGP_ATTR_NEXT_HOP
:
2621 ret
= bgp_attr_nexthop(&attr_args
);
2623 case BGP_ATTR_MULTI_EXIT_DISC
:
2624 ret
= bgp_attr_med(&attr_args
);
2626 case BGP_ATTR_LOCAL_PREF
:
2627 ret
= bgp_attr_local_pref(&attr_args
);
2629 case BGP_ATTR_ATOMIC_AGGREGATE
:
2630 ret
= bgp_attr_atomic(&attr_args
);
2632 case BGP_ATTR_AGGREGATOR
:
2633 ret
= bgp_attr_aggregator(&attr_args
);
2635 case BGP_ATTR_AS4_AGGREGATOR
:
2636 ret
= bgp_attr_as4_aggregator(&attr_args
,
2638 &as4_aggregator_addr
);
2640 case BGP_ATTR_COMMUNITIES
:
2641 ret
= bgp_attr_community(&attr_args
);
2643 case BGP_ATTR_LARGE_COMMUNITIES
:
2644 ret
= bgp_attr_large_community(&attr_args
);
2646 case BGP_ATTR_ORIGINATOR_ID
:
2647 ret
= bgp_attr_originator_id(&attr_args
);
2649 case BGP_ATTR_CLUSTER_LIST
:
2650 ret
= bgp_attr_cluster_list(&attr_args
);
2652 case BGP_ATTR_MP_REACH_NLRI
:
2653 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
2655 case BGP_ATTR_MP_UNREACH_NLRI
:
2656 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
2658 case BGP_ATTR_EXT_COMMUNITIES
:
2659 ret
= bgp_attr_ext_communities(&attr_args
);
2661 #if ENABLE_BGP_VNC_ATTR
2664 case BGP_ATTR_ENCAP
:
2665 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
2668 case BGP_ATTR_PREFIX_SID
:
2669 ret
= bgp_attr_prefix_sid(length
,
2670 &attr_args
, mp_update
);
2672 case BGP_ATTR_PMSI_TUNNEL
:
2673 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
2676 ret
= bgp_attr_unknown(&attr_args
);
2680 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
2681 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2682 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2683 ret
= BGP_ATTR_PARSE_ERROR
;
2686 if (ret
== BGP_ATTR_PARSE_EOR
) {
2688 aspath_unintern(&as4_path
);
2692 /* If hard error occurred immediately return to the caller. */
2693 if (ret
== BGP_ATTR_PARSE_ERROR
) {
2694 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
2695 "%s: Attribute %s, parse error", peer
->host
,
2696 lookup_msg(attr_str
, type
, NULL
));
2698 aspath_unintern(&as4_path
);
2701 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
2704 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
2705 "%s: Attribute %s, parse error - treating as withdrawal",
2706 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2708 aspath_unintern(&as4_path
);
2712 /* Check the fetched length. */
2713 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
2714 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
2715 "%s: BGP attribute %s, fetch error",
2716 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2717 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2718 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2720 aspath_unintern(&as4_path
);
2721 return BGP_ATTR_PARSE_ERROR
;
2725 /* Check final read pointer is same as end pointer. */
2726 if (BGP_INPUT_PNT(peer
) != endp
) {
2727 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
2728 "%s: BGP attribute %s, length mismatch", peer
->host
,
2729 lookup_msg(attr_str
, type
, NULL
));
2730 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2731 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2733 aspath_unintern(&as4_path
);
2734 return BGP_ATTR_PARSE_ERROR
;
2738 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
2739 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
2740 * This is implemented below and will result in a NOTIFICATION. If the
2741 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
2742 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
2743 * message SHOULD NOT be sent. This is implemented elsewhere.
2745 * RFC4760: An UPDATE message that carries no NLRI, other than the one
2746 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
2747 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
2748 * speaker that receives the message SHOULD ignore this attribute.
2750 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2751 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
2752 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
2753 return BGP_ATTR_PARSE_ERROR
;
2757 /* Check all mandatory well-known attributes are present */
2758 if ((ret
= bgp_attr_check(peer
, attr
)) < 0) {
2760 aspath_unintern(&as4_path
);
2765 * At this place we can see whether we got AS4_PATH and/or
2766 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2767 * We can not do this before we've read all attributes because
2768 * the as4 handling does not say whether AS4_PATH has to be sent
2769 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2770 * in relationship to AGGREGATOR.
2771 * So, to be defensive, we are not relying on any order and read
2772 * all attributes first, including these 32bit ones, and now,
2773 * afterwards, we look what and if something is to be done for as4.
2775 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2778 /* actually... this doesn't ever return failure currently, but
2779 * better safe than sorry */
2780 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
2781 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
2782 &as4_aggregator_addr
)) {
2783 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2784 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2786 aspath_unintern(&as4_path
);
2787 return BGP_ATTR_PARSE_ERROR
;
2790 /* At this stage, we have done all fiddling with as4, and the
2791 * resulting info is in attr->aggregator resp. attr->aspath
2792 * so we can chuck as4_aggregator and as4_path alltogether in
2793 * order to save memory
2796 aspath_unintern(&as4_path
); /* unintern - it is in the hash */
2797 /* The flag that we got this is still there, but that does not
2802 * The "rest" of the code does nothing with as4_aggregator.
2803 * there is no memory attached specifically which is not part
2805 * so ignoring just means do nothing.
2808 * Finally do the checks on the aspath we did not do yet
2809 * because we waited for a potentially synthesized aspath.
2811 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
2812 ret
= bgp_attr_aspath_check(peer
, attr
);
2813 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2816 /* Finally intern unknown attribute. */
2818 attr
->transit
= transit_intern(attr
->transit
);
2819 if (attr
->encap_subtlvs
)
2820 attr
->encap_subtlvs
=
2821 encap_intern(attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
2823 if (attr
->vnc_subtlvs
)
2825 encap_intern(attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
2828 return BGP_ATTR_PARSE_PROCEED
;
2832 * Extract the tunnel type from extended community
2834 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
2835 bgp_encap_types
*tunnel_type
)
2837 struct ecommunity
*ecom
;
2842 ecom
= attr
->ecommunity
;
2843 if (!ecom
|| !ecom
->size
)
2846 for (i
= 0; i
< ecom
->size
; i
++) {
2848 uint8_t type
, sub_type
;
2850 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
2853 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
2854 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
2856 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
2863 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
2864 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
2869 iana_safi_t pkt_safi
;
2872 /* Set extended bit always to encode the attribute length as 2 bytes */
2873 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
2874 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
2875 sizep
= stream_get_endp(s
);
2876 stream_putw(s
, 0); /* Marker: Attribute length. */
2879 /* Convert AFI, SAFI to values for packet. */
2880 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
2882 stream_putw(s
, pkt_afi
); /* AFI */
2883 stream_putc(s
, pkt_safi
); /* SAFI */
2887 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
2888 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
2890 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
2893 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2898 case SAFI_MULTICAST
:
2899 case SAFI_LABELED_UNICAST
:
2901 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
2905 stream_putl(s
, 0); /* RD = 0, per RFC */
2907 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2912 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2915 stream_putc(s
, 0); /* no nexthop for flowspec */
2923 case SAFI_MULTICAST
:
2924 case SAFI_LABELED_UNICAST
:
2926 if (attr
->mp_nexthop_len
2927 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2929 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2930 stream_put(s
, &attr
->mp_nexthop_global
,
2932 stream_put(s
, &attr
->mp_nexthop_local
,
2935 stream_putc(s
, IPV6_MAX_BYTELEN
);
2936 stream_put(s
, &attr
->mp_nexthop_global
,
2940 case SAFI_MPLS_VPN
: {
2941 if (attr
->mp_nexthop_len
2942 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2944 stream_putl(s
, 0); /* RD = 0, per RFC */
2946 stream_put(s
, &attr
->mp_nexthop_global
,
2948 } else if (attr
->mp_nexthop_len
2949 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2951 stream_putl(s
, 0); /* RD = 0, per RFC */
2953 stream_put(s
, &attr
->mp_nexthop_global
,
2955 stream_putl(s
, 0); /* RD = 0, per RFC */
2957 stream_put(s
, &attr
->mp_nexthop_local
,
2962 stream_putc(s
, IPV6_MAX_BYTELEN
);
2963 stream_put(s
, &attr
->mp_nexthop_global
,
2967 stream_putc(s
, 0); /* no nexthop for flowspec */
2973 if (safi
!= SAFI_FLOWSPEC
)
2975 EC_BGP_ATTR_NH_SEND_LEN
,
2976 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
2977 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
2986 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
2987 struct prefix
*p
, struct prefix_rd
*prd
,
2988 mpls_label_t
*label
, uint32_t num_labels
,
2989 int addpath_encode
, uint32_t addpath_tx_id
,
2992 if (safi
== SAFI_MPLS_VPN
) {
2994 stream_putl(s
, addpath_tx_id
);
2995 /* Label, RD, Prefix write. */
2996 stream_putc(s
, p
->prefixlen
+ 88);
2997 stream_put(s
, label
, BGP_LABEL_BYTES
);
2998 stream_put(s
, prd
->val
, 8);
2999 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3000 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3001 /* EVPN prefix - contents depend on type */
3002 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3003 addpath_encode
, addpath_tx_id
);
3004 } else if (safi
== SAFI_LABELED_UNICAST
) {
3005 /* Prefix write with label. */
3006 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3008 } else if (safi
== SAFI_FLOWSPEC
) {
3009 if (PSIZE (p
->prefixlen
)+2 < FLOWSPEC_NLRI_SIZELIMIT
)
3010 stream_putc(s
, PSIZE (p
->prefixlen
)+2);
3012 stream_putw(s
, (PSIZE (p
->prefixlen
)+2)|(0xf<<12));
3013 stream_putc(s
, 2);/* Filter type */
3014 stream_putc(s
, p
->prefixlen
);/* Prefix length */
3015 stream_put(s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
3017 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3020 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
, struct prefix
*p
)
3022 int size
= PSIZE(p
->prefixlen
);
3023 if (safi
== SAFI_MPLS_VPN
)
3025 else if (safi
== SAFI_LABELED_UNICAST
)
3026 size
+= BGP_LABEL_BYTES
;
3027 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3028 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3034 * Encodes the tunnel encapsulation attribute,
3035 * and with ENABLE_BGP_VNC the VNC attribute which uses
3036 * almost the same TLV format
3038 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3039 struct stream
*s
, struct attr
*attr
,
3042 unsigned int attrlenfield
= 0;
3043 unsigned int attrhdrlen
= 0;
3044 struct bgp_attr_encap_subtlv
*subtlvs
;
3045 struct bgp_attr_encap_subtlv
*st
;
3046 const char *attrname
;
3048 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3049 && (!attr
->encap_tunneltype
3050 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3054 case BGP_ATTR_ENCAP
:
3055 attrname
= "Tunnel Encap";
3056 subtlvs
= attr
->encap_subtlvs
;
3057 if (subtlvs
== NULL
) /* nothing to do */
3060 * The tunnel encap attr has an "outer" tlv.
3062 * L = total length of subtlvs,
3063 * V = concatenated subtlvs.
3065 attrlenfield
= 2 + 2; /* T + L */
3066 attrhdrlen
= 1 + 1; /* subTLV T + L */
3069 #if ENABLE_BGP_VNC_ATTR
3072 subtlvs
= attr
->vnc_subtlvs
;
3073 if (subtlvs
== NULL
) /* nothing to do */
3075 attrlenfield
= 0; /* no outer T + L */
3076 attrhdrlen
= 2 + 2; /* subTLV T + L */
3084 /* compute attr length */
3085 for (st
= subtlvs
; st
; st
= st
->next
) {
3086 attrlenfield
+= (attrhdrlen
+ st
->length
);
3089 if (attrlenfield
> 0xffff) {
3090 zlog_info("%s attribute is too long (length=%d), can't send it",
3091 attrname
, attrlenfield
);
3095 if (attrlenfield
> 0xff) {
3096 /* 2-octet length field */
3098 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3099 | BGP_ATTR_FLAG_EXTLEN
);
3100 stream_putc(s
, attrtype
);
3101 stream_putw(s
, attrlenfield
& 0xffff);
3103 /* 1-octet length field */
3104 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3105 stream_putc(s
, attrtype
);
3106 stream_putc(s
, attrlenfield
& 0xff);
3109 if (attrtype
== BGP_ATTR_ENCAP
) {
3110 /* write outer T+L */
3111 stream_putw(s
, attr
->encap_tunneltype
);
3112 stream_putw(s
, attrlenfield
- 4);
3115 /* write each sub-tlv */
3116 for (st
= subtlvs
; st
; st
= st
->next
) {
3117 if (attrtype
== BGP_ATTR_ENCAP
) {
3118 stream_putc(s
, st
->type
);
3119 stream_putc(s
, st
->length
);
3122 stream_putw(s
, st
->type
);
3123 stream_putw(s
, st
->length
);
3126 stream_put(s
, st
->value
, st
->length
);
3130 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3132 /* Set MP attribute length. Don't count the (2) bytes used to encode
3134 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3137 static int bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3139 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3140 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3141 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3142 PEER_FLAG_REMOVE_PRIVATE_AS
)
3143 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3144 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3145 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3146 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3147 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3148 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3153 /* Make attribute packet. */
3154 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3155 struct stream
*s
, struct attr
*attr
,
3156 struct bpacket_attr_vec_arr
*vecarr
,
3157 struct prefix
*p
, afi_t afi
, safi_t safi
,
3158 struct peer
*from
, struct prefix_rd
*prd
,
3159 mpls_label_t
*label
, uint32_t num_labels
,
3160 int addpath_encode
, uint32_t addpath_tx_id
)
3163 size_t aspath_sizep
;
3164 struct aspath
*aspath
;
3165 int send_as4_path
= 0;
3166 int send_as4_aggregator
= 0;
3167 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3172 /* Remember current pointer. */
3173 cp
= stream_get_endp(s
);
3176 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3177 && !peer_cap_enhe(peer
, afi
, safi
))) {
3178 size_t mpattrlen_pos
= 0;
3180 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3182 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3183 num_labels
, addpath_encode
,
3184 addpath_tx_id
, attr
);
3185 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3188 /* Origin attribute. */
3189 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3190 stream_putc(s
, BGP_ATTR_ORIGIN
);
3192 stream_putc(s
, attr
->origin
);
3194 /* AS path attribute. */
3196 /* If remote-peer is EBGP */
3197 if (peer
->sort
== BGP_PEER_EBGP
3198 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3199 PEER_FLAG_AS_PATH_UNCHANGED
)
3200 || attr
->aspath
->segments
== NULL
)
3201 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3202 PEER_FLAG_RSERVER_CLIENT
))) {
3203 aspath
= aspath_dup(attr
->aspath
);
3205 /* Even though we may not be configured for confederations we
3207 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3208 aspath
= aspath_delete_confed_seq(aspath
);
3210 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3211 /* Stuff our path CONFED_ID on the front */
3212 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3214 if (peer
->change_local_as
) {
3215 /* If replace-as is specified, we only use the
3216 change_local_as when
3217 advertising routes. */
3218 if (!CHECK_FLAG(peer
->flags
,
3219 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3220 if (bgp_append_local_as(peer
, afi
,
3222 aspath
= aspath_add_seq(
3223 aspath
, peer
->local_as
);
3224 aspath
= aspath_add_seq(aspath
,
3225 peer
->change_local_as
);
3227 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3230 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3231 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3233 aspath
= aspath_dup(attr
->aspath
);
3234 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3236 aspath
= attr
->aspath
;
3238 /* If peer is not AS4 capable, then:
3239 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3240 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3242 * types are in it (i.e. exclude them if they are there)
3243 * AND do this only if there is at least one asnum > 65535 in the
3245 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3247 * all ASnums > 65535 to BGP_AS_TRANS
3250 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3251 stream_putc(s
, BGP_ATTR_AS_PATH
);
3252 aspath_sizep
= stream_get_endp(s
);
3254 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3256 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3259 if (!use32bit
&& aspath_has_as4(aspath
))
3261 1; /* we'll do this later, at the correct place */
3263 /* Nexthop attribute. */
3264 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3265 && !peer_cap_enhe(peer
, afi
, safi
)) {
3266 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3268 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3269 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3270 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3271 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3274 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3275 } else if (peer_cap_enhe(from
, afi
, safi
)
3276 || (nh_afi
== AFI_IP6
)) {
3278 * Likely this is the case when an IPv4 prefix was
3279 * received with Extended Next-hop capability in this
3280 * or another vrf and is now being advertised to
3281 * non-ENHE peers. Since peer_cap_enhe only checks
3282 * peers in this vrf, also check the nh_afi to catch
3283 * the case where the originator was in another vrf.
3284 * Setting the mandatory (ipv4) next-hop attribute here
3285 * to enable implicit next-hop self with correct A-F
3286 * (ipv4 address family).
3288 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3289 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3290 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3293 stream_put_ipv4(s
, 0);
3297 /* MED attribute. */
3298 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3299 || bgp
->maxmed_active
) {
3300 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3301 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3303 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3307 /* Local preference. */
3308 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3309 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3310 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3312 stream_putl(s
, attr
->local_pref
);
3315 /* Atomic aggregate. */
3316 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3317 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3318 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3323 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3324 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3325 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3326 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3329 /* AS4 capable peer */
3331 stream_putl(s
, attr
->aggregator_as
);
3333 /* 2-byte AS peer */
3336 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3338 if (attr
->aggregator_as
> 65535) {
3339 stream_putw(s
, BGP_AS_TRANS
);
3341 /* we have to send AS4_AGGREGATOR, too.
3342 * we'll do that later in order to send
3343 * attributes in ascending
3346 send_as4_aggregator
= 1;
3348 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3350 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3353 /* Community attribute. */
3354 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3355 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3356 if (attr
->community
->size
* 4 > 255) {
3358 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3359 | BGP_ATTR_FLAG_EXTLEN
);
3360 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3361 stream_putw(s
, attr
->community
->size
* 4);
3364 BGP_ATTR_FLAG_OPTIONAL
3365 | BGP_ATTR_FLAG_TRANS
);
3366 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3367 stream_putc(s
, attr
->community
->size
* 4);
3369 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3373 * Large Community attribute.
3375 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3376 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3377 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3378 if (lcom_length(attr
->lcommunity
) > 255) {
3380 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3381 | BGP_ATTR_FLAG_EXTLEN
);
3382 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3383 stream_putw(s
, lcom_length(attr
->lcommunity
));
3386 BGP_ATTR_FLAG_OPTIONAL
3387 | BGP_ATTR_FLAG_TRANS
);
3388 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3389 stream_putc(s
, lcom_length(attr
->lcommunity
));
3391 stream_put(s
, attr
->lcommunity
->val
,
3392 lcom_length(attr
->lcommunity
));
3395 /* Route Reflector. */
3396 if (peer
->sort
== BGP_PEER_IBGP
&& from
3397 && from
->sort
== BGP_PEER_IBGP
) {
3398 /* Originator ID. */
3399 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3400 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3403 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3404 stream_put_in_addr(s
, &attr
->originator_id
);
3406 stream_put_in_addr(s
, &from
->remote_id
);
3409 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3410 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3412 if (attr
->cluster
) {
3413 stream_putc(s
, attr
->cluster
->length
+ 4);
3414 /* If this peer configuration's parent BGP has
3416 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3417 stream_put_in_addr(s
, &bgp
->cluster_id
);
3419 stream_put_in_addr(s
, &bgp
->router_id
);
3420 stream_put(s
, attr
->cluster
->list
,
3421 attr
->cluster
->length
);
3424 /* If this peer configuration's parent BGP has
3426 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3427 stream_put_in_addr(s
, &bgp
->cluster_id
);
3429 stream_put_in_addr(s
, &bgp
->router_id
);
3433 /* Extended Communities attribute. */
3434 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3435 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3436 if (peer
->sort
== BGP_PEER_IBGP
3437 || peer
->sort
== BGP_PEER_CONFED
) {
3438 if (attr
->ecommunity
->size
* 8 > 255) {
3440 BGP_ATTR_FLAG_OPTIONAL
3441 | BGP_ATTR_FLAG_TRANS
3442 | BGP_ATTR_FLAG_EXTLEN
);
3443 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3444 stream_putw(s
, attr
->ecommunity
->size
* 8);
3447 BGP_ATTR_FLAG_OPTIONAL
3448 | BGP_ATTR_FLAG_TRANS
);
3449 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3450 stream_putc(s
, attr
->ecommunity
->size
* 8);
3452 stream_put(s
, attr
->ecommunity
->val
,
3453 attr
->ecommunity
->size
* 8);
3457 int ecom_tr_size
= 0;
3460 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3461 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3464 if (CHECK_FLAG(tbit
,
3465 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3472 if (ecom_tr_size
* 8 > 255) {
3475 BGP_ATTR_FLAG_OPTIONAL
3476 | BGP_ATTR_FLAG_TRANS
3477 | BGP_ATTR_FLAG_EXTLEN
);
3479 BGP_ATTR_EXT_COMMUNITIES
);
3480 stream_putw(s
, ecom_tr_size
* 8);
3484 BGP_ATTR_FLAG_OPTIONAL
3485 | BGP_ATTR_FLAG_TRANS
);
3487 BGP_ATTR_EXT_COMMUNITIES
);
3488 stream_putc(s
, ecom_tr_size
* 8);
3491 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3492 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3497 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3500 stream_put(s
, pnt
, 8);
3506 /* Label index attribute. */
3507 if (safi
== SAFI_LABELED_UNICAST
) {
3508 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3509 uint32_t label_index
;
3511 label_index
= attr
->label_index
;
3513 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
3515 BGP_ATTR_FLAG_OPTIONAL
3516 | BGP_ATTR_FLAG_TRANS
);
3517 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3519 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3521 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3522 stream_putc(s
, 0); // reserved
3523 stream_putw(s
, 0); // flags
3524 stream_putl(s
, label_index
);
3529 if (send_as4_path
) {
3530 /* If the peer is NOT As4 capable, AND */
3531 /* there are ASnums > 65535 in path THEN
3532 * give out AS4_PATH */
3534 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3536 * Hm, I wonder... confederation things *should* only be at
3537 * the beginning of an aspath, right? Then we should use
3538 * aspath_delete_confed_seq for this, because it is already
3540 * Folks, talk to me: what is reasonable here!?
3542 aspath
= aspath_delete_confed_seq(aspath
);
3545 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3546 | BGP_ATTR_FLAG_EXTLEN
);
3547 stream_putc(s
, BGP_ATTR_AS4_PATH
);
3548 aspath_sizep
= stream_get_endp(s
);
3550 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
3553 if (aspath
!= attr
->aspath
)
3554 aspath_free(aspath
);
3556 if (send_as4_aggregator
) {
3557 /* send AS4_AGGREGATOR, at this place */
3558 /* this section of code moved here in order to ensure the
3560 * *ascending* order of attributes
3562 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3563 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
3565 stream_putl(s
, attr
->aggregator_as
);
3566 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3569 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3570 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3571 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
3572 /* Tunnel Encap attribute */
3573 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3575 #if ENABLE_BGP_VNC_ATTR
3577 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3582 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
3583 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3584 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
3585 stream_putc(s
, 9); // Length
3586 stream_putc(s
, 0); // Flags
3587 stream_putc(s
, attr
->pmsi_tnl_type
);
3588 stream_put(s
, &(attr
->label
),
3589 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
3590 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3591 // Unicast tunnel endpoint IP address
3594 /* Unknown transit attribute. */
3596 stream_put(s
, attr
->transit
->val
, attr
->transit
->length
);
3598 /* Return total size of attribute. */
3599 return stream_get_endp(s
) - cp
;
3602 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
3604 unsigned long attrlen_pnt
;
3606 iana_safi_t pkt_safi
;
3608 /* Set extended bit always to encode the attribute length as 2 bytes */
3609 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3610 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
3612 attrlen_pnt
= stream_get_endp(s
);
3613 stream_putw(s
, 0); /* Length of this attribute. */
3615 /* Convert AFI, SAFI to values for packet. */
3616 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3618 stream_putw(s
, pkt_afi
);
3619 stream_putc(s
, pkt_safi
);
3624 void bgp_packet_mpunreach_prefix(struct stream
*s
, struct prefix
*p
, afi_t afi
,
3625 safi_t safi
, struct prefix_rd
*prd
,
3626 mpls_label_t
*label
, uint32_t num_labels
,
3627 int addpath_encode
, uint32_t addpath_tx_id
,
3630 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
3632 if (safi
== SAFI_LABELED_UNICAST
) {
3633 label
= (mpls_label_t
*)wlabel
;
3637 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
3638 addpath_encode
, addpath_tx_id
, attr
);
3641 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
3643 bgp_packet_mpattr_end(s
, attrlen_pnt
);
3646 /* Initialization of attribute. */
3647 void bgp_attr_init(void)
3659 void bgp_attr_finish(void)
3664 ecommunity_finish();
3665 lcommunity_finish();
3671 /* Make attribute packet. */
3672 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
3673 struct prefix
*prefix
)
3678 struct aspath
*aspath
;
3679 int addpath_encode
= 0;
3680 uint32_t addpath_tx_id
= 0;
3682 /* Remember current pointer. */
3683 cp
= stream_get_endp(s
);
3685 /* Place holder of length. */
3688 /* Origin attribute. */
3689 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3690 stream_putc(s
, BGP_ATTR_ORIGIN
);
3692 stream_putc(s
, attr
->origin
);
3694 aspath
= attr
->aspath
;
3696 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3697 stream_putc(s
, BGP_ATTR_AS_PATH
);
3698 aspath_lenp
= stream_get_endp(s
);
3701 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
3703 /* Nexthop attribute. */
3704 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3705 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
3706 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3707 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3709 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3712 /* MED attribute. */
3713 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
3714 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3715 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3717 stream_putl(s
, attr
->med
);
3720 /* Local preference. */
3721 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
3722 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3723 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3725 stream_putl(s
, attr
->local_pref
);
3728 /* Atomic aggregate. */
3729 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3730 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3731 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3736 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3737 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3738 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3740 stream_putl(s
, attr
->aggregator_as
);
3741 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3744 /* Community attribute. */
3745 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3746 if (attr
->community
->size
* 4 > 255) {
3748 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3749 | BGP_ATTR_FLAG_EXTLEN
);
3750 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3751 stream_putw(s
, attr
->community
->size
* 4);
3754 BGP_ATTR_FLAG_OPTIONAL
3755 | BGP_ATTR_FLAG_TRANS
);
3756 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3757 stream_putc(s
, attr
->community
->size
* 4);
3759 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3762 /* Large Community attribute. */
3763 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
3764 if (lcom_length(attr
->lcommunity
) > 255) {
3766 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3767 | BGP_ATTR_FLAG_EXTLEN
);
3768 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3769 stream_putw(s
, lcom_length(attr
->lcommunity
));
3772 BGP_ATTR_FLAG_OPTIONAL
3773 | BGP_ATTR_FLAG_TRANS
);
3774 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3775 stream_putc(s
, lcom_length(attr
->lcommunity
));
3778 stream_put(s
, attr
->lcommunity
->val
,
3779 lcom_length(attr
->lcommunity
));
3782 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3783 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
3784 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
3785 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
3788 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3789 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3790 sizep
= stream_get_endp(s
);
3793 stream_putc(s
, 0); /* Marker: Attribute length. */
3794 stream_putw(s
, AFI_IP6
); /* AFI */
3795 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3798 stream_putc(s
, attr
->mp_nexthop_len
);
3799 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3800 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3801 stream_put(s
, &attr
->mp_nexthop_local
,
3808 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
3811 /* Set MP attribute length. */
3812 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
3816 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3817 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
3819 BGP_ATTR_FLAG_OPTIONAL
3820 | BGP_ATTR_FLAG_TRANS
);
3821 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3823 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3824 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3825 stream_putc(s
, 0); // reserved
3826 stream_putw(s
, 0); // flags
3827 stream_putl(s
, attr
->label_index
);
3831 /* Return total size of attribute. */
3832 len
= stream_get_endp(s
) - cp
- 2;
3833 stream_putw_at(s
, cp
, len
);