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 static void transit_unintern(struct transit
**transit
)
426 if ((*transit
)->refcnt
)
427 (*transit
)->refcnt
--;
429 if ((*transit
)->refcnt
== 0) {
430 hash_release(transit_hash
, *transit
);
431 transit_free(*transit
);
436 static unsigned int transit_hash_key_make(const void *p
)
438 const struct transit
*transit
= p
;
440 return jhash(transit
->val
, transit
->length
, 0);
443 static bool transit_hash_cmp(const void *p1
, const void *p2
)
445 const struct transit
*transit1
= p1
;
446 const struct transit
*transit2
= p2
;
448 return (transit1
->length
== transit2
->length
449 && memcmp(transit1
->val
, transit2
->val
, transit1
->length
) == 0);
452 static void transit_init(void)
454 transit_hash
= hash_create(transit_hash_key_make
, transit_hash_cmp
,
458 static void transit_finish(void)
460 hash_clean(transit_hash
, (void (*)(void *))transit_free
);
461 hash_free(transit_hash
);
465 /* Attribute hash routines. */
466 static struct hash
*attrhash
;
468 unsigned long int attr_count(void)
470 return attrhash
->count
;
473 unsigned long int attr_unknown_count(void)
475 return transit_hash
->count
;
478 unsigned int attrhash_key_make(const void *p
)
480 const struct attr
*attr
= (struct attr
*)p
;
482 #define MIX(val) key = jhash_1word(val, key)
483 #define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
485 MIX3(attr
->origin
, attr
->nexthop
.s_addr
, attr
->med
);
486 MIX3(attr
->local_pref
, attr
->aggregator_as
,
487 attr
->aggregator_addr
.s_addr
);
488 MIX3(attr
->weight
, attr
->mp_nexthop_global_in
.s_addr
,
489 attr
->originator_id
.s_addr
);
490 MIX3(attr
->tag
, attr
->label
, attr
->label_index
);
493 MIX(aspath_key_make(attr
->aspath
));
495 MIX(community_hash_make(attr
->community
));
497 if (attr
->lcommunity
)
498 MIX(lcommunity_hash_make(attr
->lcommunity
));
499 if (attr
->ecommunity
)
500 MIX(ecommunity_hash_make(attr
->ecommunity
));
502 MIX(cluster_hash_key_make(attr
->cluster
));
504 MIX(transit_hash_key_make(attr
->transit
));
505 if (attr
->encap_subtlvs
)
506 MIX(encap_hash_key_make(attr
->encap_subtlvs
));
508 if (attr
->vnc_subtlvs
)
509 MIX(encap_hash_key_make(attr
->vnc_subtlvs
));
511 MIX(attr
->mp_nexthop_len
);
512 key
= jhash(attr
->mp_nexthop_global
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
513 key
= jhash(attr
->mp_nexthop_local
.s6_addr
, IPV6_MAX_BYTELEN
, key
);
514 MIX3(attr
->nh_ifindex
, attr
->nh_lla_ifindex
, attr
->distance
);
515 MIX(attr
->rmap_table_id
);
520 bool attrhash_cmp(const void *p1
, const void *p2
)
522 const struct attr
*attr1
= p1
;
523 const struct attr
*attr2
= p2
;
525 if (attr1
->flag
== attr2
->flag
&& attr1
->origin
== attr2
->origin
526 && attr1
->nexthop
.s_addr
== attr2
->nexthop
.s_addr
527 && attr1
->aspath
== attr2
->aspath
528 && attr1
->community
== attr2
->community
&& attr1
->med
== attr2
->med
529 && attr1
->local_pref
== attr2
->local_pref
530 && attr1
->rmap_change_flags
== attr2
->rmap_change_flags
) {
531 if (attr1
->aggregator_as
== attr2
->aggregator_as
532 && attr1
->aggregator_addr
.s_addr
533 == attr2
->aggregator_addr
.s_addr
534 && attr1
->weight
== attr2
->weight
535 && attr1
->tag
== attr2
->tag
536 && attr1
->label_index
== attr2
->label_index
537 && attr1
->mp_nexthop_len
== attr2
->mp_nexthop_len
538 && attr1
->ecommunity
== attr2
->ecommunity
539 && attr1
->lcommunity
== attr2
->lcommunity
540 && attr1
->cluster
== attr2
->cluster
541 && attr1
->transit
== attr2
->transit
542 && attr1
->rmap_table_id
== attr2
->rmap_table_id
543 && (attr1
->encap_tunneltype
== attr2
->encap_tunneltype
)
544 && encap_same(attr1
->encap_subtlvs
, attr2
->encap_subtlvs
)
546 && encap_same(attr1
->vnc_subtlvs
, attr2
->vnc_subtlvs
)
548 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_global
,
549 &attr2
->mp_nexthop_global
)
550 && IPV6_ADDR_SAME(&attr1
->mp_nexthop_local
,
551 &attr2
->mp_nexthop_local
)
552 && IPV4_ADDR_SAME(&attr1
->mp_nexthop_global_in
,
553 &attr2
->mp_nexthop_global_in
)
554 && IPV4_ADDR_SAME(&attr1
->originator_id
,
555 &attr2
->originator_id
)
556 && overlay_index_same(attr1
, attr2
)
557 && attr1
->nh_ifindex
== attr2
->nh_ifindex
558 && attr1
->nh_lla_ifindex
== attr2
->nh_lla_ifindex
559 && attr1
->distance
== attr2
->distance
)
566 static void attrhash_init(void)
569 hash_create(attrhash_key_make
, attrhash_cmp
, "BGP Attributes");
573 * special for hash_clean below
575 static void attr_vfree(void *attr
)
577 XFREE(MTYPE_ATTR
, attr
);
580 static void attrhash_finish(void)
582 hash_clean(attrhash
, attr_vfree
);
587 static void attr_show_all_iterator(struct hash_bucket
*bucket
, struct vty
*vty
)
589 struct attr
*attr
= bucket
->data
;
591 vty_out(vty
, "attr[%ld] nexthop %s\n", attr
->refcnt
,
592 inet_ntoa(attr
->nexthop
));
593 vty_out(vty
, "\tflags: %" PRIu64
" med: %u local_pref: %u origin: %u weight: %u label: %u\n",
594 attr
->flag
, attr
->med
, attr
->local_pref
, attr
->origin
,
595 attr
->weight
, attr
->label
);
598 void attr_show_all(struct vty
*vty
)
600 hash_iterate(attrhash
, (void (*)(struct hash_bucket
*,
601 void *))attr_show_all_iterator
,
605 static void *bgp_attr_hash_alloc(void *p
)
607 struct attr
*val
= (struct attr
*)p
;
610 attr
= XMALLOC(MTYPE_ATTR
, sizeof(struct attr
));
612 if (val
->encap_subtlvs
) {
613 val
->encap_subtlvs
= NULL
;
616 if (val
->vnc_subtlvs
) {
617 val
->vnc_subtlvs
= NULL
;
624 /* Internet argument attribute. */
625 struct attr
*bgp_attr_intern(struct attr
*attr
)
629 /* Intern referenced strucutre. */
631 if (!attr
->aspath
->refcnt
)
632 attr
->aspath
= aspath_intern(attr
->aspath
);
634 attr
->aspath
->refcnt
++;
636 if (attr
->community
) {
637 if (!attr
->community
->refcnt
)
638 attr
->community
= community_intern(attr
->community
);
640 attr
->community
->refcnt
++;
643 if (attr
->ecommunity
) {
644 if (!attr
->ecommunity
->refcnt
)
645 attr
->ecommunity
= ecommunity_intern(attr
->ecommunity
);
647 attr
->ecommunity
->refcnt
++;
649 if (attr
->lcommunity
) {
650 if (!attr
->lcommunity
->refcnt
)
651 attr
->lcommunity
= lcommunity_intern(attr
->lcommunity
);
653 attr
->lcommunity
->refcnt
++;
656 if (!attr
->cluster
->refcnt
)
657 attr
->cluster
= cluster_intern(attr
->cluster
);
659 attr
->cluster
->refcnt
++;
662 if (!attr
->transit
->refcnt
)
663 attr
->transit
= transit_intern(attr
->transit
);
665 attr
->transit
->refcnt
++;
667 if (attr
->encap_subtlvs
) {
668 if (!attr
->encap_subtlvs
->refcnt
)
669 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
672 attr
->encap_subtlvs
->refcnt
++;
675 if (attr
->vnc_subtlvs
) {
676 if (!attr
->vnc_subtlvs
->refcnt
)
677 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
680 attr
->vnc_subtlvs
->refcnt
++;
684 /* At this point, attr only contains intern'd pointers. that means
685 * if we find it in attrhash, it has all the same pointers and we
686 * correctly updated the refcounts on these.
687 * If we don't find it, we need to allocate a one because in all
688 * cases this returns a new reference to a hashed attr, but the input
690 find
= (struct attr
*)hash_get(attrhash
, attr
, bgp_attr_hash_alloc
);
696 /* Make network statement's attribute. */
697 struct attr
*bgp_attr_default_set(struct attr
*attr
, uint8_t origin
)
699 memset(attr
, 0, sizeof(struct attr
));
701 attr
->origin
= origin
;
702 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
703 attr
->aspath
= aspath_empty();
704 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
705 attr
->weight
= BGP_ATTR_DEFAULT_WEIGHT
;
707 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
708 attr
->label
= MPLS_INVALID_LABEL
;
709 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
710 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
715 /* Create the attributes for an aggregate */
716 struct attr
*bgp_attr_aggregate_intern(struct bgp
*bgp
, uint8_t origin
,
717 struct aspath
*aspath
,
718 struct community
*community
,
719 struct ecommunity
*ecommunity
,
720 struct lcommunity
*lcommunity
,
721 struct bgp_aggregate
*aggregate
,
722 uint8_t atomic_aggregate
,
729 memset(&attr
, 0, sizeof(struct attr
));
731 /* Origin attribute. */
732 attr
.origin
= origin
;
733 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
735 /* AS path attribute. */
737 attr
.aspath
= aspath_intern(aspath
);
739 attr
.aspath
= aspath_empty();
740 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
742 /* Next hop attribute. */
743 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
746 uint32_t gshut
= COMMUNITY_GSHUT
;
748 /* If we are not shutting down ourselves and we are
749 * aggregating a route that contains the GSHUT community we
750 * need to remove that community when creating the aggregate */
751 if (!bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)
752 && community_include(community
, gshut
)) {
753 community_del_val(community
, &gshut
);
756 attr
.community
= community
;
757 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
761 attr
.ecommunity
= ecommunity
;
762 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
766 attr
.lcommunity
= lcommunity
;
767 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
770 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
771 bgp_attr_add_gshut_community(&attr
);
774 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
775 attr
.label
= MPLS_INVALID_LABEL
;
776 attr
.weight
= BGP_ATTR_DEFAULT_WEIGHT
;
777 attr
.mp_nexthop_len
= IPV6_MAX_BYTELEN
;
778 if (!aggregate
->as_set
|| atomic_aggregate
)
779 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
780 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
781 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
))
782 attr
.aggregator_as
= bgp
->confed_id
;
784 attr
.aggregator_as
= bgp
->as
;
785 attr
.aggregator_addr
= bgp
->router_id
;
786 attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
787 attr
.label
= MPLS_INVALID_LABEL
;
789 /* Apply route-map */
790 if (aggregate
->rmap
.name
) {
791 struct attr attr_tmp
= attr
;
792 struct bgp_path_info rmap_path
;
794 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
795 rmap_path
.peer
= bgp
->peer_self
;
796 rmap_path
.attr
= &attr_tmp
;
798 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
800 ret
= route_map_apply(aggregate
->rmap
.map
, p
, RMAP_BGP
,
803 bgp
->peer_self
->rmap_type
= 0;
805 if (ret
== RMAP_DENYMATCH
) {
806 /* Free uninterned attribute. */
807 bgp_attr_flush(&attr_tmp
);
809 /* Unintern original. */
810 aspath_unintern(&attr
.aspath
);
814 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
815 bgp_attr_add_gshut_community(&attr_tmp
);
817 new = bgp_attr_intern(&attr_tmp
);
820 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
821 bgp_attr_add_gshut_community(&attr
);
823 new = bgp_attr_intern(&attr
);
826 aspath_unintern(&new->aspath
);
830 /* Unintern just the sub-components of the attr, but not the attr */
831 void bgp_attr_unintern_sub(struct attr
*attr
)
833 /* aspath refcount shoud be decrement. */
835 aspath_unintern(&attr
->aspath
);
836 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
));
839 community_unintern(&attr
->community
);
840 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
842 if (attr
->ecommunity
)
843 ecommunity_unintern(&attr
->ecommunity
);
844 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
));
846 if (attr
->lcommunity
)
847 lcommunity_unintern(&attr
->lcommunity
);
848 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
851 cluster_unintern(attr
->cluster
);
852 UNSET_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
));
855 transit_unintern(&attr
->transit
);
857 if (attr
->encap_subtlvs
)
858 encap_unintern(&attr
->encap_subtlvs
, ENCAP_SUBTLV_TYPE
);
861 if (attr
->vnc_subtlvs
)
862 encap_unintern(&attr
->vnc_subtlvs
, VNC_SUBTLV_TYPE
);
867 * We have some show commands that let you experimentally
868 * apply a route-map. When we apply the route-map
869 * we are reseting values but not saving them for
870 * posterity via intern'ing( because route-maps don't
871 * do that) but at this point in time we need
872 * to compare the new attr to the old and if the
873 * routemap has changed it we need to, as Snoop Dog says,
874 * Drop it like it's hot
876 void bgp_attr_undup(struct attr
*new, struct attr
*old
)
878 if (new->aspath
!= old
->aspath
)
879 aspath_free(new->aspath
);
881 if (new->community
!= old
->community
)
882 community_free(&new->community
);
884 if (new->ecommunity
!= old
->ecommunity
)
885 ecommunity_free(&new->ecommunity
);
887 if (new->lcommunity
!= old
->lcommunity
)
888 lcommunity_free(&new->lcommunity
);
891 /* Free bgp attribute and aspath. */
892 void bgp_attr_unintern(struct attr
**pattr
)
894 struct attr
*attr
= *pattr
;
898 /* Decrement attribute reference. */
903 /* If reference becomes zero then free attribute object. */
904 if (attr
->refcnt
== 0) {
905 ret
= hash_release(attrhash
, attr
);
907 XFREE(MTYPE_ATTR
, attr
);
911 bgp_attr_unintern_sub(&tmp
);
914 void bgp_attr_flush(struct attr
*attr
)
916 if (attr
->aspath
&& !attr
->aspath
->refcnt
) {
917 aspath_free(attr
->aspath
);
920 if (attr
->community
&& !attr
->community
->refcnt
)
921 community_free(&attr
->community
);
922 if (attr
->ecommunity
&& !attr
->ecommunity
->refcnt
)
923 ecommunity_free(&attr
->ecommunity
);
924 if (attr
->lcommunity
&& !attr
->lcommunity
->refcnt
)
925 lcommunity_free(&attr
->lcommunity
);
926 if (attr
->cluster
&& !attr
->cluster
->refcnt
) {
927 cluster_free(attr
->cluster
);
928 attr
->cluster
= NULL
;
930 if (attr
->transit
&& !attr
->transit
->refcnt
) {
931 transit_free(attr
->transit
);
932 attr
->transit
= NULL
;
934 if (attr
->encap_subtlvs
&& !attr
->encap_subtlvs
->refcnt
) {
935 encap_free(attr
->encap_subtlvs
);
936 attr
->encap_subtlvs
= NULL
;
939 if (attr
->vnc_subtlvs
&& !attr
->vnc_subtlvs
->refcnt
) {
940 encap_free(attr
->vnc_subtlvs
);
941 attr
->vnc_subtlvs
= NULL
;
946 /* Implement draft-scudder-idr-optional-transitive behaviour and
947 * avoid resetting sessions for malformed attributes which are
948 * are partial/optional and hence where the error likely was not
949 * introduced by the sending neighbour.
951 static bgp_attr_parse_ret_t
952 bgp_attr_malformed(struct bgp_attr_parser_args
*args
, uint8_t subcode
,
955 struct peer
*const peer
= args
->peer
;
956 const uint8_t flags
= args
->flags
;
957 /* startp and length must be special-cased, as whether or not to
958 * send the attribute data with the NOTIFY depends on the error,
959 * the caller therefore signals this with the seperate length argument
961 uint8_t *notify_datap
= (length
> 0 ? args
->startp
: NULL
);
963 /* Only relax error handling for eBGP peers */
964 if (peer
->sort
!= BGP_PEER_EBGP
) {
965 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
966 notify_datap
, length
);
967 return BGP_ATTR_PARSE_ERROR
;
970 /* Adjust the stream getp to the end of the attribute, in case we can
971 * still proceed but the caller hasn't read all the attribute.
973 stream_set_getp(BGP_INPUT(peer
),
974 (args
->startp
- STREAM_DATA(BGP_INPUT(peer
)))
977 switch (args
->type
) {
978 /* where an attribute is relatively inconsequential, e.g. it does not
979 * affect route selection, and can be safely ignored, then any such
980 * attributes which are malformed should just be ignored and the route
981 * processed as normal.
983 case BGP_ATTR_AS4_AGGREGATOR
:
984 case BGP_ATTR_AGGREGATOR
:
985 case BGP_ATTR_ATOMIC_AGGREGATE
:
986 return BGP_ATTR_PARSE_PROCEED
;
988 /* Core attributes, particularly ones which may influence route
989 * selection, should always cause session resets
991 case BGP_ATTR_ORIGIN
:
992 case BGP_ATTR_AS_PATH
:
993 case BGP_ATTR_NEXT_HOP
:
994 case BGP_ATTR_MULTI_EXIT_DISC
:
995 case BGP_ATTR_LOCAL_PREF
:
996 case BGP_ATTR_COMMUNITIES
:
997 case BGP_ATTR_ORIGINATOR_ID
:
998 case BGP_ATTR_CLUSTER_LIST
:
999 case BGP_ATTR_MP_REACH_NLRI
:
1000 case BGP_ATTR_MP_UNREACH_NLRI
:
1001 case BGP_ATTR_EXT_COMMUNITIES
:
1002 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
, subcode
,
1003 notify_datap
, length
);
1004 return BGP_ATTR_PARSE_ERROR
;
1007 /* Partial optional attributes that are malformed should not cause
1008 * the whole session to be reset. Instead treat it as a withdrawal
1009 * of the routes, if possible.
1011 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)
1012 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1013 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
))
1014 return BGP_ATTR_PARSE_WITHDRAW
;
1016 /* default to reset */
1017 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1020 /* Find out what is wrong with the path attribute flag bits and log the error.
1021 "Flag bits" here stand for Optional, Transitive and Partial, but not for
1022 Extended Length. Checking O/T/P bits at once implies, that the attribute
1023 being diagnosed is defined by RFC as either a "well-known" or an "optional,
1024 non-transitive" attribute. */
1026 bgp_attr_flags_diagnose(struct bgp_attr_parser_args
*args
,
1027 uint8_t desired_flags
/* how RFC says it must be */
1030 uint8_t seen
= 0, i
;
1031 uint8_t real_flags
= args
->flags
;
1032 const uint8_t attr_code
= args
->type
;
1034 desired_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1035 real_flags
&= ~BGP_ATTR_FLAG_EXTLEN
;
1036 for (i
= 0; i
<= 2; i
++) /* O,T,P, but not E */
1037 if (CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1038 != CHECK_FLAG(real_flags
, attr_flag_str
[i
].key
)) {
1039 flog_err(EC_BGP_ATTR_FLAG
,
1040 "%s attribute must%s be flagged as \"%s\"",
1041 lookup_msg(attr_str
, attr_code
, NULL
),
1042 CHECK_FLAG(desired_flags
, attr_flag_str
[i
].key
)
1045 attr_flag_str
[i
].str
);
1050 "Strange, %s called for attr %s, but no problem found with flags"
1051 " (real flags 0x%x, desired 0x%x)",
1052 __func__
, lookup_msg(attr_str
, attr_code
, NULL
),
1053 real_flags
, desired_flags
);
1057 /* Required flags for attributes. EXTLEN will be masked off when testing,
1058 * as will PARTIAL for optional+transitive attributes.
1060 const uint8_t attr_flags_values
[] = {
1061 [BGP_ATTR_ORIGIN
] = BGP_ATTR_FLAG_TRANS
,
1062 [BGP_ATTR_AS_PATH
] = BGP_ATTR_FLAG_TRANS
,
1063 [BGP_ATTR_NEXT_HOP
] = BGP_ATTR_FLAG_TRANS
,
1064 [BGP_ATTR_MULTI_EXIT_DISC
] = BGP_ATTR_FLAG_OPTIONAL
,
1065 [BGP_ATTR_LOCAL_PREF
] = BGP_ATTR_FLAG_TRANS
,
1066 [BGP_ATTR_ATOMIC_AGGREGATE
] = BGP_ATTR_FLAG_TRANS
,
1067 [BGP_ATTR_AGGREGATOR
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1068 [BGP_ATTR_COMMUNITIES
] = BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
,
1069 [BGP_ATTR_ORIGINATOR_ID
] = BGP_ATTR_FLAG_OPTIONAL
,
1070 [BGP_ATTR_CLUSTER_LIST
] = BGP_ATTR_FLAG_OPTIONAL
,
1071 [BGP_ATTR_MP_REACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1072 [BGP_ATTR_MP_UNREACH_NLRI
] = BGP_ATTR_FLAG_OPTIONAL
,
1073 [BGP_ATTR_EXT_COMMUNITIES
] =
1074 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1075 [BGP_ATTR_AS4_PATH
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1076 [BGP_ATTR_AS4_AGGREGATOR
] =
1077 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1078 [BGP_ATTR_PMSI_TUNNEL
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1079 [BGP_ATTR_LARGE_COMMUNITIES
] =
1080 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1081 [BGP_ATTR_PREFIX_SID
] = BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
,
1083 static const size_t attr_flags_values_max
= array_size(attr_flags_values
) - 1;
1085 static int bgp_attr_flag_invalid(struct bgp_attr_parser_args
*args
)
1087 uint8_t mask
= BGP_ATTR_FLAG_EXTLEN
;
1088 const uint8_t flags
= args
->flags
;
1089 const uint8_t attr_code
= args
->type
;
1091 /* there may be attributes we don't know about */
1092 if (attr_code
> attr_flags_values_max
)
1094 if (attr_flags_values
[attr_code
] == 0)
1097 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1101 if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL
, flags
)
1102 && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS
, flags
)) {
1105 "%s well-known attributes must have transitive flag set (%x)",
1106 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1110 /* "For well-known attributes and for optional non-transitive
1112 * the Partial bit MUST be set to 0."
1114 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_PARTIAL
)) {
1115 if (!CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)) {
1116 flog_err(EC_BGP_ATTR_FLAG
,
1117 "%s well-known attribute "
1118 "must NOT have the partial flag set (%x)",
1119 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1122 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1123 && !CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
)) {
1124 flog_err(EC_BGP_ATTR_FLAG
,
1125 "%s optional + transitive attribute "
1126 "must NOT have the partial flag set (%x)",
1127 lookup_msg(attr_str
, attr_code
, NULL
), flags
);
1132 /* Optional transitive attributes may go through speakers that don't
1133 * reocgnise them and set the Partial bit.
1135 if (CHECK_FLAG(flags
, BGP_ATTR_FLAG_OPTIONAL
)
1136 && CHECK_FLAG(flags
, BGP_ATTR_FLAG_TRANS
))
1137 SET_FLAG(mask
, BGP_ATTR_FLAG_PARTIAL
);
1139 if ((flags
& ~mask
) == attr_flags_values
[attr_code
])
1142 bgp_attr_flags_diagnose(args
, attr_flags_values
[attr_code
]);
1146 /* Get origin attribute of the update message. */
1147 static bgp_attr_parse_ret_t
bgp_attr_origin(struct bgp_attr_parser_args
*args
)
1149 struct peer
*const peer
= args
->peer
;
1150 struct attr
*const attr
= args
->attr
;
1151 const bgp_size_t length
= args
->length
;
1153 /* If any recognized attribute has Attribute Length that conflicts
1154 with the expected length (based on the attribute type code), then
1155 the Error Subcode is set to Attribute Length Error. The Data
1156 field contains the erroneous attribute (type, length and
1159 flog_err(EC_BGP_ATTR_LEN
,
1160 "Origin attribute length is not one %d", length
);
1161 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1165 /* Fetch origin attribute. */
1166 attr
->origin
= stream_getc(BGP_INPUT(peer
));
1168 /* If the ORIGIN attribute has an undefined value, then the Error
1169 Subcode is set to Invalid Origin Attribute. The Data field
1170 contains the unrecognized attribute (type, length and value). */
1171 if ((attr
->origin
!= BGP_ORIGIN_IGP
) && (attr
->origin
!= BGP_ORIGIN_EGP
)
1172 && (attr
->origin
!= BGP_ORIGIN_INCOMPLETE
)) {
1173 flog_err(EC_BGP_ATTR_ORIGIN
,
1174 "Origin attribute value is invalid %d", attr
->origin
);
1175 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_INVAL_ORIGIN
,
1179 /* Set oring attribute flag. */
1180 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
);
1185 /* Parse AS path information. This function is wrapper of
1187 static int bgp_attr_aspath(struct bgp_attr_parser_args
*args
)
1189 struct attr
*const attr
= args
->attr
;
1190 struct peer
*const peer
= args
->peer
;
1191 const bgp_size_t length
= args
->length
;
1194 * peer with AS4 => will get 4Byte ASnums
1195 * otherwise, will get 16 Bit
1197 attr
->aspath
= aspath_parse(peer
->curr
, length
,
1198 CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
));
1200 /* In case of IBGP, length will be zero. */
1201 if (!attr
->aspath
) {
1202 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1203 "Malformed AS path from %s, length is %d", peer
->host
,
1205 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1209 /* Set aspath attribute flag. */
1210 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
);
1212 return BGP_ATTR_PARSE_PROCEED
;
1215 static bgp_attr_parse_ret_t
bgp_attr_aspath_check(struct peer
*const peer
,
1216 struct attr
*const attr
)
1218 /* These checks were part of bgp_attr_aspath, but with
1219 * as4 we should to check aspath things when
1220 * aspath synthesizing with as4_path has already taken place.
1221 * Otherwise we check ASPATH and use the synthesized thing, and that is
1223 * So do the checks later, i.e. here
1225 struct aspath
*aspath
;
1227 /* Confederation sanity check. */
1228 if ((peer
->sort
== BGP_PEER_CONFED
1229 && !aspath_left_confed_check(attr
->aspath
))
1230 || (peer
->sort
== BGP_PEER_EBGP
1231 && aspath_confed_check(attr
->aspath
))) {
1232 flog_err(EC_BGP_ATTR_MAL_AS_PATH
, "Malformed AS path from %s",
1234 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1235 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1236 return BGP_ATTR_PARSE_ERROR
;
1239 /* First AS check for EBGP. */
1240 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_ENFORCE_FIRST_AS
)) {
1241 if (peer
->sort
== BGP_PEER_EBGP
1242 && !aspath_firstas_check(attr
->aspath
, peer
->as
)) {
1243 flog_err(EC_BGP_ATTR_FIRST_AS
,
1244 "%s incorrect first AS (must be %u)",
1245 peer
->host
, peer
->as
);
1246 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
1247 BGP_NOTIFY_UPDATE_MAL_AS_PATH
);
1248 return BGP_ATTR_PARSE_ERROR
;
1252 /* local-as prepend */
1253 if (peer
->change_local_as
1254 && !CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
)) {
1255 aspath
= aspath_dup(attr
->aspath
);
1256 aspath
= aspath_add_seq(aspath
, peer
->change_local_as
);
1257 aspath_unintern(&attr
->aspath
);
1258 attr
->aspath
= aspath_intern(aspath
);
1261 return BGP_ATTR_PARSE_PROCEED
;
1264 /* Parse AS4 path information. This function is another wrapper of
1266 static int bgp_attr_as4_path(struct bgp_attr_parser_args
*args
,
1267 struct aspath
**as4_path
)
1269 struct peer
*const peer
= args
->peer
;
1270 struct attr
*const attr
= args
->attr
;
1271 const bgp_size_t length
= args
->length
;
1273 *as4_path
= aspath_parse(peer
->curr
, length
, 1);
1275 /* In case of IBGP, length will be zero. */
1277 flog_err(EC_BGP_ATTR_MAL_AS_PATH
,
1278 "Malformed AS4 path from %s, length is %d", peer
->host
,
1280 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_MAL_AS_PATH
,
1284 /* Set aspath attribute flag. */
1285 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
);
1287 return BGP_ATTR_PARSE_PROCEED
;
1291 * Check that the nexthop attribute is valid.
1293 bgp_attr_parse_ret_t
1294 bgp_attr_nexthop_valid(struct peer
*peer
, struct attr
*attr
)
1296 in_addr_t nexthop_h
;
1298 nexthop_h
= ntohl(attr
->nexthop
.s_addr
);
1299 if ((IPV4_NET0(nexthop_h
) || IPV4_NET127(nexthop_h
)
1300 || IPV4_CLASS_DE(nexthop_h
))
1301 && !BGP_DEBUG(allow_martians
, ALLOW_MARTIANS
)) {
1302 uint8_t data
[7]; /* type(2) + length(1) + nhop(4) */
1303 char buf
[INET_ADDRSTRLEN
];
1305 inet_ntop(AF_INET
, &attr
->nexthop
.s_addr
, buf
,
1307 flog_err(EC_BGP_ATTR_MARTIAN_NH
, "Martian nexthop %s",
1309 data
[0] = BGP_ATTR_FLAG_TRANS
;
1310 data
[1] = BGP_ATTR_NEXT_HOP
;
1311 data
[2] = BGP_ATTR_NHLEN_IPV4
;
1312 memcpy(&data
[3], &attr
->nexthop
.s_addr
, BGP_ATTR_NHLEN_IPV4
);
1313 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
1314 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP
,
1316 return BGP_ATTR_PARSE_ERROR
;
1319 return BGP_ATTR_PARSE_PROCEED
;
1322 /* Nexthop attribute. */
1323 static bgp_attr_parse_ret_t
bgp_attr_nexthop(struct bgp_attr_parser_args
*args
)
1325 struct peer
*const peer
= args
->peer
;
1326 struct attr
*const attr
= args
->attr
;
1327 const bgp_size_t length
= args
->length
;
1329 /* Check nexthop attribute length. */
1331 flog_err(EC_BGP_ATTR_LEN
,
1332 "Nexthop attribute length isn't four [%d]", length
);
1334 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1338 attr
->nexthop
.s_addr
= stream_get_ipv4(peer
->curr
);
1339 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1341 return BGP_ATTR_PARSE_PROCEED
;
1344 /* MED atrribute. */
1345 static bgp_attr_parse_ret_t
bgp_attr_med(struct bgp_attr_parser_args
*args
)
1347 struct peer
*const peer
= args
->peer
;
1348 struct attr
*const attr
= args
->attr
;
1349 const bgp_size_t length
= args
->length
;
1353 flog_err(EC_BGP_ATTR_LEN
,
1354 "MED attribute length isn't four [%d]", length
);
1356 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1360 attr
->med
= stream_getl(peer
->curr
);
1362 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1364 return BGP_ATTR_PARSE_PROCEED
;
1367 /* Local preference attribute. */
1368 static bgp_attr_parse_ret_t
1369 bgp_attr_local_pref(struct bgp_attr_parser_args
*args
)
1371 struct peer
*const peer
= args
->peer
;
1372 struct attr
*const attr
= args
->attr
;
1373 const bgp_size_t length
= args
->length
;
1377 flog_err(EC_BGP_ATTR_LEN
,
1378 "LOCAL_PREF attribute length isn't 4 [%u]", length
);
1379 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1383 /* If it is contained in an UPDATE message that is received from an
1384 external peer, then this attribute MUST be ignored by the
1385 receiving speaker. */
1386 if (peer
->sort
== BGP_PEER_EBGP
) {
1387 stream_forward_getp(peer
->curr
, length
);
1388 return BGP_ATTR_PARSE_PROCEED
;
1391 attr
->local_pref
= stream_getl(peer
->curr
);
1393 /* Set the local-pref flag. */
1394 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1396 return BGP_ATTR_PARSE_PROCEED
;
1399 /* Atomic aggregate. */
1400 static int bgp_attr_atomic(struct bgp_attr_parser_args
*args
)
1402 struct attr
*const attr
= args
->attr
;
1403 const bgp_size_t length
= args
->length
;
1407 flog_err(EC_BGP_ATTR_LEN
,
1408 "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1410 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1414 /* Set atomic aggregate flag. */
1415 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
1417 return BGP_ATTR_PARSE_PROCEED
;
1420 /* Aggregator attribute */
1421 static int bgp_attr_aggregator(struct bgp_attr_parser_args
*args
)
1423 struct peer
*const peer
= args
->peer
;
1424 struct attr
*const attr
= args
->attr
;
1425 const bgp_size_t length
= args
->length
;
1429 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1430 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1433 if (length
!= wantedlen
) {
1434 flog_err(EC_BGP_ATTR_LEN
,
1435 "AGGREGATOR attribute length isn't %u [%u]", wantedlen
,
1437 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1441 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
))
1442 attr
->aggregator_as
= stream_getl(peer
->curr
);
1444 attr
->aggregator_as
= stream_getw(peer
->curr
);
1445 attr
->aggregator_addr
.s_addr
= stream_get_ipv4(peer
->curr
);
1447 /* Set atomic aggregate flag. */
1448 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
1450 return BGP_ATTR_PARSE_PROCEED
;
1453 /* New Aggregator attribute */
1454 static bgp_attr_parse_ret_t
1455 bgp_attr_as4_aggregator(struct bgp_attr_parser_args
*args
,
1456 as_t
*as4_aggregator_as
,
1457 struct in_addr
*as4_aggregator_addr
)
1459 struct peer
*const peer
= args
->peer
;
1460 struct attr
*const attr
= args
->attr
;
1461 const bgp_size_t length
= args
->length
;
1464 flog_err(EC_BGP_ATTR_LEN
, "New Aggregator length is not 8 [%d]",
1466 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1470 *as4_aggregator_as
= stream_getl(peer
->curr
);
1471 as4_aggregator_addr
->s_addr
= stream_get_ipv4(peer
->curr
);
1473 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
);
1475 return BGP_ATTR_PARSE_PROCEED
;
1478 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
1480 static bgp_attr_parse_ret_t
1481 bgp_attr_munge_as4_attrs(struct peer
*const peer
, struct attr
*const attr
,
1482 struct aspath
*as4_path
, as_t as4_aggregator
,
1483 struct in_addr
*as4_aggregator_addr
)
1485 int ignore_as4_path
= 0;
1486 struct aspath
*newpath
;
1488 if (!attr
->aspath
) {
1489 /* NULL aspath shouldn't be possible as bgp_attr_parse should
1491 * checked that all well-known, mandatory attributes were
1494 * Can only be a problem with peer itself - hard error
1496 return BGP_ATTR_PARSE_ERROR
;
1499 if (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) {
1500 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
1502 * It is worth a warning though, because the peer really
1503 * should not send them
1505 if (BGP_DEBUG(as4
, AS4
)) {
1506 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))
1507 zlog_debug("[AS4] %s %s AS4_PATH", peer
->host
,
1508 "AS4 capable peer, yet it sent");
1511 & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
)))
1512 zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
1514 "AS4 capable peer, yet it sent");
1517 return BGP_ATTR_PARSE_PROCEED
;
1520 /* We have a asn16 peer. First, look for AS4_AGGREGATOR
1521 * because that may override AS4_PATH
1523 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR
))) {
1524 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
1526 * if the as_number in aggregator is not AS_TRANS,
1527 * then AS4_AGGREGATOR and AS4_PATH shall be ignored
1528 * and the Aggregator shall be taken as
1529 * info on the aggregating node, and the AS_PATH
1530 * shall be taken as the AS_PATH
1532 * the Aggregator shall be ignored and the
1533 * AS4_AGGREGATOR shall be taken as the
1534 * Aggregating node and the AS_PATH is to be
1535 * constructed "as in all other cases"
1537 if (attr
->aggregator_as
!= BGP_AS_TRANS
) {
1539 if (BGP_DEBUG(as4
, AS4
))
1541 "[AS4] %s BGP not AS4 capable peer"
1542 " send AGGREGATOR != AS_TRANS and"
1543 " AS4_AGGREGATOR, so ignore"
1544 " AS4_AGGREGATOR and AS4_PATH",
1546 ignore_as4_path
= 1;
1548 /* "New_aggregator shall be taken as aggregator"
1550 attr
->aggregator_as
= as4_aggregator
;
1551 attr
->aggregator_addr
.s_addr
=
1552 as4_aggregator_addr
->s_addr
;
1555 /* We received a AS4_AGGREGATOR but no AGGREGATOR.
1556 * That is bogus - but reading the conditions
1557 * we have to handle AS4_AGGREGATOR as if it were
1558 * AGGREGATOR in that case
1560 if (BGP_DEBUG(as4
, AS4
))
1562 "[AS4] %s BGP not AS4 capable peer send"
1563 " AS4_AGGREGATOR but no AGGREGATOR, will take"
1564 " it as if AGGREGATOR with AS_TRANS had been there",
1566 attr
->aggregator_as
= as4_aggregator
;
1567 /* sweep it under the carpet and simulate a "good"
1569 attr
->flag
|= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
));
1573 /* need to reconcile NEW_AS_PATH and AS_PATH */
1574 if (!ignore_as4_path
1575 && (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH
)))) {
1576 newpath
= aspath_reconcile_as4(attr
->aspath
, as4_path
);
1578 return BGP_ATTR_PARSE_ERROR
;
1580 aspath_unintern(&attr
->aspath
);
1581 attr
->aspath
= aspath_intern(newpath
);
1583 return BGP_ATTR_PARSE_PROCEED
;
1586 /* Community attribute. */
1587 static bgp_attr_parse_ret_t
1588 bgp_attr_community(struct bgp_attr_parser_args
*args
)
1590 struct peer
*const peer
= args
->peer
;
1591 struct attr
*const attr
= args
->attr
;
1592 const bgp_size_t length
= args
->length
;
1595 attr
->community
= NULL
;
1596 return BGP_ATTR_PARSE_PROCEED
;
1600 community_parse((uint32_t *)stream_pnt(peer
->curr
), length
);
1602 /* XXX: fix community_parse to use stream API and remove this */
1603 stream_forward_getp(peer
->curr
, length
);
1605 if (!attr
->community
)
1606 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1609 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1611 return BGP_ATTR_PARSE_PROCEED
;
1614 /* Originator ID attribute. */
1615 static bgp_attr_parse_ret_t
1616 bgp_attr_originator_id(struct bgp_attr_parser_args
*args
)
1618 struct peer
*const peer
= args
->peer
;
1619 struct attr
*const attr
= args
->attr
;
1620 const bgp_size_t length
= args
->length
;
1624 flog_err(EC_BGP_ATTR_LEN
, "Bad originator ID length %d",
1627 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1631 attr
->originator_id
.s_addr
= stream_get_ipv4(peer
->curr
);
1633 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
1635 return BGP_ATTR_PARSE_PROCEED
;
1638 /* Cluster list attribute. */
1639 static bgp_attr_parse_ret_t
1640 bgp_attr_cluster_list(struct bgp_attr_parser_args
*args
)
1642 struct peer
*const peer
= args
->peer
;
1643 struct attr
*const attr
= args
->attr
;
1644 const bgp_size_t length
= args
->length
;
1648 flog_err(EC_BGP_ATTR_LEN
, "Bad cluster list length %d", length
);
1650 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
1655 cluster_parse((struct in_addr
*)stream_pnt(peer
->curr
), length
);
1657 /* XXX: Fix cluster_parse to use stream API and then remove this */
1658 stream_forward_getp(peer
->curr
, length
);
1660 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
);
1662 return BGP_ATTR_PARSE_PROCEED
;
1665 /* Multiprotocol reachability information parse. */
1666 int bgp_mp_reach_parse(struct bgp_attr_parser_args
*args
,
1667 struct bgp_nlri
*mp_update
)
1671 iana_safi_t pkt_safi
;
1673 bgp_size_t nlri_len
;
1676 struct peer
*const peer
= args
->peer
;
1677 struct attr
*const attr
= args
->attr
;
1678 const bgp_size_t length
= args
->length
;
1680 /* Set end of packet. */
1681 s
= BGP_INPUT(peer
);
1682 start
= stream_get_getp(s
);
1684 /* safe to read statically sized header? */
1685 #define BGP_MP_REACH_MIN_SIZE 5
1686 #define LEN_LEFT (length - (stream_get_getp(s) - start))
1687 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_REACH_MIN_SIZE
)) {
1688 zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
1689 __func__
, peer
->host
, (unsigned long)length
);
1690 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1693 /* Load AFI, SAFI. */
1694 pkt_afi
= stream_getw(s
);
1695 pkt_safi
= stream_getc(s
);
1697 /* Convert AFI, SAFI to internal values, check. */
1698 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1699 /* Log if AFI or SAFI is unrecognized. This is not an error
1701 * the attribute is otherwise malformed.
1703 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1705 "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
1706 peer
->host
, iana_afi2str(pkt_afi
),
1707 iana_safi2str(pkt_safi
));
1708 return BGP_ATTR_PARSE_ERROR
;
1711 /* Get nexthop length. */
1712 attr
->mp_nexthop_len
= stream_getc(s
);
1714 if (LEN_LEFT
< attr
->mp_nexthop_len
) {
1716 "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
1717 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1718 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1721 /* Nexthop length check. */
1722 switch (attr
->mp_nexthop_len
) {
1724 if (safi
!= SAFI_FLOWSPEC
) {
1725 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
1726 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1727 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1730 case BGP_ATTR_NHLEN_VPNV4
:
1731 stream_getl(s
); /* RD high */
1732 stream_getl(s
); /* RD low */
1734 * NOTE: intentional fall through
1735 * - for consistency in rx processing
1737 * The following comment is to signal GCC this intention
1738 * and suppress the warning
1741 case BGP_ATTR_NHLEN_IPV4
:
1742 stream_get(&attr
->mp_nexthop_global_in
, s
, IPV4_MAX_BYTELEN
);
1743 /* Probably needed for RFC 2283 */
1744 if (attr
->nexthop
.s_addr
== 0)
1745 memcpy(&attr
->nexthop
.s_addr
,
1746 &attr
->mp_nexthop_global_in
, IPV4_MAX_BYTELEN
);
1748 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
1749 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
1750 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL
) {
1751 stream_getl(s
); /* RD high */
1752 stream_getl(s
); /* RD low */
1754 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1755 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1756 if (!peer
->nexthop
.ifp
) {
1757 zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
1759 return BGP_ATTR_PARSE_WITHDRAW
;
1761 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1764 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
1765 case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
:
1766 if (attr
->mp_nexthop_len
1767 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1768 stream_getl(s
); /* RD high */
1769 stream_getl(s
); /* RD low */
1771 stream_get(&attr
->mp_nexthop_global
, s
, IPV6_MAX_BYTELEN
);
1772 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
1773 if (!peer
->nexthop
.ifp
) {
1774 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",
1776 return BGP_ATTR_PARSE_WITHDRAW
;
1778 attr
->nh_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1780 if (attr
->mp_nexthop_len
1781 == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
) {
1782 stream_getl(s
); /* RD high */
1783 stream_getl(s
); /* RD low */
1785 stream_get(&attr
->mp_nexthop_local
, s
, IPV6_MAX_BYTELEN
);
1786 if (!IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
)) {
1787 char buf1
[INET6_ADDRSTRLEN
];
1788 char buf2
[INET6_ADDRSTRLEN
];
1790 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
1792 "%s sent next-hops %s and %s. Ignoring non-LL value",
1795 &attr
->mp_nexthop_global
,
1796 buf1
, INET6_ADDRSTRLEN
),
1798 &attr
->mp_nexthop_local
, buf2
,
1801 attr
->mp_nexthop_len
= IPV6_MAX_BYTELEN
;
1803 if (!peer
->nexthop
.ifp
) {
1804 zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
1806 return BGP_ATTR_PARSE_WITHDRAW
;
1808 attr
->nh_lla_ifindex
= peer
->nexthop
.ifp
->ifindex
;
1811 zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
1812 __func__
, peer
->host
, attr
->mp_nexthop_len
);
1813 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1817 zlog_info("%s: %s sent SNPA which couldn't be read",
1818 __func__
, peer
->host
);
1819 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1824 if ((val
= stream_getc(s
)))
1826 EC_BGP_DEFUNCT_SNPA_LEN
,
1827 "%s sent non-zero value, %u, for defunct SNPA-length field",
1831 /* must have nrli_len, what is left of the attribute */
1832 nlri_len
= LEN_LEFT
;
1833 if (nlri_len
> STREAM_READABLE(s
)) {
1834 zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
1835 __func__
, peer
->host
);
1836 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1840 zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
1841 __func__
, peer
->host
);
1843 mp_update
->afi
= afi
;
1844 mp_update
->safi
= safi
;
1845 return BGP_ATTR_PARSE_EOR
;
1848 mp_update
->afi
= afi
;
1849 mp_update
->safi
= safi
;
1850 mp_update
->nlri
= stream_pnt(s
);
1851 mp_update
->length
= nlri_len
;
1853 stream_forward_getp(s
, nlri_len
);
1855 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
);
1857 return BGP_ATTR_PARSE_PROCEED
;
1861 /* Multiprotocol unreachable parse */
1862 int bgp_mp_unreach_parse(struct bgp_attr_parser_args
*args
,
1863 struct bgp_nlri
*mp_withdraw
)
1868 iana_safi_t pkt_safi
;
1870 uint16_t withdraw_len
;
1871 struct peer
*const peer
= args
->peer
;
1872 struct attr
*const attr
= args
->attr
;
1873 const bgp_size_t length
= args
->length
;
1877 #define BGP_MP_UNREACH_MIN_SIZE 3
1878 if ((length
> STREAM_READABLE(s
)) || (length
< BGP_MP_UNREACH_MIN_SIZE
))
1879 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS
;
1881 pkt_afi
= stream_getw(s
);
1882 pkt_safi
= stream_getc(s
);
1884 /* Convert AFI, SAFI to internal values, check. */
1885 if (bgp_map_afi_safi_iana2int(pkt_afi
, pkt_safi
, &afi
, &safi
)) {
1886 /* Log if AFI or SAFI is unrecognized. This is not an error
1888 * the attribute is otherwise malformed.
1890 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
1892 "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
1893 peer
->host
, iana_afi2str(pkt_afi
),
1894 iana_safi2str(pkt_safi
));
1895 return BGP_ATTR_PARSE_ERROR
;
1898 withdraw_len
= length
- BGP_MP_UNREACH_MIN_SIZE
;
1900 mp_withdraw
->afi
= afi
;
1901 mp_withdraw
->safi
= safi
;
1902 mp_withdraw
->nlri
= stream_pnt(s
);
1903 mp_withdraw
->length
= withdraw_len
;
1905 stream_forward_getp(s
, withdraw_len
);
1907 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
);
1909 return BGP_ATTR_PARSE_PROCEED
;
1912 /* Large Community attribute. */
1913 static bgp_attr_parse_ret_t
1914 bgp_attr_large_community(struct bgp_attr_parser_args
*args
)
1916 struct peer
*const peer
= args
->peer
;
1917 struct attr
*const attr
= args
->attr
;
1918 const bgp_size_t length
= args
->length
;
1921 * Large community follows new attribute format.
1924 attr
->lcommunity
= NULL
;
1925 /* Empty extcomm doesn't seem to be invalid per se */
1926 return BGP_ATTR_PARSE_PROCEED
;
1930 lcommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1931 /* XXX: fix ecommunity_parse to use stream API */
1932 stream_forward_getp(peer
->curr
, length
);
1934 if (!attr
->lcommunity
)
1935 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1938 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1940 return BGP_ATTR_PARSE_PROCEED
;
1943 /* Extended Community attribute. */
1944 static bgp_attr_parse_ret_t
1945 bgp_attr_ext_communities(struct bgp_attr_parser_args
*args
)
1947 struct peer
*const peer
= args
->peer
;
1948 struct attr
*const attr
= args
->attr
;
1949 const bgp_size_t length
= args
->length
;
1953 attr
->ecommunity
= NULL
;
1954 /* Empty extcomm doesn't seem to be invalid per se */
1955 return BGP_ATTR_PARSE_PROCEED
;
1959 ecommunity_parse((uint8_t *)stream_pnt(peer
->curr
), length
);
1960 /* XXX: fix ecommunity_parse to use stream API */
1961 stream_forward_getp(peer
->curr
, length
);
1963 if (!attr
->ecommunity
)
1964 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
1967 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1969 /* Extract MAC mobility sequence number, if any. */
1970 attr
->mm_seqnum
= bgp_attr_mac_mobility_seqnum(attr
, &sticky
);
1971 attr
->sticky
= sticky
;
1973 /* Check if this is a Gateway MAC-IP advertisement */
1974 attr
->default_gw
= bgp_attr_default_gw(attr
);
1976 /* Handle scenario where router flag ecommunity is not
1977 * set but default gw ext community is present.
1978 * Use default gateway, set and propogate R-bit.
1980 if (attr
->default_gw
)
1981 attr
->router_flag
= 1;
1983 /* Check EVPN Neighbor advertisement flags, R-bit */
1984 bgp_attr_evpn_na_flag(attr
, &attr
->router_flag
);
1986 /* Extract the Rmac, if any */
1987 if (bgp_attr_rmac(attr
, &attr
->rmac
)) {
1988 if (bgp_debug_update(peer
, NULL
, NULL
, 1) &&
1989 bgp_mac_exist(&attr
->rmac
)) {
1990 char buf1
[ETHER_ADDR_STRLEN
];
1992 zlog_debug("%s: router mac %s is self mac",
1994 prefix_mac2str(&attr
->rmac
, buf1
,
2000 /* Get the tunnel type from encap extended community */
2001 bgp_attr_extcom_tunnel_type(attr
,
2002 (bgp_encap_types
*)&attr
->encap_tunneltype
);
2004 return BGP_ATTR_PARSE_PROCEED
;
2007 /* Parse Tunnel Encap attribute in an UPDATE */
2008 static int bgp_attr_encap(uint8_t type
, struct peer
*peer
, /* IN */
2009 bgp_size_t length
, /* IN: attr's length field */
2010 struct attr
*attr
, /* IN: caller already allocated */
2011 uint8_t flag
, /* IN: attr's flags field */
2015 uint16_t tunneltype
= 0;
2017 total
= length
+ (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 4 : 3);
2019 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
)
2020 || !CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2022 "Tunnel Encap attribute flag isn't optional and transitive %d",
2024 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2025 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2030 if (BGP_ATTR_ENCAP
== type
) {
2031 /* read outer TLV type and length */
2032 uint16_t tlv_length
;
2036 "Tunnel Encap attribute not long enough to contain outer T,L");
2037 bgp_notify_send_with_data(
2038 peer
, BGP_NOTIFY_UPDATE_ERR
,
2039 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2042 tunneltype
= stream_getw(BGP_INPUT(peer
));
2043 tlv_length
= stream_getw(BGP_INPUT(peer
));
2046 if (tlv_length
!= length
) {
2047 zlog_info("%s: tlv_length(%d) != length(%d)",
2048 __func__
, tlv_length
, length
);
2052 while (length
>= 4) {
2053 uint16_t subtype
= 0;
2054 uint16_t sublength
= 0;
2055 struct bgp_attr_encap_subtlv
*tlv
;
2057 if (BGP_ATTR_ENCAP
== type
) {
2058 subtype
= stream_getc(BGP_INPUT(peer
));
2059 sublength
= stream_getc(BGP_INPUT(peer
));
2063 subtype
= stream_getw(BGP_INPUT(peer
));
2064 sublength
= stream_getw(BGP_INPUT(peer
));
2069 if (sublength
> length
) {
2071 "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2073 bgp_notify_send_with_data(
2074 peer
, BGP_NOTIFY_UPDATE_ERR
,
2075 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
, startp
, total
);
2079 /* alloc and copy sub-tlv */
2080 /* TBD make sure these are freed when attributes are released */
2081 tlv
= XCALLOC(MTYPE_ENCAP_TLV
,
2082 sizeof(struct bgp_attr_encap_subtlv
) + sublength
);
2083 tlv
->type
= subtype
;
2084 tlv
->length
= sublength
;
2085 stream_get(tlv
->value
, peer
->curr
, sublength
);
2086 length
-= sublength
;
2088 /* attach tlv to encap chain */
2089 if (BGP_ATTR_ENCAP
== type
) {
2090 struct bgp_attr_encap_subtlv
*stlv_last
;
2091 for (stlv_last
= attr
->encap_subtlvs
;
2092 stlv_last
&& stlv_last
->next
;
2093 stlv_last
= stlv_last
->next
)
2096 stlv_last
->next
= tlv
;
2098 attr
->encap_subtlvs
= tlv
;
2102 struct bgp_attr_encap_subtlv
*stlv_last
;
2103 for (stlv_last
= attr
->vnc_subtlvs
;
2104 stlv_last
&& stlv_last
->next
;
2105 stlv_last
= stlv_last
->next
)
2108 stlv_last
->next
= tlv
;
2110 attr
->vnc_subtlvs
= tlv
;
2116 if (BGP_ATTR_ENCAP
== type
) {
2117 attr
->encap_tunneltype
= tunneltype
;
2121 /* spurious leftover data */
2123 "Tunnel Encap attribute length is bad: %d leftover octets",
2125 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2126 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2135 * Read an individual SID value returning how much data we have read
2136 * Returns 0 if there was an error that needs to be passed up the stack
2138 static bgp_attr_parse_ret_t
bgp_attr_psid_sub(int32_t type
,
2140 struct bgp_attr_parser_args
*args
,
2141 struct bgp_nlri
*mp_update
)
2143 struct peer
*const peer
= args
->peer
;
2144 struct attr
*const attr
= args
->attr
;
2145 uint32_t label_index
;
2146 struct in6_addr ipv6_sid
;
2148 uint32_t srgb_range
;
2151 if (type
== BGP_PREFIX_SID_LABEL_INDEX
) {
2152 if (length
!= BGP_PREFIX_SID_LABEL_INDEX_LENGTH
) {
2155 "Prefix SID label index length is %d instead of %d",
2156 length
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
2157 return bgp_attr_malformed(args
,
2158 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2162 /* Ignore flags and reserved */
2163 stream_getc(peer
->curr
);
2164 stream_getw(peer
->curr
);
2166 /* Fetch the label index and see if it is valid. */
2167 label_index
= stream_getl(peer
->curr
);
2168 if (label_index
== BGP_INVALID_LABEL_INDEX
)
2169 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2172 /* Store label index; subsequently, we'll check on
2174 attr
->label_index
= label_index
;
2177 * Ignore the Label index attribute unless received for
2181 if (!mp_update
->length
2182 || mp_update
->safi
!= SAFI_LABELED_UNICAST
)
2183 attr
->label_index
= BGP_INVALID_LABEL_INDEX
;
2186 /* Placeholder code for the IPv6 SID type */
2187 else if (type
== BGP_PREFIX_SID_IPV6
) {
2188 if (length
!= BGP_PREFIX_SID_IPV6_LENGTH
) {
2189 flog_err(EC_BGP_ATTR_LEN
,
2190 "Prefix SID IPv6 length is %d instead of %d",
2191 length
, BGP_PREFIX_SID_IPV6_LENGTH
);
2192 return bgp_attr_malformed(args
,
2193 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2197 /* Ignore reserved */
2198 stream_getc(peer
->curr
);
2199 stream_getw(peer
->curr
);
2201 stream_get(&ipv6_sid
, peer
->curr
, 16);
2204 /* Placeholder code for the Originator SRGB type */
2205 else if (type
== BGP_PREFIX_SID_ORIGINATOR_SRGB
) {
2207 stream_getw(peer
->curr
);
2211 if (length
% BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
) {
2214 "Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
2215 length
, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
);
2216 return bgp_attr_malformed(
2217 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2221 srgb_count
= length
/ BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH
;
2223 for (int i
= 0; i
< srgb_count
; i
++) {
2224 stream_get(&srgb_base
, peer
->curr
, 3);
2225 stream_get(&srgb_range
, peer
->curr
, 3);
2230 * Placeholder code for Unsupported TLV
2231 * - SRv6 L3 Service TLV (type5)
2232 * - SRv6 L2 Service TLV (type6)
2234 else if (type
== BGP_PREFIX_SID_SRV6_L3_SERVICE
2235 || type
== BGP_PREFIX_SID_SRV6_L2_SERVICE
) {
2236 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2238 "%s attr Prefix-SID sub-type=%u is not supported, skipped",
2240 for (int i
= 0; i
< length
; i
++)
2241 stream_getc(peer
->curr
);
2244 return BGP_ATTR_PARSE_PROCEED
;
2247 /* Prefix SID attribute
2248 * draft-ietf-idr-bgp-prefix-sid-05
2250 bgp_attr_parse_ret_t
2251 bgp_attr_prefix_sid(int32_t tlength
, struct bgp_attr_parser_args
*args
,
2252 struct bgp_nlri
*mp_update
)
2254 struct peer
*const peer
= args
->peer
;
2255 struct attr
*const attr
= args
->attr
;
2256 bgp_attr_parse_ret_t ret
;
2258 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2261 int32_t type
, length
;
2263 type
= stream_getc(peer
->curr
);
2264 length
= stream_getw(peer
->curr
);
2266 ret
= bgp_attr_psid_sub(type
, length
, args
, mp_update
);
2268 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2271 * Subtract length + the T and the L
2272 * since length is the Vector portion
2274 tlength
-= length
+ 3;
2279 "Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
2281 return bgp_attr_malformed(args
,
2282 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2287 return BGP_ATTR_PARSE_PROCEED
;
2290 /* PMSI tunnel attribute (RFC 6514)
2291 * Basic validation checks done here.
2293 static bgp_attr_parse_ret_t
2294 bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args
*args
)
2296 struct peer
*const peer
= args
->peer
;
2297 struct attr
*const attr
= args
->attr
;
2298 const bgp_size_t length
= args
->length
;
2300 int attr_parse_len
= 2 + BGP_LABEL_BYTES
;
2302 /* Verify that the receiver is expecting "ingress replication" as we
2303 * can only support that.
2305 if (length
< attr_parse_len
) {
2306 flog_err(EC_BGP_ATTR_LEN
, "Bad PMSI tunnel attribute length %d",
2308 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2311 stream_getc(peer
->curr
); /* Flags */
2312 tnl_type
= stream_getc(peer
->curr
);
2313 if (tnl_type
> PMSI_TNLTYPE_MAX
) {
2314 flog_err(EC_BGP_ATTR_PMSI_TYPE
,
2315 "Invalid PMSI tunnel attribute type %d", tnl_type
);
2316 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR
,
2319 if (tnl_type
== PMSI_TNLTYPE_INGR_REPL
) {
2321 flog_err(EC_BGP_ATTR_PMSI_LEN
,
2322 "Bad PMSI tunnel attribute length %d for IR",
2324 return bgp_attr_malformed(
2325 args
, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
,
2330 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
);
2331 attr
->pmsi_tnl_type
= tnl_type
;
2332 stream_get(&attr
->label
, peer
->curr
, BGP_LABEL_BYTES
);
2334 /* Forward read pointer of input stream. */
2335 stream_forward_getp(peer
->curr
, length
- attr_parse_len
);
2337 return BGP_ATTR_PARSE_PROCEED
;
2340 /* BGP unknown attribute treatment. */
2341 static bgp_attr_parse_ret_t
bgp_attr_unknown(struct bgp_attr_parser_args
*args
)
2343 bgp_size_t total
= args
->total
;
2344 struct transit
*transit
;
2345 struct peer
*const peer
= args
->peer
;
2346 struct attr
*const attr
= args
->attr
;
2347 uint8_t *const startp
= args
->startp
;
2348 const uint8_t type
= args
->type
;
2349 const uint8_t flag
= args
->flags
;
2350 const bgp_size_t length
= args
->length
;
2352 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2354 "%s Unknown attribute is received (type %d, length %d)",
2355 peer
->host
, type
, length
);
2357 /* Forward read pointer of input stream. */
2358 stream_forward_getp(peer
->curr
, length
);
2360 /* If any of the mandatory well-known attributes are not recognized,
2361 then the Error Subcode is set to Unrecognized Well-known
2362 Attribute. The Data field contains the unrecognized attribute
2363 (type, length and value). */
2364 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_OPTIONAL
)) {
2365 return bgp_attr_malformed(args
, BGP_NOTIFY_UPDATE_UNREC_ATTR
,
2369 /* Unrecognized non-transitive optional attributes must be quietly
2370 ignored and not passed along to other BGP peers. */
2371 if (!CHECK_FLAG(flag
, BGP_ATTR_FLAG_TRANS
))
2372 return BGP_ATTR_PARSE_PROCEED
;
2374 /* If a path with recognized transitive optional attribute is
2375 accepted and passed along to other BGP peers and the Partial bit
2376 in the Attribute Flags octet is set to 1 by some previous AS, it
2377 is not set back to 0 by the current AS. */
2378 SET_FLAG(*startp
, BGP_ATTR_FLAG_PARTIAL
);
2380 /* Store transitive attribute to the end of attr->transit. */
2382 attr
->transit
= XCALLOC(MTYPE_TRANSIT
, sizeof(struct transit
));
2384 transit
= attr
->transit
;
2387 transit
->val
= XREALLOC(MTYPE_TRANSIT_VAL
, transit
->val
,
2388 transit
->length
+ total
);
2390 transit
->val
= XMALLOC(MTYPE_TRANSIT_VAL
, total
);
2392 memcpy(transit
->val
+ transit
->length
, startp
, total
);
2393 transit
->length
+= total
;
2395 return BGP_ATTR_PARSE_PROCEED
;
2398 /* Well-known attribute check. */
2399 static int bgp_attr_check(struct peer
*peer
, struct attr
*attr
)
2403 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
2405 if (CHECK_FLAG(peer
->cap
, PEER_CAP_RESTART_RCV
) && !attr
->flag
)
2406 return BGP_ATTR_PARSE_PROCEED
;
2408 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
2409 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
2410 are present, it should. Check for any other attribute being present
2413 if ((!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)) &&
2414 CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI
))))
2415 return BGP_ATTR_PARSE_PROCEED
;
2417 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN
)))
2418 type
= BGP_ATTR_ORIGIN
;
2420 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
)))
2421 type
= BGP_ATTR_AS_PATH
;
2423 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
2425 * NLRI is empty. We can't easily check NLRI empty here though.
2427 if (!CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2428 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
)))
2429 type
= BGP_ATTR_NEXT_HOP
;
2431 if (peer
->sort
== BGP_PEER_IBGP
2432 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
2433 type
= BGP_ATTR_LOCAL_PREF
;
2436 flog_warn(EC_BGP_MISSING_ATTRIBUTE
,
2437 "%s Missing well-known attribute %s.", peer
->host
,
2438 lookup_msg(attr_str
, type
, NULL
));
2439 bgp_notify_send_with_data(peer
, BGP_NOTIFY_UPDATE_ERR
,
2440 BGP_NOTIFY_UPDATE_MISS_ATTR
, &type
,
2442 return BGP_ATTR_PARSE_ERROR
;
2444 return BGP_ATTR_PARSE_PROCEED
;
2447 /* Read attribute of update packet. This function is called from
2448 bgp_update_receive() in bgp_packet.c. */
2449 bgp_attr_parse_ret_t
bgp_attr_parse(struct peer
*peer
, struct attr
*attr
,
2450 bgp_size_t size
, struct bgp_nlri
*mp_update
,
2451 struct bgp_nlri
*mp_withdraw
)
2453 bgp_attr_parse_ret_t ret
;
2457 uint8_t *startp
, *endp
;
2459 uint8_t seen
[BGP_ATTR_BITMAP_SIZE
];
2460 /* we need the as4_path only until we have synthesized the as_path with
2462 /* same goes for as4_aggregator */
2463 struct aspath
*as4_path
= NULL
;
2464 as_t as4_aggregator
= 0;
2465 struct in_addr as4_aggregator_addr
= {.s_addr
= 0};
2467 /* Initialize bitmap. */
2468 memset(seen
, 0, BGP_ATTR_BITMAP_SIZE
);
2470 /* End pointer of BGP attribute. */
2471 endp
= BGP_INPUT_PNT(peer
) + size
;
2473 /* Get attributes to the end of attribute length. */
2474 while (BGP_INPUT_PNT(peer
) < endp
) {
2475 /* Check remaining length check.*/
2476 if (endp
- BGP_INPUT_PNT(peer
) < BGP_ATTR_MIN_LEN
) {
2477 /* XXX warning: long int format, int arg (arg 5) */
2479 EC_BGP_ATTRIBUTE_TOO_SMALL
,
2480 "%s: error BGP attribute length %lu is smaller than min len",
2482 (unsigned long)(endp
2483 - stream_pnt(BGP_INPUT(peer
))));
2485 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2486 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2487 ret
= BGP_ATTR_PARSE_ERROR
;
2491 /* Fetch attribute flag and type. */
2492 startp
= BGP_INPUT_PNT(peer
);
2493 /* "The lower-order four bits of the Attribute Flags octet are
2494 unused. They MUST be zero when sent and MUST be ignored when
2496 flag
= 0xF0 & stream_getc(BGP_INPUT(peer
));
2497 type
= stream_getc(BGP_INPUT(peer
));
2499 /* Check whether Extended-Length applies and is in bounds */
2500 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
)
2501 && ((endp
- startp
) < (BGP_ATTR_MIN_LEN
+ 1))) {
2503 EC_BGP_EXT_ATTRIBUTE_TOO_SMALL
,
2504 "%s: Extended length set, but just %lu bytes of attr header",
2506 (unsigned long)(endp
2507 - stream_pnt(BGP_INPUT(peer
))));
2509 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2510 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2511 ret
= BGP_ATTR_PARSE_ERROR
;
2515 /* Check extended attribue length bit. */
2516 if (CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
))
2517 length
= stream_getw(BGP_INPUT(peer
));
2519 length
= stream_getc(BGP_INPUT(peer
));
2521 /* If any attribute appears more than once in the UPDATE
2522 message, then the Error Subcode is set to Malformed Attribute
2525 if (CHECK_BITMAP(seen
, type
)) {
2527 EC_BGP_ATTRIBUTE_REPEATED
,
2528 "%s: error BGP attribute type %d appears twice in a message",
2531 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2532 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2533 ret
= BGP_ATTR_PARSE_ERROR
;
2537 /* Set type to bitmap to check duplicate attribute. `type' is
2538 unsigned char so it never overflow bitmap range. */
2540 SET_BITMAP(seen
, type
);
2542 /* Overflow check. */
2543 attr_endp
= BGP_INPUT_PNT(peer
) + length
;
2545 if (attr_endp
> endp
) {
2547 EC_BGP_ATTRIBUTE_TOO_LARGE
,
2548 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p",
2549 peer
->host
, type
, length
, size
, attr_endp
,
2553 * If any recognized attribute has an Attribute
2554 * Length that conflicts with the expected length
2555 * (based on the attribute type code), then the
2556 * Error Subcode MUST be set to Attribute Length
2557 * Error. The Data field MUST contain the erroneous
2558 * attribute (type, length, and value).
2560 * We do not currently have a good way to determine the
2561 * length of the attribute independent of the length
2562 * received in the message. Instead we send the
2563 * minimum between the amount of data we have and the
2564 * amount specified by the attribute length field.
2566 * Instead of directly passing in the packet buffer and
2567 * offset we use the stream_get* functions to read into
2568 * a stack buffer, since they perform bounds checking
2569 * and we are working with untrusted data.
2571 unsigned char ndata
[BGP_MAX_PACKET_SIZE
];
2572 memset(ndata
, 0x00, sizeof(ndata
));
2574 CHECK_FLAG(flag
, BGP_ATTR_FLAG_EXTLEN
) ? 2 : 1;
2575 /* Rewind to end of flag field */
2576 stream_forward_getp(BGP_INPUT(peer
), -(1 + lfl
));
2578 stream_get(&ndata
[0], BGP_INPUT(peer
), 1);
2580 stream_get(&ndata
[1], BGP_INPUT(peer
), lfl
);
2582 size_t atl
= attr_endp
- startp
;
2583 size_t ndl
= MIN(atl
, STREAM_READABLE(BGP_INPUT(peer
)));
2584 stream_get(&ndata
[lfl
+ 1], BGP_INPUT(peer
), ndl
);
2586 bgp_notify_send_with_data(
2587 peer
, BGP_NOTIFY_UPDATE_ERR
,
2588 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
, ndata
,
2591 ret
= BGP_ATTR_PARSE_ERROR
;
2595 struct bgp_attr_parser_args attr_args
= {
2602 .total
= attr_endp
- startp
,
2606 /* If any recognized attribute has Attribute Flags that conflict
2607 with the Attribute Type Code, then the Error Subcode is set
2609 Attribute Flags Error. The Data field contains the erroneous
2610 attribute (type, length and value). */
2611 if (bgp_attr_flag_invalid(&attr_args
)) {
2612 ret
= bgp_attr_malformed(
2613 &attr_args
, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR
,
2615 if (ret
== BGP_ATTR_PARSE_PROCEED
)
2620 /* OK check attribute and store it's value. */
2622 case BGP_ATTR_ORIGIN
:
2623 ret
= bgp_attr_origin(&attr_args
);
2625 case BGP_ATTR_AS_PATH
:
2626 ret
= bgp_attr_aspath(&attr_args
);
2628 case BGP_ATTR_AS4_PATH
:
2629 ret
= bgp_attr_as4_path(&attr_args
, &as4_path
);
2631 case BGP_ATTR_NEXT_HOP
:
2632 ret
= bgp_attr_nexthop(&attr_args
);
2634 case BGP_ATTR_MULTI_EXIT_DISC
:
2635 ret
= bgp_attr_med(&attr_args
);
2637 case BGP_ATTR_LOCAL_PREF
:
2638 ret
= bgp_attr_local_pref(&attr_args
);
2640 case BGP_ATTR_ATOMIC_AGGREGATE
:
2641 ret
= bgp_attr_atomic(&attr_args
);
2643 case BGP_ATTR_AGGREGATOR
:
2644 ret
= bgp_attr_aggregator(&attr_args
);
2646 case BGP_ATTR_AS4_AGGREGATOR
:
2647 ret
= bgp_attr_as4_aggregator(&attr_args
,
2649 &as4_aggregator_addr
);
2651 case BGP_ATTR_COMMUNITIES
:
2652 ret
= bgp_attr_community(&attr_args
);
2654 case BGP_ATTR_LARGE_COMMUNITIES
:
2655 ret
= bgp_attr_large_community(&attr_args
);
2657 case BGP_ATTR_ORIGINATOR_ID
:
2658 ret
= bgp_attr_originator_id(&attr_args
);
2660 case BGP_ATTR_CLUSTER_LIST
:
2661 ret
= bgp_attr_cluster_list(&attr_args
);
2663 case BGP_ATTR_MP_REACH_NLRI
:
2664 ret
= bgp_mp_reach_parse(&attr_args
, mp_update
);
2666 case BGP_ATTR_MP_UNREACH_NLRI
:
2667 ret
= bgp_mp_unreach_parse(&attr_args
, mp_withdraw
);
2669 case BGP_ATTR_EXT_COMMUNITIES
:
2670 ret
= bgp_attr_ext_communities(&attr_args
);
2672 #if ENABLE_BGP_VNC_ATTR
2675 case BGP_ATTR_ENCAP
:
2676 ret
= bgp_attr_encap(type
, peer
, length
, attr
, flag
,
2679 case BGP_ATTR_PREFIX_SID
:
2680 ret
= bgp_attr_prefix_sid(length
,
2681 &attr_args
, mp_update
);
2683 case BGP_ATTR_PMSI_TUNNEL
:
2684 ret
= bgp_attr_pmsi_tunnel(&attr_args
);
2687 ret
= bgp_attr_unknown(&attr_args
);
2691 if (ret
== BGP_ATTR_PARSE_ERROR_NOTIFYPLS
) {
2692 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2693 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2694 ret
= BGP_ATTR_PARSE_ERROR
;
2698 if (ret
== BGP_ATTR_PARSE_EOR
) {
2702 if (ret
== BGP_ATTR_PARSE_ERROR
) {
2703 flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR
,
2704 "%s: Attribute %s, parse error", peer
->host
,
2705 lookup_msg(attr_str
, type
, NULL
));
2708 if (ret
== BGP_ATTR_PARSE_WITHDRAW
) {
2710 EC_BGP_ATTRIBUTE_PARSE_WITHDRAW
,
2711 "%s: Attribute %s, parse error - treating as withdrawal",
2712 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2716 /* Check the fetched length. */
2717 if (BGP_INPUT_PNT(peer
) != attr_endp
) {
2718 flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR
,
2719 "%s: BGP attribute %s, fetch error",
2720 peer
->host
, lookup_msg(attr_str
, type
, NULL
));
2721 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2722 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2723 ret
= BGP_ATTR_PARSE_ERROR
;
2728 /* Check final read pointer is same as end pointer. */
2729 if (BGP_INPUT_PNT(peer
) != endp
) {
2730 flog_warn(EC_BGP_ATTRIBUTES_MISMATCH
,
2731 "%s: BGP attribute %s, length mismatch", peer
->host
,
2732 lookup_msg(attr_str
, type
, NULL
));
2733 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2734 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR
);
2736 ret
= BGP_ATTR_PARSE_ERROR
;
2741 * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
2742 * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
2743 * This is implemented below and will result in a NOTIFICATION. If the
2744 * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
2745 * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
2746 * message SHOULD NOT be sent. This is implemented elsewhere.
2748 * RFC4760: An UPDATE message that carries no NLRI, other than the one
2749 * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
2750 * attribute. If such a message contains the NEXT_HOP attribute, the BGP
2751 * speaker that receives the message SHOULD ignore this attribute.
2753 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
))
2754 && !CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI
))) {
2755 if (bgp_attr_nexthop_valid(peer
, attr
) < 0) {
2756 ret
= BGP_ATTR_PARSE_ERROR
;
2761 /* Check all mandatory well-known attributes are present */
2762 if ((ret
= bgp_attr_check(peer
, attr
)) < 0)
2766 * At this place we can see whether we got AS4_PATH and/or
2767 * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
2768 * We can not do this before we've read all attributes because
2769 * the as4 handling does not say whether AS4_PATH has to be sent
2770 * after AS_PATH or not - and when AS4_AGGREGATOR will be send
2771 * in relationship to AGGREGATOR.
2772 * So, to be defensive, we are not relying on any order and read
2773 * all attributes first, including these 32bit ones, and now,
2774 * afterwards, we look what and if something is to be done for as4.
2776 * It is possible to not have AS_PATH, e.g. GR EoR and sole
2779 /* actually... this doesn't ever return failure currently, but
2780 * better safe than sorry */
2781 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))
2782 && bgp_attr_munge_as4_attrs(peer
, attr
, as4_path
, as4_aggregator
,
2783 &as4_aggregator_addr
)) {
2784 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
2785 BGP_NOTIFY_UPDATE_MAL_ATTR
);
2786 ret
= BGP_ATTR_PARSE_ERROR
;
2791 * Finally do the checks on the aspath we did not do yet
2792 * because we waited for a potentially synthesized aspath.
2794 if (attr
->flag
& (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH
))) {
2795 ret
= bgp_attr_aspath_check(peer
, attr
);
2796 if (ret
!= BGP_ATTR_PARSE_PROCEED
)
2800 ret
= BGP_ATTR_PARSE_PROCEED
;
2804 * At this stage, we have done all fiddling with as4, and the
2805 * resulting info is in attr->aggregator resp. attr->aspath so
2806 * we can chuck as4_aggregator and as4_path alltogether in order
2811 * unintern - it is in the hash
2812 * The flag that we got this is still there, but that
2813 * does not do any trouble
2815 aspath_unintern(&as4_path
);
2818 if (ret
!= BGP_ATTR_PARSE_ERROR
) {
2819 /* Finally intern unknown attribute. */
2821 attr
->transit
= transit_intern(attr
->transit
);
2822 if (attr
->encap_subtlvs
)
2823 attr
->encap_subtlvs
= encap_intern(attr
->encap_subtlvs
,
2826 if (attr
->vnc_subtlvs
)
2827 attr
->vnc_subtlvs
= encap_intern(attr
->vnc_subtlvs
,
2831 if (attr
->transit
) {
2832 transit_free(attr
->transit
);
2833 attr
->transit
= NULL
;
2836 bgp_attr_flush_encap(attr
);
2841 assert(attr
->transit
->refcnt
> 0);
2842 if (attr
->encap_subtlvs
)
2843 assert(attr
->encap_subtlvs
->refcnt
> 0);
2845 if (attr
->vnc_subtlvs
)
2846 assert(attr
->vnc_subtlvs
->refcnt
> 0);
2853 * Extract the tunnel type from extended community
2855 void bgp_attr_extcom_tunnel_type(struct attr
*attr
,
2856 bgp_encap_types
*tunnel_type
)
2858 struct ecommunity
*ecom
;
2863 ecom
= attr
->ecommunity
;
2864 if (!ecom
|| !ecom
->size
)
2867 for (i
= 0; i
< ecom
->size
; i
++) {
2869 uint8_t type
, sub_type
;
2871 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
2874 if (!(type
== ECOMMUNITY_ENCODE_OPAQUE
&&
2875 sub_type
== ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
))
2877 *tunnel_type
= ((pnt
[6] << 8) | pnt
[7]);
2884 size_t bgp_packet_mpattr_start(struct stream
*s
, struct peer
*peer
, afi_t afi
,
2885 safi_t safi
, struct bpacket_attr_vec_arr
*vecarr
,
2890 iana_safi_t pkt_safi
;
2893 /* Set extended bit always to encode the attribute length as 2 bytes */
2894 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
2895 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
2896 sizep
= stream_get_endp(s
);
2897 stream_putw(s
, 0); /* Marker: Attribute length. */
2900 /* Convert AFI, SAFI to values for packet. */
2901 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
2903 stream_putw(s
, pkt_afi
); /* AFI */
2904 stream_putc(s
, pkt_safi
); /* SAFI */
2908 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
2909 nh_afi
= peer_cap_enhe(peer
, afi
, safi
) ? AFI_IP6
: AFI_IP
;
2911 nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
2914 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
, attr
);
2919 case SAFI_MULTICAST
:
2920 case SAFI_LABELED_UNICAST
:
2922 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
2926 stream_putl(s
, 0); /* RD = 0, per RFC */
2928 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2933 stream_put(s
, &attr
->mp_nexthop_global_in
, 4);
2936 stream_putc(s
, 0); /* no nexthop for flowspec */
2944 case SAFI_MULTICAST
:
2945 case SAFI_LABELED_UNICAST
:
2947 if (attr
->mp_nexthop_len
2948 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2950 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
);
2951 stream_put(s
, &attr
->mp_nexthop_global
,
2953 stream_put(s
, &attr
->mp_nexthop_local
,
2956 stream_putc(s
, IPV6_MAX_BYTELEN
);
2957 stream_put(s
, &attr
->mp_nexthop_global
,
2961 case SAFI_MPLS_VPN
: {
2962 if (attr
->mp_nexthop_len
2963 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
2965 stream_putl(s
, 0); /* RD = 0, per RFC */
2967 stream_put(s
, &attr
->mp_nexthop_global
,
2969 } else if (attr
->mp_nexthop_len
2970 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
2972 stream_putl(s
, 0); /* RD = 0, per RFC */
2974 stream_put(s
, &attr
->mp_nexthop_global
,
2976 stream_putl(s
, 0); /* RD = 0, per RFC */
2978 stream_put(s
, &attr
->mp_nexthop_local
,
2983 stream_putc(s
, IPV6_MAX_BYTELEN
);
2984 stream_put(s
, &attr
->mp_nexthop_global
,
2988 stream_putc(s
, 0); /* no nexthop for flowspec */
2994 if (safi
!= SAFI_FLOWSPEC
)
2996 EC_BGP_ATTR_NH_SEND_LEN
,
2997 "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
2998 peer
->host
, afi
, safi
, attr
->mp_nexthop_len
);
3007 void bgp_packet_mpattr_prefix(struct stream
*s
, afi_t afi
, safi_t safi
,
3008 struct prefix
*p
, struct prefix_rd
*prd
,
3009 mpls_label_t
*label
, uint32_t num_labels
,
3010 int addpath_encode
, uint32_t addpath_tx_id
,
3013 if (safi
== SAFI_MPLS_VPN
) {
3015 stream_putl(s
, addpath_tx_id
);
3016 /* Label, RD, Prefix write. */
3017 stream_putc(s
, p
->prefixlen
+ 88);
3018 stream_put(s
, label
, BGP_LABEL_BYTES
);
3019 stream_put(s
, prd
->val
, 8);
3020 stream_put(s
, &p
->u
.prefix
, PSIZE(p
->prefixlen
));
3021 } else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
3022 /* EVPN prefix - contents depend on type */
3023 bgp_evpn_encode_prefix(s
, p
, prd
, label
, num_labels
, attr
,
3024 addpath_encode
, addpath_tx_id
);
3025 } else if (safi
== SAFI_LABELED_UNICAST
) {
3026 /* Prefix write with label. */
3027 stream_put_labeled_prefix(s
, p
, label
, addpath_encode
,
3029 } else if (safi
== SAFI_FLOWSPEC
) {
3030 if (PSIZE (p
->prefixlen
)+2 < FLOWSPEC_NLRI_SIZELIMIT
)
3031 stream_putc(s
, PSIZE (p
->prefixlen
)+2);
3033 stream_putw(s
, (PSIZE (p
->prefixlen
)+2)|(0xf<<12));
3034 stream_putc(s
, 2);/* Filter type */
3035 stream_putc(s
, p
->prefixlen
);/* Prefix length */
3036 stream_put(s
, &p
->u
.prefix
, PSIZE (p
->prefixlen
));
3038 stream_put_prefix_addpath(s
, p
, addpath_encode
, addpath_tx_id
);
3041 size_t bgp_packet_mpattr_prefix_size(afi_t afi
, safi_t safi
, struct prefix
*p
)
3043 int size
= PSIZE(p
->prefixlen
);
3044 if (safi
== SAFI_MPLS_VPN
)
3046 else if (safi
== SAFI_LABELED_UNICAST
)
3047 size
+= BGP_LABEL_BYTES
;
3048 else if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3049 size
+= 232; // TODO: Maximum possible for type-2, type-3 and
3055 * Encodes the tunnel encapsulation attribute,
3056 * and with ENABLE_BGP_VNC the VNC attribute which uses
3057 * almost the same TLV format
3059 static void bgp_packet_mpattr_tea(struct bgp
*bgp
, struct peer
*peer
,
3060 struct stream
*s
, struct attr
*attr
,
3063 unsigned int attrlenfield
= 0;
3064 unsigned int attrhdrlen
= 0;
3065 struct bgp_attr_encap_subtlv
*subtlvs
;
3066 struct bgp_attr_encap_subtlv
*st
;
3067 const char *attrname
;
3069 if (!attr
|| (attrtype
== BGP_ATTR_ENCAP
3070 && (!attr
->encap_tunneltype
3071 || attr
->encap_tunneltype
== BGP_ENCAP_TYPE_MPLS
)))
3075 case BGP_ATTR_ENCAP
:
3076 attrname
= "Tunnel Encap";
3077 subtlvs
= attr
->encap_subtlvs
;
3078 if (subtlvs
== NULL
) /* nothing to do */
3081 * The tunnel encap attr has an "outer" tlv.
3083 * L = total length of subtlvs,
3084 * V = concatenated subtlvs.
3086 attrlenfield
= 2 + 2; /* T + L */
3087 attrhdrlen
= 1 + 1; /* subTLV T + L */
3090 #if ENABLE_BGP_VNC_ATTR
3093 subtlvs
= attr
->vnc_subtlvs
;
3094 if (subtlvs
== NULL
) /* nothing to do */
3096 attrlenfield
= 0; /* no outer T + L */
3097 attrhdrlen
= 2 + 2; /* subTLV T + L */
3105 /* compute attr length */
3106 for (st
= subtlvs
; st
; st
= st
->next
) {
3107 attrlenfield
+= (attrhdrlen
+ st
->length
);
3110 if (attrlenfield
> 0xffff) {
3111 zlog_info("%s attribute is too long (length=%d), can't send it",
3112 attrname
, attrlenfield
);
3116 if (attrlenfield
> 0xff) {
3117 /* 2-octet length field */
3119 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3120 | BGP_ATTR_FLAG_EXTLEN
);
3121 stream_putc(s
, attrtype
);
3122 stream_putw(s
, attrlenfield
& 0xffff);
3124 /* 1-octet length field */
3125 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
);
3126 stream_putc(s
, attrtype
);
3127 stream_putc(s
, attrlenfield
& 0xff);
3130 if (attrtype
== BGP_ATTR_ENCAP
) {
3131 /* write outer T+L */
3132 stream_putw(s
, attr
->encap_tunneltype
);
3133 stream_putw(s
, attrlenfield
- 4);
3136 /* write each sub-tlv */
3137 for (st
= subtlvs
; st
; st
= st
->next
) {
3138 if (attrtype
== BGP_ATTR_ENCAP
) {
3139 stream_putc(s
, st
->type
);
3140 stream_putc(s
, st
->length
);
3143 stream_putw(s
, st
->type
);
3144 stream_putw(s
, st
->length
);
3147 stream_put(s
, st
->value
, st
->length
);
3151 void bgp_packet_mpattr_end(struct stream
*s
, size_t sizep
)
3153 /* Set MP attribute length. Don't count the (2) bytes used to encode
3155 stream_putw_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 2);
3158 static int bgp_append_local_as(struct peer
*peer
, afi_t afi
, safi_t safi
)
3160 if (!BGP_AS_IS_PRIVATE(peer
->local_as
)
3161 || (BGP_AS_IS_PRIVATE(peer
->local_as
)
3162 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3163 PEER_FLAG_REMOVE_PRIVATE_AS
)
3164 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3165 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
3166 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3167 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
3168 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3169 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)))
3174 /* Make attribute packet. */
3175 bgp_size_t
bgp_packet_attribute(struct bgp
*bgp
, struct peer
*peer
,
3176 struct stream
*s
, struct attr
*attr
,
3177 struct bpacket_attr_vec_arr
*vecarr
,
3178 struct prefix
*p
, afi_t afi
, safi_t safi
,
3179 struct peer
*from
, struct prefix_rd
*prd
,
3180 mpls_label_t
*label
, uint32_t num_labels
,
3181 int addpath_encode
, uint32_t addpath_tx_id
)
3184 size_t aspath_sizep
;
3185 struct aspath
*aspath
;
3186 int send_as4_path
= 0;
3187 int send_as4_aggregator
= 0;
3188 int use32bit
= (CHECK_FLAG(peer
->cap
, PEER_CAP_AS4_RCV
)) ? 1 : 0;
3193 /* Remember current pointer. */
3194 cp
= stream_get_endp(s
);
3197 && !((afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
3198 && !peer_cap_enhe(peer
, afi
, safi
))) {
3199 size_t mpattrlen_pos
= 0;
3201 mpattrlen_pos
= bgp_packet_mpattr_start(s
, peer
, afi
, safi
,
3203 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
,
3204 num_labels
, addpath_encode
,
3205 addpath_tx_id
, attr
);
3206 bgp_packet_mpattr_end(s
, mpattrlen_pos
);
3209 /* Origin attribute. */
3210 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3211 stream_putc(s
, BGP_ATTR_ORIGIN
);
3213 stream_putc(s
, attr
->origin
);
3215 /* AS path attribute. */
3217 /* If remote-peer is EBGP */
3218 if (peer
->sort
== BGP_PEER_EBGP
3219 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3220 PEER_FLAG_AS_PATH_UNCHANGED
)
3221 || attr
->aspath
->segments
== NULL
)
3222 && (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3223 PEER_FLAG_RSERVER_CLIENT
))) {
3224 aspath
= aspath_dup(attr
->aspath
);
3226 /* Even though we may not be configured for confederations we
3228 * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
3229 aspath
= aspath_delete_confed_seq(aspath
);
3231 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
3232 /* Stuff our path CONFED_ID on the front */
3233 aspath
= aspath_add_seq(aspath
, bgp
->confed_id
);
3235 if (peer
->change_local_as
) {
3236 /* If replace-as is specified, we only use the
3237 change_local_as when
3238 advertising routes. */
3239 if (!CHECK_FLAG(peer
->flags
,
3240 PEER_FLAG_LOCAL_AS_REPLACE_AS
))
3241 if (bgp_append_local_as(peer
, afi
,
3243 aspath
= aspath_add_seq(
3244 aspath
, peer
->local_as
);
3245 aspath
= aspath_add_seq(aspath
,
3246 peer
->change_local_as
);
3248 aspath
= aspath_add_seq(aspath
, peer
->local_as
);
3251 } else if (peer
->sort
== BGP_PEER_CONFED
) {
3252 /* A confed member, so we need to do the AS_CONFED_SEQUENCE
3254 aspath
= aspath_dup(attr
->aspath
);
3255 aspath
= aspath_add_confed_seq(aspath
, peer
->local_as
);
3257 aspath
= attr
->aspath
;
3259 /* If peer is not AS4 capable, then:
3260 * - send the created AS_PATH out as AS4_PATH (optional, transitive),
3261 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
3263 * types are in it (i.e. exclude them if they are there)
3264 * AND do this only if there is at least one asnum > 65535 in the
3266 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
3268 * all ASnums > 65535 to BGP_AS_TRANS
3271 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3272 stream_putc(s
, BGP_ATTR_AS_PATH
);
3273 aspath_sizep
= stream_get_endp(s
);
3275 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, use32bit
));
3277 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
3280 if (!use32bit
&& aspath_has_as4(aspath
))
3282 1; /* we'll do this later, at the correct place */
3284 /* Nexthop attribute. */
3285 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
3286 && !peer_cap_enhe(peer
, afi
, safi
)) {
3287 afi_t nh_afi
= BGP_NEXTHOP_AFI_FROM_NHLEN(attr
->mp_nexthop_len
);
3289 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3290 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3291 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3292 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3295 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3296 } else if (peer_cap_enhe(from
, afi
, safi
)
3297 || (nh_afi
== AFI_IP6
)) {
3299 * Likely this is the case when an IPv4 prefix was
3300 * received with Extended Next-hop capability in this
3301 * or another vrf and is now being advertised to
3302 * non-ENHE peers. Since peer_cap_enhe only checks
3303 * peers in this vrf, also check the nh_afi to catch
3304 * the case where the originator was in another vrf.
3305 * Setting the mandatory (ipv4) next-hop attribute here
3306 * to enable implicit next-hop self with correct A-F
3307 * (ipv4 address family).
3309 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3310 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3311 bpacket_attr_vec_arr_set_vec(vecarr
, BGP_ATTR_VEC_NH
, s
,
3314 stream_put_ipv4(s
, 0);
3318 /* MED attribute. */
3319 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)
3320 || bgp
->maxmed_active
) {
3321 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3322 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3324 stream_putl(s
, (bgp
->maxmed_active
? bgp
->maxmed_value
3328 /* Local preference. */
3329 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
3330 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3331 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3333 stream_putl(s
, attr
->local_pref
);
3336 /* Atomic aggregate. */
3337 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3338 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3339 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3344 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3345 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
3346 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3347 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3350 /* AS4 capable peer */
3352 stream_putl(s
, attr
->aggregator_as
);
3354 /* 2-byte AS peer */
3357 /* Is ASN representable in 2-bytes? Or must AS_TRANS be
3359 if (attr
->aggregator_as
> 65535) {
3360 stream_putw(s
, BGP_AS_TRANS
);
3362 /* we have to send AS4_AGGREGATOR, too.
3363 * we'll do that later in order to send
3364 * attributes in ascending
3367 send_as4_aggregator
= 1;
3369 stream_putw(s
, (uint16_t)attr
->aggregator_as
);
3371 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3374 /* Community attribute. */
3375 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_COMMUNITY
)
3376 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
))) {
3377 if (attr
->community
->size
* 4 > 255) {
3379 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3380 | BGP_ATTR_FLAG_EXTLEN
);
3381 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3382 stream_putw(s
, attr
->community
->size
* 4);
3385 BGP_ATTR_FLAG_OPTIONAL
3386 | BGP_ATTR_FLAG_TRANS
);
3387 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3388 stream_putc(s
, attr
->community
->size
* 4);
3390 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3394 * Large Community attribute.
3396 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3397 PEER_FLAG_SEND_LARGE_COMMUNITY
)
3398 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))) {
3399 if (lcom_length(attr
->lcommunity
) > 255) {
3401 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3402 | BGP_ATTR_FLAG_EXTLEN
);
3403 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3404 stream_putw(s
, lcom_length(attr
->lcommunity
));
3407 BGP_ATTR_FLAG_OPTIONAL
3408 | BGP_ATTR_FLAG_TRANS
);
3409 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3410 stream_putc(s
, lcom_length(attr
->lcommunity
));
3412 stream_put(s
, attr
->lcommunity
->val
,
3413 lcom_length(attr
->lcommunity
));
3416 /* Route Reflector. */
3417 if (peer
->sort
== BGP_PEER_IBGP
&& from
3418 && from
->sort
== BGP_PEER_IBGP
) {
3419 /* Originator ID. */
3420 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3421 stream_putc(s
, BGP_ATTR_ORIGINATOR_ID
);
3424 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
3425 stream_put_in_addr(s
, &attr
->originator_id
);
3427 stream_put_in_addr(s
, &from
->remote_id
);
3430 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3431 stream_putc(s
, BGP_ATTR_CLUSTER_LIST
);
3433 if (attr
->cluster
) {
3434 stream_putc(s
, attr
->cluster
->length
+ 4);
3435 /* If this peer configuration's parent BGP has
3437 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3438 stream_put_in_addr(s
, &bgp
->cluster_id
);
3440 stream_put_in_addr(s
, &bgp
->router_id
);
3441 stream_put(s
, attr
->cluster
->list
,
3442 attr
->cluster
->length
);
3445 /* If this peer configuration's parent BGP has
3447 if (bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
3448 stream_put_in_addr(s
, &bgp
->cluster_id
);
3450 stream_put_in_addr(s
, &bgp
->router_id
);
3454 /* Extended Communities attribute. */
3455 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SEND_EXT_COMMUNITY
)
3456 && (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3457 if (peer
->sort
== BGP_PEER_IBGP
3458 || peer
->sort
== BGP_PEER_CONFED
) {
3459 if (attr
->ecommunity
->size
* 8 > 255) {
3461 BGP_ATTR_FLAG_OPTIONAL
3462 | BGP_ATTR_FLAG_TRANS
3463 | BGP_ATTR_FLAG_EXTLEN
);
3464 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3465 stream_putw(s
, attr
->ecommunity
->size
* 8);
3468 BGP_ATTR_FLAG_OPTIONAL
3469 | BGP_ATTR_FLAG_TRANS
);
3470 stream_putc(s
, BGP_ATTR_EXT_COMMUNITIES
);
3471 stream_putc(s
, attr
->ecommunity
->size
* 8);
3473 stream_put(s
, attr
->ecommunity
->val
,
3474 attr
->ecommunity
->size
* 8);
3478 int ecom_tr_size
= 0;
3481 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3482 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3485 if (CHECK_FLAG(tbit
,
3486 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3493 if (ecom_tr_size
* 8 > 255) {
3496 BGP_ATTR_FLAG_OPTIONAL
3497 | BGP_ATTR_FLAG_TRANS
3498 | BGP_ATTR_FLAG_EXTLEN
);
3500 BGP_ATTR_EXT_COMMUNITIES
);
3501 stream_putw(s
, ecom_tr_size
* 8);
3505 BGP_ATTR_FLAG_OPTIONAL
3506 | BGP_ATTR_FLAG_TRANS
);
3508 BGP_ATTR_EXT_COMMUNITIES
);
3509 stream_putc(s
, ecom_tr_size
* 8);
3512 for (i
= 0; i
< attr
->ecommunity
->size
; i
++) {
3513 pnt
= attr
->ecommunity
->val
+ (i
* 8);
3518 ECOMMUNITY_FLAG_NON_TRANSITIVE
))
3521 stream_put(s
, pnt
, 8);
3527 /* Label index attribute. */
3528 if (safi
== SAFI_LABELED_UNICAST
) {
3529 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3530 uint32_t label_index
;
3532 label_index
= attr
->label_index
;
3534 if (label_index
!= BGP_INVALID_LABEL_INDEX
) {
3536 BGP_ATTR_FLAG_OPTIONAL
3537 | BGP_ATTR_FLAG_TRANS
);
3538 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3540 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3542 BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3543 stream_putc(s
, 0); // reserved
3544 stream_putw(s
, 0); // flags
3545 stream_putl(s
, label_index
);
3550 if (send_as4_path
) {
3551 /* If the peer is NOT As4 capable, AND */
3552 /* there are ASnums > 65535 in path THEN
3553 * give out AS4_PATH */
3555 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
3557 * Hm, I wonder... confederation things *should* only be at
3558 * the beginning of an aspath, right? Then we should use
3559 * aspath_delete_confed_seq for this, because it is already
3561 * Folks, talk to me: what is reasonable here!?
3563 aspath
= aspath_delete_confed_seq(aspath
);
3566 BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_OPTIONAL
3567 | BGP_ATTR_FLAG_EXTLEN
);
3568 stream_putc(s
, BGP_ATTR_AS4_PATH
);
3569 aspath_sizep
= stream_get_endp(s
);
3571 stream_putw_at(s
, aspath_sizep
, aspath_put(s
, aspath
, 1));
3574 if (aspath
!= attr
->aspath
)
3575 aspath_free(aspath
);
3577 if (send_as4_aggregator
) {
3578 /* send AS4_AGGREGATOR, at this place */
3579 /* this section of code moved here in order to ensure the
3581 * *ascending* order of attributes
3583 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3584 stream_putc(s
, BGP_ATTR_AS4_AGGREGATOR
);
3586 stream_putl(s
, attr
->aggregator_as
);
3587 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3590 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3591 && (safi
== SAFI_ENCAP
|| safi
== SAFI_MPLS_VPN
))
3592 || (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)) {
3593 /* Tunnel Encap attribute */
3594 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_ENCAP
);
3596 #if ENABLE_BGP_VNC_ATTR
3598 bgp_packet_mpattr_tea(bgp
, peer
, s
, attr
, BGP_ATTR_VNC
);
3603 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
3604 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3605 stream_putc(s
, BGP_ATTR_PMSI_TUNNEL
);
3606 stream_putc(s
, 9); // Length
3607 stream_putc(s
, 0); // Flags
3608 stream_putc(s
, attr
->pmsi_tnl_type
);
3609 stream_put(s
, &(attr
->label
),
3610 BGP_LABEL_BYTES
); // MPLS Label / VXLAN VNI
3611 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3612 // Unicast tunnel endpoint IP address
3615 /* Unknown transit attribute. */
3617 stream_put(s
, attr
->transit
->val
, attr
->transit
->length
);
3619 /* Return total size of attribute. */
3620 return stream_get_endp(s
) - cp
;
3623 size_t bgp_packet_mpunreach_start(struct stream
*s
, afi_t afi
, safi_t safi
)
3625 unsigned long attrlen_pnt
;
3627 iana_safi_t pkt_safi
;
3629 /* Set extended bit always to encode the attribute length as 2 bytes */
3630 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN
);
3631 stream_putc(s
, BGP_ATTR_MP_UNREACH_NLRI
);
3633 attrlen_pnt
= stream_get_endp(s
);
3634 stream_putw(s
, 0); /* Length of this attribute. */
3636 /* Convert AFI, SAFI to values for packet. */
3637 bgp_map_afi_safi_int2iana(afi
, safi
, &pkt_afi
, &pkt_safi
);
3639 stream_putw(s
, pkt_afi
);
3640 stream_putc(s
, pkt_safi
);
3645 void bgp_packet_mpunreach_prefix(struct stream
*s
, struct prefix
*p
, afi_t afi
,
3646 safi_t safi
, struct prefix_rd
*prd
,
3647 mpls_label_t
*label
, uint32_t num_labels
,
3648 int addpath_encode
, uint32_t addpath_tx_id
,
3651 uint8_t wlabel
[3] = {0x80, 0x00, 0x00};
3653 if (safi
== SAFI_LABELED_UNICAST
) {
3654 label
= (mpls_label_t
*)wlabel
;
3658 bgp_packet_mpattr_prefix(s
, afi
, safi
, p
, prd
, label
, num_labels
,
3659 addpath_encode
, addpath_tx_id
, attr
);
3662 void bgp_packet_mpunreach_end(struct stream
*s
, size_t attrlen_pnt
)
3664 bgp_packet_mpattr_end(s
, attrlen_pnt
);
3667 /* Initialization of attribute. */
3668 void bgp_attr_init(void)
3680 void bgp_attr_finish(void)
3685 ecommunity_finish();
3686 lcommunity_finish();
3692 /* Make attribute packet. */
3693 void bgp_dump_routes_attr(struct stream
*s
, struct attr
*attr
,
3694 struct prefix
*prefix
)
3699 struct aspath
*aspath
;
3700 int addpath_encode
= 0;
3701 uint32_t addpath_tx_id
= 0;
3703 /* Remember current pointer. */
3704 cp
= stream_get_endp(s
);
3706 /* Place holder of length. */
3709 /* Origin attribute. */
3710 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3711 stream_putc(s
, BGP_ATTR_ORIGIN
);
3713 stream_putc(s
, attr
->origin
);
3715 aspath
= attr
->aspath
;
3717 stream_putc(s
, BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN
);
3718 stream_putc(s
, BGP_ATTR_AS_PATH
);
3719 aspath_lenp
= stream_get_endp(s
);
3722 stream_putw_at(s
, aspath_lenp
, aspath_put(s
, aspath
, 1));
3724 /* Nexthop attribute. */
3725 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
3726 if (prefix
!= NULL
&& prefix
->family
!= AF_INET6
) {
3727 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3728 stream_putc(s
, BGP_ATTR_NEXT_HOP
);
3730 stream_put_ipv4(s
, attr
->nexthop
.s_addr
);
3733 /* MED attribute. */
3734 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
3735 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3736 stream_putc(s
, BGP_ATTR_MULTI_EXIT_DISC
);
3738 stream_putl(s
, attr
->med
);
3741 /* Local preference. */
3742 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
3743 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3744 stream_putc(s
, BGP_ATTR_LOCAL_PREF
);
3746 stream_putl(s
, attr
->local_pref
);
3749 /* Atomic aggregate. */
3750 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
3751 stream_putc(s
, BGP_ATTR_FLAG_TRANS
);
3752 stream_putc(s
, BGP_ATTR_ATOMIC_AGGREGATE
);
3757 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
)) {
3758 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
);
3759 stream_putc(s
, BGP_ATTR_AGGREGATOR
);
3761 stream_putl(s
, attr
->aggregator_as
);
3762 stream_put_ipv4(s
, attr
->aggregator_addr
.s_addr
);
3765 /* Community attribute. */
3766 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
)) {
3767 if (attr
->community
->size
* 4 > 255) {
3769 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3770 | BGP_ATTR_FLAG_EXTLEN
);
3771 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3772 stream_putw(s
, attr
->community
->size
* 4);
3775 BGP_ATTR_FLAG_OPTIONAL
3776 | BGP_ATTR_FLAG_TRANS
);
3777 stream_putc(s
, BGP_ATTR_COMMUNITIES
);
3778 stream_putc(s
, attr
->community
->size
* 4);
3780 stream_put(s
, attr
->community
->val
, attr
->community
->size
* 4);
3783 /* Large Community attribute. */
3784 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
3785 if (lcom_length(attr
->lcommunity
) > 255) {
3787 BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
3788 | BGP_ATTR_FLAG_EXTLEN
);
3789 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3790 stream_putw(s
, lcom_length(attr
->lcommunity
));
3793 BGP_ATTR_FLAG_OPTIONAL
3794 | BGP_ATTR_FLAG_TRANS
);
3795 stream_putc(s
, BGP_ATTR_LARGE_COMMUNITIES
);
3796 stream_putc(s
, lcom_length(attr
->lcommunity
));
3799 stream_put(s
, attr
->lcommunity
->val
,
3800 lcom_length(attr
->lcommunity
));
3803 /* Add a MP_NLRI attribute to dump the IPv6 next hop */
3804 if (prefix
!= NULL
&& prefix
->family
== AF_INET6
3805 && (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
3806 || attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)) {
3809 stream_putc(s
, BGP_ATTR_FLAG_OPTIONAL
);
3810 stream_putc(s
, BGP_ATTR_MP_REACH_NLRI
);
3811 sizep
= stream_get_endp(s
);
3814 stream_putc(s
, 0); /* Marker: Attribute length. */
3815 stream_putw(s
, AFI_IP6
); /* AFI */
3816 stream_putc(s
, SAFI_UNICAST
); /* SAFI */
3819 stream_putc(s
, attr
->mp_nexthop_len
);
3820 stream_put(s
, &attr
->mp_nexthop_global
, IPV6_MAX_BYTELEN
);
3821 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
3822 stream_put(s
, &attr
->mp_nexthop_local
,
3829 stream_put_prefix_addpath(s
, prefix
, addpath_encode
,
3832 /* Set MP attribute length. */
3833 stream_putc_at(s
, sizep
, (stream_get_endp(s
) - sizep
) - 1);
3837 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
3838 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
3840 BGP_ATTR_FLAG_OPTIONAL
3841 | BGP_ATTR_FLAG_TRANS
);
3842 stream_putc(s
, BGP_ATTR_PREFIX_SID
);
3844 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX
);
3845 stream_putc(s
, BGP_PREFIX_SID_LABEL_INDEX_LENGTH
);
3846 stream_putc(s
, 0); // reserved
3847 stream_putw(s
, 0); // flags
3848 stream_putl(s
, attr
->label_index
);
3852 /* Return total size of attribute. */
3853 len
= stream_get_endp(s
) - cp
- 2;
3854 stream_putw_at(s
, cp
, len
);